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