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