Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/isakmp_natd.c, revision 1.1.1.1
1.1 misho 1: /*
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
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: uint64_t spi_i, spi_r;
133: uint16_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 indicating 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>