2 * Copyright (C) 2006-2011 Tobias Brunner,
3 * Copyright (C) 2006-2007 Martin Willi
4 * Copyright (C) 2006 Daniel Roethlisberger
5 * HSR Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * Copyright (C) 2012 Volker RĂ¼melin
21 * Permission is hereby granted, free of charge, to any person obtaining a copy
22 * of this software and associated documentation files (the "Software"), to deal
23 * in the Software without restriction, including without limitation the rights
24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 * copies of the Software, and to permit persons to whom the Software is
26 * furnished to do so, subject to the following conditions:
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40 #include "isakmp_natd.h"
45 #include <sa/ikev1/keymat_v1.h>
46 #include <config/peer_cfg.h>
47 #include <crypto/hashers/hasher.h>
48 #include <encoding/payloads/hash_payload.h>
50 typedef struct private_isakmp_natd_t private_isakmp_natd_t
;
53 * Private members of a ike_natt_t task.
55 struct private_isakmp_natd_t
{
68 * Are we the initiator?
73 * Keymat derivation (from SA)
78 * Did we process any NAT detection payloads for a source address?
83 * Did we process any NAT detection payloads for a destination address?
88 * Have we found a matching source address NAT hash?
93 * Have we found a matching destination address NAT hash?
99 * Check if UDP encapsulation has to be forced either by config or required
100 * by the kernel interface
102 static bool force_encap(ike_cfg_t
*ike_cfg
)
104 if (!ike_cfg
->force_encap(ike_cfg
))
106 return charon
->kernel
->get_features(charon
->kernel
) &
107 KERNEL_REQUIRE_UDP_ENCAPSULATION
;
113 * Get NAT-D payload type (RFC 3947 or RFC 3947 drafts).
115 static payload_type_t
get_nat_d_payload_type(ike_sa_t
*ike_sa
)
117 if (ike_sa
->supports_extension(ike_sa
, EXT_NATT_DRAFT_02_03
))
119 return PLV1_NAT_D_DRAFT_00_03
;
125 * Build NAT detection hash for a host.
127 static chunk_t
generate_natd_hash(private_isakmp_natd_t
*this,
128 ike_sa_id_t
*ike_sa_id
, host_t
*host
)
131 chunk_t natd_chunk
, natd_hash
;
132 uint64_t spi_i
, spi_r
;
135 hasher
= this->keymat
->get_hasher(this->keymat
);
138 DBG1(DBG_IKE
, "no hasher available to build NAT-D payload");
142 spi_i
= ike_sa_id
->get_initiator_spi(ike_sa_id
);
143 spi_r
= ike_sa_id
->get_responder_spi(ike_sa_id
);
144 port
= htons(host
->get_port(host
));
146 /* natd_hash = HASH(CKY-I | CKY-R | IP | Port) */
147 natd_chunk
= chunk_cata("cccc", chunk_from_thing(spi_i
),
148 chunk_from_thing(spi_r
), host
->get_address(host
),
149 chunk_from_thing(port
));
150 if (!hasher
->allocate_hash(hasher
, natd_chunk
, &natd_hash
))
152 DBG1(DBG_IKE
, "creating NAT-D payload hash failed");
155 DBG3(DBG_IKE
, "natd_chunk %B", &natd_chunk
);
156 DBG3(DBG_IKE
, "natd_hash %B", &natd_hash
);
162 * Build a faked NAT-D payload to enforce UDP encapsulation.
164 static chunk_t
generate_natd_hash_faked(private_isakmp_natd_t
*this)
170 hasher
= this->keymat
->get_hasher(this->keymat
);
173 DBG1(DBG_IKE
, "no hasher available to build NAT-D payload");
176 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
178 !rng
->allocate_bytes(rng
, hasher
->get_hash_size(hasher
), &chunk
))
180 DBG1(DBG_IKE
, "unable to get random bytes for NAT-D fake");
189 * Build a NAT-D payload.
191 static hash_payload_t
*build_natd_payload(private_isakmp_natd_t
*this, bool src
,
194 hash_payload_t
*payload
;
198 config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
199 if (src
&& force_encap(config
))
201 hash
= generate_natd_hash_faked(this);
205 ike_sa_id_t
*ike_sa_id
= this->ike_sa
->get_id(this->ike_sa
);
206 hash
= generate_natd_hash(this, ike_sa_id
, host
);
212 payload
= hash_payload_create(get_nat_d_payload_type(this->ike_sa
));
213 payload
->set_hash(payload
, hash
);
219 * Add NAT-D payloads to the message.
221 static void add_natd_payloads(private_isakmp_natd_t
*this, message_t
*message
)
223 hash_payload_t
*payload
;
226 /* destination has to be added first */
227 host
= message
->get_destination(message
);
228 payload
= build_natd_payload(this, FALSE
, host
);
231 message
->add_payload(message
, (payload_t
*)payload
);
234 /* source is added second, compared with IKEv2 we always know the source,
235 * as these payloads are added in the second Phase 1 exchange or the
236 * response to the first */
237 host
= message
->get_source(message
);
238 payload
= build_natd_payload(this, TRUE
, host
);
241 message
->add_payload(message
, (payload_t
*)payload
);
246 * Read NAT-D payloads from message and evaluate them.
248 static void process_payloads(private_isakmp_natd_t
*this, message_t
*message
)
250 enumerator_t
*enumerator
;
252 hash_payload_t
*hash_payload
;
253 chunk_t hash
, src_hash
, dst_hash
;
254 ike_sa_id_t
*ike_sa_id
;
258 /* precompute hashes for incoming NAT-D comparison */
259 ike_sa_id
= message
->get_ike_sa_id(message
);
260 me
= message
->get_destination(message
);
261 other
= message
->get_source(message
);
262 dst_hash
= generate_natd_hash(this, ike_sa_id
, me
);
263 src_hash
= generate_natd_hash(this, ike_sa_id
, other
);
265 DBG3(DBG_IKE
, "precalculated src_hash %B", &src_hash
);
266 DBG3(DBG_IKE
, "precalculated dst_hash %B", &dst_hash
);
268 enumerator
= message
->create_payload_enumerator(message
);
269 while (enumerator
->enumerate(enumerator
, &payload
))
271 if (payload
->get_type(payload
) != PLV1_NAT_D
&&
272 payload
->get_type(payload
) != PLV1_NAT_D_DRAFT_00_03
)
276 hash_payload
= (hash_payload_t
*)payload
;
278 { /* the first NAT-D payload contains the destination hash */
279 this->dst_seen
= TRUE
;
280 hash
= hash_payload
->get_hash(hash_payload
);
281 DBG3(DBG_IKE
, "received dst_hash %B", &hash
);
282 if (chunk_equals(hash
, dst_hash
))
284 this->dst_matched
= TRUE
;
288 /* the other NAT-D payloads contain source hashes */
289 this->src_seen
= TRUE
;
290 if (!this->src_matched
)
292 hash
= hash_payload
->get_hash(hash_payload
);
293 DBG3(DBG_IKE
, "received src_hash %B", &hash
);
294 if (chunk_equals(hash
, src_hash
))
296 this->src_matched
= TRUE
;
300 enumerator
->destroy(enumerator
);
302 chunk_free(&src_hash
);
303 chunk_free(&dst_hash
);
305 if (this->src_seen
&& this->dst_seen
)
307 this->ike_sa
->set_condition(this->ike_sa
, COND_NAT_HERE
,
309 this->ike_sa
->set_condition(this->ike_sa
, COND_NAT_THERE
,
311 config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
312 if (this->dst_matched
&& this->src_matched
&&
315 this->ike_sa
->set_condition(this->ike_sa
, COND_NAT_FAKE
, TRUE
);
320 METHOD(task_t
, build_i
, status_t
,
321 private_isakmp_natd_t
*this, message_t
*message
)
323 status_t result
= NEED_MORE
;
325 switch (message
->get_exchange_type(message
))
328 { /* add NAT-D payloads to the second request, already processed
329 * those by the responder contained in the first response */
334 { /* add NAT-D payloads to the second request, need to process
335 * those by the responder contained in the second response */
336 if (message
->get_payload(message
, PLV1_SECURITY_ASSOCIATION
))
337 { /* wait for the second exchange */
340 add_natd_payloads(this, message
);
349 METHOD(task_t
, process_i
, status_t
,
350 private_isakmp_natd_t
*this, message_t
*message
)
352 status_t result
= NEED_MORE
;
354 if (!this->ike_sa
->supports_extension(this->ike_sa
, EXT_NATT
))
355 { /* we didn't receive VIDs indicating support for NAT-T */
359 switch (message
->get_exchange_type(message
))
362 { /* process NAT-D payloads in the second response, added them in the
363 * second request already, so we're done afterwards */
364 if (message
->get_payload(message
, PLV1_SECURITY_ASSOCIATION
))
365 { /* wait for the second exchange */
372 { /* process NAT-D payloads in the first response, add them in the
373 * following second request */
374 process_payloads(this, message
);
376 if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
378 this->ike_sa
->float_ports(this->ike_sa
);
388 METHOD(task_t
, process_r
, status_t
,
389 private_isakmp_natd_t
*this, message_t
*message
)
391 status_t result
= NEED_MORE
;
393 if (!this->ike_sa
->supports_extension(this->ike_sa
, EXT_NATT
))
394 { /* we didn't receive VIDs indicating NAT-T support */
398 switch (message
->get_exchange_type(message
))
401 { /* process NAT-D payloads in the second request, already added ours
402 * in the first response */
407 { /* process NAT-D payloads in the second request, need to add ours
408 * to the second response */
409 if (message
->get_payload(message
, PLV1_SECURITY_ASSOCIATION
))
410 { /* wait for the second exchange */
413 process_payloads(this, message
);
422 METHOD(task_t
, build_r
, status_t
,
423 private_isakmp_natd_t
*this, message_t
*message
)
425 switch (message
->get_exchange_type(message
))
428 { /* add NAT-D payloads to second response, already processed those
429 * contained in the second request */
430 if (message
->get_payload(message
, PLV1_SECURITY_ASSOCIATION
))
431 { /* wait for the second exchange */
434 add_natd_payloads(this, message
);
438 { /* add NAT-D payloads to the first response, process those contained
439 * in the following second request */
440 add_natd_payloads(this, message
);
449 METHOD(task_t
, get_type
, task_type_t
,
450 private_isakmp_natd_t
*this)
452 return TASK_ISAKMP_NATD
;
455 METHOD(task_t
, migrate
, void,
456 private_isakmp_natd_t
*this, ike_sa_t
*ike_sa
)
458 this->ike_sa
= ike_sa
;
459 this->keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
460 this->src_seen
= FALSE
;
461 this->dst_seen
= FALSE
;
462 this->src_matched
= FALSE
;
463 this->dst_matched
= FALSE
;
466 METHOD(task_t
, destroy
, void,
467 private_isakmp_natd_t
*this)
473 * Described in header.
475 isakmp_natd_t
*isakmp_natd_create(ike_sa_t
*ike_sa
, bool initiator
)
477 private_isakmp_natd_t
*this;
482 .get_type
= _get_type
,
488 .keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
),
489 .initiator
= initiator
,
494 this->public.task
.build
= _build_i
;
495 this->public.task
.process
= _process_i
;
499 this->public.task
.build
= _build_r
;
500 this->public.task
.process
= _process_r
;
503 return &this->public;