ike: Maintain per-IKE_SA CHILD_SAs in the global CHILD_SA manager
[strongswan.git] / src / libcharon / sa / ikev2 / tasks / ike_mobike.c
1 /*
2 * Copyright (C) 2010-2014 Tobias Brunner
3 * Copyright (C) 2007 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "ike_mobike.h"
18
19 #include <string.h>
20
21 #include <hydra.h>
22 #include <daemon.h>
23 #include <sa/ikev2/tasks/ike_natd.h>
24 #include <encoding/payloads/notify_payload.h>
25
26 #define COOKIE2_SIZE 16
27 #define MAX_ADDITIONAL_ADDRS 8
28
29 typedef struct private_ike_mobike_t private_ike_mobike_t;
30
31 /**
32 * Private members of a ike_mobike_t task.
33 */
34 struct private_ike_mobike_t {
35
36 /**
37 * Public methods and task_t interface.
38 */
39 ike_mobike_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 * cookie2 value to verify new addresses
53 */
54 chunk_t cookie2;
55
56 /**
57 * NAT discovery reusing the TASK_IKE_NATD task
58 */
59 ike_natd_t *natd;
60
61 /**
62 * use task to update addresses
63 */
64 bool update;
65
66 /**
67 * do routability check
68 */
69 bool check;
70
71 /**
72 * include address list update
73 */
74 bool address;
75
76 /**
77 * additional addresses got updated
78 */
79 bool addresses_updated;
80
81 /**
82 * whether the pending updates counter was increased
83 */
84 bool pending_update;
85 };
86
87 /**
88 * read notifys from message and evaluate them
89 */
90 static void process_payloads(private_ike_mobike_t *this, message_t *message)
91 {
92 enumerator_t *enumerator;
93 payload_t *payload;
94 bool first = TRUE;
95
96 enumerator = message->create_payload_enumerator(message);
97 while (enumerator->enumerate(enumerator, &payload))
98 {
99 int family = AF_INET;
100 notify_payload_t *notify;
101 chunk_t data;
102 host_t *host;
103
104 if (payload->get_type(payload) != PLV2_NOTIFY)
105 {
106 continue;
107 }
108 notify = (notify_payload_t*)payload;
109 switch (notify->get_notify_type(notify))
110 {
111 case MOBIKE_SUPPORTED:
112 {
113 peer_cfg_t *peer_cfg;
114
115 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
116 if (!this->initiator &&
117 peer_cfg && !peer_cfg->use_mobike(peer_cfg))
118 {
119 DBG1(DBG_IKE, "peer supports MOBIKE, but disabled in config");
120 }
121 else
122 {
123 DBG1(DBG_IKE, "peer supports MOBIKE");
124 this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
125 }
126 break;
127 }
128 case COOKIE2:
129 {
130 chunk_free(&this->cookie2);
131 this->cookie2 = chunk_clone(notify->get_notification_data(notify));
132 break;
133 }
134 case ADDITIONAL_IP6_ADDRESS:
135 {
136 family = AF_INET6;
137 /* fall through */
138 }
139 case ADDITIONAL_IP4_ADDRESS:
140 {
141 if (first)
142 { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
143 this->ike_sa->clear_peer_addresses(this->ike_sa);
144 first = FALSE;
145 /* add the peer's current address to the list */
146 host = message->get_source(message);
147 this->ike_sa->add_peer_address(this->ike_sa,
148 host->clone(host));
149 }
150 data = notify->get_notification_data(notify);
151 host = host_create_from_chunk(family, data, 0);
152 DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host);
153 this->ike_sa->add_peer_address(this->ike_sa, host);
154 this->addresses_updated = TRUE;
155 break;
156 }
157 case UPDATE_SA_ADDRESSES:
158 {
159 this->update = TRUE;
160 break;
161 }
162 case NO_ADDITIONAL_ADDRESSES:
163 {
164 this->ike_sa->clear_peer_addresses(this->ike_sa);
165 /* add the peer's current address to the list */
166 host = message->get_source(message);
167 this->ike_sa->add_peer_address(this->ike_sa, host->clone(host));
168 this->addresses_updated = TRUE;
169 break;
170 }
171 case NAT_DETECTION_SOURCE_IP:
172 case NAT_DETECTION_DESTINATION_IP:
173 {
174 /* NAT check in this MOBIKE exchange, create subtask for it */
175 if (this->natd == NULL)
176 {
177 this->natd = ike_natd_create(this->ike_sa, this->initiator);
178 }
179 break;
180 }
181 default:
182 break;
183 }
184 }
185 enumerator->destroy(enumerator);
186 }
187
188 /**
189 * Add ADDITIONAL_*_ADDRESS notifys depending on our address list
190 */
191 static void build_address_list(private_ike_mobike_t *this, message_t *message)
192 {
193 enumerator_t *enumerator;
194 host_t *host, *me;
195 notify_type_t type;
196 int added = 0;
197
198 me = this->ike_sa->get_my_host(this->ike_sa);
199 enumerator = hydra->kernel_interface->create_address_enumerator(
200 hydra->kernel_interface, ADDR_TYPE_REGULAR);
201 while (enumerator->enumerate(enumerator, (void**)&host))
202 {
203 if (me->ip_equals(me, host))
204 { /* "ADDITIONAL" means do not include IKE_SAs host */
205 continue;
206 }
207 switch (host->get_family(host))
208 {
209 case AF_INET:
210 type = ADDITIONAL_IP4_ADDRESS;
211 break;
212 case AF_INET6:
213 type = ADDITIONAL_IP6_ADDRESS;
214 break;
215 default:
216 continue;
217 }
218 message->add_notify(message, FALSE, type, host->get_address(host));
219 if (++added >= MAX_ADDITIONAL_ADDRS)
220 { /* limit number of notifys, some implementations do not like too
221 * many of them (f.e. strongSwan ;-) */
222 break;
223 }
224 }
225 if (!added)
226 {
227 message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty);
228 }
229 enumerator->destroy(enumerator);
230 }
231
232 /**
233 * build a cookie and add it to the message
234 */
235 static bool build_cookie(private_ike_mobike_t *this, message_t *message)
236 {
237 rng_t *rng;
238
239 chunk_free(&this->cookie2);
240 rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
241 if (!rng || !rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2))
242 {
243 DESTROY_IF(rng);
244 return FALSE;
245 }
246 message->add_notify(message, FALSE, COOKIE2, this->cookie2);
247 rng->destroy(rng);
248 return TRUE;
249 }
250
251 /**
252 * update addresses of associated CHILD_SAs
253 */
254 static void update_children(private_ike_mobike_t *this)
255 {
256 enumerator_t *enumerator;
257 child_sa_t *child_sa;
258 linked_list_t *vips;
259 status_t status;
260 host_t *host;
261
262 vips = linked_list_create();
263
264 enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
265 while (enumerator->enumerate(enumerator, &host))
266 {
267 vips->insert_last(vips, host);
268 }
269 enumerator->destroy(enumerator);
270
271 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
272 while (enumerator->enumerate(enumerator, (void**)&child_sa))
273 {
274 status = child_sa->update(child_sa,
275 this->ike_sa->get_my_host(this->ike_sa),
276 this->ike_sa->get_other_host(this->ike_sa), vips,
277 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
278 switch (status)
279 {
280 case NOT_SUPPORTED:
281 this->ike_sa->rekey_child_sa(this->ike_sa,
282 child_sa->get_protocol(child_sa),
283 child_sa->get_spi(child_sa, TRUE));
284 break;
285 case SUCCESS:
286 charon->child_sa_manager->remove(charon->child_sa_manager,
287 child_sa);
288 charon->child_sa_manager->add(charon->child_sa_manager,
289 child_sa, this->ike_sa);
290 break;
291 default:
292 break;
293 }
294 }
295 enumerator->destroy(enumerator);
296
297 vips->destroy(vips);
298 }
299
300 /**
301 * Apply the port of the old host, if its ip equals the new, use port otherwise.
302 */
303 static void apply_port(host_t *host, host_t *old, u_int16_t port, bool local)
304 {
305 if (host->ip_equals(host, old))
306 {
307 port = old->get_port(old);
308 }
309 else if (local && port == charon->socket->get_port(charon->socket, FALSE))
310 {
311 port = charon->socket->get_port(charon->socket, TRUE);
312 }
313 else if (!local && port == IKEV2_UDP_PORT)
314 {
315 port = IKEV2_NATT_PORT;
316 }
317 host->set_port(host, port);
318 }
319
320 METHOD(ike_mobike_t, transmit, bool,
321 private_ike_mobike_t *this, packet_t *packet)
322 {
323 host_t *me, *other, *me_old, *other_old;
324 enumerator_t *enumerator;
325 ike_cfg_t *ike_cfg;
326 packet_t *copy;
327 int family = AF_UNSPEC;
328 bool found = FALSE;
329
330 me_old = this->ike_sa->get_my_host(this->ike_sa);
331 other_old = this->ike_sa->get_other_host(this->ike_sa);
332 ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
333
334 if (!this->check)
335 {
336 me = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
337 other_old, me_old);
338 if (me)
339 {
340 if (me->ip_equals(me, me_old))
341 {
342 charon->sender->send(charon->sender, packet->clone(packet));
343 me->destroy(me);
344 return TRUE;
345 }
346 me->destroy(me);
347 }
348 this->check = TRUE;
349 }
350
351 switch (charon->socket->supported_families(charon->socket))
352 {
353 case SOCKET_FAMILY_IPV4:
354 family = AF_INET;
355 break;
356 case SOCKET_FAMILY_IPV6:
357 family = AF_INET6;
358 break;
359 case SOCKET_FAMILY_BOTH:
360 case SOCKET_FAMILY_NONE:
361 break;
362 }
363
364 enumerator = this->ike_sa->create_peer_address_enumerator(this->ike_sa);
365 while (enumerator->enumerate(enumerator, (void**)&other))
366 {
367 if (family != AF_UNSPEC && other->get_family(other) != family)
368 {
369 continue;
370 }
371 me = hydra->kernel_interface->get_source_addr(
372 hydra->kernel_interface, other, NULL);
373 if (me)
374 {
375 /* reuse port for an active address, 4500 otherwise */
376 apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE);
377 other = other->clone(other);
378 apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg), FALSE);
379 DBG1(DBG_IKE, "checking path %#H - %#H", me, other);
380 copy = packet->clone(packet);
381 copy->set_source(copy, me);
382 copy->set_destination(copy, other);
383 charon->sender->send(charon->sender, copy);
384 found = TRUE;
385 }
386 }
387 enumerator->destroy(enumerator);
388 return found;
389 }
390
391 METHOD(task_t, build_i, status_t,
392 private_ike_mobike_t *this, message_t *message)
393 {
394 if (message->get_exchange_type(message) == IKE_AUTH &&
395 message->get_message_id(message) == 1)
396 { /* only in first IKE_AUTH */
397 message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
398 build_address_list(this, message);
399 }
400 else if (message->get_exchange_type(message) == INFORMATIONAL)
401 {
402 host_t *old, *new;
403
404 /* we check if the existing address is still valid */
405 old = message->get_source(message);
406 new = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
407 message->get_destination(message), old);
408 if (new)
409 {
410 if (!new->ip_equals(new, old))
411 {
412 new->set_port(new, old->get_port(old));
413 message->set_source(message, new);
414 }
415 else
416 {
417 new->destroy(new);
418 }
419 }
420 if (this->update)
421 {
422 message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES,
423 chunk_empty);
424 if (!build_cookie(this, message))
425 {
426 return FAILED;
427 }
428 update_children(this);
429 }
430 if (this->address && !this->check)
431 {
432 build_address_list(this, message);
433 }
434 if (this->natd)
435 {
436 this->natd->task.build(&this->natd->task, message);
437 }
438 }
439 return NEED_MORE;
440 }
441
442 METHOD(task_t, process_r, status_t,
443 private_ike_mobike_t *this, message_t *message)
444 {
445 if (message->get_exchange_type(message) == IKE_AUTH &&
446 message->get_message_id(message) == 1)
447 { /* only first IKE_AUTH */
448 process_payloads(this, message);
449 }
450 else if (message->get_exchange_type(message) == INFORMATIONAL)
451 {
452 process_payloads(this, message);
453 if (this->update)
454 {
455 host_t *me, *other;
456
457 me = message->get_destination(message);
458 other = message->get_source(message);
459 this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
460 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
461 }
462
463 if (this->natd)
464 {
465 this->natd->task.process(&this->natd->task, message);
466 }
467 if (this->addresses_updated && this->ike_sa->has_condition(this->ike_sa,
468 COND_ORIGINAL_INITIATOR))
469 {
470 host_t *other = message->get_source(message);
471 host_t *other_old = this->ike_sa->get_other_host(this->ike_sa);
472 if (!other->equals(other, other_old))
473 {
474 DBG1(DBG_IKE, "remote address changed from %H to %H", other_old,
475 other);
476 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
477 this->update = TRUE;
478 }
479 }
480 }
481 return NEED_MORE;
482 }
483
484 METHOD(task_t, build_r, status_t,
485 private_ike_mobike_t *this, message_t *message)
486 {
487 if (message->get_exchange_type(message) == IKE_AUTH &&
488 this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
489 {
490 if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
491 {
492 message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
493 build_address_list(this, message);
494 }
495 return SUCCESS;
496 }
497 else if (message->get_exchange_type(message) == INFORMATIONAL)
498 {
499 if (this->natd)
500 {
501 this->natd->task.build(&this->natd->task, message);
502 }
503 if (this->cookie2.ptr)
504 {
505 message->add_notify(message, FALSE, COOKIE2, this->cookie2);
506 chunk_free(&this->cookie2);
507 }
508 if (this->update)
509 {
510 update_children(this);
511 }
512 return SUCCESS;
513 }
514 return NEED_MORE;
515 }
516
517 METHOD(task_t, process_i, status_t,
518 private_ike_mobike_t *this, message_t *message)
519 {
520 if (message->get_exchange_type(message) == IKE_AUTH &&
521 this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
522 {
523 process_payloads(this, message);
524 return SUCCESS;
525 }
526 else if (message->get_exchange_type(message) == INFORMATIONAL)
527 {
528 if (this->ike_sa->get_pending_updates(this->ike_sa) > 1)
529 {
530 /* newer update queued, ignore this one */
531 return SUCCESS;
532 }
533 if (this->cookie2.ptr)
534 { /* check cookie if we included one */
535 chunk_t cookie2;
536
537 cookie2 = this->cookie2;
538 this->cookie2 = chunk_empty;
539 process_payloads(this, message);
540 if (!chunk_equals(cookie2, this->cookie2))
541 {
542 chunk_free(&cookie2);
543 DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
544 return FAILED;
545 }
546 chunk_free(&cookie2);
547 }
548 else
549 {
550 process_payloads(this, message);
551 }
552 if (this->natd)
553 {
554 this->natd->task.process(&this->natd->task, message);
555 if (this->natd->has_mapping_changed(this->natd))
556 {
557 /* force an update if mappings have changed */
558 this->update = this->check = TRUE;
559 DBG1(DBG_IKE, "detected changes in NAT mappings, "
560 "initiating MOBIKE update");
561 }
562 }
563 if (this->update)
564 {
565 /* update again, as NAT state may have changed */
566 update_children(this);
567 }
568 if (this->check)
569 {
570 host_t *me_new, *me_old, *other_new, *other_old;
571
572 me_new = message->get_destination(message);
573 other_new = message->get_source(message);
574 me_old = this->ike_sa->get_my_host(this->ike_sa);
575 other_old = this->ike_sa->get_other_host(this->ike_sa);
576
577 if (!me_new->equals(me_new, me_old))
578 {
579 this->update = TRUE;
580 this->ike_sa->set_my_host(this->ike_sa, me_new->clone(me_new));
581 }
582 if (!other_new->equals(other_new, other_old))
583 {
584 this->update = TRUE;
585 this->ike_sa->set_other_host(this->ike_sa, other_new->clone(other_new));
586 }
587 if (this->update)
588 {
589 /* use the same task to ... */
590 if (!this->ike_sa->has_condition(this->ike_sa,
591 COND_ORIGINAL_INITIATOR))
592 { /*... send an updated list of addresses as responder */
593 update_children(this);
594 this->update = FALSE;
595 }
596 else
597 { /* ... send the update as original initiator */
598 if (this->natd)
599 {
600 this->natd->task.destroy(&this->natd->task);
601 }
602 this->natd = ike_natd_create(this->ike_sa, this->initiator);
603 }
604 this->check = FALSE;
605 return NEED_MORE;
606 }
607 }
608 return SUCCESS;
609 }
610 return NEED_MORE;
611 }
612
613 METHOD(ike_mobike_t, addresses, void,
614 private_ike_mobike_t *this)
615 {
616 this->address = TRUE;
617 if (!this->pending_update)
618 {
619 this->pending_update = TRUE;
620 this->ike_sa->set_pending_updates(this->ike_sa,
621 this->ike_sa->get_pending_updates(this->ike_sa) + 1);
622 }
623 }
624
625 METHOD(ike_mobike_t, roam, void,
626 private_ike_mobike_t *this, bool address)
627 {
628 this->check = TRUE;
629 this->address = address;
630 if (!this->pending_update)
631 {
632 this->pending_update = TRUE;
633 this->ike_sa->set_pending_updates(this->ike_sa,
634 this->ike_sa->get_pending_updates(this->ike_sa) + 1);
635 }
636 }
637
638 METHOD(ike_mobike_t, dpd, void,
639 private_ike_mobike_t *this)
640 {
641 if (!this->natd)
642 {
643 this->natd = ike_natd_create(this->ike_sa, this->initiator);
644 }
645 if (!this->pending_update)
646 {
647 this->pending_update = TRUE;
648 this->ike_sa->set_pending_updates(this->ike_sa,
649 this->ike_sa->get_pending_updates(this->ike_sa) + 1);
650 }
651 }
652
653 METHOD(ike_mobike_t, is_probing, bool,
654 private_ike_mobike_t *this)
655 {
656 return this->check;
657 }
658
659 METHOD(ike_mobike_t, enable_probing, void,
660 private_ike_mobike_t *this)
661 {
662 this->check = TRUE;
663 }
664
665 METHOD(task_t, get_type, task_type_t,
666 private_ike_mobike_t *this)
667 {
668 return TASK_IKE_MOBIKE;
669 }
670
671 METHOD(task_t, migrate, void,
672 private_ike_mobike_t *this, ike_sa_t *ike_sa)
673 {
674 chunk_free(&this->cookie2);
675 this->ike_sa = ike_sa;
676 if (this->natd)
677 {
678 this->natd->task.migrate(&this->natd->task, ike_sa);
679 }
680 if (this->pending_update)
681 {
682 this->ike_sa->set_pending_updates(this->ike_sa,
683 this->ike_sa->get_pending_updates(this->ike_sa) + 1);
684 }
685 }
686
687 METHOD(task_t, destroy, void,
688 private_ike_mobike_t *this)
689 {
690 if (this->pending_update)
691 {
692 this->ike_sa->set_pending_updates(this->ike_sa,
693 this->ike_sa->get_pending_updates(this->ike_sa) - 1);
694 }
695 chunk_free(&this->cookie2);
696 if (this->natd)
697 {
698 this->natd->task.destroy(&this->natd->task);
699 }
700 free(this);
701 }
702
703 /*
704 * Described in header.
705 */
706 ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
707 {
708 private_ike_mobike_t *this;
709
710 INIT(this,
711 .public = {
712 .task = {
713 .get_type = _get_type,
714 .migrate = _migrate,
715 .destroy = _destroy,
716 },
717 .addresses = _addresses,
718 .roam = _roam,
719 .dpd = _dpd,
720 .transmit = _transmit,
721 .is_probing = _is_probing,
722 .enable_probing = _enable_probing,
723 },
724 .ike_sa = ike_sa,
725 .initiator = initiator,
726 );
727
728 if (initiator)
729 {
730 this->public.task.build = _build_i;
731 this->public.task.process = _process_i;
732 }
733 else
734 {
735 this->public.task.build = _build_r;
736 this->public.task.process = _process_r;
737 }
738
739 return &this->public;
740 }