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