cbdc5e79722ab832af01d1e62bde63d9b1e49883
[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 copy = packet->clone(packet);
343 /* hosts might have been updated by a peer's MOBIKE exchange */
344 copy->set_source(copy, me_old->clone(me_old));
345 copy->set_destination(copy, other_old->clone(other_old));
346 charon->sender->send(charon->sender, copy);
347 me->destroy(me);
348 return TRUE;
349 }
350 me->destroy(me);
351 }
352 this->check = TRUE;
353 }
354
355 switch (charon->socket->supported_families(charon->socket))
356 {
357 case SOCKET_FAMILY_IPV4:
358 family = AF_INET;
359 break;
360 case SOCKET_FAMILY_IPV6:
361 family = AF_INET6;
362 break;
363 case SOCKET_FAMILY_BOTH:
364 case SOCKET_FAMILY_NONE:
365 break;
366 }
367
368 enumerator = this->ike_sa->create_peer_address_enumerator(this->ike_sa);
369 while (enumerator->enumerate(enumerator, (void**)&other))
370 {
371 if (family != AF_UNSPEC && other->get_family(other) != family)
372 {
373 continue;
374 }
375 me = hydra->kernel_interface->get_source_addr(
376 hydra->kernel_interface, other, NULL);
377 if (me)
378 {
379 /* reuse port for an active address, 4500 otherwise */
380 apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE);
381 other = other->clone(other);
382 apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg), FALSE);
383 DBG1(DBG_IKE, "checking path %#H - %#H", me, other);
384 copy = packet->clone(packet);
385 copy->set_source(copy, me);
386 copy->set_destination(copy, other);
387 charon->sender->send(charon->sender, copy);
388 found = TRUE;
389 }
390 }
391 enumerator->destroy(enumerator);
392 return found;
393 }
394
395 METHOD(task_t, build_i, status_t,
396 private_ike_mobike_t *this, message_t *message)
397 {
398 if (message->get_exchange_type(message) == IKE_AUTH &&
399 message->get_message_id(message) == 1)
400 { /* only in first IKE_AUTH */
401 message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
402 build_address_list(this, message);
403 }
404 else if (message->get_exchange_type(message) == INFORMATIONAL)
405 {
406 host_t *old, *new;
407
408 /* we check if the existing address is still valid */
409 old = message->get_source(message);
410 new = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
411 message->get_destination(message), old);
412 if (new)
413 {
414 if (!new->ip_equals(new, old))
415 {
416 new->set_port(new, old->get_port(old));
417 message->set_source(message, new);
418 }
419 else
420 {
421 new->destroy(new);
422 }
423 }
424 if (this->update)
425 {
426 message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES,
427 chunk_empty);
428 if (!build_cookie(this, message))
429 {
430 return FAILED;
431 }
432 update_children(this);
433 }
434 if (this->address && !this->check)
435 {
436 build_address_list(this, message);
437 }
438 if (this->natd)
439 {
440 this->natd->task.build(&this->natd->task, message);
441 }
442 }
443 return NEED_MORE;
444 }
445
446 METHOD(task_t, process_r, status_t,
447 private_ike_mobike_t *this, message_t *message)
448 {
449 if (message->get_exchange_type(message) == IKE_AUTH &&
450 message->get_message_id(message) == 1)
451 { /* only first IKE_AUTH */
452 process_payloads(this, message);
453 }
454 else if (message->get_exchange_type(message) == INFORMATIONAL)
455 {
456 process_payloads(this, message);
457 if (this->update)
458 {
459 host_t *me, *other;
460
461 me = message->get_destination(message);
462 other = message->get_source(message);
463 this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
464 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
465 }
466
467 if (this->natd)
468 {
469 this->natd->task.process(&this->natd->task, message);
470 }
471 if (this->addresses_updated && this->ike_sa->has_condition(this->ike_sa,
472 COND_ORIGINAL_INITIATOR))
473 {
474 host_t *other = message->get_source(message);
475 host_t *other_old = this->ike_sa->get_other_host(this->ike_sa);
476 if (!other->equals(other, other_old))
477 {
478 DBG1(DBG_IKE, "remote address changed from %H to %H", other_old,
479 other);
480 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
481 this->update = TRUE;
482 }
483 }
484 }
485 return NEED_MORE;
486 }
487
488 METHOD(task_t, build_r, status_t,
489 private_ike_mobike_t *this, message_t *message)
490 {
491 if (message->get_exchange_type(message) == IKE_AUTH &&
492 this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
493 {
494 if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
495 {
496 message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
497 build_address_list(this, message);
498 }
499 return SUCCESS;
500 }
501 else if (message->get_exchange_type(message) == INFORMATIONAL)
502 {
503 if (this->natd)
504 {
505 this->natd->task.build(&this->natd->task, message);
506 }
507 if (this->cookie2.ptr)
508 {
509 message->add_notify(message, FALSE, COOKIE2, this->cookie2);
510 chunk_free(&this->cookie2);
511 }
512 if (this->update)
513 {
514 update_children(this);
515 }
516 return SUCCESS;
517 }
518 return NEED_MORE;
519 }
520
521 METHOD(task_t, process_i, status_t,
522 private_ike_mobike_t *this, message_t *message)
523 {
524 if (message->get_exchange_type(message) == IKE_AUTH &&
525 this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
526 {
527 process_payloads(this, message);
528 return SUCCESS;
529 }
530 else if (message->get_exchange_type(message) == INFORMATIONAL)
531 {
532 if (this->ike_sa->get_pending_updates(this->ike_sa) > 1)
533 {
534 /* newer update queued, ignore this one */
535 return SUCCESS;
536 }
537 if (this->cookie2.ptr)
538 { /* check cookie if we included one */
539 chunk_t cookie2;
540
541 cookie2 = this->cookie2;
542 this->cookie2 = chunk_empty;
543 process_payloads(this, message);
544 if (!chunk_equals_const(cookie2, this->cookie2))
545 {
546 chunk_free(&cookie2);
547 DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
548 return FAILED;
549 }
550 chunk_free(&cookie2);
551 }
552 else
553 {
554 process_payloads(this, message);
555 }
556 if (this->natd)
557 {
558 this->natd->task.process(&this->natd->task, message);
559 if (this->natd->has_mapping_changed(this->natd))
560 {
561 /* force an update if mappings have changed */
562 this->update = this->check = TRUE;
563 DBG1(DBG_IKE, "detected changes in NAT mappings, "
564 "initiating MOBIKE update");
565 }
566 }
567 if (this->update)
568 {
569 /* update again, as NAT state may have changed */
570 update_children(this);
571 }
572 if (this->check)
573 {
574 host_t *me_new, *me_old, *other_new, *other_old;
575
576 me_new = message->get_destination(message);
577 other_new = message->get_source(message);
578 me_old = this->ike_sa->get_my_host(this->ike_sa);
579 other_old = this->ike_sa->get_other_host(this->ike_sa);
580
581 if (!me_new->equals(me_new, me_old))
582 {
583 this->update = TRUE;
584 this->ike_sa->set_my_host(this->ike_sa, me_new->clone(me_new));
585 }
586 if (!other_new->equals(other_new, other_old))
587 {
588 this->update = TRUE;
589 this->ike_sa->set_other_host(this->ike_sa, other_new->clone(other_new));
590 }
591 if (this->update)
592 {
593 /* use the same task to ... */
594 if (!this->ike_sa->has_condition(this->ike_sa,
595 COND_ORIGINAL_INITIATOR))
596 { /*... send an updated list of addresses as responder */
597 update_children(this);
598 this->update = FALSE;
599 }
600 else
601 { /* ... send the update as original initiator */
602 if (this->natd)
603 {
604 this->natd->task.destroy(&this->natd->task);
605 }
606 this->natd = ike_natd_create(this->ike_sa, this->initiator);
607 }
608 this->check = FALSE;
609 return NEED_MORE;
610 }
611 }
612 return SUCCESS;
613 }
614 return NEED_MORE;
615 }
616
617 METHOD(ike_mobike_t, addresses, void,
618 private_ike_mobike_t *this)
619 {
620 this->address = TRUE;
621 if (!this->pending_update)
622 {
623 this->pending_update = TRUE;
624 this->ike_sa->set_pending_updates(this->ike_sa,
625 this->ike_sa->get_pending_updates(this->ike_sa) + 1);
626 }
627 }
628
629 METHOD(ike_mobike_t, roam, void,
630 private_ike_mobike_t *this, bool address)
631 {
632 this->check = TRUE;
633 this->address = address;
634 if (!this->pending_update)
635 {
636 this->pending_update = TRUE;
637 this->ike_sa->set_pending_updates(this->ike_sa,
638 this->ike_sa->get_pending_updates(this->ike_sa) + 1);
639 }
640 }
641
642 METHOD(ike_mobike_t, dpd, void,
643 private_ike_mobike_t *this)
644 {
645 if (!this->natd)
646 {
647 this->natd = ike_natd_create(this->ike_sa, this->initiator);
648 }
649 if (!this->pending_update)
650 {
651 this->pending_update = TRUE;
652 this->ike_sa->set_pending_updates(this->ike_sa,
653 this->ike_sa->get_pending_updates(this->ike_sa) + 1);
654 }
655 }
656
657 METHOD(ike_mobike_t, is_probing, bool,
658 private_ike_mobike_t *this)
659 {
660 return this->check;
661 }
662
663 METHOD(ike_mobike_t, enable_probing, void,
664 private_ike_mobike_t *this)
665 {
666 this->check = TRUE;
667 }
668
669 METHOD(task_t, get_type, task_type_t,
670 private_ike_mobike_t *this)
671 {
672 return TASK_IKE_MOBIKE;
673 }
674
675 METHOD(task_t, migrate, void,
676 private_ike_mobike_t *this, ike_sa_t *ike_sa)
677 {
678 chunk_free(&this->cookie2);
679 this->ike_sa = ike_sa;
680 if (this->natd)
681 {
682 this->natd->task.migrate(&this->natd->task, ike_sa);
683 }
684 if (this->pending_update)
685 {
686 this->ike_sa->set_pending_updates(this->ike_sa,
687 this->ike_sa->get_pending_updates(this->ike_sa) + 1);
688 }
689 }
690
691 METHOD(task_t, destroy, void,
692 private_ike_mobike_t *this)
693 {
694 if (this->pending_update)
695 {
696 this->ike_sa->set_pending_updates(this->ike_sa,
697 this->ike_sa->get_pending_updates(this->ike_sa) - 1);
698 }
699 chunk_free(&this->cookie2);
700 if (this->natd)
701 {
702 this->natd->task.destroy(&this->natd->task);
703 }
704 free(this);
705 }
706
707 /*
708 * Described in header.
709 */
710 ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
711 {
712 private_ike_mobike_t *this;
713
714 INIT(this,
715 .public = {
716 .task = {
717 .get_type = _get_type,
718 .migrate = _migrate,
719 .destroy = _destroy,
720 },
721 .addresses = _addresses,
722 .roam = _roam,
723 .dpd = _dpd,
724 .transmit = _transmit,
725 .is_probing = _is_probing,
726 .enable_probing = _enable_probing,
727 },
728 .ike_sa = ike_sa,
729 .initiator = initiator,
730 );
731
732 if (initiator)
733 {
734 this->public.task.build = _build_i;
735 this->public.task.process = _process_i;
736 }
737 else
738 {
739 this->public.task.build = _build_r;
740 this->public.task.process = _process_r;
741 }
742
743 return &this->public;
744 }