]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/ikev1/tasks/isakmp_natd.c
Spelling fixes
[thirdparty/strongswan.git] / src / libcharon / sa / ikev1 / tasks / isakmp_natd.c
CommitLineData
1cc4ec46
TB
1/*
2 * Copyright (C) 2006-2011 Tobias Brunner,
3 * Copyright (C) 2006-2007 Martin Willi
4 * Copyright (C) 2006 Daniel Roethlisberger
1b671669 5 * HSR Hochschule fuer Technik Rapperswil
1cc4ec46
TB
6 *
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>.
11 *
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
15 * for more details.
16 */
17
0ff8d20a
VR
18/*
19 * Copyright (C) 2012 Volker Rümelin
20 *
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:
27 *
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
30 *
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
37 * THE SOFTWARE.
38 */
39
79d6fc7f 40#include "isakmp_natd.h"
1cc4ec46
TB
41
42#include <string.h>
43
1cc4ec46 44#include <daemon.h>
15a682f4 45#include <sa/ikev1/keymat_v1.h>
1cc4ec46
TB
46#include <config/peer_cfg.h>
47#include <crypto/hashers/hasher.h>
48#include <encoding/payloads/hash_payload.h>
49
79d6fc7f 50typedef struct private_isakmp_natd_t private_isakmp_natd_t;
1cc4ec46
TB
51
52/**
53 * Private members of a ike_natt_t task.
54 */
79d6fc7f 55struct private_isakmp_natd_t {
1cc4ec46
TB
56
57 /**
58 * Public interface.
59 */
79d6fc7f 60 isakmp_natd_t public;
1cc4ec46
TB
61
62 /**
63 * Assigned IKE_SA.
64 */
65 ike_sa_t *ike_sa;
66
67 /**
68 * Are we the initiator?
69 */
70 bool initiator;
71
72 /**
73 * Keymat derivation (from SA)
74 */
75 keymat_v1_t *keymat;
76
77 /**
78 * Did we process any NAT detection payloads for a source address?
79 */
80 bool src_seen;
81
82 /**
83 * Did we process any NAT detection payloads for a destination address?
84 */
85 bool dst_seen;
86
87 /**
88 * Have we found a matching source address NAT hash?
89 */
90 bool src_matched;
91
92 /**
93 * Have we found a matching destination address NAT hash?
94 */
95 bool dst_matched;
96};
97
01955eec
TB
98/**
99 * Check if UDP encapsulation has to be forced either by config or required
100 * by the kernel interface
101 */
102static bool force_encap(ike_cfg_t *ike_cfg)
103{
104 if (!ike_cfg->force_encap(ike_cfg))
105 {
8394ea2a 106 return charon->kernel->get_features(charon->kernel) &
01955eec
TB
107 KERNEL_REQUIRE_UDP_ENCAPSULATION;
108 }
109 return TRUE;
110}
111
0ff8d20a
VR
112/**
113 * Get NAT-D payload type (RFC 3947 or RFC 3947 drafts).
114 */
115static payload_type_t get_nat_d_payload_type(ike_sa_t *ike_sa)
116{
117 if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
118 {
3ecfc83c 119 return PLV1_NAT_D_DRAFT_00_03;
0ff8d20a 120 }
3ecfc83c 121 return PLV1_NAT_D;
0ff8d20a
VR
122}
123
1cc4ec46
TB
124/**
125 * Build NAT detection hash for a host.
126 */
79d6fc7f 127static chunk_t generate_natd_hash(private_isakmp_natd_t *this,
1cc4ec46
TB
128 ike_sa_id_t *ike_sa_id, host_t *host)
129{
130 hasher_t *hasher;
131 chunk_t natd_chunk, natd_hash;
b12c53ce
AS
132 uint64_t spi_i, spi_r;
133 uint16_t port;
1cc4ec46
TB
134
135 hasher = this->keymat->get_hasher(this->keymat);
136 if (!hasher)
137 {
138 DBG1(DBG_IKE, "no hasher available to build NAT-D payload");
139 return chunk_empty;
140 }
141
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));
145
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));
87dd205b
MW
150 if (!hasher->allocate_hash(hasher, natd_chunk, &natd_hash))
151 {
152 DBG1(DBG_IKE, "creating NAT-D payload hash failed");
153 return chunk_empty;
154 }
1cc4ec46
TB
155 DBG3(DBG_IKE, "natd_chunk %B", &natd_chunk);
156 DBG3(DBG_IKE, "natd_hash %B", &natd_hash);
157
158 return natd_hash;
159}
160
161/**
162 * Build a faked NAT-D payload to enforce UDP encapsulation.
163 */
79d6fc7f 164static chunk_t generate_natd_hash_faked(private_isakmp_natd_t *this)
1cc4ec46
TB
165{
166 hasher_t *hasher;
167 chunk_t chunk;
168 rng_t *rng;
169
170 hasher = this->keymat->get_hasher(this->keymat);
171 if (!hasher)
172 {
173 DBG1(DBG_IKE, "no hasher available to build NAT-D payload");
174 return chunk_empty;
175 }
176 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
92f20747
TB
177 if (!rng ||
178 !rng->allocate_bytes(rng, hasher->get_hash_size(hasher), &chunk))
1cc4ec46
TB
179 {
180 DBG1(DBG_IKE, "unable to get random bytes for NAT-D fake");
92f20747 181 DESTROY_IF(rng);
1cc4ec46
TB
182 return chunk_empty;
183 }
1cc4ec46
TB
184 rng->destroy(rng);
185 return chunk;
186}
187
188/**
189 * Build a NAT-D payload.
190 */
79d6fc7f 191static hash_payload_t *build_natd_payload(private_isakmp_natd_t *this, bool src,
1cc4ec46
TB
192 host_t *host)
193{
194 hash_payload_t *payload;
195 ike_cfg_t *config;
196 chunk_t hash;
197
198 config = this->ike_sa->get_ike_cfg(this->ike_sa);
01955eec 199 if (src && force_encap(config))
1cc4ec46
TB
200 {
201 hash = generate_natd_hash_faked(this);
202 }
203 else
204 {
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);
207 }
87dd205b
MW
208 if (!hash.len)
209 {
210 return NULL;
211 }
0ff8d20a 212 payload = hash_payload_create(get_nat_d_payload_type(this->ike_sa));
1cc4ec46
TB
213 payload->set_hash(payload, hash);
214 chunk_free(&hash);
215 return payload;
216}
217
218/**
219 * Add NAT-D payloads to the message.
220 */
79d6fc7f 221static void add_natd_payloads(private_isakmp_natd_t *this, message_t *message)
1cc4ec46
TB
222{
223 hash_payload_t *payload;
224 host_t *host;
225
226 /* destination has to be added first */
227 host = message->get_destination(message);
228 payload = build_natd_payload(this, FALSE, host);
87dd205b
MW
229 if (payload)
230 {
231 message->add_payload(message, (payload_t*)payload);
232 }
1cc4ec46
TB
233
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);
87dd205b
MW
239 if (payload)
240 {
241 message->add_payload(message, (payload_t*)payload);
242 }
1cc4ec46
TB
243}
244
245/**
246 * Read NAT-D payloads from message and evaluate them.
247 */
79d6fc7f 248static void process_payloads(private_isakmp_natd_t *this, message_t *message)
1cc4ec46
TB
249{
250 enumerator_t *enumerator;
251 payload_t *payload;
252 hash_payload_t *hash_payload;
253 chunk_t hash, src_hash, dst_hash;
254 ike_sa_id_t *ike_sa_id;
255 host_t *me, *other;
256 ike_cfg_t *config;
257
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);
264
265 DBG3(DBG_IKE, "precalculated src_hash %B", &src_hash);
266 DBG3(DBG_IKE, "precalculated dst_hash %B", &dst_hash);
267
268 enumerator = message->create_payload_enumerator(message);
269 while (enumerator->enumerate(enumerator, &payload))
270 {
3ecfc83c
MW
271 if (payload->get_type(payload) != PLV1_NAT_D &&
272 payload->get_type(payload) != PLV1_NAT_D_DRAFT_00_03)
1cc4ec46
TB
273 {
274 continue;
275 }
276 hash_payload = (hash_payload_t*)payload;
277 if (!this->dst_seen)
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))
283 {
284 this->dst_matched = TRUE;
285 }
286 continue;
287 }
288 /* the other NAT-D payloads contain source hashes */
289 this->src_seen = TRUE;
290 if (!this->src_matched)
291 {
292 hash = hash_payload->get_hash(hash_payload);
293 DBG3(DBG_IKE, "received src_hash %B", &hash);
294 if (chunk_equals(hash, src_hash))
295 {
296 this->src_matched = TRUE;
297 }
298 }
299 }
300 enumerator->destroy(enumerator);
301
302 chunk_free(&src_hash);
303 chunk_free(&dst_hash);
304
305 if (this->src_seen && this->dst_seen)
306 {
307 this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE,
308 !this->dst_matched);
309 this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE,
310 !this->src_matched);
311 config = this->ike_sa->get_ike_cfg(this->ike_sa);
312 if (this->dst_matched && this->src_matched &&
01955eec 313 force_encap(config))
1cc4ec46
TB
314 {
315 this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE);
316 }
317 }
318}
319
320METHOD(task_t, build_i, status_t,
79d6fc7f 321 private_isakmp_natd_t *this, message_t *message)
1cc4ec46
TB
322{
323 status_t result = NEED_MORE;
324
325 switch (message->get_exchange_type(message))
326 {
327 case AGGRESSIVE:
328 { /* add NAT-D payloads to the second request, already processed
329 * those by the responder contained in the first response */
330 result = SUCCESS;
331 /* fall */
332 }
333 case ID_PROT:
334 { /* add NAT-D payloads to the second request, need to process
335 * those by the responder contained in the second response */
3ecfc83c 336 if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
1cc4ec46
TB
337 { /* wait for the second exchange */
338 return NEED_MORE;
339 }
340 add_natd_payloads(this, message);
341 return result;
342 }
343 default:
344 break;
345 }
346 return SUCCESS;
347}
348
349METHOD(task_t, process_i, status_t,
79d6fc7f 350 private_isakmp_natd_t *this, message_t *message)
1cc4ec46
TB
351{
352 status_t result = NEED_MORE;
353
354 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
b3ab7a48 355 { /* we didn't receive VIDs indicating support for NAT-T */
1cc4ec46
TB
356 return SUCCESS;
357 }
358
359 switch (message->get_exchange_type(message))
360 {
361 case ID_PROT:
362 { /* process NAT-D payloads in the second response, added them in the
363 * second request already, so we're done afterwards */
3ecfc83c 364 if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
1cc4ec46
TB
365 { /* wait for the second exchange */
366 return NEED_MORE;
367 }
368 result = SUCCESS;
369 /* fall */
370 }
371 case AGGRESSIVE:
372 { /* process NAT-D payloads in the first response, add them in the
373 * following second request */
374 process_payloads(this, message);
375
376 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
377 {
378 this->ike_sa->float_ports(this->ike_sa);
379 }
380 return result;
381 }
382 default:
383 break;
384 }
385 return SUCCESS;
386}
387
388METHOD(task_t, process_r, status_t,
79d6fc7f 389 private_isakmp_natd_t *this, message_t *message)
1cc4ec46
TB
390{
391 status_t result = NEED_MORE;
392
393 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
394 { /* we didn't receive VIDs indicating NAT-T support */
395 return SUCCESS;
396 }
397
398 switch (message->get_exchange_type(message))
399 {
400 case AGGRESSIVE:
ef33a4ab 401 { /* process NAT-D payloads in the second request, already added ours
1cc4ec46
TB
402 * in the first response */
403 result = SUCCESS;
404 /* fall */
405 }
406 case ID_PROT:
407 { /* process NAT-D payloads in the second request, need to add ours
408 * to the second response */
3ecfc83c 409 if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
1cc4ec46
TB
410 { /* wait for the second exchange */
411 return NEED_MORE;
412 }
413 process_payloads(this, message);
414 return result;
415 }
416 default:
417 break;
418 }
419 return SUCCESS;
420}
421
422METHOD(task_t, build_r, status_t,
79d6fc7f 423 private_isakmp_natd_t *this, message_t *message)
1cc4ec46
TB
424{
425 switch (message->get_exchange_type(message))
426 {
427 case ID_PROT:
428 { /* add NAT-D payloads to second response, already processed those
429 * contained in the second request */
3ecfc83c 430 if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
1cc4ec46
TB
431 { /* wait for the second exchange */
432 return NEED_MORE;
433 }
434 add_natd_payloads(this, message);
435 return SUCCESS;
436 }
437 case AGGRESSIVE:
438 { /* add NAT-D payloads to the first response, process those contained
439 * in the following second request */
440 add_natd_payloads(this, message);
441 return NEED_MORE;
442 }
443 default:
444 break;
445 }
446 return SUCCESS;
447}
448
449METHOD(task_t, get_type, task_type_t,
79d6fc7f 450 private_isakmp_natd_t *this)
1cc4ec46 451{
79d6fc7f 452 return TASK_ISAKMP_NATD;
1cc4ec46
TB
453}
454
455METHOD(task_t, migrate, void,
79d6fc7f 456 private_isakmp_natd_t *this, ike_sa_t *ike_sa)
1cc4ec46
TB
457{
458 this->ike_sa = ike_sa;
94450913 459 this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
1cc4ec46
TB
460 this->src_seen = FALSE;
461 this->dst_seen = FALSE;
462 this->src_matched = FALSE;
463 this->dst_matched = FALSE;
464}
465
466METHOD(task_t, destroy, void,
79d6fc7f 467 private_isakmp_natd_t *this)
1cc4ec46
TB
468{
469 free(this);
470}
471
472/*
473 * Described in header.
474 */
79d6fc7f 475isakmp_natd_t *isakmp_natd_create(ike_sa_t *ike_sa, bool initiator)
1cc4ec46 476{
79d6fc7f 477 private_isakmp_natd_t *this;
1cc4ec46
TB
478
479 INIT(this,
480 .public = {
481 .task = {
482 .get_type = _get_type,
483 .migrate = _migrate,
484 .destroy = _destroy,
485 },
486 },
487 .ike_sa = ike_sa,
488 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
489 .initiator = initiator,
490 );
491
492 if (initiator)
493 {
494 this->public.task.build = _build_i;
495 this->public.task.process = _process_i;
496 }
497 else
498 {
499 this->public.task.build = _build_r;
500 this->public.task.process = _process_r;
501 }
502
503 return &this->public;
504}