libhydra: Move kernel interface to libcharon
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / isakmp_natd.c
1 /*
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
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
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
40 #include "isakmp_natd.h"
41
42 #include <string.h>
43
44 #include <daemon.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>
49
50 typedef struct private_isakmp_natd_t private_isakmp_natd_t;
51
52 /**
53 * Private members of a ike_natt_t task.
54 */
55 struct private_isakmp_natd_t {
56
57 /**
58 * Public interface.
59 */
60 isakmp_natd_t public;
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
98 /**
99 * Check if UDP encapsulation has to be forced either by config or required
100 * by the kernel interface
101 */
102 static bool force_encap(ike_cfg_t *ike_cfg)
103 {
104 if (!ike_cfg->force_encap(ike_cfg))
105 {
106 return charon->kernel->get_features(charon->kernel) &
107 KERNEL_REQUIRE_UDP_ENCAPSULATION;
108 }
109 return TRUE;
110 }
111
112 /**
113 * Get NAT-D payload type (RFC 3947 or RFC 3947 drafts).
114 */
115 static 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 {
119 return PLV1_NAT_D_DRAFT_00_03;
120 }
121 return PLV1_NAT_D;
122 }
123
124 /**
125 * Build NAT detection hash for a host.
126 */
127 static chunk_t generate_natd_hash(private_isakmp_natd_t *this,
128 ike_sa_id_t *ike_sa_id, host_t *host)
129 {
130 hasher_t *hasher;
131 chunk_t natd_chunk, natd_hash;
132 u_int64_t spi_i, spi_r;
133 u_int16_t port;
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));
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 }
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 */
164 static chunk_t generate_natd_hash_faked(private_isakmp_natd_t *this)
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);
177 if (!rng ||
178 !rng->allocate_bytes(rng, hasher->get_hash_size(hasher), &chunk))
179 {
180 DBG1(DBG_IKE, "unable to get random bytes for NAT-D fake");
181 DESTROY_IF(rng);
182 return chunk_empty;
183 }
184 rng->destroy(rng);
185 return chunk;
186 }
187
188 /**
189 * Build a NAT-D payload.
190 */
191 static hash_payload_t *build_natd_payload(private_isakmp_natd_t *this, bool src,
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);
199 if (src && force_encap(config))
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 }
208 if (!hash.len)
209 {
210 return NULL;
211 }
212 payload = hash_payload_create(get_nat_d_payload_type(this->ike_sa));
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 */
221 static void add_natd_payloads(private_isakmp_natd_t *this, message_t *message)
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);
229 if (payload)
230 {
231 message->add_payload(message, (payload_t*)payload);
232 }
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);
239 if (payload)
240 {
241 message->add_payload(message, (payload_t*)payload);
242 }
243 }
244
245 /**
246 * Read NAT-D payloads from message and evaluate them.
247 */
248 static void process_payloads(private_isakmp_natd_t *this, message_t *message)
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 {
271 if (payload->get_type(payload) != PLV1_NAT_D &&
272 payload->get_type(payload) != PLV1_NAT_D_DRAFT_00_03)
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 &&
313 force_encap(config))
314 {
315 this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE);
316 }
317 }
318 }
319
320 METHOD(task_t, build_i, status_t,
321 private_isakmp_natd_t *this, message_t *message)
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 */
336 if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
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
349 METHOD(task_t, process_i, status_t,
350 private_isakmp_natd_t *this, message_t *message)
351 {
352 status_t result = NEED_MORE;
353
354 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
355 { /* we didn't receive VIDs inidcating support for NAT-T */
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 */
364 if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
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
388 METHOD(task_t, process_r, status_t,
389 private_isakmp_natd_t *this, message_t *message)
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:
401 { /* process NAT-D payloads in the second request, already added ours
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 */
409 if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
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
422 METHOD(task_t, build_r, status_t,
423 private_isakmp_natd_t *this, message_t *message)
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 */
430 if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
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
449 METHOD(task_t, get_type, task_type_t,
450 private_isakmp_natd_t *this)
451 {
452 return TASK_ISAKMP_NATD;
453 }
454
455 METHOD(task_t, migrate, void,
456 private_isakmp_natd_t *this, ike_sa_t *ike_sa)
457 {
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;
464 }
465
466 METHOD(task_t, destroy, void,
467 private_isakmp_natd_t *this)
468 {
469 free(this);
470 }
471
472 /*
473 * Described in header.
474 */
475 isakmp_natd_t *isakmp_natd_create(ike_sa_t *ike_sa, bool initiator)
476 {
477 private_isakmp_natd_t *this;
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 }