91da4d3e602443cf7c3bd0949aba3a322070b42c
[strongswan.git] / src / libcharon / sa / child_sa.c
1 /*
2 * Copyright (C) 2006-2017 Tobias Brunner
3 * Copyright (C) 2016 Andreas Steffen
4 * Copyright (C) 2005-2008 Martin Willi
5 * Copyright (C) 2006 Daniel Roethlisberger
6 * Copyright (C) 2005 Jan Hutter
7 * HSR Hochschule fuer Technik Rapperswil
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
18 */
19
20 #define _GNU_SOURCE
21 #include "child_sa.h"
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <time.h>
26
27 #include <daemon.h>
28 #include <collections/array.h>
29
30 ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
31 "CREATED",
32 "ROUTED",
33 "INSTALLING",
34 "INSTALLED",
35 "UPDATING",
36 "REKEYING",
37 "REKEYED",
38 "RETRYING",
39 "DELETING",
40 "DESTROYING",
41 );
42
43 ENUM_FLAGS(child_sa_outbound_state_names, CHILD_OUTBOUND_REGISTERED, CHILD_OUTBOUND_POLICIES,
44 "REGISTERED",
45 "SA",
46 "POLICIES",
47 );
48
49 typedef struct private_child_sa_t private_child_sa_t;
50
51 /**
52 * Private data of a child_sa_t object.
53 */
54 struct private_child_sa_t {
55 /**
56 * Public interface of child_sa_t.
57 */
58 child_sa_t public;
59
60 /**
61 * address of us
62 */
63 host_t *my_addr;
64
65 /**
66 * address of remote
67 */
68 host_t *other_addr;
69
70 /**
71 * our actually used SPI, 0 if unused
72 */
73 uint32_t my_spi;
74
75 /**
76 * others used SPI, 0 if unused
77 */
78 uint32_t other_spi;
79
80 /**
81 * our Compression Parameter Index (CPI) used, 0 if unused
82 */
83 uint16_t my_cpi;
84
85 /**
86 * others Compression Parameter Index (CPI) used, 0 if unused
87 */
88 uint16_t other_cpi;
89
90 /**
91 * Array for local traffic selectors
92 */
93 array_t *my_ts;
94
95 /**
96 * Array for remote traffic selectors
97 */
98 array_t *other_ts;
99
100 /**
101 * Outbound encryption key cached during a rekeying
102 */
103 chunk_t encr_r;
104
105 /**
106 * Outbound integrity key cached during a rekeying
107 */
108 chunk_t integ_r;
109
110 /**
111 * Whether the outbound SA has only been registered yet during a rekeying
112 */
113 child_sa_outbound_state_t outbound_state;
114
115 /**
116 * Whether the peer supports TFCv3
117 */
118 bool tfcv3;
119
120 /**
121 * The outbound SPI of the CHILD_SA that replaced this one during a rekeying
122 */
123 uint32_t rekey_spi;
124
125 /**
126 * Protocol used to protect this SA, ESP|AH
127 */
128 protocol_id_t protocol;
129
130 /**
131 * reqid used for this child_sa
132 */
133 uint32_t reqid;
134
135 /**
136 * Did we allocate/confirm and must release the reqid?
137 */
138 bool reqid_allocated;
139
140 /**
141 * Is the reqid statically configured
142 */
143 bool static_reqid;
144
145 /**
146 * Unique CHILD_SA identifier
147 */
148 uint32_t unique_id;
149
150 /**
151 * Whether FWD policieis in the outbound direction should be installed
152 */
153 bool policies_fwd_out;
154
155 /**
156 * inbound mark used for this child_sa
157 */
158 mark_t mark_in;
159
160 /**
161 * outbound mark used for this child_sa
162 */
163 mark_t mark_out;
164
165 /**
166 * absolute time when rekeying is scheduled
167 */
168 time_t rekey_time;
169
170 /**
171 * absolute time when the SA expires
172 */
173 time_t expire_time;
174
175 /**
176 * absolute time when SA has been installed
177 */
178 time_t install_time;
179
180 /**
181 * state of the CHILD_SA
182 */
183 child_sa_state_t state;
184
185 /**
186 * TRUE if this CHILD_SA is used to install trap policies
187 */
188 bool trap;
189
190 /**
191 * Specifies if UDP encapsulation is enabled (NAT traversal)
192 */
193 bool encap;
194
195 /**
196 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
197 */
198 ipcomp_transform_t ipcomp;
199
200 /**
201 * mode this SA uses, tunnel/transport
202 */
203 ipsec_mode_t mode;
204
205 /**
206 * Action to enforce if peer closes the CHILD_SA
207 */
208 action_t close_action;
209
210 /**
211 * Action to enforce if peer is considered dead
212 */
213 action_t dpd_action;
214
215 /**
216 * selected proposal
217 */
218 proposal_t *proposal;
219
220 /**
221 * config used to create this child
222 */
223 child_cfg_t *config;
224
225 /**
226 * time of last use in seconds (inbound)
227 */
228 time_t my_usetime;
229
230 /**
231 * time of last use in seconds (outbound)
232 */
233 time_t other_usetime;
234
235 /**
236 * last number of inbound bytes
237 */
238 uint64_t my_usebytes;
239
240 /**
241 * last number of outbound bytes
242 */
243 uint64_t other_usebytes;
244
245 /**
246 * last number of inbound packets
247 */
248 uint64_t my_usepackets;
249
250 /**
251 * last number of outbound bytes
252 */
253 uint64_t other_usepackets;
254 };
255
256 /**
257 * Convert an IKEv2 specific protocol identifier to the IP protocol identifier
258 */
259 static inline uint8_t proto_ike2ip(protocol_id_t protocol)
260 {
261 switch (protocol)
262 {
263 case PROTO_ESP:
264 return IPPROTO_ESP;
265 case PROTO_AH:
266 return IPPROTO_AH;
267 default:
268 return protocol;
269 }
270 }
271
272 /**
273 * Returns the mark to use on the inbound SA
274 */
275 static inline mark_t mark_in_sa(private_child_sa_t *this)
276 {
277 if (this->config->has_option(this->config, OPT_MARK_IN_SA))
278 {
279 return this->mark_in;
280 }
281 return (mark_t){};
282 }
283
284 METHOD(child_sa_t, get_name, char*,
285 private_child_sa_t *this)
286 {
287 return this->config->get_name(this->config);
288 }
289
290 METHOD(child_sa_t, get_reqid, uint32_t,
291 private_child_sa_t *this)
292 {
293 return this->reqid;
294 }
295
296 METHOD(child_sa_t, get_unique_id, uint32_t,
297 private_child_sa_t *this)
298 {
299 return this->unique_id;
300 }
301
302 METHOD(child_sa_t, get_config, child_cfg_t*,
303 private_child_sa_t *this)
304 {
305 return this->config;
306 }
307
308 METHOD(child_sa_t, set_state, void,
309 private_child_sa_t *this, child_sa_state_t state)
310 {
311 if (this->state != state)
312 {
313 DBG2(DBG_CHD, "CHILD_SA %s{%d} state change: %N => %N",
314 get_name(this), this->unique_id,
315 child_sa_state_names, this->state,
316 child_sa_state_names, state);
317 charon->bus->child_state_change(charon->bus, &this->public, state);
318 this->state = state;
319 }
320 }
321
322 METHOD(child_sa_t, get_state, child_sa_state_t,
323 private_child_sa_t *this)
324 {
325 return this->state;
326 }
327
328 METHOD(child_sa_t, get_outbound_state, child_sa_outbound_state_t,
329 private_child_sa_t *this)
330 {
331 return this->outbound_state;
332 }
333
334 METHOD(child_sa_t, get_spi, uint32_t,
335 private_child_sa_t *this, bool inbound)
336 {
337 return inbound ? this->my_spi : this->other_spi;
338 }
339
340 METHOD(child_sa_t, get_cpi, uint16_t,
341 private_child_sa_t *this, bool inbound)
342 {
343 return inbound ? this->my_cpi : this->other_cpi;
344 }
345
346 METHOD(child_sa_t, get_protocol, protocol_id_t,
347 private_child_sa_t *this)
348 {
349 return this->protocol;
350 }
351
352 METHOD(child_sa_t, set_protocol, void,
353 private_child_sa_t *this, protocol_id_t protocol)
354 {
355 this->protocol = protocol;
356 }
357
358 METHOD(child_sa_t, get_mode, ipsec_mode_t,
359 private_child_sa_t *this)
360 {
361 return this->mode;
362 }
363
364 METHOD(child_sa_t, set_mode, void,
365 private_child_sa_t *this, ipsec_mode_t mode)
366 {
367 this->mode = mode;
368 }
369
370 METHOD(child_sa_t, has_encap, bool,
371 private_child_sa_t *this)
372 {
373 return this->encap;
374 }
375
376 METHOD(child_sa_t, get_ipcomp, ipcomp_transform_t,
377 private_child_sa_t *this)
378 {
379 return this->ipcomp;
380 }
381
382 METHOD(child_sa_t, set_ipcomp, void,
383 private_child_sa_t *this, ipcomp_transform_t ipcomp)
384 {
385 this->ipcomp = ipcomp;
386 }
387
388 METHOD(child_sa_t, set_close_action, void,
389 private_child_sa_t *this, action_t action)
390 {
391 this->close_action = action;
392 }
393
394 METHOD(child_sa_t, get_close_action, action_t,
395 private_child_sa_t *this)
396 {
397 return this->close_action;
398 }
399
400 METHOD(child_sa_t, set_dpd_action, void,
401 private_child_sa_t *this, action_t action)
402 {
403 this->dpd_action = action;
404 }
405
406 METHOD(child_sa_t, get_dpd_action, action_t,
407 private_child_sa_t *this)
408 {
409 return this->dpd_action;
410 }
411
412 METHOD(child_sa_t, get_proposal, proposal_t*,
413 private_child_sa_t *this)
414 {
415 return this->proposal;
416 }
417
418 METHOD(child_sa_t, set_proposal, void,
419 private_child_sa_t *this, proposal_t *proposal)
420 {
421 this->proposal = proposal->clone(proposal);
422 }
423
424 METHOD(child_sa_t, create_ts_enumerator, enumerator_t*,
425 private_child_sa_t *this, bool local)
426 {
427 if (local)
428 {
429 return array_create_enumerator(this->my_ts);
430 }
431 return array_create_enumerator(this->other_ts);
432 }
433
434 typedef struct policy_enumerator_t policy_enumerator_t;
435
436 /**
437 * Private policy enumerator
438 */
439 struct policy_enumerator_t {
440 /** implements enumerator_t */
441 enumerator_t public;
442 /** enumerator over own TS */
443 enumerator_t *mine;
444 /** enumerator over others TS */
445 enumerator_t *other;
446 /** array of others TS, to recreate enumerator */
447 array_t *array;
448 /** currently enumerating TS for "me" side */
449 traffic_selector_t *ts;
450 };
451
452 METHOD(enumerator_t, policy_enumerate, bool,
453 policy_enumerator_t *this, va_list args)
454 {
455 traffic_selector_t *other_ts, **my_out, **other_out;
456
457 VA_ARGS_VGET(args, my_out, other_out);
458
459 while (this->ts || this->mine->enumerate(this->mine, &this->ts))
460 {
461 if (!this->other->enumerate(this->other, &other_ts))
462 { /* end of others list, restart with new of mine */
463 this->other->destroy(this->other);
464 this->other = array_create_enumerator(this->array);
465 this->ts = NULL;
466 continue;
467 }
468 if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
469 { /* family mismatch */
470 continue;
471 }
472 if (this->ts->get_protocol(this->ts) &&
473 other_ts->get_protocol(other_ts) &&
474 this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
475 { /* protocol mismatch */
476 continue;
477 }
478 if (my_out)
479 {
480 *my_out = this->ts;
481 }
482 if (other_out)
483 {
484 *other_out = other_ts;
485 }
486 return TRUE;
487 }
488 return FALSE;
489 }
490
491 METHOD(enumerator_t, policy_destroy, void,
492 policy_enumerator_t *this)
493 {
494 this->mine->destroy(this->mine);
495 this->other->destroy(this->other);
496 free(this);
497 }
498
499 METHOD(child_sa_t, create_policy_enumerator, enumerator_t*,
500 private_child_sa_t *this)
501 {
502 policy_enumerator_t *e;
503
504 INIT(e,
505 .public = {
506 .enumerate = enumerator_enumerate_default,
507 .venumerate = _policy_enumerate,
508 .destroy = _policy_destroy,
509 },
510 .mine = array_create_enumerator(this->my_ts),
511 .other = array_create_enumerator(this->other_ts),
512 .array = this->other_ts,
513 .ts = NULL,
514 );
515
516 return &e->public;
517 }
518
519 /**
520 * update the cached usebytes
521 * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
522 * are available, and NOT_SUPPORTED if the kernel interface does not support
523 * querying the usebytes.
524 */
525 static status_t update_usebytes(private_child_sa_t *this, bool inbound)
526 {
527 status_t status = FAILED;
528 uint64_t bytes, packets;
529 time_t time;
530
531 if (inbound)
532 {
533 if (this->my_spi)
534 {
535 kernel_ipsec_sa_id_t id = {
536 .src = this->other_addr,
537 .dst = this->my_addr,
538 .spi = this->my_spi,
539 .proto = proto_ike2ip(this->protocol),
540 .mark = mark_in_sa(this),
541 };
542 kernel_ipsec_query_sa_t query = {};
543
544 status = charon->kernel->query_sa(charon->kernel, &id, &query,
545 &bytes, &packets, &time);
546 if (status == SUCCESS)
547 {
548 if (bytes > this->my_usebytes)
549 {
550 this->my_usebytes = bytes;
551 this->my_usepackets = packets;
552 if (time)
553 {
554 this->my_usetime = time;
555 }
556 }
557 else
558 {
559 status = FAILED;
560 }
561 }
562 }
563 }
564 else
565 {
566 if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
567 {
568 kernel_ipsec_sa_id_t id = {
569 .src = this->my_addr,
570 .dst = this->other_addr,
571 .spi = this->other_spi,
572 .proto = proto_ike2ip(this->protocol),
573 .mark = this->mark_out,
574 };
575 kernel_ipsec_query_sa_t query = {};
576
577 status = charon->kernel->query_sa(charon->kernel, &id, &query,
578 &bytes, &packets, &time);
579 if (status == SUCCESS)
580 {
581 if (bytes > this->other_usebytes)
582 {
583 this->other_usebytes = bytes;
584 this->other_usepackets = packets;
585 if (time)
586 {
587 this->other_usetime = time;
588 }
589 }
590 else
591 {
592 status = FAILED;
593 }
594 }
595 }
596 }
597 return status;
598 }
599
600 /**
601 * updates the cached usetime
602 */
603 static bool update_usetime(private_child_sa_t *this, bool inbound)
604 {
605 enumerator_t *enumerator;
606 traffic_selector_t *my_ts, *other_ts;
607 time_t last_use = 0;
608
609 enumerator = create_policy_enumerator(this);
610 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
611 {
612 time_t in, out, fwd;
613
614 if (inbound)
615 {
616 kernel_ipsec_policy_id_t id = {
617 .dir = POLICY_IN,
618 .src_ts = other_ts,
619 .dst_ts = my_ts,
620 .mark = this->mark_in,
621 };
622 kernel_ipsec_query_policy_t query = {};
623
624 if (charon->kernel->query_policy(charon->kernel, &id, &query,
625 &in) == SUCCESS)
626 {
627 last_use = max(last_use, in);
628 }
629 if (this->mode != MODE_TRANSPORT)
630 {
631 id.dir = POLICY_FWD;
632 if (charon->kernel->query_policy(charon->kernel, &id, &query,
633 &fwd) == SUCCESS)
634 {
635 last_use = max(last_use, fwd);
636 }
637 }
638 }
639 else
640 {
641 kernel_ipsec_policy_id_t id = {
642 .dir = POLICY_OUT,
643 .src_ts = my_ts,
644 .dst_ts = other_ts,
645 .mark = this->mark_out,
646 .interface = this->config->get_interface(this->config),
647 };
648 kernel_ipsec_query_policy_t query = {};
649
650 if (charon->kernel->query_policy(charon->kernel, &id, &query,
651 &out) == SUCCESS)
652 {
653 last_use = max(last_use, out);
654 }
655 }
656 }
657 enumerator->destroy(enumerator);
658
659 if (last_use == 0)
660 {
661 return FALSE;
662 }
663 if (inbound)
664 {
665 this->my_usetime = last_use;
666 }
667 else
668 {
669 this->other_usetime = last_use;
670 }
671 return TRUE;
672 }
673
674 METHOD(child_sa_t, get_usestats, void,
675 private_child_sa_t *this, bool inbound,
676 time_t *time, uint64_t *bytes, uint64_t *packets)
677 {
678 if ((!bytes && !packets) || update_usebytes(this, inbound) != FAILED)
679 {
680 /* there was traffic since last update or the kernel interface
681 * does not support querying the number of usebytes.
682 */
683 if (time)
684 {
685 if (!update_usetime(this, inbound) && !bytes && !packets)
686 {
687 /* if policy query did not yield a usetime, query SAs instead */
688 update_usebytes(this, inbound);
689 }
690 }
691 }
692 if (time)
693 {
694 *time = inbound ? this->my_usetime : this->other_usetime;
695 }
696 if (bytes)
697 {
698 *bytes = inbound ? this->my_usebytes : this->other_usebytes;
699 }
700 if (packets)
701 {
702 *packets = inbound ? this->my_usepackets : this->other_usepackets;
703 }
704 }
705
706 METHOD(child_sa_t, get_mark, mark_t,
707 private_child_sa_t *this, bool inbound)
708 {
709 if (inbound)
710 {
711 return this->mark_in;
712 }
713 return this->mark_out;
714 }
715
716 METHOD(child_sa_t, get_lifetime, time_t,
717 private_child_sa_t *this, bool hard)
718 {
719 return hard ? this->expire_time : this->rekey_time;
720 }
721
722 METHOD(child_sa_t, get_installtime, time_t,
723 private_child_sa_t *this)
724 {
725 return this->install_time;
726 }
727
728 METHOD(child_sa_t, alloc_spi, uint32_t,
729 private_child_sa_t *this, protocol_id_t protocol)
730 {
731 if (charon->kernel->get_spi(charon->kernel, this->other_addr, this->my_addr,
732 proto_ike2ip(protocol), &this->my_spi) == SUCCESS)
733 {
734 /* if we allocate a SPI, but then are unable to establish the SA, we
735 * need to know the protocol family to delete the partial SA */
736 this->protocol = protocol;
737 return this->my_spi;
738 }
739 return 0;
740 }
741
742 METHOD(child_sa_t, alloc_cpi, uint16_t,
743 private_child_sa_t *this)
744 {
745 if (charon->kernel->get_cpi(charon->kernel, this->other_addr, this->my_addr,
746 &this->my_cpi) == SUCCESS)
747 {
748 return this->my_cpi;
749 }
750 return 0;
751 }
752
753 /**
754 * Install the given SA in the kernel
755 */
756 static status_t install_internal(private_child_sa_t *this, chunk_t encr,
757 chunk_t integ, uint32_t spi, uint16_t cpi, bool initiator, bool inbound,
758 bool tfcv3)
759 {
760 uint16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
761 uint16_t esn = NO_EXT_SEQ_NUMBERS;
762 linked_list_t *my_ts, *other_ts, *src_ts, *dst_ts;
763 time_t now;
764 kernel_ipsec_sa_id_t id;
765 kernel_ipsec_add_sa_t sa;
766 lifetime_cfg_t *lifetime;
767 uint32_t tfc = 0;
768 host_t *src, *dst;
769 status_t status;
770 bool update = FALSE;
771
772 /* BEET requires the bound address from the traffic selectors */
773 my_ts = linked_list_create_from_enumerator(
774 array_create_enumerator(this->my_ts));
775 other_ts = linked_list_create_from_enumerator(
776 array_create_enumerator(this->other_ts));
777
778 /* now we have to decide which spi to use. Use self allocated, if "in",
779 * or the one in the proposal, if not "in" (others). Additionally,
780 * source and dest host switch depending on the role */
781 if (inbound)
782 {
783 dst = this->my_addr;
784 src = this->other_addr;
785 if (this->my_spi == spi)
786 { /* alloc_spi has been called, do an SA update */
787 update = TRUE;
788 }
789 this->my_spi = spi;
790 this->my_cpi = cpi;
791 dst_ts = my_ts;
792 src_ts = other_ts;
793 }
794 else
795 {
796 src = this->my_addr;
797 dst = this->other_addr;
798 this->other_spi = spi;
799 this->other_cpi = cpi;
800 src_ts = my_ts;
801 dst_ts = other_ts;
802
803 if (tfcv3)
804 {
805 tfc = this->config->get_tfc(this->config);
806 }
807 this->outbound_state |= CHILD_OUTBOUND_SA;
808 }
809
810 DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
811 protocol_id_names, this->protocol);
812
813 /* send SA down to the kernel */
814 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
815
816 this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
817 &enc_alg, &size);
818 this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
819 &int_alg, &size);
820 this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
821 &esn, NULL);
822
823 if (int_alg == AUTH_HMAC_SHA2_256_128 &&
824 this->config->has_option(this->config, OPT_SHA256_96))
825 {
826 DBG2(DBG_CHD, " using %N with 96-bit truncation",
827 integrity_algorithm_names, int_alg);
828 int_alg = AUTH_HMAC_SHA2_256_96;
829 }
830
831 if (!this->reqid_allocated && !this->static_reqid)
832 {
833 status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts,
834 this->mark_in, this->mark_out, &this->reqid);
835 if (status != SUCCESS)
836 {
837 my_ts->destroy(my_ts);
838 other_ts->destroy(other_ts);
839 return status;
840 }
841 this->reqid_allocated = TRUE;
842 }
843
844 lifetime = this->config->get_lifetime(this->config, TRUE);
845
846 now = time_monotonic(NULL);
847 if (lifetime->time.rekey)
848 {
849 if (this->rekey_time)
850 {
851 this->rekey_time = min(this->rekey_time, now + lifetime->time.rekey);
852 }
853 else
854 {
855 this->rekey_time = now + lifetime->time.rekey;
856 }
857 }
858 if (lifetime->time.life)
859 {
860 this->expire_time = now + lifetime->time.life;
861 }
862
863 if (!lifetime->time.jitter && !inbound)
864 { /* avoid triggering multiple rekey events */
865 lifetime->time.rekey = 0;
866 }
867
868 id = (kernel_ipsec_sa_id_t){
869 .src = src,
870 .dst = dst,
871 .spi = spi,
872 .proto = proto_ike2ip(this->protocol),
873 .mark = inbound ? mark_in_sa(this) : this->mark_out,
874 };
875 sa = (kernel_ipsec_add_sa_t){
876 .reqid = this->reqid,
877 .mode = this->mode,
878 .src_ts = src_ts,
879 .dst_ts = dst_ts,
880 .interface = inbound ? NULL : this->config->get_interface(this->config),
881 .lifetime = lifetime,
882 .enc_alg = enc_alg,
883 .enc_key = encr,
884 .int_alg = int_alg,
885 .int_key = integ,
886 .replay_window = this->config->get_replay_window(this->config),
887 .tfc = tfc,
888 .ipcomp = this->ipcomp,
889 .cpi = cpi,
890 .encap = this->encap,
891 .hw_offload = this->config->has_option(this->config, OPT_HW_OFFLOAD),
892 .esn = esn,
893 .initiator = initiator,
894 .inbound = inbound,
895 .update = update,
896 };
897
898 status = charon->kernel->add_sa(charon->kernel, &id, &sa);
899
900 my_ts->destroy(my_ts);
901 other_ts->destroy(other_ts);
902 free(lifetime);
903
904 return status;
905 }
906
907 METHOD(child_sa_t, install, status_t,
908 private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
909 uint16_t cpi, bool initiator, bool inbound, bool tfcv3)
910 {
911 return install_internal(this, encr, integ, spi, cpi, initiator, inbound,
912 tfcv3);
913 }
914
915 /**
916 * Check kernel interface if policy updates are required
917 */
918 static bool require_policy_update()
919 {
920 kernel_feature_t f;
921
922 f = charon->kernel->get_features(charon->kernel);
923 return !(f & KERNEL_NO_POLICY_UPDATES);
924 }
925
926 /**
927 * Prepare SA config to install/delete policies
928 */
929 static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
930 ipsec_sa_cfg_t *other_sa)
931 {
932 enumerator_t *enumerator;
933
934 *my_sa = (ipsec_sa_cfg_t){
935 .mode = this->mode,
936 .reqid = this->reqid,
937 .ipcomp = {
938 .transform = this->ipcomp,
939 },
940 };
941 *other_sa = *my_sa;
942
943 my_sa->ipcomp.cpi = this->my_cpi;
944 other_sa->ipcomp.cpi = this->other_cpi;
945
946 if (this->protocol == PROTO_ESP)
947 {
948 my_sa->esp.use = TRUE;
949 my_sa->esp.spi = this->my_spi;
950 other_sa->esp.use = TRUE;
951 other_sa->esp.spi = this->other_spi;
952 }
953 else
954 {
955 my_sa->ah.use = TRUE;
956 my_sa->ah.spi = this->my_spi;
957 other_sa->ah.use = TRUE;
958 other_sa->ah.spi = this->other_spi;
959 }
960
961 enumerator = create_policy_enumerator(this);
962 while (enumerator->enumerate(enumerator, NULL, NULL))
963 {
964 my_sa->policy_count++;
965 other_sa->policy_count++;
966 }
967 enumerator->destroy(enumerator);
968 }
969
970 /**
971 * Install inbound policie(s): in, fwd
972 */
973 static status_t install_policies_inbound(private_child_sa_t *this,
974 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
975 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
976 ipsec_sa_cfg_t *other_sa, policy_type_t type,
977 policy_priority_t priority, uint32_t manual_prio)
978 {
979 kernel_ipsec_policy_id_t in_id = {
980 .dir = POLICY_IN,
981 .src_ts = other_ts,
982 .dst_ts = my_ts,
983 .mark = this->mark_in,
984 };
985 kernel_ipsec_manage_policy_t in_policy = {
986 .type = type,
987 .prio = priority,
988 .manual_prio = manual_prio,
989 .src = other_addr,
990 .dst = my_addr,
991 .sa = my_sa,
992 };
993 status_t status = SUCCESS;
994
995 status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
996 if (this->mode != MODE_TRANSPORT)
997 {
998 in_id.dir = POLICY_FWD;
999 status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
1000 }
1001 return status;
1002 }
1003
1004 /**
1005 * Install outbound policie(s): out, [fwd]
1006 */
1007 static status_t install_policies_outbound(private_child_sa_t *this,
1008 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1009 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1010 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1011 policy_priority_t priority, uint32_t manual_prio)
1012 {
1013 kernel_ipsec_policy_id_t out_id = {
1014 .dir = POLICY_OUT,
1015 .src_ts = my_ts,
1016 .dst_ts = other_ts,
1017 .mark = this->mark_out,
1018 .interface = this->config->get_interface(this->config),
1019 };
1020 kernel_ipsec_manage_policy_t out_policy = {
1021 .type = type,
1022 .prio = priority,
1023 .manual_prio = manual_prio,
1024 .src = my_addr,
1025 .dst = other_addr,
1026 .sa = other_sa,
1027 };
1028 status_t status = SUCCESS;
1029
1030 status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
1031
1032 if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
1033 {
1034 /* install an "outbound" FWD policy in case there is a drop policy
1035 * matching outbound forwarded traffic, to allow another tunnel to use
1036 * the reversed subnets and do the same we don't set a reqid (this also
1037 * allows the kernel backend to distinguish between the two types of
1038 * FWD policies). To avoid problems with symmetrically overlapping
1039 * policies of two SAs we install them with reduced priority. As they
1040 * basically act as bypass policies for drop policies we use a higher
1041 * priority than is used for them. */
1042 out_id.dir = POLICY_FWD;
1043 other_sa->reqid = 0;
1044 if (priority == POLICY_PRIORITY_DEFAULT)
1045 {
1046 out_policy.prio = POLICY_PRIORITY_ROUTED;
1047 }
1048 status |= charon->kernel->add_policy(charon->kernel, &out_id,
1049 &out_policy);
1050 /* reset the reqid for any other further policies */
1051 other_sa->reqid = this->reqid;
1052 }
1053 return status;
1054 }
1055
1056 /**
1057 * Install all policies
1058 */
1059 static status_t install_policies_internal(private_child_sa_t *this,
1060 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1061 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1062 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1063 policy_priority_t priority, uint32_t manual_prio)
1064 {
1065 status_t status = SUCCESS;
1066
1067 status |= install_policies_inbound(this, my_addr, other_addr, my_ts,
1068 other_ts, my_sa, other_sa, type,
1069 priority, manual_prio);
1070 status |= install_policies_outbound(this, my_addr, other_addr, my_ts,
1071 other_ts, my_sa, other_sa, type,
1072 priority, manual_prio);
1073 return status;
1074 }
1075
1076 /**
1077 * Delete inbound policies: in, fwd
1078 */
1079 static void del_policies_inbound(private_child_sa_t *this,
1080 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1081 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1082 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1083 policy_priority_t priority, uint32_t manual_prio)
1084 {
1085 kernel_ipsec_policy_id_t in_id = {
1086 .dir = POLICY_IN,
1087 .src_ts = other_ts,
1088 .dst_ts = my_ts,
1089 .mark = this->mark_in,
1090 };
1091 kernel_ipsec_manage_policy_t in_policy = {
1092 .type = type,
1093 .prio = priority,
1094 .manual_prio = manual_prio,
1095 .src = other_addr,
1096 .dst = my_addr,
1097 .sa = my_sa,
1098 };
1099
1100 charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
1101
1102 if (this->mode != MODE_TRANSPORT)
1103 {
1104 in_id.dir = POLICY_FWD;
1105 charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
1106 }
1107 }
1108
1109 /**
1110 * Delete outbound policies: out, [fwd]
1111 */
1112 static void del_policies_outbound(private_child_sa_t *this,
1113 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1114 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1115 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1116 policy_priority_t priority, uint32_t manual_prio)
1117 {
1118 kernel_ipsec_policy_id_t out_id = {
1119 .dir = POLICY_OUT,
1120 .src_ts = my_ts,
1121 .dst_ts = other_ts,
1122 .mark = this->mark_out,
1123 .interface = this->config->get_interface(this->config),
1124 };
1125 kernel_ipsec_manage_policy_t out_policy = {
1126 .type = type,
1127 .prio = priority,
1128 .manual_prio = manual_prio,
1129 .src = my_addr,
1130 .dst = other_addr,
1131 .sa = other_sa,
1132 };
1133
1134 charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
1135
1136 if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
1137 {
1138 out_id.dir = POLICY_FWD;
1139 other_sa->reqid = 0;
1140 if (priority == POLICY_PRIORITY_DEFAULT)
1141 {
1142 out_policy.prio = POLICY_PRIORITY_ROUTED;
1143 }
1144 charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
1145 other_sa->reqid = this->reqid;
1146 }
1147 }
1148
1149 /**
1150 * Delete in- and outbound policies
1151 */
1152 static void del_policies_internal(private_child_sa_t *this,
1153 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1154 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1155 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1156 policy_priority_t priority, uint32_t manual_prio)
1157 {
1158 del_policies_outbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
1159 other_sa, type, priority, manual_prio);
1160 del_policies_inbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
1161 other_sa, type, priority, manual_prio);
1162 }
1163
1164 METHOD(child_sa_t, set_policies, void,
1165 private_child_sa_t *this, linked_list_t *my_ts_list,
1166 linked_list_t *other_ts_list)
1167 {
1168 enumerator_t *enumerator;
1169 traffic_selector_t *my_ts, *other_ts;
1170
1171 if (array_count(this->my_ts))
1172 {
1173 array_destroy_offset(this->my_ts,
1174 offsetof(traffic_selector_t, destroy));
1175 this->my_ts = array_create(0, 0);
1176 }
1177 enumerator = my_ts_list->create_enumerator(my_ts_list);
1178 while (enumerator->enumerate(enumerator, &my_ts))
1179 {
1180 array_insert(this->my_ts, ARRAY_TAIL, my_ts->clone(my_ts));
1181 }
1182 enumerator->destroy(enumerator);
1183 array_sort(this->my_ts, (void*)traffic_selector_cmp, NULL);
1184
1185 if (array_count(this->other_ts))
1186 {
1187 array_destroy_offset(this->other_ts,
1188 offsetof(traffic_selector_t, destroy));
1189 this->other_ts = array_create(0, 0);
1190 }
1191 enumerator = other_ts_list->create_enumerator(other_ts_list);
1192 while (enumerator->enumerate(enumerator, &other_ts))
1193 {
1194 array_insert(this->other_ts, ARRAY_TAIL, other_ts->clone(other_ts));
1195 }
1196 enumerator->destroy(enumerator);
1197 array_sort(this->other_ts, (void*)traffic_selector_cmp, NULL);
1198 }
1199
1200 METHOD(child_sa_t, install_policies, status_t,
1201 private_child_sa_t *this)
1202 {
1203 enumerator_t *enumerator;
1204 linked_list_t *my_ts_list, *other_ts_list;
1205 traffic_selector_t *my_ts, *other_ts;
1206 status_t status = SUCCESS;
1207 bool install_outbound = FALSE;
1208
1209 if (!this->reqid_allocated && !this->static_reqid)
1210 {
1211 my_ts_list = linked_list_create_from_enumerator(
1212 array_create_enumerator(this->my_ts));
1213 other_ts_list = linked_list_create_from_enumerator(
1214 array_create_enumerator(this->other_ts));
1215 status = charon->kernel->alloc_reqid(
1216 charon->kernel, my_ts_list, other_ts_list,
1217 this->mark_in, this->mark_out, &this->reqid);
1218 my_ts_list->destroy(my_ts_list);
1219 other_ts_list->destroy(other_ts_list);
1220 if (status != SUCCESS)
1221 {
1222 return status;
1223 }
1224 this->reqid_allocated = TRUE;
1225 }
1226
1227 if (!(this->outbound_state & CHILD_OUTBOUND_REGISTERED))
1228 {
1229 install_outbound = TRUE;
1230 this->outbound_state |= CHILD_OUTBOUND_POLICIES;
1231 }
1232
1233 if (!this->config->has_option(this->config, OPT_NO_POLICIES))
1234 {
1235 policy_priority_t priority;
1236 ipsec_sa_cfg_t my_sa, other_sa;
1237 uint32_t manual_prio;
1238
1239 prepare_sa_cfg(this, &my_sa, &other_sa);
1240 manual_prio = this->config->get_manual_prio(this->config);
1241
1242 /* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
1243 * entry) we install a trap policy */
1244 this->trap = this->state == CHILD_CREATED;
1245 priority = this->trap ? POLICY_PRIORITY_ROUTED
1246 : POLICY_PRIORITY_DEFAULT;
1247
1248 /* enumerate pairs of traffic selectors */
1249 enumerator = create_policy_enumerator(this);
1250 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1251 {
1252 /* install outbound drop policy to avoid packets leaving unencrypted
1253 * when updating policies */
1254 if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
1255 require_policy_update() && install_outbound)
1256 {
1257 status |= install_policies_outbound(this, this->my_addr,
1258 this->other_addr, my_ts, other_ts,
1259 &my_sa, &other_sa, POLICY_DROP,
1260 POLICY_PRIORITY_FALLBACK, 0);
1261 }
1262
1263 status |= install_policies_inbound(this, this->my_addr,
1264 this->other_addr, my_ts, other_ts,
1265 &my_sa, &other_sa, POLICY_IPSEC,
1266 priority, manual_prio);
1267
1268 if (install_outbound)
1269 {
1270 status |= install_policies_outbound(this, this->my_addr,
1271 this->other_addr, my_ts, other_ts,
1272 &my_sa, &other_sa, POLICY_IPSEC,
1273 priority, manual_prio);
1274 }
1275 if (status != SUCCESS)
1276 {
1277 break;
1278 }
1279 }
1280 enumerator->destroy(enumerator);
1281 }
1282
1283 if (status == SUCCESS && this->trap)
1284 {
1285 set_state(this, CHILD_ROUTED);
1286 }
1287 return status;
1288 }
1289
1290 METHOD(child_sa_t, register_outbound, status_t,
1291 private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
1292 uint16_t cpi, bool tfcv3)
1293 {
1294 status_t status;
1295
1296 /* if the kernel supports installing SPIs with policies we install the
1297 * SA immediately as it will only be used once we update the policies */
1298 if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
1299 {
1300 status = install_internal(this, encr, integ, spi, cpi, FALSE, FALSE,
1301 tfcv3);
1302 }
1303 else
1304 {
1305 DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
1306 this->protocol);
1307 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
1308 this->other_addr);
1309
1310 this->other_spi = spi;
1311 this->other_cpi = cpi;
1312 this->encr_r = chunk_clone(encr);
1313 this->integ_r = chunk_clone(integ);
1314 this->tfcv3 = tfcv3;
1315 status = SUCCESS;
1316 }
1317 this->outbound_state |= CHILD_OUTBOUND_REGISTERED;
1318 return status;
1319 }
1320
1321 METHOD(child_sa_t, install_outbound, status_t,
1322 private_child_sa_t *this)
1323 {
1324 enumerator_t *enumerator;
1325 traffic_selector_t *my_ts, *other_ts;
1326 status_t status = SUCCESS;
1327
1328 if (!(this->outbound_state & CHILD_OUTBOUND_SA))
1329 {
1330 status = install_internal(this, this->encr_r, this->integ_r,
1331 this->other_spi, this->other_cpi, FALSE,
1332 FALSE, this->tfcv3);
1333 chunk_clear(&this->encr_r);
1334 chunk_clear(&this->integ_r);
1335 }
1336 this->outbound_state &= ~CHILD_OUTBOUND_REGISTERED;
1337 if (status != SUCCESS)
1338 {
1339 return status;
1340 }
1341 if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
1342 !(this->outbound_state & CHILD_OUTBOUND_POLICIES))
1343 {
1344 ipsec_sa_cfg_t my_sa, other_sa;
1345 uint32_t manual_prio;
1346
1347 prepare_sa_cfg(this, &my_sa, &other_sa);
1348 manual_prio = this->config->get_manual_prio(this->config);
1349
1350 enumerator = create_policy_enumerator(this);
1351 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1352 {
1353 /* install outbound drop policy to avoid packets leaving unencrypted
1354 * when updating policies */
1355 if (manual_prio == 0 && require_policy_update())
1356 {
1357 status |= install_policies_outbound(this, this->my_addr,
1358 this->other_addr, my_ts, other_ts,
1359 &my_sa, &other_sa, POLICY_DROP,
1360 POLICY_PRIORITY_FALLBACK, 0);
1361 }
1362 status |= install_policies_outbound(this, this->my_addr,
1363 this->other_addr, my_ts, other_ts,
1364 &my_sa, &other_sa, POLICY_IPSEC,
1365 POLICY_PRIORITY_DEFAULT, manual_prio);
1366 if (status != SUCCESS)
1367 {
1368 break;
1369 }
1370 }
1371 enumerator->destroy(enumerator);
1372 }
1373 this->outbound_state |= CHILD_OUTBOUND_POLICIES;
1374 return status;
1375 }
1376
1377 METHOD(child_sa_t, remove_outbound, void,
1378 private_child_sa_t *this)
1379 {
1380 enumerator_t *enumerator;
1381 traffic_selector_t *my_ts, *other_ts;
1382
1383 if (!(this->outbound_state & CHILD_OUTBOUND_SA))
1384 {
1385 if (this->outbound_state & CHILD_OUTBOUND_REGISTERED)
1386 {
1387 chunk_clear(&this->encr_r);
1388 chunk_clear(&this->integ_r);
1389 this->outbound_state = CHILD_OUTBOUND_NONE;
1390 }
1391 return;
1392 }
1393
1394 if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
1395 (this->outbound_state & CHILD_OUTBOUND_POLICIES))
1396 {
1397 ipsec_sa_cfg_t my_sa, other_sa;
1398 uint32_t manual_prio;
1399
1400 prepare_sa_cfg(this, &my_sa, &other_sa);
1401 manual_prio = this->config->get_manual_prio(this->config);
1402
1403 enumerator = create_policy_enumerator(this);
1404 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1405 {
1406 del_policies_outbound(this, this->my_addr, this->other_addr,
1407 my_ts, other_ts, &my_sa, &other_sa,
1408 POLICY_IPSEC, POLICY_PRIORITY_DEFAULT,
1409 manual_prio);
1410 if (manual_prio == 0 && require_policy_update())
1411 {
1412 del_policies_outbound(this, this->my_addr, this->other_addr,
1413 my_ts, other_ts, &my_sa, &other_sa,
1414 POLICY_DROP, POLICY_PRIORITY_FALLBACK, 0);
1415 }
1416 }
1417 enumerator->destroy(enumerator);
1418 }
1419
1420 kernel_ipsec_sa_id_t id = {
1421 .src = this->my_addr,
1422 .dst = this->other_addr,
1423 .spi = this->other_spi,
1424 .proto = proto_ike2ip(this->protocol),
1425 .mark = this->mark_out,
1426 };
1427 kernel_ipsec_del_sa_t sa = {
1428 .cpi = this->other_cpi,
1429 };
1430 charon->kernel->del_sa(charon->kernel, &id, &sa);
1431 this->outbound_state = CHILD_OUTBOUND_NONE;
1432 }
1433
1434 METHOD(child_sa_t, set_rekey_spi, void,
1435 private_child_sa_t *this, uint32_t spi)
1436 {
1437 this->rekey_spi = spi;
1438 }
1439
1440 METHOD(child_sa_t, get_rekey_spi, uint32_t,
1441 private_child_sa_t *this)
1442 {
1443 return this->rekey_spi;
1444 }
1445
1446 CALLBACK(reinstall_vip, void,
1447 host_t *vip, va_list args)
1448 {
1449 host_t *me;
1450 char *iface;
1451
1452 VA_ARGS_VGET(args, me);
1453 if (charon->kernel->get_interface(charon->kernel, me, &iface))
1454 {
1455 charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
1456 charon->kernel->add_ip(charon->kernel, vip, -1, iface);
1457 free(iface);
1458 }
1459 }
1460
1461 METHOD(child_sa_t, update, status_t,
1462 private_child_sa_t *this, host_t *me, host_t *other, linked_list_t *vips,
1463 bool encap)
1464 {
1465 child_sa_state_t old;
1466 bool transport_proxy_mode;
1467
1468 /* anything changed at all? */
1469 if (me->equals(me, this->my_addr) &&
1470 other->equals(other, this->other_addr) && this->encap == encap)
1471 {
1472 return SUCCESS;
1473 }
1474
1475 old = this->state;
1476 set_state(this, CHILD_UPDATING);
1477 transport_proxy_mode = this->mode == MODE_TRANSPORT &&
1478 this->config->has_option(this->config,
1479 OPT_PROXY_MODE);
1480
1481 if (!transport_proxy_mode)
1482 {
1483 /* update our (initiator) SA */
1484 if (this->my_spi)
1485 {
1486 kernel_ipsec_sa_id_t id = {
1487 .src = this->other_addr,
1488 .dst = this->my_addr,
1489 .spi = this->my_spi,
1490 .proto = proto_ike2ip(this->protocol),
1491 .mark = mark_in_sa(this),
1492 };
1493 kernel_ipsec_update_sa_t sa = {
1494 .cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
1495 .new_src = other,
1496 .new_dst = me,
1497 .encap = this->encap,
1498 .new_encap = encap,
1499 };
1500 if (charon->kernel->update_sa(charon->kernel, &id,
1501 &sa) == NOT_SUPPORTED)
1502 {
1503 set_state(this, old);
1504 return NOT_SUPPORTED;
1505 }
1506 }
1507
1508 /* update his (responder) SA */
1509 if (this->other_spi)
1510 {
1511 kernel_ipsec_sa_id_t id = {
1512 .src = this->my_addr,
1513 .dst = this->other_addr,
1514 .spi = this->other_spi,
1515 .proto = proto_ike2ip(this->protocol),
1516 .mark = this->mark_out,
1517 };
1518 kernel_ipsec_update_sa_t sa = {
1519 .cpi = this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
1520 .new_src = me,
1521 .new_dst = other,
1522 .encap = this->encap,
1523 .new_encap = encap,
1524 };
1525 if (charon->kernel->update_sa(charon->kernel, &id,
1526 &sa) == NOT_SUPPORTED)
1527 {
1528 set_state(this, old);
1529 return NOT_SUPPORTED;
1530 }
1531 }
1532 }
1533
1534 if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
1535 require_policy_update())
1536 {
1537 if (!me->ip_equals(me, this->my_addr) ||
1538 !other->ip_equals(other, this->other_addr))
1539 {
1540 ipsec_sa_cfg_t my_sa, other_sa;
1541 enumerator_t *enumerator;
1542 traffic_selector_t *my_ts, *other_ts;
1543 uint32_t manual_prio;
1544
1545 prepare_sa_cfg(this, &my_sa, &other_sa);
1546 manual_prio = this->config->get_manual_prio(this->config);
1547
1548 /* always use high priorities, as hosts getting updated are INSTALLED */
1549 enumerator = create_policy_enumerator(this);
1550 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1551 {
1552 traffic_selector_t *old_my_ts = NULL, *old_other_ts = NULL;
1553
1554 /* remove old policies first */
1555 del_policies_internal(this, this->my_addr, this->other_addr,
1556 my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
1557 POLICY_PRIORITY_DEFAULT, manual_prio);
1558
1559 /* check if we have to update a "dynamic" traffic selector */
1560 if (!me->ip_equals(me, this->my_addr) &&
1561 my_ts->is_host(my_ts, this->my_addr))
1562 {
1563 old_my_ts = my_ts->clone(my_ts);
1564 my_ts->set_address(my_ts, me);
1565 }
1566 if (!other->ip_equals(other, this->other_addr) &&
1567 other_ts->is_host(other_ts, this->other_addr))
1568 {
1569 old_other_ts = other_ts->clone(other_ts);
1570 other_ts->set_address(other_ts, other);
1571 }
1572
1573 /* we reinstall the virtual IP to handle interface roaming
1574 * correctly */
1575 vips->invoke_function(vips, reinstall_vip, me);
1576
1577 /* reinstall updated policies */
1578 install_policies_internal(this, me, other, my_ts, other_ts,
1579 &my_sa, &other_sa, POLICY_IPSEC,
1580 POLICY_PRIORITY_DEFAULT, manual_prio);
1581
1582 /* update fallback policies after the new policy is in place */
1583 if (manual_prio == 0)
1584 {
1585 del_policies_outbound(this, this->my_addr, this->other_addr,
1586 old_my_ts ?: my_ts,
1587 old_other_ts ?: other_ts,
1588 &my_sa, &other_sa, POLICY_DROP,
1589 POLICY_PRIORITY_FALLBACK, 0);
1590 install_policies_outbound(this, me, other, my_ts, other_ts,
1591 &my_sa, &other_sa, POLICY_DROP,
1592 POLICY_PRIORITY_FALLBACK, 0);
1593 }
1594 DESTROY_IF(old_my_ts);
1595 DESTROY_IF(old_other_ts);
1596 }
1597 enumerator->destroy(enumerator);
1598 }
1599 }
1600
1601 if (!transport_proxy_mode)
1602 {
1603 /* apply hosts */
1604 if (!me->equals(me, this->my_addr))
1605 {
1606 this->my_addr->destroy(this->my_addr);
1607 this->my_addr = me->clone(me);
1608 }
1609 if (!other->equals(other, this->other_addr))
1610 {
1611 this->other_addr->destroy(this->other_addr);
1612 this->other_addr = other->clone(other);
1613 }
1614 }
1615
1616 this->encap = encap;
1617 set_state(this, old);
1618
1619 return SUCCESS;
1620 }
1621
1622 METHOD(child_sa_t, destroy, void,
1623 private_child_sa_t *this)
1624 {
1625 enumerator_t *enumerator;
1626 traffic_selector_t *my_ts, *other_ts;
1627 policy_priority_t priority;
1628
1629 priority = this->trap ? POLICY_PRIORITY_ROUTED : POLICY_PRIORITY_DEFAULT;
1630
1631 set_state(this, CHILD_DESTROYING);
1632
1633 if (!this->config->has_option(this->config, OPT_NO_POLICIES))
1634 {
1635 ipsec_sa_cfg_t my_sa, other_sa;
1636 uint32_t manual_prio;
1637 bool del_outbound;
1638
1639 prepare_sa_cfg(this, &my_sa, &other_sa);
1640 manual_prio = this->config->get_manual_prio(this->config);
1641 del_outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) ||
1642 this->trap;
1643
1644 /* delete all policies in the kernel */
1645 enumerator = create_policy_enumerator(this);
1646 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1647 {
1648 if (del_outbound)
1649 {
1650 del_policies_outbound(this, this->my_addr,
1651 this->other_addr, my_ts, other_ts,
1652 &my_sa, &other_sa, POLICY_IPSEC,
1653 priority, manual_prio);
1654 }
1655 del_policies_inbound(this, this->my_addr, this->other_addr,
1656 my_ts, other_ts, &my_sa, &other_sa,
1657 POLICY_IPSEC, priority, manual_prio);
1658 if (!this->trap && manual_prio == 0 && require_policy_update() &&
1659 del_outbound)
1660 {
1661 del_policies_outbound(this, this->my_addr, this->other_addr,
1662 my_ts, other_ts, &my_sa, &other_sa,
1663 POLICY_DROP, POLICY_PRIORITY_FALLBACK, 0);
1664 }
1665 }
1666 enumerator->destroy(enumerator);
1667 }
1668
1669 /* delete SAs in the kernel, if they are set up */
1670 if (this->my_spi)
1671 {
1672 kernel_ipsec_sa_id_t id = {
1673 .src = this->other_addr,
1674 .dst = this->my_addr,
1675 .spi = this->my_spi,
1676 .proto = proto_ike2ip(this->protocol),
1677 .mark = mark_in_sa(this),
1678 };
1679 kernel_ipsec_del_sa_t sa = {
1680 .cpi = this->my_cpi,
1681 };
1682 charon->kernel->del_sa(charon->kernel, &id, &sa);
1683 }
1684 if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
1685 {
1686 kernel_ipsec_sa_id_t id = {
1687 .src = this->my_addr,
1688 .dst = this->other_addr,
1689 .spi = this->other_spi,
1690 .proto = proto_ike2ip(this->protocol),
1691 .mark = this->mark_out,
1692 };
1693 kernel_ipsec_del_sa_t sa = {
1694 .cpi = this->other_cpi,
1695 };
1696 charon->kernel->del_sa(charon->kernel, &id, &sa);
1697 }
1698
1699 if (this->reqid_allocated)
1700 {
1701 if (charon->kernel->release_reqid(charon->kernel,
1702 this->reqid, this->mark_in, this->mark_out) != SUCCESS)
1703 {
1704 DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
1705 }
1706 }
1707
1708 array_destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
1709 array_destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
1710 this->my_addr->destroy(this->my_addr);
1711 this->other_addr->destroy(this->other_addr);
1712 DESTROY_IF(this->proposal);
1713 this->config->destroy(this->config);
1714 chunk_clear(&this->encr_r);
1715 chunk_clear(&this->integ_r);
1716 free(this);
1717 }
1718
1719 /**
1720 * Get proxy address for one side, if any
1721 */
1722 static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local)
1723 {
1724 host_t *host = NULL;
1725 uint8_t mask;
1726 enumerator_t *enumerator;
1727 linked_list_t *ts_list, *list;
1728 traffic_selector_t *ts;
1729
1730 list = linked_list_create_with_items(ike, NULL);
1731 ts_list = config->get_traffic_selectors(config, local, NULL, list);
1732 list->destroy(list);
1733
1734 enumerator = ts_list->create_enumerator(ts_list);
1735 while (enumerator->enumerate(enumerator, &ts))
1736 {
1737 if (ts->is_host(ts, NULL) && ts->to_subnet(ts, &host, &mask))
1738 {
1739 DBG1(DBG_CHD, "%s address: %H is a transport mode proxy for %H",
1740 local ? "my" : "other", ike, host);
1741 break;
1742 }
1743 }
1744 enumerator->destroy(enumerator);
1745 ts_list->destroy_offset(ts_list, offsetof(traffic_selector_t, destroy));
1746
1747 if (!host)
1748 {
1749 host = ike->clone(ike);
1750 }
1751 return host;
1752 }
1753
1754 /**
1755 * Described in header.
1756 */
1757 child_sa_t * child_sa_create(host_t *me, host_t* other,
1758 child_cfg_t *config, uint32_t rekey, bool encap,
1759 u_int mark_in, u_int mark_out)
1760 {
1761 private_child_sa_t *this;
1762 static refcount_t unique_id = 0, unique_mark = 0;
1763 refcount_t mark = 0;
1764
1765 INIT(this,
1766 .public = {
1767 .get_name = _get_name,
1768 .get_reqid = _get_reqid,
1769 .get_unique_id = _get_unique_id,
1770 .get_config = _get_config,
1771 .get_state = _get_state,
1772 .set_state = _set_state,
1773 .get_outbound_state = _get_outbound_state,
1774 .get_spi = _get_spi,
1775 .get_cpi = _get_cpi,
1776 .get_protocol = _get_protocol,
1777 .set_protocol = _set_protocol,
1778 .get_mode = _get_mode,
1779 .set_mode = _set_mode,
1780 .get_proposal = _get_proposal,
1781 .set_proposal = _set_proposal,
1782 .get_lifetime = _get_lifetime,
1783 .get_installtime = _get_installtime,
1784 .get_usestats = _get_usestats,
1785 .get_mark = _get_mark,
1786 .has_encap = _has_encap,
1787 .get_ipcomp = _get_ipcomp,
1788 .set_ipcomp = _set_ipcomp,
1789 .get_close_action = _get_close_action,
1790 .set_close_action = _set_close_action,
1791 .get_dpd_action = _get_dpd_action,
1792 .set_dpd_action = _set_dpd_action,
1793 .alloc_spi = _alloc_spi,
1794 .alloc_cpi = _alloc_cpi,
1795 .install = _install,
1796 .register_outbound = _register_outbound,
1797 .install_outbound = _install_outbound,
1798 .remove_outbound = _remove_outbound,
1799 .set_rekey_spi = _set_rekey_spi,
1800 .get_rekey_spi = _get_rekey_spi,
1801 .update = _update,
1802 .set_policies = _set_policies,
1803 .install_policies = _install_policies,
1804 .create_ts_enumerator = _create_ts_enumerator,
1805 .create_policy_enumerator = _create_policy_enumerator,
1806 .destroy = _destroy,
1807 },
1808 .encap = encap,
1809 .ipcomp = IPCOMP_NONE,
1810 .state = CHILD_CREATED,
1811 .my_ts = array_create(0, 0),
1812 .other_ts = array_create(0, 0),
1813 .protocol = PROTO_NONE,
1814 .mode = MODE_TUNNEL,
1815 .close_action = config->get_close_action(config),
1816 .dpd_action = config->get_dpd_action(config),
1817 .reqid = config->get_reqid(config),
1818 .unique_id = ref_get(&unique_id),
1819 .mark_in = config->get_mark(config, TRUE),
1820 .mark_out = config->get_mark(config, FALSE),
1821 .install_time = time_monotonic(NULL),
1822 .policies_fwd_out = config->has_option(config, OPT_FWD_OUT_POLICIES),
1823 );
1824
1825 this->config = config;
1826 config->get_ref(config);
1827
1828 if (mark_in)
1829 {
1830 this->mark_in.value = mark_in;
1831 }
1832 if (mark_out)
1833 {
1834 this->mark_out.value = mark_out;
1835 }
1836
1837 if (MARK_IS_UNIQUE(this->mark_in.value) ||
1838 MARK_IS_UNIQUE(this->mark_out.value))
1839 {
1840 bool unique_dir;
1841
1842 unique_dir = this->mark_in.value == MARK_UNIQUE_DIR ||
1843 this->mark_out.value == MARK_UNIQUE_DIR;
1844
1845 if (!unique_dir)
1846 {
1847 mark = ref_get(&unique_mark);
1848 }
1849 if (MARK_IS_UNIQUE(this->mark_in.value))
1850 {
1851 if (unique_dir)
1852 {
1853 mark = ref_get(&unique_mark);
1854 }
1855 this->mark_in.value = mark;
1856 }
1857 if (MARK_IS_UNIQUE(this->mark_out.value))
1858 {
1859 if (unique_dir)
1860 {
1861 mark = ref_get(&unique_mark);
1862 }
1863 this->mark_out.value = mark;
1864 }
1865 }
1866
1867 if (!this->reqid)
1868 {
1869 /* reuse old reqid if we are rekeying an existing CHILD_SA. While the
1870 * reqid cache would find the same reqid for our selectors, this does
1871 * not work in a special case: If an SA is triggered by a trap policy,
1872 * but the negotiated SA gets narrowed, we still must reuse the same
1873 * reqid to successfully "trigger" the SA on the kernel level. Rekeying
1874 * such an SA requires an explicit reqid, as the cache currently knows
1875 * the original selectors only for that reqid. */
1876 if (rekey)
1877 {
1878 this->reqid = rekey;
1879 }
1880 else
1881 {
1882 this->reqid = charon->traps->find_reqid(charon->traps, config);
1883 }
1884 }
1885 else
1886 {
1887 this->static_reqid = TRUE;
1888 }
1889
1890 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
1891 if (config->get_mode(config) == MODE_TRANSPORT &&
1892 config->has_option(config, OPT_PROXY_MODE))
1893 {
1894 this->mode = MODE_TRANSPORT;
1895
1896 this->my_addr = get_proxy_addr(config, me, TRUE);
1897 this->other_addr = get_proxy_addr(config, other, FALSE);
1898 }
1899 else
1900 {
1901 this->my_addr = me->clone(me);
1902 this->other_addr = other->clone(other);
1903 }
1904 return &this->public;
1905 }