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