d7f957d50a7a2c0ed4985ad8f0e1e032f1e9ec59
[strongswan.git] / src / libcharon / sa / tasks / ike_natd_v1.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 #include "ike_natd_v1.h"
19
20 #include <string.h>
21
22 #include <hydra.h>
23 #include <daemon.h>
24 #include <sa/keymat_v1.h>
25 #include <config/peer_cfg.h>
26 #include <crypto/hashers/hasher.h>
27 #include <encoding/payloads/hash_payload.h>
28
29 typedef struct private_ike_natd_v1_t private_ike_natd_v1_t;
30
31 /**
32 * Private members of a ike_natt_t task.
33 */
34 struct private_ike_natd_v1_t {
35
36 /**
37 * Public interface.
38 */
39 ike_natd_v1_t public;
40
41 /**
42 * Assigned IKE_SA.
43 */
44 ike_sa_t *ike_sa;
45
46 /**
47 * Are we the initiator?
48 */
49 bool initiator;
50
51 /**
52 * Keymat derivation (from SA)
53 */
54 keymat_v1_t *keymat;
55
56 /**
57 * Did we process any NAT detection payloads for a source address?
58 */
59 bool src_seen;
60
61 /**
62 * Did we process any NAT detection payloads for a destination address?
63 */
64 bool dst_seen;
65
66 /**
67 * Have we found a matching source address NAT hash?
68 */
69 bool src_matched;
70
71 /**
72 * Have we found a matching destination address NAT hash?
73 */
74 bool dst_matched;
75 };
76
77 /**
78 * Build NAT detection hash for a host.
79 */
80 static chunk_t generate_natd_hash(private_ike_natd_v1_t *this,
81 ike_sa_id_t *ike_sa_id, host_t *host)
82 {
83 hasher_t *hasher;
84 chunk_t natd_chunk, natd_hash;
85 u_int64_t spi_i, spi_r;
86 u_int16_t port;
87
88 hasher = this->keymat->get_hasher(this->keymat);
89 if (!hasher)
90 {
91 DBG1(DBG_IKE, "no hasher available to build NAT-D payload");
92 return chunk_empty;
93 }
94
95 spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
96 spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
97 port = htons(host->get_port(host));
98
99 /* natd_hash = HASH(CKY-I | CKY-R | IP | Port) */
100 natd_chunk = chunk_cata("cccc", chunk_from_thing(spi_i),
101 chunk_from_thing(spi_r), host->get_address(host),
102 chunk_from_thing(port));
103 hasher->allocate_hash(hasher, natd_chunk, &natd_hash);
104 DBG3(DBG_IKE, "natd_chunk %B", &natd_chunk);
105 DBG3(DBG_IKE, "natd_hash %B", &natd_hash);
106
107 return natd_hash;
108 }
109
110 /**
111 * Build a faked NAT-D payload to enforce UDP encapsulation.
112 */
113 static chunk_t generate_natd_hash_faked(private_ike_natd_v1_t *this)
114 {
115 hasher_t *hasher;
116 chunk_t chunk;
117 rng_t *rng;
118
119 hasher = this->keymat->get_hasher(this->keymat);
120 if (!hasher)
121 {
122 DBG1(DBG_IKE, "no hasher available to build NAT-D payload");
123 return chunk_empty;
124 }
125 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
126 if (!rng)
127 {
128 DBG1(DBG_IKE, "unable to get random bytes for NAT-D fake");
129 return chunk_empty;
130 }
131 rng->allocate_bytes(rng, hasher->get_hash_size(hasher), &chunk);
132 rng->destroy(rng);
133 return chunk;
134 }
135
136 /**
137 * Build a NAT-D payload.
138 */
139 static hash_payload_t *build_natd_payload(private_ike_natd_v1_t *this, bool src,
140 host_t *host)
141 {
142 hash_payload_t *payload;
143 ike_cfg_t *config;
144 chunk_t hash;
145
146 config = this->ike_sa->get_ike_cfg(this->ike_sa);
147 if (src && config->force_encap(config))
148 {
149 hash = generate_natd_hash_faked(this);
150 }
151 else
152 {
153 ike_sa_id_t *ike_sa_id = this->ike_sa->get_id(this->ike_sa);
154 hash = generate_natd_hash(this, ike_sa_id, host);
155 }
156 payload = hash_payload_create(NAT_D_V1);
157 payload->set_hash(payload, hash);
158 chunk_free(&hash);
159 return payload;
160 }
161
162 /**
163 * Add NAT-D payloads to the message.
164 */
165 static void add_natd_payloads(private_ike_natd_v1_t *this, message_t *message)
166 {
167 hash_payload_t *payload;
168 host_t *host;
169
170 /* destination has to be added first */
171 host = message->get_destination(message);
172 payload = build_natd_payload(this, FALSE, host);
173 message->add_payload(message, (payload_t*)payload);
174
175 /* source is added second, compared with IKEv2 we always know the source,
176 * as these payloads are added in the second Phase 1 exchange or the
177 * response to the first */
178 host = message->get_source(message);
179 payload = build_natd_payload(this, TRUE, host);
180 message->add_payload(message, (payload_t*)payload);
181 }
182
183 /**
184 * Read NAT-D payloads from message and evaluate them.
185 */
186 static void process_payloads(private_ike_natd_v1_t *this, message_t *message)
187 {
188 enumerator_t *enumerator;
189 payload_t *payload;
190 hash_payload_t *hash_payload;
191 chunk_t hash, src_hash, dst_hash;
192 ike_sa_id_t *ike_sa_id;
193 host_t *me, *other;
194 ike_cfg_t *config;
195
196 /* precompute hashes for incoming NAT-D comparison */
197 ike_sa_id = message->get_ike_sa_id(message);
198 me = message->get_destination(message);
199 other = message->get_source(message);
200 dst_hash = generate_natd_hash(this, ike_sa_id, me);
201 src_hash = generate_natd_hash(this, ike_sa_id, other);
202
203 DBG3(DBG_IKE, "precalculated src_hash %B", &src_hash);
204 DBG3(DBG_IKE, "precalculated dst_hash %B", &dst_hash);
205
206 enumerator = message->create_payload_enumerator(message);
207 while (enumerator->enumerate(enumerator, &payload))
208 {
209 if (payload->get_type(payload) != NAT_D_V1)
210 {
211 continue;
212 }
213 hash_payload = (hash_payload_t*)payload;
214 if (!this->dst_seen)
215 { /* the first NAT-D payload contains the destination hash */
216 this->dst_seen = TRUE;
217 hash = hash_payload->get_hash(hash_payload);
218 DBG3(DBG_IKE, "received dst_hash %B", &hash);
219 if (chunk_equals(hash, dst_hash))
220 {
221 this->dst_matched = TRUE;
222 }
223 continue;
224 }
225 /* the other NAT-D payloads contain source hashes */
226 this->src_seen = TRUE;
227 if (!this->src_matched)
228 {
229 hash = hash_payload->get_hash(hash_payload);
230 DBG3(DBG_IKE, "received src_hash %B", &hash);
231 if (chunk_equals(hash, src_hash))
232 {
233 this->src_matched = TRUE;
234 }
235 }
236 }
237 enumerator->destroy(enumerator);
238
239 chunk_free(&src_hash);
240 chunk_free(&dst_hash);
241
242 if (this->src_seen && this->dst_seen)
243 {
244 this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE,
245 !this->dst_matched);
246 this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE,
247 !this->src_matched);
248 config = this->ike_sa->get_ike_cfg(this->ike_sa);
249 if (this->dst_matched && this->src_matched &&
250 config->force_encap(config))
251 {
252 this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE);
253 }
254 }
255 }
256
257 METHOD(task_t, build_i, status_t,
258 private_ike_natd_v1_t *this, message_t *message)
259 {
260 status_t result = NEED_MORE;
261
262 switch (message->get_exchange_type(message))
263 {
264 case AGGRESSIVE:
265 { /* add NAT-D payloads to the second request, already processed
266 * those by the responder contained in the first response */
267 result = SUCCESS;
268 /* fall */
269 }
270 case ID_PROT:
271 { /* add NAT-D payloads to the second request, need to process
272 * those by the responder contained in the second response */
273 if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
274 { /* wait for the second exchange */
275 return NEED_MORE;
276 }
277 add_natd_payloads(this, message);
278 return result;
279 }
280 default:
281 break;
282 }
283 return SUCCESS;
284 }
285
286 METHOD(task_t, process_i, status_t,
287 private_ike_natd_v1_t *this, message_t *message)
288 {
289 status_t result = NEED_MORE;
290
291 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
292 { /* we didn't receive VIDs inidcating support for NAT-T */
293 return SUCCESS;
294 }
295
296 switch (message->get_exchange_type(message))
297 {
298 case ID_PROT:
299 { /* process NAT-D payloads in the second response, added them in the
300 * second request already, so we're done afterwards */
301 if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
302 { /* wait for the second exchange */
303 return NEED_MORE;
304 }
305 result = SUCCESS;
306 /* fall */
307 }
308 case AGGRESSIVE:
309 { /* process NAT-D payloads in the first response, add them in the
310 * following second request */
311 process_payloads(this, message);
312
313 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
314 {
315 this->ike_sa->float_ports(this->ike_sa);
316 }
317 return result;
318 }
319 default:
320 break;
321 }
322 return SUCCESS;
323 }
324
325 METHOD(task_t, process_r, status_t,
326 private_ike_natd_v1_t *this, message_t *message)
327 {
328 status_t result = NEED_MORE;
329
330 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
331 { /* we didn't receive VIDs indicating NAT-T support */
332 return SUCCESS;
333 }
334
335 switch (message->get_exchange_type(message))
336 {
337 case AGGRESSIVE:
338 { /* proccess NAT-D payloads in the second request, already added ours
339 * in the first response */
340 result = SUCCESS;
341 /* fall */
342 }
343 case ID_PROT:
344 { /* process NAT-D payloads in the second request, need to add ours
345 * to the second response */
346 if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
347 { /* wait for the second exchange */
348 return NEED_MORE;
349 }
350 process_payloads(this, message);
351 return result;
352 }
353 default:
354 break;
355 }
356 return SUCCESS;
357 }
358
359 METHOD(task_t, build_r, status_t,
360 private_ike_natd_v1_t *this, message_t *message)
361 {
362 switch (message->get_exchange_type(message))
363 {
364 case ID_PROT:
365 { /* add NAT-D payloads to second response, already processed those
366 * contained in the second request */
367 if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
368 { /* wait for the second exchange */
369 return NEED_MORE;
370 }
371 add_natd_payloads(this, message);
372 return SUCCESS;
373 }
374 case AGGRESSIVE:
375 { /* add NAT-D payloads to the first response, process those contained
376 * in the following second request */
377 add_natd_payloads(this, message);
378 return NEED_MORE;
379 }
380 default:
381 break;
382 }
383 return SUCCESS;
384 }
385
386 METHOD(task_t, get_type, task_type_t,
387 private_ike_natd_v1_t *this)
388 {
389 return TASK_IKE_NATD_V1;
390 }
391
392 METHOD(task_t, migrate, void,
393 private_ike_natd_v1_t *this, ike_sa_t *ike_sa)
394 {
395 this->ike_sa = ike_sa;
396 this->src_seen = FALSE;
397 this->dst_seen = FALSE;
398 this->src_matched = FALSE;
399 this->dst_matched = FALSE;
400 }
401
402 METHOD(task_t, destroy, void,
403 private_ike_natd_v1_t *this)
404 {
405 free(this);
406 }
407
408 /*
409 * Described in header.
410 */
411 ike_natd_v1_t *ike_natd_v1_create(ike_sa_t *ike_sa, bool initiator)
412 {
413 private_ike_natd_v1_t *this;
414
415 INIT(this,
416 .public = {
417 .task = {
418 .get_type = _get_type,
419 .migrate = _migrate,
420 .destroy = _destroy,
421 },
422 },
423 .ike_sa = ike_sa,
424 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
425 .initiator = initiator,
426 );
427
428 if (initiator)
429 {
430 this->public.task.build = _build_i;
431 this->public.task.process = _process_i;
432 }
433 else
434 {
435 this->public.task.build = _build_r;
436 this->public.task.process = _process_r;
437 }
438
439 return &this->public;
440 }