ikev2: Schedule a timeout for the delete message following passive IKE rekeying
[strongswan.git] / src / libcharon / plugins / vici / vici_config.c
1 /*
2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #define _GNU_SOURCE
17
18 #include "vici_config.h"
19 #include "vici_builder.h"
20
21 #include <daemon.h>
22 #include <threading/rwlock.h>
23 #include <collections/array.h>
24 #include <collections/linked_list.h>
25
26 #include <stdio.h>
27
28 /**
29 * Magic value for an undefined lifetime
30 */
31 #define LFT_UNDEFINED (~(u_int64_t)0)
32
33 /**
34 * Default IKE rekey time
35 */
36 #define LFT_DEFAULT_IKE_REKEY (4 * 60 * 60)
37
38 /**
39 * Default CHILD rekey time
40 */
41 #define LFT_DEFAULT_CHILD_REKEY (1 * 60 * 60)
42
43 /**
44 * Undefined replay window
45 */
46 #define REPLAY_UNDEFINED (~(u_int32_t)0)
47
48 typedef struct private_vici_config_t private_vici_config_t;
49
50 /**
51 * Private data of an vici_config_t object.
52 */
53 struct private_vici_config_t {
54
55 /**
56 * Public vici_config_t interface.
57 */
58 vici_config_t public;
59
60 /**
61 * Dispatcher
62 */
63 vici_dispatcher_t *dispatcher;
64
65 /**
66 * List of loaded connections, as peer_cfg_t
67 */
68 linked_list_t *conns;
69
70 /**
71 * Lock for conns list
72 */
73 rwlock_t *lock;
74 };
75
76 METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
77 private_vici_config_t *this, identification_t *me, identification_t *other)
78 {
79 this->lock->read_lock(this->lock);
80 return enumerator_create_cleaner(this->conns->create_enumerator(this->conns),
81 (void*)this->lock->unlock, this->lock);
82 }
83
84 /**
85 * Enumerator filter function for ike configs
86 */
87 static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
88 {
89 *out = (*in)->get_ike_cfg(*in);
90 return TRUE;
91 }
92
93 METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
94 private_vici_config_t *this, host_t *me, host_t *other)
95 {
96 this->lock->read_lock(this->lock);
97 return enumerator_create_filter(this->conns->create_enumerator(this->conns),
98 (void*)ike_filter, this->lock,
99 (void*)this->lock->unlock);
100 }
101
102 METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
103 private_vici_config_t *this, char *name)
104 {
105 peer_cfg_t *current, *found = NULL;
106 enumerator_t *enumerator;
107
108 this->lock->read_lock(this->lock);
109 enumerator = this->conns->create_enumerator(this->conns);
110 while (enumerator->enumerate(enumerator, &current))
111 {
112 if (streq(current->get_name(current), name))
113 {
114 found = current;
115 found->get_ref(found);
116 break;
117 }
118 }
119 enumerator->destroy(enumerator);
120 this->lock->unlock(this->lock);
121
122 return found;
123 }
124
125 /**
126 * Create a (error) reply message
127 */
128 static vici_message_t* create_reply(char *fmt, ...)
129 {
130 vici_builder_t *builder;
131 va_list args;
132
133 builder = vici_builder_create();
134 builder->add_kv(builder, "success", fmt ? "no" : "yes");
135 if (fmt)
136 {
137 va_start(args, fmt);
138 builder->vadd_kv(builder, "errmsg", fmt, args);
139 va_end(args);
140 }
141 return builder->finalize(builder);
142 }
143
144 /**
145 * A rule to parse a key/value or list item
146 */
147 typedef struct {
148 /** name of the key/value or list */
149 char *name;
150 /** function to parse value */
151 bool (*parse)(void *out, chunk_t value);
152 /** result, passed to parse() */
153 void *out;
154 } parse_rule_t;
155
156 /**
157 * Parse key/values using a rule-set
158 */
159 static bool parse_rules(parse_rule_t *rules, int count, char *name,
160 chunk_t value, vici_message_t **reply)
161 {
162 int i;
163
164 for (i = 0; i < count; i++)
165 {
166 if (streq(name, rules[i].name))
167 {
168 if (rules[i].parse(rules[i].out, value))
169 {
170 return TRUE;
171 }
172 *reply = create_reply("invalid value for: %s, config discarded",
173 name);
174 return FALSE;
175 }
176 }
177 *reply = create_reply("unknown option: %s, config discarded", name);
178 return FALSE;
179 }
180
181 /**
182 * Parse callback data, passed to each callback
183 */
184 typedef struct {
185 private_vici_config_t *this;
186 vici_message_t *reply;
187 } request_data_t;
188
189 /**
190 * Data associated to a peer config
191 */
192 typedef struct {
193 request_data_t *request;
194 u_int32_t version;
195 bool aggressive;
196 bool encap;
197 bool mobike;
198 bool send_certreq;
199 bool pull;
200 cert_policy_t send_cert;
201 u_int64_t dpd_delay;
202 u_int64_t dpd_timeout;
203 fragmentation_t fragmentation;
204 unique_policy_t unique;
205 u_int32_t keyingtries;
206 u_int32_t local_port;
207 u_int32_t remote_port;
208 char *local_addrs;
209 char *remote_addrs;
210 linked_list_t *local;
211 linked_list_t *remote;
212 linked_list_t *proposals;
213 linked_list_t *children;
214 linked_list_t *vips;
215 char *pools;
216 u_int64_t reauth_time;
217 u_int64_t rekey_time;
218 u_int64_t over_time;
219 u_int64_t rand_time;
220 } peer_data_t;
221
222 /**
223 * Log relevant auth config data
224 */
225 static void log_auth(auth_cfg_t *auth)
226 {
227 enumerator_t *enumerator;
228 auth_rule_t rule;
229 union {
230 uintptr_t u;
231 identification_t *id;
232 char *str;
233 } v;
234
235 enumerator = auth->create_enumerator(auth);
236 while (enumerator->enumerate(enumerator, &rule, &v))
237 {
238 switch (rule)
239 {
240 case AUTH_RULE_AUTH_CLASS:
241 DBG2(DBG_CFG, " class = %N", auth_class_names, v.u);
242 break;
243 case AUTH_RULE_EAP_TYPE:
244 DBG2(DBG_CFG, " eap-type = %N", eap_type_names, v.u);
245 break;
246 case AUTH_RULE_EAP_VENDOR:
247 DBG2(DBG_CFG, " eap-vendor = %u", v.u);
248 break;
249 case AUTH_RULE_XAUTH_BACKEND:
250 DBG2(DBG_CFG, " xauth = %s", v.str);
251 break;
252 case AUTH_RULE_CRL_VALIDATION:
253 DBG2(DBG_CFG, " revocation = %N", cert_validation_names, v.u);
254 break;
255 case AUTH_RULE_IDENTITY:
256 DBG2(DBG_CFG, " id = %Y", v.id);
257 break;
258 case AUTH_RULE_AAA_IDENTITY:
259 DBG2(DBG_CFG, " aaa_id = %Y", v.id);
260 break;
261 case AUTH_RULE_EAP_IDENTITY:
262 DBG2(DBG_CFG, " eap_id = %Y", v.id);
263 break;
264 case AUTH_RULE_XAUTH_IDENTITY:
265 DBG2(DBG_CFG, " xauth_id = %Y", v.id);
266 break;
267 case AUTH_RULE_GROUP:
268 DBG2(DBG_CFG, " group = %Y", v.id);
269 break;
270 default:
271 break;
272 }
273 }
274 enumerator->destroy(enumerator);
275 }
276
277 /**
278 * Log parsed peer data
279 */
280 static void log_peer_data(peer_data_t *data)
281 {
282 enumerator_t *enumerator;
283 auth_cfg_t *auth;
284 host_t *host;
285
286 DBG2(DBG_CFG, " version = %u", data->version);
287 DBG2(DBG_CFG, " local_addrs = %s", data->local_addrs);
288 DBG2(DBG_CFG, " remote_addrs = %s", data->remote_addrs);
289 DBG2(DBG_CFG, " local_port = %u", data->local_port);
290 DBG2(DBG_CFG, " remote_port = %u", data->remote_port);
291 DBG2(DBG_CFG, " send_certreq = %u", data->send_certreq);
292 DBG2(DBG_CFG, " send_cert = %N", cert_policy_names, data->send_cert);
293 DBG2(DBG_CFG, " mobike = %u", data->mobike);
294 DBG2(DBG_CFG, " aggressive = %u", data->aggressive);
295 DBG2(DBG_CFG, " encap = %u", data->encap);
296 DBG2(DBG_CFG, " dpd_delay = %llu", data->dpd_delay);
297 DBG2(DBG_CFG, " dpd_timeout = %llu", data->dpd_timeout);
298 DBG2(DBG_CFG, " fragmentation = %u", data->fragmentation);
299 DBG2(DBG_CFG, " unique = %N", unique_policy_names, data->unique);
300 DBG2(DBG_CFG, " keyingtries = %u", data->keyingtries);
301 DBG2(DBG_CFG, " reauth_time = %llu", data->reauth_time);
302 DBG2(DBG_CFG, " rekey_time = %llu", data->rekey_time);
303 DBG2(DBG_CFG, " over_time = %llu", data->over_time);
304 DBG2(DBG_CFG, " rand_time = %llu", data->rand_time);
305 DBG2(DBG_CFG, " proposals = %#P", data->proposals);
306
307 if (data->vips->get_count(data->vips))
308 {
309 DBG2(DBG_CFG, " vips:");
310 }
311 enumerator = data->vips->create_enumerator(data->vips);
312 while (enumerator->enumerate(enumerator, &host))
313 {
314 DBG2(DBG_CFG, " %H", host);
315 }
316 enumerator->destroy(enumerator);
317
318 enumerator = data->local->create_enumerator(data->local);
319 while (enumerator->enumerate(enumerator, &auth))
320 {
321 DBG2(DBG_CFG, " local:");
322 log_auth(auth);
323 }
324 enumerator->destroy(enumerator);
325
326 enumerator = data->remote->create_enumerator(data->remote);
327 while (enumerator->enumerate(enumerator, &auth))
328 {
329 DBG2(DBG_CFG, " remote:");
330 log_auth(auth);
331 }
332 enumerator->destroy(enumerator);
333 }
334
335 /**
336 * Clean up peer config data
337 */
338 static void free_peer_data(peer_data_t *data)
339 {
340 data->local->destroy_offset(data->local,
341 offsetof(auth_cfg_t, destroy));
342 data->remote->destroy_offset(data->remote,
343 offsetof(auth_cfg_t, destroy));
344 data->children->destroy_offset(data->children,
345 offsetof(child_cfg_t, destroy));
346 data->proposals->destroy_offset(data->proposals,
347 offsetof(proposal_t, destroy));
348 data->vips->destroy_offset(data->vips, offsetof(host_t, destroy));
349 free(data->pools);
350 free(data->local_addrs);
351 free(data->remote_addrs);
352 }
353
354 /**
355 * CHILD config data
356 */
357 typedef struct {
358 request_data_t *request;
359 lifetime_cfg_t lft;
360 char* updown;
361 bool hostaccess;
362 bool ipcomp;
363 bool route;
364 ipsec_mode_t mode;
365 u_int32_t replay_window;
366 action_t dpd_action;
367 action_t start_action;
368 action_t close_action;
369 u_int32_t reqid;
370 u_int32_t tfc;
371 mark_t mark_in;
372 mark_t mark_out;
373 u_int64_t inactivity;
374 linked_list_t *proposals;
375 linked_list_t *local_ts;
376 linked_list_t *remote_ts;
377 } child_data_t;
378
379 /**
380 * Log parsed CHILD config data
381 */
382 static void log_child_data(child_data_t *data, char *name)
383 {
384 DBG2(DBG_CFG, " child %s:", name);
385 DBG2(DBG_CFG, " rekey_time = %llu", data->lft.time.rekey);
386 DBG2(DBG_CFG, " life_time = %llu", data->lft.time.life);
387 DBG2(DBG_CFG, " rand_time = %llu", data->lft.time.jitter);
388 DBG2(DBG_CFG, " rekey_bytes = %llu", data->lft.bytes.rekey);
389 DBG2(DBG_CFG, " life_bytes = %llu", data->lft.bytes.life);
390 DBG2(DBG_CFG, " rand_bytes = %llu", data->lft.bytes.jitter);
391 DBG2(DBG_CFG, " rekey_packets = %llu", data->lft.packets.rekey);
392 DBG2(DBG_CFG, " life_packets = %llu", data->lft.packets.life);
393 DBG2(DBG_CFG, " rand_packets = %llu", data->lft.packets.jitter);
394 DBG2(DBG_CFG, " updown = %s", data->updown);
395 DBG2(DBG_CFG, " hostaccess = %u", data->hostaccess);
396 DBG2(DBG_CFG, " ipcomp = %u", data->ipcomp);
397 DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, data->mode);
398 if (data->replay_window != REPLAY_UNDEFINED)
399 {
400 DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
401 }
402 DBG2(DBG_CFG, " dpd_action = %N", action_names, data->dpd_action);
403 DBG2(DBG_CFG, " start_action = %N", action_names, data->start_action);
404 DBG2(DBG_CFG, " close_action = %N", action_names, data->close_action);
405 DBG2(DBG_CFG, " reqid = %u", data->reqid);
406 DBG2(DBG_CFG, " tfc = %d", data->tfc);
407 DBG2(DBG_CFG, " mark_in = %u/%u",
408 data->mark_in.value, data->mark_in.mask);
409 DBG2(DBG_CFG, " mark_out = %u/%u",
410 data->mark_out.value, data->mark_out.mask);
411 DBG2(DBG_CFG, " inactivity = %llu", data->inactivity);
412 DBG2(DBG_CFG, " proposals = %#P", data->proposals);
413 DBG2(DBG_CFG, " local_ts = %#R", data->local_ts);
414 DBG2(DBG_CFG, " remote_ts = %#R", data->remote_ts);
415 }
416
417 /**
418 * Clean up CHILD config data
419 */
420 static void free_child_data(child_data_t *data)
421 {
422 data->proposals->destroy_offset(data->proposals,
423 offsetof(proposal_t, destroy));
424 data->local_ts->destroy_offset(data->local_ts,
425 offsetof(traffic_selector_t, destroy));
426 data->remote_ts->destroy_offset(data->remote_ts,
427 offsetof(traffic_selector_t, destroy));
428 free(data->updown);
429 }
430
431 /**
432 * Auth config data
433 */
434 typedef struct {
435 request_data_t *request;
436 auth_cfg_t *cfg;
437 } auth_data_t;
438
439 /**
440 * Common proposal parsing
441 */
442 static bool parse_proposal(linked_list_t *list, protocol_id_t proto, chunk_t v)
443 {
444 char buf[128];
445 proposal_t *proposal;
446
447 if (!vici_stringify(v, buf, sizeof(buf)))
448 {
449 return FALSE;
450 }
451 if (strcaseeq("default", buf))
452 {
453 proposal = proposal_create_default(proto);
454 if (proposal)
455 {
456 list->insert_last(list, proposal);
457 }
458 proposal = proposal_create_default_aead(proto);
459 if (proposal)
460 {
461 list->insert_last(list, proposal);
462 }
463 return TRUE;
464 }
465 proposal = proposal_create_from_string(proto, buf);
466 if (proposal)
467 {
468 list->insert_last(list, proposal);
469 return TRUE;
470 }
471 return FALSE;
472 }
473
474 /**
475 * Parse IKE proposal
476 */
477 CALLBACK(parse_ike_proposal, bool,
478 linked_list_t *out, chunk_t v)
479 {
480 return parse_proposal(out, PROTO_IKE, v);
481 }
482
483 /**
484 * Parse ESP proposal
485 */
486 CALLBACK(parse_esp_proposal, bool,
487 linked_list_t *out, chunk_t v)
488 {
489 return parse_proposal(out, PROTO_ESP, v);
490 }
491
492 /**
493 * Parse AH proposal
494 */
495 CALLBACK(parse_ah_proposal, bool,
496 linked_list_t *out, chunk_t v)
497 {
498 return parse_proposal(out, PROTO_AH, v);
499 }
500
501 /**
502 * Parse a traffic selector
503 */
504 CALLBACK(parse_ts, bool,
505 linked_list_t *out, chunk_t v)
506 {
507 char buf[128], *protoport, *sep, *port = "", *end;
508 traffic_selector_t *ts;
509 struct protoent *protoent;
510 struct servent *svc;
511 long int p;
512 u_int16_t from = 0, to = 0xffff;
513 u_int8_t proto = 0;
514
515 if (!vici_stringify(v, buf, sizeof(buf)))
516 {
517 return FALSE;
518 }
519
520 protoport = strchr(buf, '[');
521 if (protoport)
522 {
523 *(protoport++) = '\0';
524
525 sep = strrchr(protoport, ']');
526 if (!sep)
527 {
528 return FALSE;
529 }
530 *sep = '\0';
531
532 sep = strchr(protoport, '/');
533 if (sep)
534 { /* protocol/port */
535 *sep = '\0';
536 port = sep + 1;
537 }
538
539 if (streq(protoport, "any"))
540 {
541 proto = 0;
542 }
543 else
544 {
545 protoent = getprotobyname(protoport);
546 if (protoent)
547 {
548 proto = protoent->p_proto;
549 }
550 else
551 {
552 p = strtol(protoport, &end, 0);
553 if ((*protoport && *end) || p < 0 || p > 0xff)
554 {
555 return FALSE;
556 }
557 proto = (u_int8_t)p;
558 }
559 }
560 if (streq(port, "opaque"))
561 {
562 from = 0xffff;
563 to = 0;
564 }
565 else if (*port && !streq(port, "any"))
566 {
567 svc = getservbyname(port, NULL);
568 if (svc)
569 {
570 from = to = ntohs(svc->s_port);
571 }
572 else
573 {
574 p = strtol(port, &end, 0);
575 if (p < 0 || p > 0xffff)
576 {
577 return FALSE;
578 }
579 from = p;
580 if (*end == '-')
581 {
582 port = end + 1;
583 p = strtol(port, &end, 0);
584 if (p < 0 || p > 0xffff)
585 {
586 return FALSE;
587 }
588 }
589 to = p;
590 if (*end)
591 {
592 return FALSE;
593 }
594 }
595 }
596 }
597 if (streq(buf, "dynamic"))
598 {
599 ts = traffic_selector_create_dynamic(proto, from, to);
600 }
601 else
602 {
603 ts = traffic_selector_create_from_cidr(buf, proto, from, to);
604 }
605 if (!ts)
606 {
607 return FALSE;
608 }
609 out->insert_last(out, ts);
610 return TRUE;
611 }
612
613 /**
614 * Parse a string
615 */
616 CALLBACK(parse_string, bool,
617 char **out, chunk_t v)
618 {
619 if (!chunk_printable(v, NULL, ' '))
620 {
621 return FALSE;
622 }
623 free(*out);
624 *out = NULL;
625 if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
626 {
627 return FALSE;
628 }
629 return TRUE;
630 }
631
632 /**
633 * Map a string to an integer
634 */
635 typedef struct {
636 char *str;
637 int d;
638 } enum_map_t;
639
640 /**
641 * Parse a string to an integer mapping
642 */
643 static bool parse_map(enum_map_t *map, int count, int *out, chunk_t v)
644 {
645 char buf[128];
646 int i;
647
648 if (!vici_stringify(v, buf, sizeof(buf)))
649 {
650 return FALSE;
651 }
652 for (i = 0; i < count; i++)
653 {
654 if (strcaseeq(map[i].str, buf))
655 {
656 *out = map[i].d;
657 return TRUE;
658 }
659 }
660 return FALSE;
661 }
662
663 /**
664 * Parse a boolean
665 */
666 CALLBACK(parse_bool, bool,
667 bool *out, chunk_t v)
668 {
669 enum_map_t map[] = {
670 { "yes", TRUE },
671 { "true", TRUE },
672 { "enabled", TRUE },
673 { "1", TRUE },
674 { "no", FALSE },
675 { "false", FALSE },
676 { "disabled", FALSE },
677 { "0", FALSE },
678 };
679 int d;
680
681 if (parse_map(map, countof(map), &d, v))
682 {
683 *out = d;
684 return TRUE;
685 }
686 return FALSE;
687 }
688
689 /**
690 * Parse a ipsec_mode_t
691 */
692 CALLBACK(parse_mode, bool,
693 ipsec_mode_t *out, chunk_t v)
694 {
695 enum_map_t map[] = {
696 { "tunnel", MODE_TUNNEL },
697 { "transport", MODE_TRANSPORT },
698 { "beet", MODE_BEET },
699 { "drop", MODE_DROP },
700 { "pass", MODE_PASS },
701 };
702 int d;
703
704 if (parse_map(map, countof(map), &d, v))
705 {
706 *out = d;
707 return TRUE;
708 }
709 return FALSE;
710 }
711
712 /**
713 * Parse an action_t
714 */
715 CALLBACK(parse_action, bool,
716 action_t *out, chunk_t v)
717 {
718 enum_map_t map[] = {
719 { "start", ACTION_RESTART },
720 { "restart", ACTION_RESTART },
721 { "route", ACTION_ROUTE },
722 { "trap", ACTION_ROUTE },
723 { "none", ACTION_NONE },
724 { "clear", ACTION_NONE },
725 };
726 int d;
727
728 if (parse_map(map, countof(map), &d, v))
729 {
730 *out = d;
731 return TRUE;
732 }
733 return FALSE;
734 }
735
736 /**
737 * Parse a u_int32_t
738 */
739 CALLBACK(parse_uint32, bool,
740 u_int32_t *out, chunk_t v)
741 {
742 char buf[16], *end;
743 u_long l;
744
745 if (!vici_stringify(v, buf, sizeof(buf)))
746 {
747 return FALSE;
748 }
749 l = strtoul(buf, &end, 0);
750 if (*end == 0)
751 {
752 *out = l;
753 return TRUE;
754 }
755 return FALSE;
756 }
757
758 /**
759 * Parse a u_int64_t
760 */
761 CALLBACK(parse_uint64, bool,
762 u_int64_t *out, chunk_t v)
763 {
764 char buf[16], *end;
765 unsigned long long l;
766
767 if (!vici_stringify(v, buf, sizeof(buf)))
768 {
769 return FALSE;
770 }
771 l = strtoull(buf, &end, 0);
772 if (*end == 0)
773 {
774 *out = l;
775 return TRUE;
776 }
777 return FALSE;
778 }
779
780 /**
781 * Parse a relative time
782 */
783 CALLBACK(parse_time, bool,
784 u_int64_t *out, chunk_t v)
785 {
786 char buf[16], *end;
787 u_long l;
788
789 if (!vici_stringify(v, buf, sizeof(buf)))
790 {
791 return FALSE;
792 }
793
794 l = strtoul(buf, &end, 0);
795 while (*end == ' ')
796 {
797 end++;
798 }
799 switch (*end)
800 {
801 case 'd':
802 case 'D':
803 l *= 24;
804 /* fall */
805 case 'h':
806 case 'H':
807 l *= 60;
808 /* fall */
809 case 'm':
810 case 'M':
811 l *= 60;
812 /* fall */
813 case 's':
814 case 'S':
815 end++;
816 break;
817 case '\0':
818 break;
819 default:
820 return FALSE;
821 }
822 if (*end)
823 {
824 return FALSE;
825 }
826 *out = l;
827 return TRUE;
828 }
829
830 /**
831 * Parse byte volume
832 */
833 CALLBACK(parse_bytes, bool,
834 u_int64_t *out, chunk_t v)
835 {
836 char buf[16], *end;
837 unsigned long long l;
838
839 if (!vici_stringify(v, buf, sizeof(buf)))
840 {
841 return FALSE;
842 }
843
844 l = strtoull(buf, &end, 0);
845 while (*end == ' ')
846 {
847 end++;
848 }
849 switch (*end)
850 {
851 case 'g':
852 case 'G':
853 l *= 1024;
854 /* fall */
855 case 'm':
856 case 'M':
857 l *= 1024;
858 /* fall */
859 case 'k':
860 case 'K':
861 l *= 1024;
862 end++;
863 break;
864 case '\0':
865 break;
866 default:
867 return FALSE;
868 }
869 if (*end)
870 {
871 return FALSE;
872 }
873 *out = l;
874 return TRUE;
875 }
876
877 /**
878 * Parse a mark_t
879 */
880 CALLBACK(parse_mark, bool,
881 mark_t *out, chunk_t v)
882 {
883 char buf[32];
884
885 if (!vici_stringify(v, buf, sizeof(buf)))
886 {
887 return FALSE;
888 }
889 return mark_from_string(buf, out);
890 }
891
892 /**
893 * Parse TFC padding option
894 */
895 CALLBACK(parse_tfc, bool,
896 u_int32_t *out, chunk_t v)
897 {
898 if (chunk_equals(v, chunk_from_str("mtu")))
899 {
900 *out = -1;
901 return TRUE;
902 }
903 return parse_uint32(out, v);
904 }
905
906 /**
907 * Parse authentication config
908 */
909 CALLBACK(parse_auth, bool,
910 auth_cfg_t *cfg, chunk_t v)
911 {
912 char buf[64], *pos;
913 eap_vendor_type_t *type;
914
915 if (!vici_stringify(v, buf, sizeof(buf)))
916 {
917 return FALSE;
918 }
919 if (strcaseeq(buf, "pubkey"))
920 {
921 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
922 return TRUE;
923 }
924 if (strcaseeq(buf, "psk"))
925 {
926 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
927 return TRUE;
928 }
929 if (strcasepfx(buf, "xauth"))
930 {
931 pos = strchr(buf, '-');
932 if (pos)
933 {
934 cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
935 }
936 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
937 return TRUE;
938 }
939 if (strcasepfx(buf, "eap"))
940 {
941 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
942
943 type = eap_vendor_type_from_string(buf);
944 if (type)
945 {
946 cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
947 if (type->vendor)
948 {
949 cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
950 }
951 free(type);
952 }
953 return TRUE;
954 }
955 return FALSE;
956 }
957
958 /**
959 * Parse identity; add as auth rule to config
960 */
961 static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
962 {
963 char buf[256];
964
965 if (!vici_stringify(v, buf, sizeof(buf)))
966 {
967 return FALSE;
968 }
969 cfg->add(cfg, rule, identification_create_from_string(buf));
970 return TRUE;
971 }
972
973 /**
974 * Parse IKE identity
975 */
976 CALLBACK(parse_ike_id, bool,
977 auth_cfg_t *cfg, chunk_t v)
978 {
979 return parse_id(cfg, AUTH_RULE_IDENTITY, v);
980 }
981
982 /**
983 * Parse AAA identity
984 */
985 CALLBACK(parse_aaa_id, bool,
986 auth_cfg_t *cfg, chunk_t v)
987 {
988 return parse_id(cfg, AUTH_RULE_AAA_IDENTITY, v);
989 }
990
991 /**
992 * Parse EAP identity
993 */
994 CALLBACK(parse_eap_id, bool,
995 auth_cfg_t *cfg, chunk_t v)
996 {
997 return parse_id(cfg, AUTH_RULE_EAP_IDENTITY, v);
998 }
999
1000 /**
1001 * Parse XAuth identity
1002 */
1003 CALLBACK(parse_xauth_id, bool,
1004 auth_cfg_t *cfg, chunk_t v)
1005 {
1006 return parse_id(cfg, AUTH_RULE_XAUTH_IDENTITY, v);
1007 }
1008
1009 /**
1010 * Parse group membership
1011 */
1012 CALLBACK(parse_group, bool,
1013 auth_cfg_t *cfg, chunk_t v)
1014 {
1015 return parse_id(cfg, AUTH_RULE_GROUP, v);
1016 }
1017
1018 /**
1019 * Parse a certificate; add as auth rule to config
1020 */
1021 static bool parse_cert(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
1022 {
1023 certificate_t *cert;
1024
1025 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
1026 BUILD_BLOB_PEM, v, BUILD_END);
1027 if (cert)
1028 {
1029 cfg->add(cfg, rule, cert);
1030 return TRUE;
1031 }
1032 return FALSE;
1033 }
1034
1035 /**
1036 * Parse subject certificates
1037 */
1038 CALLBACK(parse_certs, bool,
1039 auth_cfg_t *cfg, chunk_t v)
1040 {
1041 return parse_cert(cfg, AUTH_RULE_SUBJECT_CERT, v);
1042 }
1043
1044 /**
1045 * Parse CA certificates
1046 */
1047 CALLBACK(parse_cacerts, bool,
1048 auth_cfg_t *cfg, chunk_t v)
1049 {
1050 return parse_cert(cfg, AUTH_RULE_CA_CERT, v);
1051 }
1052
1053 /**
1054 * Parse revocation status
1055 */
1056 CALLBACK(parse_revocation, bool,
1057 auth_cfg_t *cfg, chunk_t v)
1058 {
1059 enum_map_t map[] = {
1060 { "strict", VALIDATION_GOOD },
1061 { "ifuri", VALIDATION_SKIPPED },
1062 { "relaxed", VALIDATION_FAILED },
1063 };
1064 int d;
1065
1066 if (parse_map(map, countof(map), &d, v))
1067 {
1068 if (d != VALIDATION_FAILED)
1069 {
1070 cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, d);
1071 }
1072 return TRUE;
1073 }
1074 return FALSE;
1075 }
1076
1077 /**
1078 * Parse list items to comma separated strings
1079 */
1080 CALLBACK(parse_stringlist, bool,
1081 char **out, chunk_t v)
1082 {
1083 char *current;
1084
1085 if (!chunk_printable(v, NULL, ' '))
1086 {
1087 return FALSE;
1088 }
1089 current = *out;
1090 if (current)
1091 {
1092 if (asprintf(out, "%s, %.*s", current, (int)v.len, v.ptr) == -1)
1093 {
1094 return FALSE;
1095 }
1096 free(current);
1097 }
1098 else
1099 {
1100 if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
1101 {
1102 return FALSE;
1103 }
1104 }
1105 return TRUE;
1106 }
1107
1108 /**
1109 * Parse an fragmentation_t
1110 */
1111 CALLBACK(parse_frag, bool,
1112 fragmentation_t *out, chunk_t v)
1113 {
1114 enum_map_t map[] = {
1115 { "yes", FRAGMENTATION_YES },
1116 { "no", FRAGMENTATION_NO },
1117 { "force", FRAGMENTATION_FORCE },
1118 };
1119 int d;
1120
1121 if (parse_map(map, countof(map), &d, v))
1122 {
1123 *out = d;
1124 return TRUE;
1125 }
1126 return FALSE;
1127 }
1128
1129 /**
1130 * Parse a cert_policy_t
1131 */
1132 CALLBACK(parse_send_cert, bool,
1133 cert_policy_t *out, chunk_t v)
1134 {
1135 enum_map_t map[] = {
1136 { "ifasked", CERT_SEND_IF_ASKED },
1137 { "always", CERT_ALWAYS_SEND },
1138 { "never", CERT_NEVER_SEND },
1139 };
1140 int d;
1141
1142 if (parse_map(map, countof(map), &d, v))
1143 {
1144 *out = d;
1145 return TRUE;
1146 }
1147 return FALSE;
1148 }
1149
1150 /**
1151 * Parse a unique_policy_t
1152 */
1153 CALLBACK(parse_unique, bool,
1154 unique_policy_t *out, chunk_t v)
1155 {
1156 enum_map_t map[] = {
1157 { "never", UNIQUE_NEVER },
1158 { "no", UNIQUE_NO },
1159 { "replace", UNIQUE_REPLACE },
1160 { "keep", UNIQUE_KEEP },
1161 };
1162 int d;
1163
1164 if (parse_map(map, countof(map), &d, v))
1165 {
1166 *out = d;
1167 return TRUE;
1168 }
1169 return FALSE;
1170 }
1171
1172 /**
1173 * Parse host_t into a list
1174 */
1175 CALLBACK(parse_hosts, bool,
1176 linked_list_t *list, chunk_t v)
1177 {
1178 char buf[64];
1179 host_t *host;
1180
1181 if (!vici_stringify(v, buf, sizeof(buf)))
1182 {
1183 return FALSE;
1184 }
1185 host = host_create_from_string(buf, 0);
1186 if (!host)
1187 {
1188 return FALSE;
1189 }
1190 list->insert_last(list, host);
1191 return TRUE;
1192 }
1193
1194 CALLBACK(child_li, bool,
1195 child_data_t *child, vici_message_t *message, char *name, chunk_t value)
1196 {
1197 parse_rule_t rules[] = {
1198 { "ah_proposals", parse_ah_proposal, child->proposals },
1199 { "esp_proposals", parse_esp_proposal, child->proposals },
1200 { "local_ts", parse_ts, child->local_ts },
1201 { "remote_ts", parse_ts, child->remote_ts },
1202 };
1203
1204 return parse_rules(rules, countof(rules), name, value,
1205 &child->request->reply);
1206 }
1207
1208 CALLBACK(child_kv, bool,
1209 child_data_t *child, vici_message_t *message, char *name, chunk_t value)
1210 {
1211 parse_rule_t rules[] = {
1212 { "updown", parse_string, &child->updown },
1213 { "hostaccess", parse_bool, &child->hostaccess },
1214 { "mode", parse_mode, &child->mode },
1215 { "replay_window", parse_uint32, &child->replay_window },
1216 { "rekey_time", parse_time, &child->lft.time.rekey },
1217 { "life_time", parse_time, &child->lft.time.life },
1218 { "rand_time", parse_time, &child->lft.time.jitter },
1219 { "rekey_bytes", parse_bytes, &child->lft.bytes.rekey },
1220 { "life_bytes", parse_bytes, &child->lft.bytes.life },
1221 { "rand_bytes", parse_bytes, &child->lft.bytes.jitter },
1222 { "rekey_packets", parse_uint64, &child->lft.packets.rekey },
1223 { "life_packets", parse_uint64, &child->lft.packets.life },
1224 { "rand_packets", parse_uint64, &child->lft.packets.jitter },
1225 { "dpd_action", parse_action, &child->dpd_action },
1226 { "start_action", parse_action, &child->start_action },
1227 { "close_action", parse_action, &child->close_action },
1228 { "ipcomp", parse_bool, &child->ipcomp },
1229 { "inactivity", parse_time, &child->inactivity },
1230 { "reqid", parse_uint32, &child->reqid },
1231 { "mark_in", parse_mark, &child->mark_in },
1232 { "mark_out", parse_mark, &child->mark_out },
1233 { "tfc_padding", parse_tfc, &child->tfc },
1234 };
1235
1236 return parse_rules(rules, countof(rules), name, value,
1237 &child->request->reply);
1238 }
1239
1240 CALLBACK(auth_li, bool,
1241 auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
1242 {
1243 parse_rule_t rules[] = {
1244 { "groups", parse_group, auth->cfg },
1245 { "certs", parse_certs, auth->cfg },
1246 { "cacerts", parse_cacerts, auth->cfg },
1247 };
1248
1249 return parse_rules(rules, countof(rules), name, value,
1250 &auth->request->reply);
1251 }
1252
1253 CALLBACK(auth_kv, bool,
1254 auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
1255 {
1256 parse_rule_t rules[] = {
1257 { "auth", parse_auth, auth->cfg },
1258 { "id", parse_ike_id, auth->cfg },
1259 { "aaa_id", parse_aaa_id, auth->cfg },
1260 { "eap_id", parse_eap_id, auth->cfg },
1261 { "xauth_id", parse_xauth_id, auth->cfg },
1262 { "revocation", parse_revocation, auth->cfg },
1263 };
1264
1265 return parse_rules(rules, countof(rules), name, value,
1266 &auth->request->reply);
1267 }
1268
1269 CALLBACK(peer_li, bool,
1270 peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
1271 {
1272 parse_rule_t rules[] = {
1273 { "local_addrs", parse_stringlist, &peer->local_addrs },
1274 { "remote_addrs", parse_stringlist, &peer->remote_addrs },
1275 { "proposals", parse_ike_proposal, peer->proposals },
1276 { "vips", parse_hosts, peer->vips },
1277 { "pools", parse_stringlist, &peer->pools },
1278 };
1279
1280 return parse_rules(rules, countof(rules), name, value,
1281 &peer->request->reply);
1282 }
1283
1284 CALLBACK(peer_kv, bool,
1285 peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
1286 {
1287 parse_rule_t rules[] = {
1288 { "version", parse_uint32, &peer->version },
1289 { "aggressive", parse_bool, &peer->aggressive },
1290 { "pull", parse_bool, &peer->pull },
1291 { "encap", parse_bool, &peer->encap },
1292 { "mobike", parse_bool, &peer->mobike },
1293 { "dpd_delay", parse_time, &peer->dpd_delay },
1294 { "dpd_timeout", parse_time, &peer->dpd_timeout },
1295 { "fragmentation", parse_frag, &peer->fragmentation },
1296 { "send_certreq", parse_bool, &peer->send_certreq },
1297 { "send_cert", parse_send_cert, &peer->send_cert },
1298 { "keyingtries", parse_uint32, &peer->keyingtries },
1299 { "unique", parse_unique, &peer->unique },
1300 { "local_port", parse_uint32, &peer->local_port },
1301 { "remote_port", parse_uint32, &peer->remote_port },
1302 { "reauth_time", parse_time, &peer->reauth_time },
1303 { "rekey_time", parse_time, &peer->rekey_time },
1304 { "over_time", parse_time, &peer->over_time },
1305 { "rand_time", parse_time, &peer->rand_time },
1306 };
1307
1308 return parse_rules(rules, countof(rules), name, value,
1309 &peer->request->reply);
1310 }
1311
1312 CALLBACK(children_sn, bool,
1313 peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
1314 char *name)
1315 {
1316 child_data_t child = {
1317 .request = peer->request,
1318 .proposals = linked_list_create(),
1319 .local_ts = linked_list_create(),
1320 .remote_ts = linked_list_create(),
1321 .mode = MODE_TUNNEL,
1322 .replay_window = REPLAY_UNDEFINED,
1323 .dpd_action = ACTION_NONE,
1324 .start_action = ACTION_NONE,
1325 .close_action = ACTION_NONE,
1326 .lft = {
1327 .time = {
1328 .rekey = LFT_DEFAULT_CHILD_REKEY,
1329 .life = LFT_UNDEFINED,
1330 .jitter = LFT_UNDEFINED,
1331 },
1332 .bytes = {
1333 .life = LFT_UNDEFINED,
1334 .jitter = LFT_UNDEFINED,
1335 },
1336 .packets = {
1337 .life = LFT_UNDEFINED,
1338 .jitter = LFT_UNDEFINED,
1339 },
1340 }
1341 };
1342 child_cfg_t *cfg;
1343 proposal_t *proposal;
1344 traffic_selector_t *ts;
1345
1346 if (!message->parse(message, ctx, NULL, child_kv, child_li, &child))
1347 {
1348 free_child_data(&child);
1349 return FALSE;
1350 }
1351
1352 if (child.local_ts->get_count(child.local_ts) == 0)
1353 {
1354 child.local_ts->insert_last(child.local_ts,
1355 traffic_selector_create_dynamic(0, 0, 65535));
1356 }
1357 if (child.remote_ts->get_count(child.remote_ts) == 0)
1358 {
1359 child.remote_ts->insert_last(child.remote_ts,
1360 traffic_selector_create_dynamic(0, 0, 65535));
1361 }
1362 if (child.proposals->get_count(child.proposals) == 0)
1363 {
1364 proposal = proposal_create_default(PROTO_ESP);
1365 if (proposal)
1366 {
1367 child.proposals->insert_last(child.proposals, proposal);
1368 }
1369 proposal = proposal_create_default_aead(PROTO_ESP);
1370 if (proposal)
1371 {
1372 child.proposals->insert_last(child.proposals, proposal);
1373 }
1374 }
1375
1376 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1377 if (child.lft.time.life == LFT_UNDEFINED)
1378 {
1379 child.lft.time.life = child.lft.time.rekey * 110 / 100;
1380 }
1381 if (child.lft.bytes.life == LFT_UNDEFINED)
1382 {
1383 child.lft.bytes.life = child.lft.bytes.rekey * 110 / 100;
1384 }
1385 if (child.lft.packets.life == LFT_UNDEFINED)
1386 {
1387 child.lft.packets.life = child.lft.packets.rekey * 110 / 100;
1388 }
1389 /* if no rand time defined, use difference of hard and soft */
1390 if (child.lft.time.jitter == LFT_UNDEFINED)
1391 {
1392 child.lft.time.jitter = child.lft.time.life -
1393 min(child.lft.time.life, child.lft.time.rekey);
1394 }
1395 if (child.lft.bytes.jitter == LFT_UNDEFINED)
1396 {
1397 child.lft.bytes.jitter = child.lft.bytes.life -
1398 min(child.lft.bytes.life, child.lft.bytes.rekey);
1399 }
1400 if (child.lft.packets.jitter == LFT_UNDEFINED)
1401 {
1402 child.lft.packets.jitter = child.lft.packets.life -
1403 min(child.lft.packets.life, child.lft.packets.rekey);
1404 }
1405
1406 log_child_data(&child, name);
1407
1408 cfg = child_cfg_create(name, &child.lft, child.updown,
1409 child.hostaccess, child.mode, child.start_action,
1410 child.dpd_action, child.close_action, child.ipcomp,
1411 child.inactivity, child.reqid, &child.mark_in,
1412 &child.mark_out, child.tfc);
1413
1414 if (child.replay_window != REPLAY_UNDEFINED)
1415 {
1416 cfg->set_replay_window(cfg, child.replay_window);
1417 }
1418 while (child.local_ts->remove_first(child.local_ts,
1419 (void**)&ts) == SUCCESS)
1420 {
1421 cfg->add_traffic_selector(cfg, TRUE, ts);
1422 }
1423 while (child.remote_ts->remove_first(child.remote_ts,
1424 (void**)&ts) == SUCCESS)
1425 {
1426 cfg->add_traffic_selector(cfg, FALSE, ts);
1427 }
1428 while (child.proposals->remove_first(child.proposals,
1429 (void**)&proposal) == SUCCESS)
1430 {
1431 cfg->add_proposal(cfg, proposal);
1432 }
1433
1434 peer->children->insert_last(peer->children, cfg);
1435
1436 free_child_data(&child);
1437
1438 return TRUE;
1439 }
1440
1441 CALLBACK(peer_sn, bool,
1442 peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
1443 char *name)
1444 {
1445 if (strcaseeq(name, "children"))
1446 {
1447 return message->parse(message, ctx, children_sn, NULL, NULL, peer);
1448 }
1449 if (strcasepfx(name, "local") ||
1450 strcasepfx(name, "remote"))
1451 {
1452 auth_data_t auth = {
1453 .request = peer->request,
1454 .cfg = auth_cfg_create(),
1455 };
1456
1457 if (!message->parse(message, ctx, NULL, auth_kv, auth_li, &auth))
1458 {
1459 auth.cfg->destroy(auth.cfg);
1460 return FALSE;
1461 }
1462
1463 if (strcasepfx(name, "local"))
1464 {
1465 peer->local->insert_last(peer->local, auth.cfg);
1466 }
1467 else
1468 {
1469 peer->remote->insert_last(peer->remote, auth.cfg);
1470 }
1471 return TRUE;
1472 }
1473 peer->request->reply = create_reply("invalid section: %s", name);
1474 return FALSE;
1475 }
1476
1477 /**
1478 * Find reqid of an existing CHILD_SA
1479 */
1480 static u_int32_t find_reqid(child_cfg_t *cfg)
1481 {
1482 enumerator_t *enumerator, *children;
1483 child_sa_t *child_sa;
1484 ike_sa_t *ike_sa;
1485 u_int32_t reqid;
1486
1487 reqid = charon->traps->find_reqid(charon->traps, cfg);
1488 if (reqid)
1489 { /* already trapped */
1490 return reqid;
1491 }
1492
1493 enumerator = charon->controller->create_ike_sa_enumerator(
1494 charon->controller, TRUE);
1495 while (!reqid && enumerator->enumerate(enumerator, &ike_sa))
1496 {
1497 children = ike_sa->create_child_sa_enumerator(ike_sa);
1498 while (children->enumerate(children, &child_sa))
1499 {
1500 if (streq(cfg->get_name(cfg), child_sa->get_name(child_sa)))
1501 {
1502 reqid = child_sa->get_reqid(child_sa);
1503 break;
1504 }
1505 }
1506 children->destroy(children);
1507 }
1508 enumerator->destroy(enumerator);
1509 return reqid;
1510 }
1511
1512 /**
1513 * Perform start actions associated to a child config
1514 */
1515 static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
1516 child_cfg_t *child_cfg)
1517 {
1518 switch (child_cfg->get_start_action(child_cfg))
1519 {
1520 case ACTION_RESTART:
1521 DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
1522 charon->controller->initiate(charon->controller,
1523 peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
1524 NULL, NULL, 0);
1525 break;
1526 case ACTION_ROUTE:
1527 DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
1528 switch (child_cfg->get_mode(child_cfg))
1529 {
1530 case MODE_PASS:
1531 case MODE_DROP:
1532 charon->shunts->install(charon->shunts, child_cfg);
1533 break;
1534 default:
1535 charon->traps->install(charon->traps, peer_cfg, child_cfg,
1536 find_reqid(child_cfg));
1537 break;
1538 }
1539 break;
1540 default:
1541 break;
1542 }
1543 }
1544
1545 /**
1546 * Undo start actions associated to a child config
1547 */
1548 static void clear_start_action(private_vici_config_t *this,
1549 child_cfg_t *child_cfg)
1550 {
1551 enumerator_t *enumerator, *children;
1552 child_sa_t *child_sa;
1553 ike_sa_t *ike_sa;
1554 u_int32_t id = 0, *del;
1555 array_t *ids = NULL;
1556 char *name;
1557
1558 name = child_cfg->get_name(child_cfg);
1559 switch (child_cfg->get_start_action(child_cfg))
1560 {
1561 case ACTION_RESTART:
1562 enumerator = charon->controller->create_ike_sa_enumerator(
1563 charon->controller, TRUE);
1564 while (enumerator->enumerate(enumerator, &ike_sa))
1565 {
1566 children = ike_sa->create_child_sa_enumerator(ike_sa);
1567 while (children->enumerate(children, &child_sa))
1568 {
1569 if (streq(name, child_sa->get_name(child_sa)))
1570 {
1571 id = child_sa->get_unique_id(child_sa);
1572 array_insert_create(&ids, ARRAY_TAIL, &id);
1573 }
1574 }
1575 children->destroy(children);
1576 }
1577 enumerator->destroy(enumerator);
1578
1579 if (array_count(ids))
1580 {
1581 while (array_remove(ids, ARRAY_HEAD, &del))
1582 {
1583 DBG1(DBG_CFG, "closing '%s' #%u", name, *del);
1584 charon->controller->terminate_child(charon->controller,
1585 *del, NULL, NULL, 0);
1586 }
1587 array_destroy(ids);
1588 }
1589 break;
1590 case ACTION_ROUTE:
1591 DBG1(DBG_CFG, "uninstalling '%s'", name);
1592 switch (child_cfg->get_mode(child_cfg))
1593 {
1594 case MODE_PASS:
1595 case MODE_DROP:
1596 charon->shunts->uninstall(charon->shunts, name);
1597 break;
1598 default:
1599 enumerator = charon->traps->create_enumerator(charon->traps);
1600 while (enumerator->enumerate(enumerator, NULL, &child_sa))
1601 {
1602 if (streq(name, child_sa->get_name(child_sa)))
1603 {
1604 id = child_sa->get_reqid(child_sa);
1605 break;
1606 }
1607 }
1608 enumerator->destroy(enumerator);
1609 if (id)
1610 {
1611 charon->traps->uninstall(charon->traps, id);
1612 }
1613 break;
1614 }
1615 break;
1616 default:
1617 break;
1618 }
1619 }
1620
1621 /**
1622 * Run start actions associated to all child configs of a peer config
1623 */
1624 static void run_start_actions(private_vici_config_t *this, peer_cfg_t *peer_cfg)
1625 {
1626 enumerator_t *enumerator;
1627 child_cfg_t *child_cfg;
1628
1629 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
1630 while (enumerator->enumerate(enumerator, &child_cfg))
1631 {
1632 run_start_action(this, peer_cfg, child_cfg);
1633 }
1634 enumerator->destroy(enumerator);
1635 }
1636
1637 /**
1638 * Undo start actions associated to all child configs of a peer config
1639 */
1640 static void clear_start_actions(private_vici_config_t *this,
1641 peer_cfg_t *peer_cfg)
1642 {
1643 enumerator_t *enumerator;
1644 child_cfg_t *child_cfg;
1645
1646 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
1647 while (enumerator->enumerate(enumerator, &child_cfg))
1648 {
1649 clear_start_action(this, child_cfg);
1650 }
1651 enumerator->destroy(enumerator);
1652 }
1653
1654 /**
1655 * Replace children of a peer config by a new config
1656 */
1657 static void replace_children(private_vici_config_t *this,
1658 peer_cfg_t *from, peer_cfg_t *to)
1659 {
1660 enumerator_t *enumerator;
1661 child_cfg_t *child;
1662
1663 enumerator = to->create_child_cfg_enumerator(to);
1664 while (enumerator->enumerate(enumerator, &child))
1665 {
1666 to->remove_child_cfg(to, enumerator);
1667 clear_start_action(this, child);
1668 child->destroy(child);
1669 }
1670 enumerator->destroy(enumerator);
1671
1672 enumerator = from->create_child_cfg_enumerator(from);
1673 while (enumerator->enumerate(enumerator, &child))
1674 {
1675 from->remove_child_cfg(from, enumerator);
1676 to->add_child_cfg(to, child);
1677 run_start_action(this, to, child);
1678 }
1679 enumerator->destroy(enumerator);
1680 }
1681
1682 /**
1683 * Merge/replace a peer config with existing configs
1684 */
1685 static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
1686 {
1687 enumerator_t *enumerator;
1688 peer_cfg_t *current;
1689 ike_cfg_t *ike_cfg;
1690 bool merged = FALSE;
1691
1692 this->lock->write_lock(this->lock);
1693
1694 enumerator = this->conns->create_enumerator(this->conns);
1695 while (enumerator->enumerate(enumerator, &current))
1696 {
1697 if (streq(peer_cfg->get_name(peer_cfg), current->get_name(current)))
1698 {
1699 ike_cfg = current->get_ike_cfg(current);
1700 if (peer_cfg->equals(peer_cfg, current) &&
1701 ike_cfg->equals(ike_cfg, peer_cfg->get_ike_cfg(peer_cfg)))
1702 {
1703 DBG1(DBG_CFG, "updated vici connection: %s",
1704 peer_cfg->get_name(peer_cfg));
1705 replace_children(this, peer_cfg, current);
1706 peer_cfg->destroy(peer_cfg);
1707 }
1708 else
1709 {
1710 DBG1(DBG_CFG, "replaced vici connection: %s",
1711 peer_cfg->get_name(peer_cfg));
1712 this->conns->remove_at(this->conns, enumerator);
1713 clear_start_actions(this, current);
1714 current->destroy(current);
1715 this->conns->insert_last(this->conns, peer_cfg);
1716 run_start_actions(this, peer_cfg);
1717 }
1718 merged = TRUE;
1719 break;
1720 }
1721 }
1722 enumerator->destroy(enumerator);
1723
1724 if (!merged)
1725 {
1726 DBG1(DBG_CFG, "added vici connection: %s", peer_cfg->get_name(peer_cfg));
1727 this->conns->insert_last(this->conns, peer_cfg);
1728 run_start_actions(this, peer_cfg);
1729 }
1730
1731 this->lock->unlock(this->lock);
1732 }
1733
1734 CALLBACK(config_sn, bool,
1735 request_data_t *request, vici_message_t *message,
1736 vici_parse_context_t *ctx, char *name)
1737 {
1738 peer_data_t peer = {
1739 .request = request,
1740 .local = linked_list_create(),
1741 .remote = linked_list_create(),
1742 .vips = linked_list_create(),
1743 .children = linked_list_create(),
1744 .proposals = linked_list_create(),
1745 .mobike = TRUE,
1746 .send_certreq = TRUE,
1747 .pull = TRUE,
1748 .send_cert = CERT_SEND_IF_ASKED,
1749 .version = IKE_ANY,
1750 .remote_port = IKEV2_UDP_PORT,
1751 .fragmentation = FRAGMENTATION_NO,
1752 .unique = UNIQUE_NO,
1753 .keyingtries = 1,
1754 .rekey_time = LFT_DEFAULT_IKE_REKEY,
1755 .over_time = LFT_UNDEFINED,
1756 .rand_time = LFT_UNDEFINED,
1757 };
1758 enumerator_t *enumerator;
1759 peer_cfg_t *peer_cfg;
1760 ike_cfg_t *ike_cfg;
1761 child_cfg_t *child_cfg;
1762 auth_cfg_t *auth_cfg;
1763 proposal_t *proposal;
1764 host_t *host;
1765 char *str;
1766
1767 DBG2(DBG_CFG, " conn %s:", name);
1768
1769 if (!message->parse(message, ctx, peer_sn, peer_kv, peer_li, &peer))
1770 {
1771 free_peer_data(&peer);
1772 return FALSE;
1773 }
1774
1775 if (peer.local->get_count(peer.local) == 0)
1776 {
1777 free_peer_data(&peer);
1778 peer.request->reply = create_reply("missing local auth config");
1779 return FALSE;
1780 }
1781 if (peer.remote->get_count(peer.remote) == 0)
1782 {
1783 auth_cfg = auth_cfg_create();
1784 peer.remote->insert_last(peer.remote, auth_cfg);
1785 }
1786 if (peer.proposals->get_count(peer.proposals) == 0)
1787 {
1788 proposal = proposal_create_default(PROTO_IKE);
1789 if (proposal)
1790 {
1791 peer.proposals->insert_last(peer.proposals, proposal);
1792 }
1793 proposal = proposal_create_default_aead(PROTO_IKE);
1794 if (proposal)
1795 {
1796 peer.proposals->insert_last(peer.proposals, proposal);
1797 }
1798 }
1799 if (!peer.local_addrs)
1800 {
1801 peer.local_addrs = strdup("%any");
1802 }
1803 if (!peer.remote_addrs)
1804 {
1805 peer.remote_addrs = strdup("%any");
1806 }
1807 if (!peer.local_port)
1808 {
1809 peer.local_port = charon->socket->get_port(charon->socket, FALSE);
1810 }
1811
1812 if (peer.over_time == LFT_UNDEFINED)
1813 {
1814 /* default over_time to 10% of rekey/reauth time if not given */
1815 peer.over_time = max(peer.rekey_time, peer.reauth_time) / 10;
1816 }
1817 if (peer.rand_time == LFT_UNDEFINED)
1818 {
1819 /* default rand_time to over_time if not given */
1820 peer.rand_time = min(peer.over_time,
1821 max(peer.rekey_time, peer.reauth_time) / 2);
1822 }
1823
1824 log_peer_data(&peer);
1825
1826 ike_cfg = ike_cfg_create(peer.version, peer.send_certreq, peer.encap,
1827 peer.local_addrs, peer.local_port,
1828 peer.remote_addrs, peer.remote_port,
1829 peer.fragmentation, 0);
1830 peer_cfg = peer_cfg_create(name, ike_cfg, peer.send_cert, peer.unique,
1831 peer.keyingtries, peer.rekey_time, peer.reauth_time,
1832 peer.rand_time, peer.over_time, peer.mobike,
1833 peer.aggressive, peer.pull,
1834 peer.dpd_delay, peer.dpd_timeout,
1835 FALSE, NULL, NULL);
1836
1837 while (peer.local->remove_first(peer.local,
1838 (void**)&auth_cfg) == SUCCESS)
1839 {
1840 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
1841 }
1842 while (peer.remote->remove_first(peer.remote,
1843 (void**)&auth_cfg) == SUCCESS)
1844 {
1845 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
1846 }
1847 while (peer.children->remove_first(peer.children,
1848 (void**)&child_cfg) == SUCCESS)
1849 {
1850 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
1851 }
1852 while (peer.proposals->remove_first(peer.proposals,
1853 (void**)&proposal) == SUCCESS)
1854 {
1855 ike_cfg->add_proposal(ike_cfg, proposal);
1856 }
1857 while (peer.vips->remove_first(peer.vips, (void**)&host) == SUCCESS)
1858 {
1859 peer_cfg->add_virtual_ip(peer_cfg, host);
1860 }
1861 if (peer.pools)
1862 {
1863 enumerator = enumerator_create_token(peer.pools, ",", " ");
1864 while (enumerator->enumerate(enumerator, &str))
1865 {
1866 peer_cfg->add_pool(peer_cfg, str);
1867 }
1868 enumerator->destroy(enumerator);
1869 }
1870
1871 free_peer_data(&peer);
1872
1873 merge_config(request->this, peer_cfg);
1874
1875 return TRUE;
1876 }
1877
1878 CALLBACK(load_conn, vici_message_t*,
1879 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
1880 {
1881 request_data_t request = {
1882 .this = this,
1883 };
1884
1885 if (!message->parse(message, NULL, config_sn, NULL, NULL, &request))
1886 {
1887 if (request.reply)
1888 {
1889 return request.reply;
1890 }
1891 return create_reply("parsing request failed");
1892 }
1893 return create_reply(NULL);
1894 }
1895
1896 CALLBACK(unload_conn, vici_message_t*,
1897 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
1898 {
1899 enumerator_t *enumerator;
1900 peer_cfg_t *cfg;
1901 bool found = FALSE;
1902 char *conn;
1903
1904 conn = message->get_str(message, NULL, "name");
1905 if (!conn)
1906 {
1907 return create_reply("missing connection name to unload");
1908 }
1909
1910 this->lock->write_lock(this->lock);
1911 enumerator = this->conns->create_enumerator(this->conns);
1912 while (enumerator->enumerate(enumerator, &cfg))
1913 {
1914 if (streq(cfg->get_name(cfg), conn))
1915 {
1916 this->conns->remove_at(this->conns, enumerator);
1917 cfg->destroy(cfg);
1918 found = TRUE;
1919 break;
1920 }
1921 }
1922 enumerator->destroy(enumerator);
1923 this->lock->unlock(this->lock);
1924
1925 if (!found)
1926 {
1927 return create_reply("connection '%s' not found for unloading", conn);
1928 }
1929 return create_reply(NULL);
1930 }
1931
1932 CALLBACK(get_conns, vici_message_t*,
1933 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
1934 {
1935 vici_builder_t *builder;
1936 enumerator_t *enumerator;
1937 peer_cfg_t *cfg;
1938
1939 builder = vici_builder_create();
1940 builder->begin_list(builder, "conns");
1941
1942 this->lock->read_lock(this->lock);
1943 enumerator = this->conns->create_enumerator(this->conns);
1944 while (enumerator->enumerate(enumerator, &cfg))
1945 {
1946 builder->add_li(builder, "%s", cfg->get_name(cfg));
1947 }
1948 enumerator->destroy(enumerator);
1949 this->lock->unlock(this->lock);
1950
1951 builder->end_list(builder);
1952
1953 return builder->finalize(builder);
1954 }
1955
1956 static void manage_command(private_vici_config_t *this,
1957 char *name, vici_command_cb_t cb, bool reg)
1958 {
1959 this->dispatcher->manage_command(this->dispatcher, name,
1960 reg ? cb : NULL, this);
1961 }
1962
1963 /**
1964 * (Un-)register dispatcher functions
1965 */
1966 static void manage_commands(private_vici_config_t *this, bool reg)
1967 {
1968 manage_command(this, "load-conn", load_conn, reg);
1969 manage_command(this, "unload-conn", unload_conn, reg);
1970 manage_command(this, "get-conns", get_conns, reg);
1971 }
1972
1973 METHOD(vici_config_t, destroy, void,
1974 private_vici_config_t *this)
1975 {
1976 manage_commands(this, FALSE);
1977 this->conns->destroy_offset(this->conns, offsetof(peer_cfg_t, destroy));
1978 this->lock->destroy(this->lock);
1979 free(this);
1980 }
1981
1982 /**
1983 * See header
1984 */
1985 vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher)
1986 {
1987 private_vici_config_t *this;
1988
1989 INIT(this,
1990 .public = {
1991 .backend = {
1992 .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
1993 .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
1994 .get_peer_cfg_by_name = _get_peer_cfg_by_name,
1995 },
1996 .destroy = _destroy,
1997 },
1998 .dispatcher = dispatcher,
1999 .conns = linked_list_create(),
2000 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
2001 );
2002
2003 manage_commands(this, TRUE);
2004
2005 return &this->public;
2006 }