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