passing chunks, not prf+, to kernel interface
[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 * key size of enc_alg
121 */
122 u_int16_t enc_size;
123
124 /**
125 * integrity protection algorithm used for this SA
126 */
127 u_int16_t int_alg;
128
129 /**
130 * key size of int_alg
131 */
132 u_int16_t int_size;
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, size_t *encr_len,
306 integrity_algorithm_t *int_algo, size_t *int_len,
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_len = this->enc_size;
339 *int_algo = this->int_alg;
340 *int_len = this->int_size;
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 chunk_t enc_key = chunk_empty, int_key = chunk_empty;
589 int add_keymat;
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, &this->enc_size))
636 {
637 DBG2(DBG_CHD, " using %N for encryption",
638 encryption_algorithm_names, this->enc_alg);
639 }
640 if (!this->enc_size)
641 {
642 this->enc_size = lookup_keylen(keylen_enc, this->enc_alg);
643 }
644 if (this->enc_size && this->enc_alg != ENCR_UNDEFINED)
645 {
646 /* CCM/GCM needs additional keymat */
647 switch (this->enc_alg)
648 {
649 case ENCR_AES_CCM_ICV8:
650 case ENCR_AES_CCM_ICV12:
651 case ENCR_AES_CCM_ICV16:
652 add_keymat = 3;
653 break;
654 case ENCR_AES_GCM_ICV8:
655 case ENCR_AES_GCM_ICV12:
656 case ENCR_AES_GCM_ICV16:
657 add_keymat = 4;
658 break;
659 default:
660 add_keymat = 0;
661 break;
662 }
663 prf_plus->allocate_bytes(prf_plus, this->enc_size / 8 + add_keymat,
664 &enc_key);
665 }
666
667 /* select integrity algo, derive key */
668 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
669 &this->int_alg, &this->int_size))
670 {
671 DBG2(DBG_CHD, " using %N for integrity",
672 integrity_algorithm_names, this->int_alg);
673 }
674 if (!this->int_size)
675 {
676 this->int_size = lookup_keylen(keylen_int, this->int_alg);
677 }
678 if (this->int_size && this->int_alg != AUTH_UNDEFINED)
679 {
680 prf_plus->allocate_bytes(prf_plus, this->int_size / 8, &int_key);
681 }
682
683 /* send SA down to the kernel */
684 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
685
686 if (this->ipcomp != IPCOMP_NONE)
687 {
688 /* we install an additional IPComp SA */
689 cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi));
690 charon->kernel_interface->add_sa(charon->kernel_interface,
691 src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
692 ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
693 mode, this->ipcomp, FALSE, mine);
694 }
695
696 soft = this->config->get_lifetime(this->config, TRUE);
697 hard = this->config->get_lifetime(this->config, FALSE);
698 status = charon->kernel_interface->add_sa(charon->kernel_interface,
699 src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard,
700 this->enc_alg, enc_key, this->int_alg, int_key,
701 mode, IPCOMP_NONE, this->encap, mine);
702
703 chunk_clear(&enc_key);
704 chunk_clear(&int_key);
705 this->install_time = time(NULL);
706 this->rekey_time = this->install_time + soft;
707 return status;
708 }
709
710 static status_t add(private_child_sa_t *this, proposal_t *proposal,
711 ipsec_mode_t mode, prf_plus_t *prf_plus)
712 {
713 u_int32_t outbound_spi, inbound_spi;
714
715 /* backup outbound spi, as alloc overwrites it */
716 outbound_spi = proposal->get_spi(proposal);
717
718 /* get SPIs inbound SAs */
719 if (alloc_proposal(this, proposal) != SUCCESS)
720 {
721 return FAILED;
722 }
723 inbound_spi = proposal->get_spi(proposal);
724
725 /* install inbound SAs */
726 if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
727 {
728 return FAILED;
729 }
730
731 /* install outbound SAs, restore spi*/
732 proposal->set_spi(proposal, outbound_spi);
733 if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
734 {
735 return FAILED;
736 }
737 proposal->set_spi(proposal, inbound_spi);
738
739 return SUCCESS;
740 }
741
742 static status_t update(private_child_sa_t *this, proposal_t *proposal,
743 ipsec_mode_t mode, prf_plus_t *prf_plus)
744 {
745 u_int32_t inbound_spi;
746
747 /* backup received spi, as install() overwrites it */
748 inbound_spi = proposal->get_spi(proposal);
749
750 /* install outbound SAs */
751 if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
752 {
753 return FAILED;
754 }
755
756 /* restore spi */
757 proposal->set_spi(proposal, inbound_spi);
758 /* install inbound SAs */
759 if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
760 {
761 return FAILED;
762 }
763
764 return SUCCESS;
765 }
766
767 static status_t add_policies(private_child_sa_t *this,
768 linked_list_t *my_ts_list, linked_list_t *other_ts_list,
769 ipsec_mode_t mode, protocol_id_t proto)
770 {
771 iterator_t *my_iter, *other_iter;
772 traffic_selector_t *my_ts, *other_ts;
773 /* use low prio for ROUTED policies */
774 bool high_prio = (this->state != CHILD_CREATED);
775
776 if (this->protocol == PROTO_NONE)
777 { /* update if not set yet */
778 this->protocol = proto;
779 }
780
781 /* iterate over both lists */
782 my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
783 other_iter = other_ts_list->create_iterator(other_ts_list, TRUE);
784 while (my_iter->iterate(my_iter, (void**)&my_ts))
785 {
786 other_iter->reset(other_iter);
787 while (other_iter->iterate(other_iter, (void**)&other_ts))
788 {
789 /* set up policies for every entry in my_ts_list to every entry in other_ts_list */
790 status_t status;
791 sa_policy_t *policy;
792
793 if (my_ts->get_type(my_ts) != other_ts->get_type(other_ts))
794 {
795 DBG2(DBG_CHD,
796 "CHILD_SA policy uses two different IP families - ignored");
797 continue;
798 }
799
800 /* only set up policies if protocol matches, or if one is zero (any) */
801 if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts) &&
802 my_ts->get_protocol(my_ts) && other_ts->get_protocol(other_ts))
803 {
804 DBG2(DBG_CHD,
805 "CHILD_SA policy uses two different protocols - ignored");
806 continue;
807 }
808
809 /* install 3 policies: out, in and forward */
810 status = charon->kernel_interface->add_policy(charon->kernel_interface,
811 this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
812 this->protocol, this->reqid, high_prio, mode, this->ipcomp);
813
814 status |= charon->kernel_interface->add_policy(charon->kernel_interface,
815 this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
816 this->protocol, this->reqid, high_prio, mode, this->ipcomp);
817
818 status |= charon->kernel_interface->add_policy(charon->kernel_interface,
819 this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
820 this->protocol, this->reqid, high_prio, mode, this->ipcomp);
821
822 if (status != SUCCESS)
823 {
824 my_iter->destroy(my_iter);
825 other_iter->destroy(other_iter);
826 return status;
827 }
828
829 /* store policy to delete/update them later */
830 policy = malloc_thing(sa_policy_t);
831 policy->my_ts = my_ts->clone(my_ts);
832 policy->other_ts = other_ts->clone(other_ts);
833 this->policies->insert_last(this->policies, policy);
834 /* add to separate list to query them via get_*_traffic_selectors() */
835 this->my_ts->insert_last(this->my_ts, policy->my_ts);
836 this->other_ts->insert_last(this->other_ts, policy->other_ts);
837 }
838 }
839 my_iter->destroy(my_iter);
840 other_iter->destroy(other_iter);
841
842 /* switch to routed state if no SAD entry set up */
843 if (this->state == CHILD_CREATED)
844 {
845 set_state(this, CHILD_ROUTED);
846 }
847 /* needed to update hosts */
848 this->mode = mode;
849 return SUCCESS;
850 }
851
852 /**
853 * Implementation of child_sa_t.get_traffic_selectors.
854 */
855 static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
856 {
857 if (local)
858 {
859 return this->my_ts;
860 }
861 return this->other_ts;
862 }
863
864 /**
865 * Implementation of child_sa_t.get_use_time
866 */
867 static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time)
868 {
869 iterator_t *iterator;
870 sa_policy_t *policy;
871 status_t status = FAILED;
872
873 *use_time = UNDEFINED_TIME;
874
875 iterator = this->policies->create_iterator(this->policies, TRUE);
876 while (iterator->iterate(iterator, (void**)&policy))
877 {
878 if (inbound)
879 {
880 time_t in = UNDEFINED_TIME, fwd = UNDEFINED_TIME;
881
882 status = charon->kernel_interface->query_policy(
883 charon->kernel_interface,
884 policy->other_ts, policy->my_ts,
885 POLICY_IN, (u_int32_t*)&in);
886 status |= charon->kernel_interface->query_policy(
887 charon->kernel_interface,
888 policy->other_ts, policy->my_ts,
889 POLICY_FWD, (u_int32_t*)&fwd);
890 *use_time = max(in, fwd);
891 }
892 else
893 {
894 status = charon->kernel_interface->query_policy(
895 charon->kernel_interface,
896 policy->my_ts, policy->other_ts,
897 POLICY_OUT, (u_int32_t*)use_time);
898 }
899 }
900 iterator->destroy(iterator);
901 return status;
902 }
903
904 /**
905 * Implementation of child_sa_t.update_hosts.
906 */
907 static status_t update_hosts(private_child_sa_t *this,
908 host_t *me, host_t *other, bool encap)
909 {
910 /* anything changed at all? */
911 if (me->equals(me, this->me.addr) &&
912 other->equals(other, this->other.addr) && this->encap == encap)
913 {
914 return SUCCESS;
915 }
916 /* run updown script to remove iptables rules */
917 updown(this, FALSE);
918
919 this->encap = encap;
920
921 if (this->ipcomp != IPCOMP_NONE)
922 {
923 /* update our (initator) IPComp SA */
924 charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->me.cpi)),
925 IPPROTO_COMP, this->other.addr, this->me.addr, other, me, FALSE);
926 /* update his (responder) IPComp SA */
927 charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->other.cpi)),
928 IPPROTO_COMP, this->me.addr, this->other.addr, me, other, FALSE);
929 }
930
931 /* update our (initator) SA */
932 charon->kernel_interface->update_sa(charon->kernel_interface, this->me.spi,
933 this->protocol, this->other.addr, this->me.addr, other, me, encap);
934 /* update his (responder) SA */
935 charon->kernel_interface->update_sa(charon->kernel_interface, this->other.spi,
936 this->protocol, this->me.addr, this->other.addr, me, other, encap);
937
938 /* update policies */
939 if (!me->ip_equals(me, this->me.addr) ||
940 !other->ip_equals(other, this->other.addr))
941 {
942 iterator_t *iterator;
943 sa_policy_t *policy;
944
945 /* always use high priorities, as hosts getting updated are INSTALLED */
946 iterator = this->policies->create_iterator(this->policies, TRUE);
947 while (iterator->iterate(iterator, (void**)&policy))
948 {
949 /* remove old policies first */
950 charon->kernel_interface->del_policy(charon->kernel_interface,
951 policy->my_ts, policy->other_ts, POLICY_OUT);
952 charon->kernel_interface->del_policy(charon->kernel_interface,
953 policy->other_ts, policy->my_ts, POLICY_IN);
954 charon->kernel_interface->del_policy(charon->kernel_interface,
955 policy->other_ts, policy->my_ts, POLICY_FWD);
956
957 /* check whether we have to update a "dynamic" traffic selector */
958 if (!me->ip_equals(me, this->me.addr) &&
959 policy->my_ts->is_host(policy->my_ts, this->me.addr))
960 {
961 policy->my_ts->set_address(policy->my_ts, me);
962 }
963 if (!other->ip_equals(other, this->other.addr) &&
964 policy->other_ts->is_host(policy->other_ts, this->other.addr))
965 {
966 policy->other_ts->set_address(policy->other_ts, other);
967 }
968
969 /* we reinstall the virtual IP to handle interface roaming
970 * correctly */
971 if (this->virtual_ip)
972 {
973 charon->kernel_interface->del_ip(charon->kernel_interface,
974 this->virtual_ip);
975 charon->kernel_interface->add_ip(charon->kernel_interface,
976 this->virtual_ip, me);
977 }
978
979 /* reinstall updated policies */
980 charon->kernel_interface->add_policy(charon->kernel_interface,
981 me, other, policy->my_ts, policy->other_ts, POLICY_OUT,
982 this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
983 charon->kernel_interface->add_policy(charon->kernel_interface,
984 other, me, policy->other_ts, policy->my_ts, POLICY_IN,
985 this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
986 charon->kernel_interface->add_policy(charon->kernel_interface,
987 other, me, policy->other_ts, policy->my_ts, POLICY_FWD,
988 this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
989 }
990 iterator->destroy(iterator);
991 }
992
993 /* apply hosts */
994 if (!me->equals(me, this->me.addr))
995 {
996 this->me.addr->destroy(this->me.addr);
997 this->me.addr = me->clone(me);
998 }
999 if (!other->equals(other, this->other.addr))
1000 {
1001 this->other.addr->destroy(this->other.addr);
1002 this->other.addr = other->clone(other);
1003 }
1004
1005 /* install new iptables rules */
1006 updown(this, TRUE);
1007
1008 return SUCCESS;
1009 }
1010
1011 /**
1012 * Implementation of child_sa_t.set_virtual_ip.
1013 */
1014 static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
1015 {
1016 this->virtual_ip = ip->clone(ip);
1017 }
1018
1019 /**
1020 * Implementation of child_sa_t.activate_ipcomp.
1021 */
1022 static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
1023 u_int16_t other_cpi)
1024 {
1025 this->ipcomp = ipcomp;
1026 this->other.cpi = other_cpi;
1027 }
1028
1029 /**
1030 * Implementation of child_sa_t.allocate_cpi.
1031 */
1032 static u_int16_t allocate_cpi(private_child_sa_t *this)
1033 {
1034 if (!this->cpi_allocated)
1035 {
1036 charon->kernel_interface->get_cpi(charon->kernel_interface,
1037 this->other.addr, this->me.addr, this->reqid, &this->me.cpi);
1038 this->cpi_allocated = TRUE;
1039 }
1040 return this->me.cpi;
1041 }
1042
1043 /**
1044 * Implementation of child_sa_t.destroy.
1045 */
1046 static void destroy(private_child_sa_t *this)
1047 {
1048 sa_policy_t *policy;
1049
1050 if (this->state == CHILD_DELETING || this->state == CHILD_INSTALLED)
1051 {
1052 updown(this, FALSE);
1053 }
1054
1055 set_state(this, CHILD_DESTROYING);
1056
1057 /* delete SAs in the kernel, if they are set up */
1058 if (this->me.spi)
1059 {
1060 charon->kernel_interface->del_sa(charon->kernel_interface,
1061 this->me.addr, this->me.spi, this->protocol);
1062 }
1063 if (this->alloc_esp_spi && this->alloc_esp_spi != this->me.spi)
1064 {
1065 charon->kernel_interface->del_sa(charon->kernel_interface,
1066 this->me.addr, this->alloc_esp_spi, PROTO_ESP);
1067 }
1068 if (this->alloc_ah_spi && this->alloc_ah_spi != this->me.spi)
1069 {
1070 charon->kernel_interface->del_sa(charon->kernel_interface,
1071 this->me.addr, this->alloc_ah_spi, PROTO_AH);
1072 }
1073 if (this->other.spi)
1074 {
1075 charon->kernel_interface->del_sa(charon->kernel_interface,
1076 this->other.addr, this->other.spi, this->protocol);
1077 }
1078 if (this->me.cpi)
1079 {
1080 charon->kernel_interface->del_sa(charon->kernel_interface,
1081 this->me.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP);
1082 }
1083 if (this->other.cpi)
1084 {
1085 charon->kernel_interface->del_sa(charon->kernel_interface,
1086 this->other.addr, htonl(ntohs(this->other.cpi)), IPPROTO_COMP);
1087 }
1088
1089 /* delete all policies in the kernel */
1090 while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
1091 {
1092 /* let rekeyed policies, as they are used by another child_sa */
1093 charon->kernel_interface->del_policy(charon->kernel_interface,
1094 policy->my_ts, policy->other_ts,
1095 POLICY_OUT);
1096
1097 charon->kernel_interface->del_policy(charon->kernel_interface,
1098 policy->other_ts, policy->my_ts,
1099 POLICY_IN);
1100
1101 charon->kernel_interface->del_policy(charon->kernel_interface,
1102 policy->other_ts, policy->my_ts,
1103 POLICY_FWD);
1104 policy->my_ts->destroy(policy->my_ts);
1105 policy->other_ts->destroy(policy->other_ts);
1106 free(policy);
1107 }
1108 this->policies->destroy(this->policies);
1109
1110 this->my_ts->destroy(this->my_ts);
1111 this->other_ts->destroy(this->other_ts);
1112 this->me.addr->destroy(this->me.addr);
1113 this->other.addr->destroy(this->other.addr);
1114 this->me.id->destroy(this->me.id);
1115 this->other.id->destroy(this->other.id);
1116 this->config->destroy(this->config);
1117 free(this->iface);
1118 DESTROY_IF(this->virtual_ip);
1119 free(this);
1120 }
1121
1122 /*
1123 * Described in header.
1124 */
1125 child_sa_t * child_sa_create(host_t *me, host_t* other,
1126 identification_t *my_id, identification_t *other_id,
1127 child_cfg_t *config, u_int32_t rekey, bool encap)
1128 {
1129 static u_int32_t reqid = 0;
1130 private_child_sa_t *this = malloc_thing(private_child_sa_t);
1131
1132 /* public functions */
1133 this->public.get_name = (char*(*)(child_sa_t*))get_name;
1134 this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
1135 this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
1136 this->public.get_cpi = (u_int16_t(*)(child_sa_t*, bool))get_cpi;
1137 this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
1138 this->public.get_stats = (void(*)(child_sa_t*, ipsec_mode_t*,encryption_algorithm_t*,size_t*,integrity_algorithm_t*,size_t*,u_int32_t*,u_int32_t*,u_int32_t*,u_int32_t*))get_stats;
1139 this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
1140 this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))add;
1141 this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))update;
1142 this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,bool))update_hosts;
1143 this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,ipsec_mode_t,protocol_id_t))add_policies;
1144 this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
1145 this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
1146 this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
1147 this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
1148 this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
1149 this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp;
1150 this->public.allocate_cpi = (u_int16_t(*)(child_sa_t*))allocate_cpi;
1151 this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
1152 this->public.destroy = (void(*)(child_sa_t*))destroy;
1153
1154 /* private data */
1155 this->me.addr = me->clone(me);
1156 this->other.addr = other->clone(other);
1157 this->me.id = my_id->clone(my_id);
1158 this->other.id = other_id->clone(other_id);
1159 this->me.spi = 0;
1160 this->me.cpi = 0;
1161 this->other.spi = 0;
1162 this->other.cpi = 0;
1163 this->alloc_ah_spi = 0;
1164 this->alloc_esp_spi = 0;
1165 this->encap = encap;
1166 this->cpi_allocated = FALSE;
1167 this->ipcomp = IPCOMP_NONE;
1168 this->state = CHILD_CREATED;
1169 /* reuse old reqid if we are rekeying an existing CHILD_SA */
1170 this->reqid = rekey ? rekey : ++reqid;
1171 this->enc_alg = ENCR_UNDEFINED;
1172 this->enc_size = 0;
1173 this->int_alg = AUTH_UNDEFINED;
1174 this->int_size = 0;
1175 this->policies = linked_list_create();
1176 this->my_ts = linked_list_create();
1177 this->other_ts = linked_list_create();
1178 this->protocol = PROTO_NONE;
1179 this->mode = MODE_TUNNEL;
1180 this->virtual_ip = NULL;
1181 this->iface = NULL;
1182 this->config = config;
1183 config->get_ref(config);
1184
1185 return &this->public;
1186 }