2 * Copyright (C) 2006-2011 Tobias Brunner,
3 * Copyright (C) 2006-2007 Martin Willi
4 * Copyright (C) 2006 Daniel Roethlisberger
5 * 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"
46 #include <sa/ikev1/keymat_v1.h>
47 #include <config/peer_cfg.h>
48 #include <crypto/hashers/hasher.h>
49 #include <encoding/payloads/hash_payload.h>
51 typedef struct private_isakmp_natd_t private_isakmp_natd_t
;
54 * Private members of a ike_natt_t task.
56 struct private_isakmp_natd_t
{
69 * Are we the initiator?
74 * Keymat derivation (from SA)
79 * Did we process any NAT detection payloads for a source address?
84 * Did we process any NAT detection payloads for a destination address?
89 * Have we found a matching source address NAT hash?
94 * Have we found a matching destination address NAT hash?
100 * Check if UDP encapsulation has to be forced either by config or required
101 * by the kernel interface
103 static bool force_encap(ike_cfg_t
*ike_cfg
)
105 if (!ike_cfg
->force_encap(ike_cfg
))
107 return hydra
->kernel_interface
->get_features(hydra
->kernel_interface
) &
108 KERNEL_REQUIRE_UDP_ENCAPSULATION
;
114 * Get NAT-D payload type (RFC 3947 or RFC 3947 drafts).
116 static payload_type_t
get_nat_d_payload_type(ike_sa_t
*ike_sa
)
118 if (ike_sa
->supports_extension(ike_sa
, EXT_NATT_DRAFT_02_03
))
120 return PLV1_NAT_D_DRAFT_00_03
;
126 * Build NAT detection hash for a host.
128 static chunk_t
generate_natd_hash(private_isakmp_natd_t
*this,
129 ike_sa_id_t
*ike_sa_id
, host_t
*host
)
132 chunk_t natd_chunk
, natd_hash
;
133 u_int64_t spi_i
, spi_r
;
136 hasher
= this->keymat
->get_hasher(this->keymat
);
139 DBG1(DBG_IKE
, "no hasher available to build NAT-D payload");
143 spi_i
= ike_sa_id
->get_initiator_spi(ike_sa_id
);
144 spi_r
= ike_sa_id
->get_responder_spi(ike_sa_id
);
145 port
= htons(host
->get_port(host
));
147 /* natd_hash = HASH(CKY-I | CKY-R | IP | Port) */
148 natd_chunk
= chunk_cata("cccc", chunk_from_thing(spi_i
),
149 chunk_from_thing(spi_r
), host
->get_address(host
),
150 chunk_from_thing(port
));
151 if (!hasher
->allocate_hash(hasher
, natd_chunk
, &natd_hash
))
153 DBG1(DBG_IKE
, "creating NAT-D payload hash failed");
156 DBG3(DBG_IKE
, "natd_chunk %B", &natd_chunk
);
157 DBG3(DBG_IKE
, "natd_hash %B", &natd_hash
);
163 * Build a faked NAT-D payload to enforce UDP encapsulation.
165 static chunk_t
generate_natd_hash_faked(private_isakmp_natd_t
*this)
171 hasher
= this->keymat
->get_hasher(this->keymat
);
174 DBG1(DBG_IKE
, "no hasher available to build NAT-D payload");
177 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
179 !rng
->allocate_bytes(rng
, hasher
->get_hash_size(hasher
), &chunk
))
181 DBG1(DBG_IKE
, "unable to get random bytes for NAT-D fake");
190 * Build a NAT-D payload.
192 static hash_payload_t
*build_natd_payload(private_isakmp_natd_t
*this, bool src
,
195 hash_payload_t
*payload
;
199 config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
200 if (src
&& force_encap(config
))
202 hash
= generate_natd_hash_faked(this);
206 ike_sa_id_t
*ike_sa_id
= this->ike_sa
->get_id(this->ike_sa
);
207 hash
= generate_natd_hash(this, ike_sa_id
, host
);
213 payload
= hash_payload_create(get_nat_d_payload_type(this->ike_sa
));
214 payload
->set_hash(payload
, hash
);
220 * Add NAT-D payloads to the message.
222 static void add_natd_payloads(private_isakmp_natd_t
*this, message_t
*message
)
224 hash_payload_t
*payload
;
227 /* destination has to be added first */
228 host
= message
->get_destination(message
);
229 payload
= build_natd_payload(this, FALSE
, host
);
232 message
->add_payload(message
, (payload_t
*)payload
);
235 /* source is added second, compared with IKEv2 we always know the source,
236 * as these payloads are added in the second Phase 1 exchange or the
237 * response to the first */
238 host
= message
->get_source(message
);
239 payload
= build_natd_payload(this, TRUE
, host
);
242 message
->add_payload(message
, (payload_t
*)payload
);
247 * Read NAT-D payloads from message and evaluate them.
249 static void process_payloads(private_isakmp_natd_t
*this, message_t
*message
)
251 enumerator_t
*enumerator
;
253 hash_payload_t
*hash_payload
;
254 chunk_t hash
, src_hash
, dst_hash
;
255 ike_sa_id_t
*ike_sa_id
;
259 /* precompute hashes for incoming NAT-D comparison */
260 ike_sa_id
= message
->get_ike_sa_id(message
);
261 me
= message
->get_destination(message
);
262 other
= message
->get_source(message
);
263 dst_hash
= generate_natd_hash(this, ike_sa_id
, me
);
264 src_hash
= generate_natd_hash(this, ike_sa_id
, other
);
266 DBG3(DBG_IKE
, "precalculated src_hash %B", &src_hash
);
267 DBG3(DBG_IKE
, "precalculated dst_hash %B", &dst_hash
);
269 enumerator
= message
->create_payload_enumerator(message
);
270 while (enumerator
->enumerate(enumerator
, &payload
))
272 if (payload
->get_type(payload
) != PLV1_NAT_D
&&
273 payload
->get_type(payload
) != PLV1_NAT_D_DRAFT_00_03
)
277 hash_payload
= (hash_payload_t
*)payload
;
279 { /* the first NAT-D payload contains the destination hash */
280 this->dst_seen
= TRUE
;
281 hash
= hash_payload
->get_hash(hash_payload
);
282 DBG3(DBG_IKE
, "received dst_hash %B", &hash
);
283 if (chunk_equals(hash
, dst_hash
))
285 this->dst_matched
= TRUE
;
289 /* the other NAT-D payloads contain source hashes */
290 this->src_seen
= TRUE
;
291 if (!this->src_matched
)
293 hash
= hash_payload
->get_hash(hash_payload
);
294 DBG3(DBG_IKE
, "received src_hash %B", &hash
);
295 if (chunk_equals(hash
, src_hash
))
297 this->src_matched
= TRUE
;
301 enumerator
->destroy(enumerator
);
303 chunk_free(&src_hash
);
304 chunk_free(&dst_hash
);
306 if (this->src_seen
&& this->dst_seen
)
308 this->ike_sa
->set_condition(this->ike_sa
, COND_NAT_HERE
,
310 this->ike_sa
->set_condition(this->ike_sa
, COND_NAT_THERE
,
312 config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
313 if (this->dst_matched
&& this->src_matched
&&
316 this->ike_sa
->set_condition(this->ike_sa
, COND_NAT_FAKE
, TRUE
);
321 METHOD(task_t
, build_i
, status_t
,
322 private_isakmp_natd_t
*this, message_t
*message
)
324 status_t result
= NEED_MORE
;
326 switch (message
->get_exchange_type(message
))
329 { /* add NAT-D payloads to the second request, already processed
330 * those by the responder contained in the first response */
335 { /* add NAT-D payloads to the second request, need to process
336 * those by the responder contained in the second response */
337 if (message
->get_payload(message
, PLV1_SECURITY_ASSOCIATION
))
338 { /* wait for the second exchange */
341 add_natd_payloads(this, message
);
350 METHOD(task_t
, process_i
, status_t
,
351 private_isakmp_natd_t
*this, message_t
*message
)
353 status_t result
= NEED_MORE
;
355 if (!this->ike_sa
->supports_extension(this->ike_sa
, EXT_NATT
))
356 { /* we didn't receive VIDs inidcating support for NAT-T */
360 switch (message
->get_exchange_type(message
))
363 { /* process NAT-D payloads in the second response, added them in the
364 * second request already, so we're done afterwards */
365 if (message
->get_payload(message
, PLV1_SECURITY_ASSOCIATION
))
366 { /* wait for the second exchange */
373 { /* process NAT-D payloads in the first response, add them in the
374 * following second request */
375 process_payloads(this, message
);
377 if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
379 this->ike_sa
->float_ports(this->ike_sa
);
389 METHOD(task_t
, process_r
, status_t
,
390 private_isakmp_natd_t
*this, message_t
*message
)
392 status_t result
= NEED_MORE
;
394 if (!this->ike_sa
->supports_extension(this->ike_sa
, EXT_NATT
))
395 { /* we didn't receive VIDs indicating NAT-T support */
399 switch (message
->get_exchange_type(message
))
402 { /* process NAT-D payloads in the second request, already added ours
403 * in the first response */
408 { /* process NAT-D payloads in the second request, need to add ours
409 * to the second response */
410 if (message
->get_payload(message
, PLV1_SECURITY_ASSOCIATION
))
411 { /* wait for the second exchange */
414 process_payloads(this, message
);
423 METHOD(task_t
, build_r
, status_t
,
424 private_isakmp_natd_t
*this, message_t
*message
)
426 switch (message
->get_exchange_type(message
))
429 { /* add NAT-D payloads to second response, already processed those
430 * contained in the second request */
431 if (message
->get_payload(message
, PLV1_SECURITY_ASSOCIATION
))
432 { /* wait for the second exchange */
435 add_natd_payloads(this, message
);
439 { /* add NAT-D payloads to the first response, process those contained
440 * in the following second request */
441 add_natd_payloads(this, message
);
450 METHOD(task_t
, get_type
, task_type_t
,
451 private_isakmp_natd_t
*this)
453 return TASK_ISAKMP_NATD
;
456 METHOD(task_t
, migrate
, void,
457 private_isakmp_natd_t
*this, ike_sa_t
*ike_sa
)
459 this->ike_sa
= ike_sa
;
460 this->keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
461 this->src_seen
= FALSE
;
462 this->dst_seen
= FALSE
;
463 this->src_matched
= FALSE
;
464 this->dst_matched
= FALSE
;
467 METHOD(task_t
, destroy
, void,
468 private_isakmp_natd_t
*this)
474 * Described in header.
476 isakmp_natd_t
*isakmp_natd_create(ike_sa_t
*ike_sa
, bool initiator
)
478 private_isakmp_natd_t
*this;
483 .get_type
= _get_type
,
489 .keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
),
490 .initiator
= initiator
,
495 this->public.task
.build
= _build_i
;
496 this->public.task
.process
= _process_i
;
500 this->public.task
.build
= _build_r
;
501 this->public.task
.process
= _process_r
;
504 return &this->public;