1ec57c94cce83f8be5b5a15cede4a87c06599a06
[strongswan.git] / src / charon / sa / child_sa.c
1 /*
2 * Copyright (C) 2006-2008 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2006 Daniel Roethlisberger
5 * Copyright (C) 2005 Jan Hutter
6 * Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * $Id$
19 */
20
21 #define _GNU_SOURCE
22 #include "child_sa.h"
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <daemon.h>
28
29 ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
30 "CREATED",
31 "ROUTED",
32 "INSTALLED",
33 "REKEYING",
34 "DELETING",
35 "DESTROYING",
36 );
37
38 typedef struct sa_policy_t sa_policy_t;
39
40 /**
41 * Struct used to store information for a policy. This
42 * is needed since we must provide all this information
43 * for deleting a policy...
44 */
45 struct sa_policy_t {
46 /**
47 * Traffic selector for us
48 */
49 traffic_selector_t *my_ts;
50
51 /**
52 * Traffic selector for other
53 */
54 traffic_selector_t *other_ts;
55 };
56
57 typedef struct private_child_sa_t private_child_sa_t;
58
59 /**
60 * Private data of a child_sa_t object.
61 */
62 struct private_child_sa_t {
63 /**
64 * Public interface of child_sa_t.
65 */
66 child_sa_t public;
67
68 struct {
69 /** address of peer */
70 host_t *addr;
71 /** id of peer */
72 identification_t *id;
73 /** actual used SPI, 0 if unused */
74 u_int32_t spi;
75 /** Compression Parameter Index (CPI) used, 0 if unused */
76 u_int16_t cpi;
77 } me, other;
78
79 /**
80 * Allocated SPI for a ESP proposal candidates
81 */
82 u_int32_t alloc_esp_spi;
83
84 /**
85 * Allocated SPI for a AH proposal candidates
86 */
87 u_int32_t alloc_ah_spi;
88
89 /**
90 * Protocol used to protect this SA, ESP|AH
91 */
92 protocol_id_t protocol;
93
94 /**
95 * List containing sa_policy_t objects
96 */
97 linked_list_t *policies;
98
99 /**
100 * Separate list for local traffic selectors
101 */
102 linked_list_t *my_ts;
103
104 /**
105 * Separate list for remote traffic selectors
106 */
107 linked_list_t *other_ts;
108
109 /**
110 * reqid used for this child_sa
111 */
112 u_int32_t reqid;
113
114 /**
115 * encryption algorithm used for this SA
116 */
117 u_int16_t enc_alg;
118
119 /**
120 * Encryption key data
121 */
122 chunk_t enc_key;
123
124 /**
125 * integrity protection algorithm used for this SA
126 */
127 u_int16_t int_alg;
128
129 /**
130 * integrity key data
131 */
132 chunk_t int_key;
133
134 /**
135 * time, on which SA was installed
136 */
137 time_t install_time;
138
139 /**
140 * absolute time when rekeying is scheduled
141 */
142 time_t rekey_time;
143
144 /**
145 * state of the CHILD_SA
146 */
147 child_sa_state_t state;
148
149 /**
150 * Specifies if UDP encapsulation is enabled (NAT traversal)
151 */
152 bool encap;
153
154 /**
155 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
156 */
157 ipcomp_transform_t ipcomp;
158
159 /**
160 * TRUE if we allocated (or tried to allocate) a CPI
161 */
162 bool cpi_allocated;
163
164 /**
165 * mode this SA uses, tunnel/transport
166 */
167 ipsec_mode_t mode;
168
169 /**
170 * virtual IP assigned to local host
171 */
172 host_t *virtual_ip;
173
174 /**
175 * config used to create this child
176 */
177 child_cfg_t *config;
178
179 /**
180 * cached interface name for iptables
181 */
182 char *iface;
183 };
184
185 typedef struct keylen_entry_t keylen_entry_t;
186
187 /**
188 * Implicit key length for an algorithm
189 */
190 struct keylen_entry_t {
191 /** IKEv2 algorithm identifier */
192 int algo;
193 /** key length in bits */
194 int len;
195 };
196
197 #define END_OF_LIST -1
198
199 /**
200 * Keylen for encryption algos
201 */
202 keylen_entry_t keylen_enc[] = {
203 {ENCR_DES, 64},
204 {ENCR_3DES, 192},
205 {END_OF_LIST, 0}
206 };
207
208 /**
209 * Keylen for integrity algos
210 */
211 keylen_entry_t keylen_int[] = {
212 {AUTH_HMAC_MD5_96, 128},
213 {AUTH_HMAC_SHA1_96, 160},
214 {AUTH_HMAC_SHA2_256_128, 256},
215 {AUTH_HMAC_SHA2_384_192, 384},
216 {AUTH_HMAC_SHA2_512_256, 512},
217 {AUTH_AES_XCBC_96, 128},
218 {END_OF_LIST, 0}
219 };
220
221 /**
222 * Lookup key length of an algorithm
223 */
224 static int lookup_keylen(keylen_entry_t *list, int algo)
225 {
226 while (list->algo != END_OF_LIST)
227 {
228 if (algo == list->algo)
229 {
230 return list->len;
231 }
232 list++;
233 }
234 return 0;
235 }
236
237 /**
238 * Implementation of child_sa_t.get_name.
239 */
240 static char *get_name(private_child_sa_t *this)
241 {
242 return this->config->get_name(this->config);
243 }
244
245 /**
246 * Implements child_sa_t.get_reqid
247 */
248 static u_int32_t get_reqid(private_child_sa_t *this)
249 {
250 return this->reqid;
251 }
252
253 /**
254 * Implements child_sa_t.get_spi
255 */
256 u_int32_t get_spi(private_child_sa_t *this, bool inbound)
257 {
258 if (inbound)
259 {
260 return this->me.spi;
261 }
262 return this->other.spi;
263 }
264
265 /**
266 * Implements child_sa_t.get_cpi
267 */
268 u_int16_t get_cpi(private_child_sa_t *this, bool inbound)
269 {
270 if (inbound)
271 {
272 return this->me.cpi;
273 }
274 return this->other.cpi;
275 }
276
277 /**
278 * Implements child_sa_t.get_protocol
279 */
280 protocol_id_t get_protocol(private_child_sa_t *this)
281 {
282 return this->protocol;
283 }
284
285 /**
286 * Implements child_sa_t.get_state
287 */
288 static child_sa_state_t get_state(private_child_sa_t *this)
289 {
290 return this->state;
291 }
292
293 /**
294 * Implements child_sa_t.get_config
295 */
296 static child_cfg_t* get_config(private_child_sa_t *this)
297 {
298 return this->config;
299 }
300
301 /**
302 * Implementation of child_sa_t.get_stats.
303 */
304 static void get_stats(private_child_sa_t *this, ipsec_mode_t *mode,
305 encryption_algorithm_t *encr_algo, chunk_t *encr_key,
306 integrity_algorithm_t *int_algo, chunk_t *int_key,
307 u_int32_t *rekey, u_int32_t *use_in, u_int32_t *use_out,
308 u_int32_t *use_fwd)
309 {
310 sa_policy_t *policy;
311 iterator_t *iterator;
312 u_int32_t in = 0, out = 0, fwd = 0, time;
313
314 iterator = this->policies->create_iterator(this->policies, TRUE);
315 while (iterator->iterate(iterator, (void**)&policy))
316 {
317
318 if (charon->kernel_interface->query_policy(charon->kernel_interface,
319 policy->other_ts, policy->my_ts, POLICY_IN, &time) == SUCCESS)
320 {
321 in = max(in, time);
322 }
323 if (charon->kernel_interface->query_policy(charon->kernel_interface,
324 policy->my_ts, policy->other_ts, POLICY_OUT, &time) == SUCCESS)
325 {
326 out = max(out, time);
327 }
328 if (charon->kernel_interface->query_policy(charon->kernel_interface,
329 policy->other_ts, policy->my_ts, POLICY_FWD, &time) == SUCCESS)
330 {
331 fwd = max(fwd, time);
332 }
333 }
334 iterator->destroy(iterator);
335
336 *mode = this->mode;
337 *encr_algo = this->enc_alg;
338 *encr_key = this->enc_key;
339 *int_algo = this->int_alg;
340 *int_key = this->int_key;
341 *rekey = this->rekey_time;
342 *use_in = in;
343 *use_out = out;
344 *use_fwd = fwd;
345 }
346
347 /**
348 * Run the up/down script
349 */
350 static void updown(private_child_sa_t *this, bool up)
351 {
352 sa_policy_t *policy;
353 iterator_t *iterator;
354 char *script;
355
356 script = this->config->get_updown(this->config);
357
358 if (script == NULL)
359 {
360 return;
361 }
362
363 iterator = this->policies->create_iterator(this->policies, TRUE);
364 while (iterator->iterate(iterator, (void**)&policy))
365 {
366 char command[1024];
367 char *my_client, *other_client, *my_client_mask, *other_client_mask;
368 char *pos, *virtual_ip;
369 FILE *shell;
370
371 /* get subnet/bits from string */
372 asprintf(&my_client, "%R", policy->my_ts);
373 pos = strchr(my_client, '/');
374 *pos = '\0';
375 my_client_mask = pos + 1;
376 pos = strchr(my_client_mask, '[');
377 if (pos)
378 {
379 *pos = '\0';
380 }
381 asprintf(&other_client, "%R", policy->other_ts);
382 pos = strchr(other_client, '/');
383 *pos = '\0';
384 other_client_mask = pos + 1;
385 pos = strchr(other_client_mask, '[');
386 if (pos)
387 {
388 *pos = '\0';
389 }
390
391 if (this->virtual_ip)
392 {
393 asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ",
394 this->virtual_ip);
395 }
396 else
397 {
398 asprintf(&virtual_ip, "");
399 }
400
401 /* we cache the iface name, as it may not be available when
402 * the SA gets deleted */
403 if (up)
404 {
405 free(this->iface);
406 this->iface = charon->kernel_interface->get_interface(
407 charon->kernel_interface, this->me.addr);
408 }
409
410 /* build the command with all env variables.
411 * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing
412 */
413 snprintf(command, sizeof(command),
414 "2>&1 "
415 "PLUTO_VERSION='1.1' "
416 "PLUTO_VERB='%s%s%s' "
417 "PLUTO_CONNECTION='%s' "
418 "PLUTO_INTERFACE='%s' "
419 "PLUTO_REQID='%u' "
420 "PLUTO_ME='%H' "
421 "PLUTO_MY_ID='%D' "
422 "PLUTO_MY_CLIENT='%s/%s' "
423 "PLUTO_MY_CLIENT_NET='%s' "
424 "PLUTO_MY_CLIENT_MASK='%s' "
425 "PLUTO_MY_PORT='%u' "
426 "PLUTO_MY_PROTOCOL='%u' "
427 "PLUTO_PEER='%H' "
428 "PLUTO_PEER_ID='%D' "
429 "PLUTO_PEER_CLIENT='%s/%s' "
430 "PLUTO_PEER_CLIENT_NET='%s' "
431 "PLUTO_PEER_CLIENT_MASK='%s' "
432 "PLUTO_PEER_PORT='%u' "
433 "PLUTO_PEER_PROTOCOL='%u' "
434 "%s"
435 "%s"
436 "%s",
437 up ? "up" : "down",
438 policy->my_ts->is_host(policy->my_ts,
439 this->me.addr) ? "-host" : "-client",
440 this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-v6",
441 this->config->get_name(this->config),
442 this->iface ? this->iface : "unknown",
443 this->reqid,
444 this->me.addr,
445 this->me.id,
446 my_client, my_client_mask,
447 my_client, my_client_mask,
448 policy->my_ts->get_from_port(policy->my_ts),
449 policy->my_ts->get_protocol(policy->my_ts),
450 this->other.addr,
451 this->other.id,
452 other_client, other_client_mask,
453 other_client, other_client_mask,
454 policy->other_ts->get_from_port(policy->other_ts),
455 policy->other_ts->get_protocol(policy->other_ts),
456 virtual_ip,
457 this->config->get_hostaccess(this->config) ?
458 "PLUTO_HOST_ACCESS='1' " : "",
459 script);
460 free(my_client);
461 free(other_client);
462 free(virtual_ip);
463
464 DBG3(DBG_CHD, "running updown script: %s", command);
465 shell = popen(command, "r");
466
467 if (shell == NULL)
468 {
469 DBG1(DBG_CHD, "could not execute updown script '%s'", script);
470 return;
471 }
472
473 while (TRUE)
474 {
475 char resp[128];
476
477 if (fgets(resp, sizeof(resp), shell) == NULL)
478 {
479 if (ferror(shell))
480 {
481 DBG1(DBG_CHD, "error reading output from updown script");
482 return;
483 }
484 else
485 {
486 break;
487 }
488 }
489 else
490 {
491 char *e = resp + strlen(resp);
492 if (e > resp && e[-1] == '\n')
493 { /* trim trailing '\n' */
494 e[-1] = '\0';
495 }
496 DBG1(DBG_CHD, "updown: %s", resp);
497 }
498 }
499 pclose(shell);
500 }
501 iterator->destroy(iterator);
502 }
503
504 /**
505 * Implements child_sa_t.set_state
506 */
507 static void set_state(private_child_sa_t *this, child_sa_state_t state)
508 {
509 if (state == CHILD_INSTALLED)
510 {
511 updown(this, TRUE);
512 }
513 charon->bus->child_state_change(charon->bus, &this->public, state);
514 this->state = state;
515 }
516
517 /**
518 * Allocate SPI for a single proposal
519 */
520 static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
521 {
522 protocol_id_t protocol = proposal->get_protocol(proposal);
523
524 if (protocol == PROTO_AH)
525 {
526 /* get a new spi for AH, if not already done */
527 if (this->alloc_ah_spi == 0)
528 {
529 if (charon->kernel_interface->get_spi(
530 charon->kernel_interface,
531 this->other.addr, this->me.addr,
532 PROTO_AH, this->reqid,
533 &this->alloc_ah_spi) != SUCCESS)
534 {
535 return FAILED;
536 }
537 }
538 proposal->set_spi(proposal, this->alloc_ah_spi);
539 }
540 if (protocol == PROTO_ESP)
541 {
542 /* get a new spi for ESP, if not already done */
543 if (this->alloc_esp_spi == 0)
544 {
545 if (charon->kernel_interface->get_spi(
546 charon->kernel_interface,
547 this->other.addr, this->me.addr,
548 PROTO_ESP, this->reqid,
549 &this->alloc_esp_spi) != SUCCESS)
550 {
551 return FAILED;
552 }
553 }
554 proposal->set_spi(proposal, this->alloc_esp_spi);
555 }
556 return SUCCESS;
557 }
558
559
560 /**
561 * Implements child_sa_t.alloc
562 */
563 static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
564 {
565 iterator_t *iterator;
566 proposal_t *proposal;
567
568 /* iterator through proposals to update spis */
569 iterator = proposals->create_iterator(proposals, TRUE);
570 while(iterator->iterate(iterator, (void**)&proposal))
571 {
572 if (alloc_proposal(this, proposal) != SUCCESS)
573 {
574 iterator->destroy(iterator);
575 return FAILED;
576 }
577 }
578 iterator->destroy(iterator);
579 return SUCCESS;
580 }
581
582 static status_t install(private_child_sa_t *this, proposal_t *proposal,
583 ipsec_mode_t mode, prf_plus_t *prf_plus, bool mine)
584 {
585 u_int32_t spi, cpi, soft, hard;
586 host_t *src, *dst;
587 status_t status;
588 int add_keymat;
589 u_int16_t enc_size, int_size;
590
591 this->protocol = proposal->get_protocol(proposal);
592
593 /* now we have to decide which spi to use. Use self allocated, if "mine",
594 * or the one in the proposal, if not "mine" (others). Additionally,
595 * source and dest host switch depending on the role */
596 if (mine)
597 {
598 /* if we have allocated SPIs for AH and ESP, we must delete the unused
599 * one. */
600 if (this->protocol == PROTO_ESP)
601 {
602 this->me.spi = this->alloc_esp_spi;
603 if (this->alloc_ah_spi)
604 {
605 charon->kernel_interface->del_sa(charon->kernel_interface,
606 this->me.addr, this->alloc_ah_spi, PROTO_AH);
607 }
608 }
609 else
610 {
611 this->me.spi = this->alloc_ah_spi;
612 if (this->alloc_esp_spi)
613 {
614 charon->kernel_interface->del_sa(charon->kernel_interface,
615 this->me.addr, this->alloc_esp_spi, PROTO_ESP);
616 }
617 }
618 spi = this->me.spi;
619 dst = this->me.addr;
620 src = this->other.addr;
621 }
622 else
623 {
624 this->other.spi = proposal->get_spi(proposal);
625 spi = this->other.spi;
626 src = this->me.addr;
627 dst = this->other.addr;
628 }
629
630 DBG2(DBG_CHD, "adding %s %N SA", mine ? "inbound" : "outbound",
631 protocol_id_names, this->protocol);
632
633 /* select encryption algo, derive key */
634 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
635 &this->enc_alg, &enc_size))
636 {
637 DBG2(DBG_CHD, " using %N for encryption",
638 encryption_algorithm_names, this->enc_alg);
639 }
640 if (this->enc_alg != ENCR_UNDEFINED)
641 {
642 if (!enc_size)
643 {
644 enc_size = lookup_keylen(keylen_enc, this->enc_alg);
645 }
646 if (!enc_size)
647 {
648 DBG1(DBG_CHD, "no keylenth defined for %N",
649 encryption_algorithm_names, this->enc_alg);
650 return FAILED;
651 }
652 /* CCM/GCM needs additional keymat */
653 switch (this->enc_alg)
654 {
655 case ENCR_AES_CCM_ICV8:
656 case ENCR_AES_CCM_ICV12:
657 case ENCR_AES_CCM_ICV16:
658 enc_size += 24;
659 break;
660 case ENCR_AES_GCM_ICV8:
661 case ENCR_AES_GCM_ICV12:
662 case ENCR_AES_GCM_ICV16:
663 enc_size += 32;
664 break;
665 default:
666 add_keymat = 0;
667 break;
668 }
669 prf_plus->allocate_bytes(prf_plus, enc_size / 8, &this->enc_key);
670 }
671
672 /* select integrity algo, derive key */
673 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
674 &this->int_alg, &int_size))
675 {
676 DBG2(DBG_CHD, " using %N for integrity",
677 integrity_algorithm_names, this->int_alg);
678 }
679 if (this->int_alg != AUTH_UNDEFINED)
680 {
681 if (!int_size)
682 {
683 int_size = lookup_keylen(keylen_int, this->int_alg);
684 }
685 if (!enc_size)
686 {
687 DBG1(DBG_CHD, "no keylenth defined for %N",
688 integrity_algorithm_names, this->int_alg);
689 return FAILED;
690 }
691 prf_plus->allocate_bytes(prf_plus, int_size / 8, &this->int_key);
692 }
693
694 /* send SA down to the kernel */
695 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
696
697 if (this->ipcomp != IPCOMP_NONE)
698 {
699 /* we install an additional IPComp SA */
700 cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi));
701 charon->kernel_interface->add_sa(charon->kernel_interface,
702 src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
703 ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
704 mode, this->ipcomp, FALSE, mine);
705 }
706
707 soft = this->config->get_lifetime(this->config, TRUE);
708 hard = this->config->get_lifetime(this->config, FALSE);
709 status = charon->kernel_interface->add_sa(charon->kernel_interface,
710 src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard,
711 this->enc_alg, this->enc_key, this->int_alg, this->int_key,
712 mode, IPCOMP_NONE, this->encap, mine);
713
714 this->install_time = time(NULL);
715 this->rekey_time = this->install_time + soft;
716 return status;
717 }
718
719 static status_t add(private_child_sa_t *this, proposal_t *proposal,
720 ipsec_mode_t mode, prf_plus_t *prf_plus)
721 {
722 u_int32_t outbound_spi, inbound_spi;
723
724 /* backup outbound spi, as alloc overwrites it */
725 outbound_spi = proposal->get_spi(proposal);
726
727 /* get SPIs inbound SAs */
728 if (alloc_proposal(this, proposal) != SUCCESS)
729 {
730 return FAILED;
731 }
732 inbound_spi = proposal->get_spi(proposal);
733
734 /* install inbound SAs */
735 if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
736 {
737 return FAILED;
738 }
739
740 /* install outbound SAs, restore spi*/
741 proposal->set_spi(proposal, outbound_spi);
742 if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
743 {
744 return FAILED;
745 }
746 proposal->set_spi(proposal, inbound_spi);
747
748 return SUCCESS;
749 }
750
751 static status_t update(private_child_sa_t *this, proposal_t *proposal,
752 ipsec_mode_t mode, prf_plus_t *prf_plus)
753 {
754 u_int32_t inbound_spi;
755
756 /* backup received spi, as install() overwrites it */
757 inbound_spi = proposal->get_spi(proposal);
758
759 /* install outbound SAs */
760 if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
761 {
762 return FAILED;
763 }
764
765 /* restore spi */
766 proposal->set_spi(proposal, inbound_spi);
767 /* install inbound SAs */
768 if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
769 {
770 return FAILED;
771 }
772
773 return SUCCESS;
774 }
775
776 static status_t add_policies(private_child_sa_t *this,
777 linked_list_t *my_ts_list, linked_list_t *other_ts_list,
778 ipsec_mode_t mode, protocol_id_t proto)
779 {
780 iterator_t *my_iter, *other_iter;
781 traffic_selector_t *my_ts, *other_ts;
782 /* use low prio for ROUTED policies */
783 bool high_prio = (this->state != CHILD_CREATED);
784
785 if (this->protocol == PROTO_NONE)
786 { /* update if not set yet */
787 this->protocol = proto;
788 }
789
790 /* iterate over both lists */
791 my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
792 other_iter = other_ts_list->create_iterator(other_ts_list, TRUE);
793 while (my_iter->iterate(my_iter, (void**)&my_ts))
794 {
795 other_iter->reset(other_iter);
796 while (other_iter->iterate(other_iter, (void**)&other_ts))
797 {
798 /* set up policies for every entry in my_ts_list to every entry in other_ts_list */
799 status_t status;
800 sa_policy_t *policy;
801
802 if (my_ts->get_type(my_ts) != other_ts->get_type(other_ts))
803 {
804 DBG2(DBG_CHD,
805 "CHILD_SA policy uses two different IP families - ignored");
806 continue;
807 }
808
809 /* only set up policies if protocol matches, or if one is zero (any) */
810 if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts) &&
811 my_ts->get_protocol(my_ts) && other_ts->get_protocol(other_ts))
812 {
813 DBG2(DBG_CHD,
814 "CHILD_SA policy uses two different protocols - ignored");
815 continue;
816 }
817
818 /* install 3 policies: out, in and forward */
819 status = charon->kernel_interface->add_policy(charon->kernel_interface,
820 this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
821 this->protocol, this->reqid, high_prio, mode, this->ipcomp);
822
823 status |= charon->kernel_interface->add_policy(charon->kernel_interface,
824 this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
825 this->protocol, this->reqid, high_prio, mode, this->ipcomp);
826
827 status |= charon->kernel_interface->add_policy(charon->kernel_interface,
828 this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
829 this->protocol, this->reqid, high_prio, mode, this->ipcomp);
830
831 if (status != SUCCESS)
832 {
833 my_iter->destroy(my_iter);
834 other_iter->destroy(other_iter);
835 return status;
836 }
837
838 /* store policy to delete/update them later */
839 policy = malloc_thing(sa_policy_t);
840 policy->my_ts = my_ts->clone(my_ts);
841 policy->other_ts = other_ts->clone(other_ts);
842 this->policies->insert_last(this->policies, policy);
843 /* add to separate list to query them via get_*_traffic_selectors() */
844 this->my_ts->insert_last(this->my_ts, policy->my_ts);
845 this->other_ts->insert_last(this->other_ts, policy->other_ts);
846 }
847 }
848 my_iter->destroy(my_iter);
849 other_iter->destroy(other_iter);
850
851 /* switch to routed state if no SAD entry set up */
852 if (this->state == CHILD_CREATED)
853 {
854 set_state(this, CHILD_ROUTED);
855 }
856 /* needed to update hosts */
857 this->mode = mode;
858 return SUCCESS;
859 }
860
861 /**
862 * Implementation of child_sa_t.get_traffic_selectors.
863 */
864 static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
865 {
866 if (local)
867 {
868 return this->my_ts;
869 }
870 return this->other_ts;
871 }
872
873 /**
874 * Implementation of child_sa_t.get_use_time
875 */
876 static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time)
877 {
878 iterator_t *iterator;
879 sa_policy_t *policy;
880 status_t status = FAILED;
881
882 *use_time = UNDEFINED_TIME;
883
884 iterator = this->policies->create_iterator(this->policies, TRUE);
885 while (iterator->iterate(iterator, (void**)&policy))
886 {
887 if (inbound)
888 {
889 time_t in = UNDEFINED_TIME, fwd = UNDEFINED_TIME;
890
891 status = charon->kernel_interface->query_policy(
892 charon->kernel_interface,
893 policy->other_ts, policy->my_ts,
894 POLICY_IN, (u_int32_t*)&in);
895 status |= charon->kernel_interface->query_policy(
896 charon->kernel_interface,
897 policy->other_ts, policy->my_ts,
898 POLICY_FWD, (u_int32_t*)&fwd);
899 *use_time = max(in, fwd);
900 }
901 else
902 {
903 status = charon->kernel_interface->query_policy(
904 charon->kernel_interface,
905 policy->my_ts, policy->other_ts,
906 POLICY_OUT, (u_int32_t*)use_time);
907 }
908 }
909 iterator->destroy(iterator);
910 return status;
911 }
912
913 /**
914 * Implementation of child_sa_t.update_hosts.
915 */
916 static status_t update_hosts(private_child_sa_t *this,
917 host_t *me, host_t *other, bool encap)
918 {
919 /* anything changed at all? */
920 if (me->equals(me, this->me.addr) &&
921 other->equals(other, this->other.addr) && this->encap == encap)
922 {
923 return SUCCESS;
924 }
925 /* run updown script to remove iptables rules */
926 updown(this, FALSE);
927
928 this->encap = encap;
929
930 if (this->ipcomp != IPCOMP_NONE)
931 {
932 /* update our (initator) IPComp SA */
933 charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->me.cpi)),
934 IPPROTO_COMP, this->other.addr, this->me.addr, other, me, FALSE);
935 /* update his (responder) IPComp SA */
936 charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->other.cpi)),
937 IPPROTO_COMP, this->me.addr, this->other.addr, me, other, FALSE);
938 }
939
940 /* update our (initator) SA */
941 charon->kernel_interface->update_sa(charon->kernel_interface, this->me.spi,
942 this->protocol, this->other.addr, this->me.addr, other, me, encap);
943 /* update his (responder) SA */
944 charon->kernel_interface->update_sa(charon->kernel_interface, this->other.spi,
945 this->protocol, this->me.addr, this->other.addr, me, other, encap);
946
947 /* update policies */
948 if (!me->ip_equals(me, this->me.addr) ||
949 !other->ip_equals(other, this->other.addr))
950 {
951 iterator_t *iterator;
952 sa_policy_t *policy;
953
954 /* always use high priorities, as hosts getting updated are INSTALLED */
955 iterator = this->policies->create_iterator(this->policies, TRUE);
956 while (iterator->iterate(iterator, (void**)&policy))
957 {
958 /* remove old policies first */
959 charon->kernel_interface->del_policy(charon->kernel_interface,
960 policy->my_ts, policy->other_ts, POLICY_OUT);
961 charon->kernel_interface->del_policy(charon->kernel_interface,
962 policy->other_ts, policy->my_ts, POLICY_IN);
963 charon->kernel_interface->del_policy(charon->kernel_interface,
964 policy->other_ts, policy->my_ts, POLICY_FWD);
965
966 /* check whether we have to update a "dynamic" traffic selector */
967 if (!me->ip_equals(me, this->me.addr) &&
968 policy->my_ts->is_host(policy->my_ts, this->me.addr))
969 {
970 policy->my_ts->set_address(policy->my_ts, me);
971 }
972 if (!other->ip_equals(other, this->other.addr) &&
973 policy->other_ts->is_host(policy->other_ts, this->other.addr))
974 {
975 policy->other_ts->set_address(policy->other_ts, other);
976 }
977
978 /* we reinstall the virtual IP to handle interface roaming
979 * correctly */
980 if (this->virtual_ip)
981 {
982 charon->kernel_interface->del_ip(charon->kernel_interface,
983 this->virtual_ip);
984 charon->kernel_interface->add_ip(charon->kernel_interface,
985 this->virtual_ip, me);
986 }
987
988 /* reinstall updated policies */
989 charon->kernel_interface->add_policy(charon->kernel_interface,
990 me, other, policy->my_ts, policy->other_ts, POLICY_OUT,
991 this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
992 charon->kernel_interface->add_policy(charon->kernel_interface,
993 other, me, policy->other_ts, policy->my_ts, POLICY_IN,
994 this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
995 charon->kernel_interface->add_policy(charon->kernel_interface,
996 other, me, policy->other_ts, policy->my_ts, POLICY_FWD,
997 this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
998 }
999 iterator->destroy(iterator);
1000 }
1001
1002 /* apply hosts */
1003 if (!me->equals(me, this->me.addr))
1004 {
1005 this->me.addr->destroy(this->me.addr);
1006 this->me.addr = me->clone(me);
1007 }
1008 if (!other->equals(other, this->other.addr))
1009 {
1010 this->other.addr->destroy(this->other.addr);
1011 this->other.addr = other->clone(other);
1012 }
1013
1014 /* install new iptables rules */
1015 updown(this, TRUE);
1016
1017 return SUCCESS;
1018 }
1019
1020 /**
1021 * Implementation of child_sa_t.set_virtual_ip.
1022 */
1023 static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
1024 {
1025 this->virtual_ip = ip->clone(ip);
1026 }
1027
1028 /**
1029 * Implementation of child_sa_t.activate_ipcomp.
1030 */
1031 static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
1032 u_int16_t other_cpi)
1033 {
1034 this->ipcomp = ipcomp;
1035 this->other.cpi = other_cpi;
1036 }
1037
1038 /**
1039 * Implementation of child_sa_t.allocate_cpi.
1040 */
1041 static u_int16_t allocate_cpi(private_child_sa_t *this)
1042 {
1043 if (!this->cpi_allocated)
1044 {
1045 charon->kernel_interface->get_cpi(charon->kernel_interface,
1046 this->other.addr, this->me.addr, this->reqid, &this->me.cpi);
1047 this->cpi_allocated = TRUE;
1048 }
1049 return this->me.cpi;
1050 }
1051
1052 /**
1053 * Implementation of child_sa_t.destroy.
1054 */
1055 static void destroy(private_child_sa_t *this)
1056 {
1057 sa_policy_t *policy;
1058
1059 if (this->state == CHILD_DELETING || this->state == CHILD_INSTALLED)
1060 {
1061 updown(this, FALSE);
1062 }
1063
1064 set_state(this, CHILD_DESTROYING);
1065
1066 /* delete SAs in the kernel, if they are set up */
1067 if (this->me.spi)
1068 {
1069 charon->kernel_interface->del_sa(charon->kernel_interface,
1070 this->me.addr, this->me.spi, this->protocol);
1071 }
1072 if (this->alloc_esp_spi && this->alloc_esp_spi != this->me.spi)
1073 {
1074 charon->kernel_interface->del_sa(charon->kernel_interface,
1075 this->me.addr, this->alloc_esp_spi, PROTO_ESP);
1076 }
1077 if (this->alloc_ah_spi && this->alloc_ah_spi != this->me.spi)
1078 {
1079 charon->kernel_interface->del_sa(charon->kernel_interface,
1080 this->me.addr, this->alloc_ah_spi, PROTO_AH);
1081 }
1082 if (this->other.spi)
1083 {
1084 charon->kernel_interface->del_sa(charon->kernel_interface,
1085 this->other.addr, this->other.spi, this->protocol);
1086 }
1087 if (this->me.cpi)
1088 {
1089 charon->kernel_interface->del_sa(charon->kernel_interface,
1090 this->me.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP);
1091 }
1092 if (this->other.cpi)
1093 {
1094 charon->kernel_interface->del_sa(charon->kernel_interface,
1095 this->other.addr, htonl(ntohs(this->other.cpi)), IPPROTO_COMP);
1096 }
1097
1098 /* delete all policies in the kernel */
1099 while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
1100 {
1101 /* let rekeyed policies, as they are used by another child_sa */
1102 charon->kernel_interface->del_policy(charon->kernel_interface,
1103 policy->my_ts, policy->other_ts,
1104 POLICY_OUT);
1105
1106 charon->kernel_interface->del_policy(charon->kernel_interface,
1107 policy->other_ts, policy->my_ts,
1108 POLICY_IN);
1109
1110 charon->kernel_interface->del_policy(charon->kernel_interface,
1111 policy->other_ts, policy->my_ts,
1112 POLICY_FWD);
1113 policy->my_ts->destroy(policy->my_ts);
1114 policy->other_ts->destroy(policy->other_ts);
1115 free(policy);
1116 }
1117 this->policies->destroy(this->policies);
1118
1119 chunk_clear(&this->enc_key);
1120 chunk_clear(&this->int_key);
1121 this->my_ts->destroy(this->my_ts);
1122 this->other_ts->destroy(this->other_ts);
1123 this->me.addr->destroy(this->me.addr);
1124 this->other.addr->destroy(this->other.addr);
1125 this->me.id->destroy(this->me.id);
1126 this->other.id->destroy(this->other.id);
1127 this->config->destroy(this->config);
1128 free(this->iface);
1129 DESTROY_IF(this->virtual_ip);
1130 free(this);
1131 }
1132
1133 /*
1134 * Described in header.
1135 */
1136 child_sa_t * child_sa_create(host_t *me, host_t* other,
1137 identification_t *my_id, identification_t *other_id,
1138 child_cfg_t *config, u_int32_t rekey, bool encap)
1139 {
1140 static u_int32_t reqid = 0;
1141 private_child_sa_t *this = malloc_thing(private_child_sa_t);
1142
1143 /* public functions */
1144 this->public.get_name = (char*(*)(child_sa_t*))get_name;
1145 this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
1146 this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
1147 this->public.get_cpi = (u_int16_t(*)(child_sa_t*, bool))get_cpi;
1148 this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
1149 this->public.get_stats = (void(*)(child_sa_t*, ipsec_mode_t*,encryption_algorithm_t*,chunk_t*,integrity_algorithm_t*,chunk_t*,u_int32_t*,u_int32_t*,u_int32_t*,u_int32_t*))get_stats;
1150 this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
1151 this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))add;
1152 this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))update;
1153 this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,bool))update_hosts;
1154 this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,ipsec_mode_t,protocol_id_t))add_policies;
1155 this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
1156 this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
1157 this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
1158 this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
1159 this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
1160 this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp;
1161 this->public.allocate_cpi = (u_int16_t(*)(child_sa_t*))allocate_cpi;
1162 this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
1163 this->public.destroy = (void(*)(child_sa_t*))destroy;
1164
1165 /* private data */
1166 this->me.addr = me->clone(me);
1167 this->other.addr = other->clone(other);
1168 this->me.id = my_id->clone(my_id);
1169 this->other.id = other_id->clone(other_id);
1170 this->me.spi = 0;
1171 this->me.cpi = 0;
1172 this->other.spi = 0;
1173 this->other.cpi = 0;
1174 this->alloc_ah_spi = 0;
1175 this->alloc_esp_spi = 0;
1176 this->encap = encap;
1177 this->cpi_allocated = FALSE;
1178 this->ipcomp = IPCOMP_NONE;
1179 this->state = CHILD_CREATED;
1180 /* reuse old reqid if we are rekeying an existing CHILD_SA */
1181 this->reqid = rekey ? rekey : ++reqid;
1182 this->enc_alg = ENCR_UNDEFINED;
1183 this->enc_key = chunk_empty;
1184 this->int_alg = AUTH_UNDEFINED;
1185 this->int_key = chunk_empty;
1186 this->policies = linked_list_create();
1187 this->my_ts = linked_list_create();
1188 this->other_ts = linked_list_create();
1189 this->protocol = PROTO_NONE;
1190 this->mode = MODE_TUNNEL;
1191 this->virtual_ip = NULL;
1192 this->iface = NULL;
1193 this->config = config;
1194 config->get_ref(config);
1195
1196 return &this->public;
1197 }