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