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