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