Support of IP address ranges in traffic selectors
[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-2016 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 if (strchr(buf, '-'))
650 {
651 host_t *lower, *upper;
652 ts_type_t type;
653
654 if (host_create_from_range(buf, &lower, &upper))
655 {
656 type = (lower->get_family(lower) == AF_INET) ?
657 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
658 ts = traffic_selector_create_from_bytes(proto, type,
659 lower->get_address(lower), from,
660 upper->get_address(upper), to);
661 lower->destroy(lower);
662 upper->destroy(upper);
663 }
664 }
665 else
666 {
667 ts = traffic_selector_create_from_cidr(buf, proto, from, to);
668 }
669 if (!ts)
670 {
671 return FALSE;
672 }
673 out->insert_last(out, ts);
674 return TRUE;
675 }
676
677 /**
678 * Parse a string
679 */
680 CALLBACK(parse_string, bool,
681 char **out, chunk_t v)
682 {
683 if (!chunk_printable(v, NULL, ' '))
684 {
685 return FALSE;
686 }
687 free(*out);
688 *out = NULL;
689 if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
690 {
691 return FALSE;
692 }
693 return TRUE;
694 }
695
696 /**
697 * Map a string to an integer
698 */
699 typedef struct {
700 char *str;
701 int d;
702 } enum_map_t;
703
704 /**
705 * Parse a string to an integer mapping
706 */
707 static bool parse_map(enum_map_t *map, int count, int *out, chunk_t v)
708 {
709 char buf[128];
710 int i;
711
712 if (!vici_stringify(v, buf, sizeof(buf)))
713 {
714 return FALSE;
715 }
716 for (i = 0; i < count; i++)
717 {
718 if (strcaseeq(map[i].str, buf))
719 {
720 *out = map[i].d;
721 return TRUE;
722 }
723 }
724 return FALSE;
725 }
726
727 /**
728 * Parse a boolean
729 */
730 CALLBACK(parse_bool, bool,
731 bool *out, chunk_t v)
732 {
733 enum_map_t map[] = {
734 { "yes", TRUE },
735 { "true", TRUE },
736 { "enabled", TRUE },
737 { "1", TRUE },
738 { "no", FALSE },
739 { "false", FALSE },
740 { "disabled", FALSE },
741 { "0", FALSE },
742 };
743 int d;
744
745 if (parse_map(map, countof(map), &d, v))
746 {
747 *out = d;
748 return TRUE;
749 }
750 return FALSE;
751 }
752
753 /**
754 * Parse a ipsec_mode_t
755 */
756 CALLBACK(parse_mode, bool,
757 ipsec_mode_t *out, chunk_t v)
758 {
759 enum_map_t map[] = {
760 { "tunnel", MODE_TUNNEL },
761 { "transport", MODE_TRANSPORT },
762 { "beet", MODE_BEET },
763 { "drop", MODE_DROP },
764 { "pass", MODE_PASS },
765 };
766 int d;
767
768 if (parse_map(map, countof(map), &d, v))
769 {
770 *out = d;
771 return TRUE;
772 }
773 return FALSE;
774 }
775
776 /**
777 * Parse an action_t
778 */
779 CALLBACK(parse_action, bool,
780 action_t *out, chunk_t v)
781 {
782 enum_map_t map[] = {
783 { "start", ACTION_RESTART },
784 { "restart", ACTION_RESTART },
785 { "route", ACTION_ROUTE },
786 { "trap", ACTION_ROUTE },
787 { "none", ACTION_NONE },
788 { "clear", ACTION_NONE },
789 };
790 int d;
791
792 if (parse_map(map, countof(map), &d, v))
793 {
794 *out = d;
795 return TRUE;
796 }
797 return FALSE;
798 }
799
800 /**
801 * Parse a u_int32_t
802 */
803 CALLBACK(parse_uint32, bool,
804 u_int32_t *out, chunk_t v)
805 {
806 char buf[16], *end;
807 u_long l;
808
809 if (!vici_stringify(v, buf, sizeof(buf)))
810 {
811 return FALSE;
812 }
813 l = strtoul(buf, &end, 0);
814 if (*end == 0)
815 {
816 *out = l;
817 return TRUE;
818 }
819 return FALSE;
820 }
821
822 /**
823 * Parse a u_int64_t
824 */
825 CALLBACK(parse_uint64, bool,
826 u_int64_t *out, chunk_t v)
827 {
828 char buf[16], *end;
829 unsigned long long l;
830
831 if (!vici_stringify(v, buf, sizeof(buf)))
832 {
833 return FALSE;
834 }
835 l = strtoull(buf, &end, 0);
836 if (*end == 0)
837 {
838 *out = l;
839 return TRUE;
840 }
841 return FALSE;
842 }
843
844 /**
845 * Parse a relative time
846 */
847 CALLBACK(parse_time, bool,
848 u_int64_t *out, chunk_t v)
849 {
850 char buf[16], *end;
851 u_long l;
852
853 if (!vici_stringify(v, buf, sizeof(buf)))
854 {
855 return FALSE;
856 }
857
858 l = strtoul(buf, &end, 0);
859 while (*end == ' ')
860 {
861 end++;
862 }
863 switch (*end)
864 {
865 case 'd':
866 case 'D':
867 l *= 24;
868 /* fall */
869 case 'h':
870 case 'H':
871 l *= 60;
872 /* fall */
873 case 'm':
874 case 'M':
875 l *= 60;
876 /* fall */
877 case 's':
878 case 'S':
879 end++;
880 break;
881 case '\0':
882 break;
883 default:
884 return FALSE;
885 }
886 if (*end)
887 {
888 return FALSE;
889 }
890 *out = l;
891 return TRUE;
892 }
893
894 /**
895 * Parse byte volume
896 */
897 CALLBACK(parse_bytes, bool,
898 u_int64_t *out, chunk_t v)
899 {
900 char buf[16], *end;
901 unsigned long long l;
902
903 if (!vici_stringify(v, buf, sizeof(buf)))
904 {
905 return FALSE;
906 }
907
908 l = strtoull(buf, &end, 0);
909 while (*end == ' ')
910 {
911 end++;
912 }
913 switch (*end)
914 {
915 case 'g':
916 case 'G':
917 l *= 1024;
918 /* fall */
919 case 'm':
920 case 'M':
921 l *= 1024;
922 /* fall */
923 case 'k':
924 case 'K':
925 l *= 1024;
926 end++;
927 break;
928 case '\0':
929 break;
930 default:
931 return FALSE;
932 }
933 if (*end)
934 {
935 return FALSE;
936 }
937 *out = l;
938 return TRUE;
939 }
940
941 /**
942 * Parse a mark_t
943 */
944 CALLBACK(parse_mark, bool,
945 mark_t *out, chunk_t v)
946 {
947 char buf[32];
948
949 if (!vici_stringify(v, buf, sizeof(buf)))
950 {
951 return FALSE;
952 }
953 return mark_from_string(buf, out);
954 }
955
956 /**
957 * Parse TFC padding option
958 */
959 CALLBACK(parse_tfc, bool,
960 u_int32_t *out, chunk_t v)
961 {
962 if (chunk_equals(v, chunk_from_str("mtu")))
963 {
964 *out = -1;
965 return TRUE;
966 }
967 return parse_uint32(out, v);
968 }
969
970 /**
971 * Parse authentication config
972 */
973 CALLBACK(parse_auth, bool,
974 auth_cfg_t *cfg, chunk_t v)
975 {
976 char buf[64], *pos;
977 eap_vendor_type_t *type;
978
979 if (!vici_stringify(v, buf, sizeof(buf)))
980 {
981 return FALSE;
982 }
983 if (strpfx(buf, "ike:") ||
984 strpfx(buf, "pubkey") ||
985 strpfx(buf, "rsa") ||
986 strpfx(buf, "ecdsa") ||
987 strpfx(buf, "bliss"))
988 {
989 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
990 cfg->add_pubkey_constraints(cfg, buf, TRUE);
991 return TRUE;
992 }
993 if (strcaseeq(buf, "psk"))
994 {
995 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
996 return TRUE;
997 }
998 if (strcasepfx(buf, "xauth"))
999 {
1000 pos = strchr(buf, '-');
1001 if (pos)
1002 {
1003 cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
1004 }
1005 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
1006 return TRUE;
1007 }
1008 if (strcasepfx(buf, "eap"))
1009 {
1010 char *pos;
1011
1012 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
1013
1014 pos = strchr(buf, ':');
1015 if (pos)
1016 {
1017 *pos = 0;
1018 cfg->add_pubkey_constraints(cfg, pos + 1, FALSE);
1019 }
1020 type = eap_vendor_type_from_string(buf);
1021 if (type)
1022 {
1023 cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
1024 if (type->vendor)
1025 {
1026 cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
1027 }
1028 free(type);
1029 }
1030 return TRUE;
1031 }
1032 return FALSE;
1033 }
1034
1035 /**
1036 * Parse identity; add as auth rule to config
1037 */
1038 static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
1039 {
1040 char buf[256];
1041
1042 if (!vici_stringify(v, buf, sizeof(buf)))
1043 {
1044 return FALSE;
1045 }
1046 cfg->add(cfg, rule, identification_create_from_string(buf));
1047 return TRUE;
1048 }
1049
1050 /**
1051 * Parse IKE identity
1052 */
1053 CALLBACK(parse_ike_id, bool,
1054 auth_cfg_t *cfg, chunk_t v)
1055 {
1056 return parse_id(cfg, AUTH_RULE_IDENTITY, v);
1057 }
1058
1059 /**
1060 * Parse AAA identity
1061 */
1062 CALLBACK(parse_aaa_id, bool,
1063 auth_cfg_t *cfg, chunk_t v)
1064 {
1065 return parse_id(cfg, AUTH_RULE_AAA_IDENTITY, v);
1066 }
1067
1068 /**
1069 * Parse EAP identity
1070 */
1071 CALLBACK(parse_eap_id, bool,
1072 auth_cfg_t *cfg, chunk_t v)
1073 {
1074 return parse_id(cfg, AUTH_RULE_EAP_IDENTITY, v);
1075 }
1076
1077 /**
1078 * Parse XAuth identity
1079 */
1080 CALLBACK(parse_xauth_id, bool,
1081 auth_cfg_t *cfg, chunk_t v)
1082 {
1083 return parse_id(cfg, AUTH_RULE_XAUTH_IDENTITY, v);
1084 }
1085
1086 /**
1087 * Parse group membership
1088 */
1089 CALLBACK(parse_group, bool,
1090 auth_cfg_t *cfg, chunk_t v)
1091 {
1092 return parse_id(cfg, AUTH_RULE_GROUP, v);
1093 }
1094
1095 /**
1096 * Parse a certificate; add as auth rule to config
1097 */
1098 static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
1099 {
1100 vici_authority_t *authority;
1101 vici_cred_t *cred;
1102 certificate_t *cert;
1103
1104 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
1105 BUILD_BLOB_PEM, v, BUILD_END);
1106 if (cert)
1107 {
1108 if (rule == AUTH_RULE_SUBJECT_CERT)
1109 {
1110 authority = auth->request->this->authority;
1111 authority->check_for_hash_and_url(authority, cert);
1112 }
1113 cred = auth->request->this->cred;
1114 cert = cred->add_cert(cred, cert);
1115 auth->cfg->add(auth->cfg, rule, cert);
1116 return TRUE;
1117 }
1118 return FALSE;
1119 }
1120
1121 /**
1122 * Parse subject certificates
1123 */
1124 CALLBACK(parse_certs, bool,
1125 auth_data_t *auth, chunk_t v)
1126 {
1127 return parse_cert(auth, AUTH_RULE_SUBJECT_CERT, v);
1128 }
1129
1130 /**
1131 * Parse CA certificates
1132 */
1133 CALLBACK(parse_cacerts, bool,
1134 auth_data_t *auth, chunk_t v)
1135 {
1136 return parse_cert(auth, AUTH_RULE_CA_CERT, v);
1137 }
1138
1139 /**
1140 * Parse raw public keys
1141 */
1142 CALLBACK(parse_pubkeys, bool,
1143 auth_data_t *auth, chunk_t v)
1144 {
1145 vici_cred_t *cred;
1146 certificate_t *cert;
1147
1148 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
1149 BUILD_BLOB_PEM, v, BUILD_END);
1150 if (cert)
1151 {
1152 cred = auth->request->this->cred;
1153 cert = cred->add_cert(cred, cert);
1154 auth->cfg->add(auth->cfg, AUTH_RULE_SUBJECT_CERT, cert);
1155 return TRUE;
1156 }
1157 return FALSE;
1158 }
1159
1160 /**
1161 * Parse revocation status
1162 */
1163 CALLBACK(parse_revocation, bool,
1164 auth_cfg_t *cfg, chunk_t v)
1165 {
1166 enum_map_t map[] = {
1167 { "strict", VALIDATION_GOOD },
1168 { "ifuri", VALIDATION_SKIPPED },
1169 { "relaxed", VALIDATION_FAILED },
1170 };
1171 int d;
1172
1173 if (parse_map(map, countof(map), &d, v))
1174 {
1175 if (d != VALIDATION_FAILED)
1176 {
1177 cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, d);
1178 }
1179 return TRUE;
1180 }
1181 return FALSE;
1182 }
1183
1184 /**
1185 * Parse list items to comma separated strings
1186 */
1187 CALLBACK(parse_stringlist, bool,
1188 char **out, chunk_t v)
1189 {
1190 char *current;
1191
1192 if (!chunk_printable(v, NULL, ' '))
1193 {
1194 return FALSE;
1195 }
1196 current = *out;
1197 if (current)
1198 {
1199 if (asprintf(out, "%s, %.*s", current, (int)v.len, v.ptr) == -1)
1200 {
1201 return FALSE;
1202 }
1203 free(current);
1204 }
1205 else
1206 {
1207 if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
1208 {
1209 return FALSE;
1210 }
1211 }
1212 return TRUE;
1213 }
1214
1215 /**
1216 * Parse an fragmentation_t
1217 */
1218 CALLBACK(parse_frag, bool,
1219 fragmentation_t *out, chunk_t v)
1220 {
1221 enum_map_t map[] = {
1222 { "yes", FRAGMENTATION_YES },
1223 { "no", FRAGMENTATION_NO },
1224 { "force", FRAGMENTATION_FORCE },
1225 };
1226 int d;
1227
1228 if (parse_map(map, countof(map), &d, v))
1229 {
1230 *out = d;
1231 return TRUE;
1232 }
1233 return FALSE;
1234 }
1235
1236 /**
1237 * Parse a cert_policy_t
1238 */
1239 CALLBACK(parse_send_cert, bool,
1240 cert_policy_t *out, chunk_t v)
1241 {
1242 enum_map_t map[] = {
1243 { "ifasked", CERT_SEND_IF_ASKED },
1244 { "always", CERT_ALWAYS_SEND },
1245 { "never", CERT_NEVER_SEND },
1246 };
1247 int d;
1248
1249 if (parse_map(map, countof(map), &d, v))
1250 {
1251 *out = d;
1252 return TRUE;
1253 }
1254 return FALSE;
1255 }
1256
1257 /**
1258 * Parse a unique_policy_t
1259 */
1260 CALLBACK(parse_unique, bool,
1261 unique_policy_t *out, chunk_t v)
1262 {
1263 enum_map_t map[] = {
1264 { "never", UNIQUE_NEVER },
1265 { "no", UNIQUE_NO },
1266 { "replace", UNIQUE_REPLACE },
1267 { "keep", UNIQUE_KEEP },
1268 };
1269 int d;
1270
1271 if (parse_map(map, countof(map), &d, v))
1272 {
1273 *out = d;
1274 return TRUE;
1275 }
1276 return FALSE;
1277 }
1278
1279 /**
1280 * Parse host_t into a list
1281 */
1282 CALLBACK(parse_hosts, bool,
1283 linked_list_t *list, chunk_t v)
1284 {
1285 char buf[64];
1286 host_t *host;
1287
1288 if (!vici_stringify(v, buf, sizeof(buf)))
1289 {
1290 return FALSE;
1291 }
1292 host = host_create_from_string(buf, 0);
1293 if (!host)
1294 {
1295 return FALSE;
1296 }
1297 list->insert_last(list, host);
1298 return TRUE;
1299 }
1300
1301 CALLBACK(child_li, bool,
1302 child_data_t *child, vici_message_t *message, char *name, chunk_t value)
1303 {
1304 parse_rule_t rules[] = {
1305 { "ah_proposals", parse_ah_proposal, child->proposals },
1306 { "esp_proposals", parse_esp_proposal, child->proposals },
1307 { "local_ts", parse_ts, child->local_ts },
1308 { "remote_ts", parse_ts, child->remote_ts },
1309 };
1310
1311 return parse_rules(rules, countof(rules), name, value,
1312 &child->request->reply);
1313 }
1314
1315 CALLBACK(child_kv, bool,
1316 child_data_t *child, vici_message_t *message, char *name, chunk_t value)
1317 {
1318 parse_rule_t rules[] = {
1319 { "updown", parse_string, &child->updown },
1320 { "hostaccess", parse_bool, &child->hostaccess },
1321 { "mode", parse_mode, &child->mode },
1322 { "policies", parse_bool, &child->policies },
1323 { "replay_window", parse_uint32, &child->replay_window },
1324 { "rekey_time", parse_time, &child->lft.time.rekey },
1325 { "life_time", parse_time, &child->lft.time.life },
1326 { "rand_time", parse_time, &child->lft.time.jitter },
1327 { "rekey_bytes", parse_bytes, &child->lft.bytes.rekey },
1328 { "life_bytes", parse_bytes, &child->lft.bytes.life },
1329 { "rand_bytes", parse_bytes, &child->lft.bytes.jitter },
1330 { "rekey_packets", parse_uint64, &child->lft.packets.rekey },
1331 { "life_packets", parse_uint64, &child->lft.packets.life },
1332 { "rand_packets", parse_uint64, &child->lft.packets.jitter },
1333 { "dpd_action", parse_action, &child->dpd_action },
1334 { "start_action", parse_action, &child->start_action },
1335 { "close_action", parse_action, &child->close_action },
1336 { "ipcomp", parse_bool, &child->ipcomp },
1337 { "inactivity", parse_time, &child->inactivity },
1338 { "reqid", parse_uint32, &child->reqid },
1339 { "mark_in", parse_mark, &child->mark_in },
1340 { "mark_out", parse_mark, &child->mark_out },
1341 { "tfc_padding", parse_tfc, &child->tfc },
1342 };
1343
1344 return parse_rules(rules, countof(rules), name, value,
1345 &child->request->reply);
1346 }
1347
1348 CALLBACK(auth_li, bool,
1349 auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
1350 {
1351 parse_rule_t rules[] = {
1352 { "groups", parse_group, auth->cfg },
1353 { "certs", parse_certs, auth },
1354 { "cacerts", parse_cacerts, auth },
1355 { "pubkeys", parse_pubkeys, auth },
1356 };
1357
1358 return parse_rules(rules, countof(rules), name, value,
1359 &auth->request->reply);
1360 }
1361
1362 CALLBACK(auth_kv, bool,
1363 auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
1364 {
1365 parse_rule_t rules[] = {
1366 { "auth", parse_auth, auth->cfg },
1367 { "id", parse_ike_id, auth->cfg },
1368 { "aaa_id", parse_aaa_id, auth->cfg },
1369 { "eap_id", parse_eap_id, auth->cfg },
1370 { "xauth_id", parse_xauth_id, auth->cfg },
1371 { "revocation", parse_revocation, auth->cfg },
1372 { "round", parse_uint32, &auth->round },
1373 };
1374
1375 return parse_rules(rules, countof(rules), name, value,
1376 &auth->request->reply);
1377 }
1378
1379 CALLBACK(peer_li, bool,
1380 peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
1381 {
1382 parse_rule_t rules[] = {
1383 { "local_addrs", parse_stringlist, &peer->local_addrs },
1384 { "remote_addrs", parse_stringlist, &peer->remote_addrs },
1385 { "proposals", parse_ike_proposal, peer->proposals },
1386 { "vips", parse_hosts, peer->vips },
1387 { "pools", parse_stringlist, &peer->pools },
1388 };
1389
1390 return parse_rules(rules, countof(rules), name, value,
1391 &peer->request->reply);
1392 }
1393
1394 CALLBACK(peer_kv, bool,
1395 peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
1396 {
1397 parse_rule_t rules[] = {
1398 { "version", parse_uint32, &peer->version },
1399 { "aggressive", parse_bool, &peer->aggressive },
1400 { "pull", parse_bool, &peer->pull },
1401 { "encap", parse_bool, &peer->encap },
1402 { "mobike", parse_bool, &peer->mobike },
1403 { "dpd_delay", parse_time, &peer->dpd_delay },
1404 { "dpd_timeout", parse_time, &peer->dpd_timeout },
1405 { "fragmentation", parse_frag, &peer->fragmentation },
1406 { "send_certreq", parse_bool, &peer->send_certreq },
1407 { "send_cert", parse_send_cert, &peer->send_cert },
1408 { "keyingtries", parse_uint32, &peer->keyingtries },
1409 { "unique", parse_unique, &peer->unique },
1410 { "local_port", parse_uint32, &peer->local_port },
1411 { "remote_port", parse_uint32, &peer->remote_port },
1412 { "reauth_time", parse_time, &peer->reauth_time },
1413 { "rekey_time", parse_time, &peer->rekey_time },
1414 { "over_time", parse_time, &peer->over_time },
1415 { "rand_time", parse_time, &peer->rand_time },
1416 };
1417
1418 return parse_rules(rules, countof(rules), name, value,
1419 &peer->request->reply);
1420 }
1421
1422 CALLBACK(children_sn, bool,
1423 peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
1424 char *name)
1425 {
1426 child_data_t child = {
1427 .request = peer->request,
1428 .proposals = linked_list_create(),
1429 .local_ts = linked_list_create(),
1430 .remote_ts = linked_list_create(),
1431 .mode = MODE_TUNNEL,
1432 .policies = TRUE,
1433 .replay_window = REPLAY_UNDEFINED,
1434 .dpd_action = ACTION_NONE,
1435 .start_action = ACTION_NONE,
1436 .close_action = ACTION_NONE,
1437 .lft = {
1438 .time = {
1439 .rekey = LFT_DEFAULT_CHILD_REKEY,
1440 .life = LFT_UNDEFINED,
1441 .jitter = LFT_UNDEFINED,
1442 },
1443 .bytes = {
1444 .rekey = LFT_UNDEFINED,
1445 .life = LFT_UNDEFINED,
1446 .jitter = LFT_UNDEFINED,
1447 },
1448 .packets = {
1449 .rekey = LFT_UNDEFINED,
1450 .life = LFT_UNDEFINED,
1451 .jitter = LFT_UNDEFINED,
1452 },
1453 }
1454 };
1455 child_cfg_t *cfg;
1456 proposal_t *proposal;
1457 traffic_selector_t *ts;
1458
1459 if (!message->parse(message, ctx, NULL, child_kv, child_li, &child))
1460 {
1461 free_child_data(&child);
1462 return FALSE;
1463 }
1464
1465 if (child.local_ts->get_count(child.local_ts) == 0)
1466 {
1467 child.local_ts->insert_last(child.local_ts,
1468 traffic_selector_create_dynamic(0, 0, 65535));
1469 }
1470 if (child.remote_ts->get_count(child.remote_ts) == 0)
1471 {
1472 child.remote_ts->insert_last(child.remote_ts,
1473 traffic_selector_create_dynamic(0, 0, 65535));
1474 }
1475 if (child.proposals->get_count(child.proposals) == 0)
1476 {
1477 proposal = proposal_create_default(PROTO_ESP);
1478 if (proposal)
1479 {
1480 child.proposals->insert_last(child.proposals, proposal);
1481 }
1482 proposal = proposal_create_default_aead(PROTO_ESP);
1483 if (proposal)
1484 {
1485 child.proposals->insert_last(child.proposals, proposal);
1486 }
1487 }
1488
1489 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1490 if (child.lft.time.life == LFT_UNDEFINED)
1491 {
1492 child.lft.time.life = child.lft.time.rekey * 110 / 100;
1493 }
1494 if (child.lft.bytes.life == LFT_UNDEFINED)
1495 {
1496 child.lft.bytes.life = child.lft.bytes.rekey * 110 / 100;
1497 }
1498 if (child.lft.packets.life == LFT_UNDEFINED)
1499 {
1500 child.lft.packets.life = child.lft.packets.rekey * 110 / 100;
1501 }
1502 /* if no soft lifetime specified, add one at hard lifetime - 10% */
1503 if (child.lft.bytes.rekey == LFT_UNDEFINED)
1504 {
1505 child.lft.bytes.rekey = child.lft.bytes.life * 90 / 100;
1506 }
1507 if (child.lft.packets.rekey == LFT_UNDEFINED)
1508 {
1509 child.lft.packets.rekey = child.lft.packets.life * 90 / 100;
1510 }
1511 /* if no rand time defined, use difference of hard and soft */
1512 if (child.lft.time.jitter == LFT_UNDEFINED)
1513 {
1514 child.lft.time.jitter = child.lft.time.life -
1515 min(child.lft.time.life, child.lft.time.rekey);
1516 }
1517 if (child.lft.bytes.jitter == LFT_UNDEFINED)
1518 {
1519 child.lft.bytes.jitter = child.lft.bytes.life -
1520 min(child.lft.bytes.life, child.lft.bytes.rekey);
1521 }
1522 if (child.lft.packets.jitter == LFT_UNDEFINED)
1523 {
1524 child.lft.packets.jitter = child.lft.packets.life -
1525 min(child.lft.packets.life, child.lft.packets.rekey);
1526 }
1527
1528 log_child_data(&child, name);
1529
1530 cfg = child_cfg_create(name, &child.lft, child.updown,
1531 child.hostaccess, child.mode, child.start_action,
1532 child.dpd_action, child.close_action, child.ipcomp,
1533 child.inactivity, child.reqid, &child.mark_in,
1534 &child.mark_out, child.tfc);
1535
1536 cfg->set_mipv6_options(cfg, FALSE, child.policies);
1537
1538 if (child.replay_window != REPLAY_UNDEFINED)
1539 {
1540 cfg->set_replay_window(cfg, child.replay_window);
1541 }
1542 while (child.local_ts->remove_first(child.local_ts,
1543 (void**)&ts) == SUCCESS)
1544 {
1545 cfg->add_traffic_selector(cfg, TRUE, ts);
1546 }
1547 while (child.remote_ts->remove_first(child.remote_ts,
1548 (void**)&ts) == SUCCESS)
1549 {
1550 cfg->add_traffic_selector(cfg, FALSE, ts);
1551 }
1552 while (child.proposals->remove_first(child.proposals,
1553 (void**)&proposal) == SUCCESS)
1554 {
1555 cfg->add_proposal(cfg, proposal);
1556 }
1557
1558 peer->children->insert_last(peer->children, cfg);
1559
1560 free_child_data(&child);
1561
1562 return TRUE;
1563 }
1564
1565 CALLBACK(peer_sn, bool,
1566 peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
1567 char *name)
1568 {
1569 if (strcaseeq(name, "children"))
1570 {
1571 return message->parse(message, ctx, children_sn, NULL, NULL, peer);
1572 }
1573 if (strcasepfx(name, "local") ||
1574 strcasepfx(name, "remote"))
1575 {
1576 enumerator_t *enumerator;
1577 linked_list_t *auths;
1578 auth_data_t *auth, *current;
1579 auth_rule_t rule;
1580 certificate_t *cert;
1581 pubkey_cert_t *pubkey_cert;
1582 identification_t *id;
1583 bool default_id = FALSE;
1584
1585 INIT(auth,
1586 .request = peer->request,
1587 .cfg = auth_cfg_create(),
1588 );
1589
1590 if (!message->parse(message, ctx, NULL, auth_kv, auth_li, auth))
1591 {
1592 free_auth_data(auth);
1593 return FALSE;
1594 }
1595 id = auth->cfg->get(auth->cfg, AUTH_RULE_IDENTITY);
1596
1597 enumerator = auth->cfg->create_enumerator(auth->cfg);
1598 while (enumerator->enumerate(enumerator, &rule, &cert))
1599 {
1600 if (rule == AUTH_RULE_SUBJECT_CERT && !default_id)
1601 {
1602 if (id == NULL)
1603 {
1604 id = cert->get_subject(cert);
1605 DBG1(DBG_CFG, " id not specified, defaulting to"
1606 " cert subject '%Y'", id);
1607 auth->cfg->add(auth->cfg, AUTH_RULE_IDENTITY, id->clone(id));
1608 default_id = TRUE;
1609 }
1610 else if (cert->get_type(cert) == CERT_TRUSTED_PUBKEY &&
1611 id->get_type != ID_ANY)
1612 {
1613 /* set the subject of all raw public keys to the id */
1614 pubkey_cert = (pubkey_cert_t*)cert;
1615 pubkey_cert->set_subject(pubkey_cert, id);
1616 }
1617 }
1618 }
1619 enumerator->destroy(enumerator);
1620
1621 auths = strcasepfx(name, "local") ? peer->local : peer->remote;
1622 enumerator = auths->create_enumerator(auths);
1623 while (enumerator->enumerate(enumerator, &current))
1624 {
1625 if (auth->round < current->round)
1626 {
1627 break;
1628 }
1629 }
1630 auths->insert_before(auths, enumerator, auth);
1631 enumerator->destroy(enumerator);
1632 return TRUE;
1633 }
1634 peer->request->reply = create_reply("invalid section: %s", name);
1635 return FALSE;
1636 }
1637
1638 /**
1639 * Find reqid of an existing CHILD_SA
1640 */
1641 static u_int32_t find_reqid(child_cfg_t *cfg)
1642 {
1643 enumerator_t *enumerator, *children;
1644 child_sa_t *child_sa;
1645 ike_sa_t *ike_sa;
1646 u_int32_t reqid;
1647
1648 reqid = charon->traps->find_reqid(charon->traps, cfg);
1649 if (reqid)
1650 { /* already trapped */
1651 return reqid;
1652 }
1653
1654 enumerator = charon->controller->create_ike_sa_enumerator(
1655 charon->controller, TRUE);
1656 while (!reqid && enumerator->enumerate(enumerator, &ike_sa))
1657 {
1658 children = ike_sa->create_child_sa_enumerator(ike_sa);
1659 while (children->enumerate(children, &child_sa))
1660 {
1661 if (streq(cfg->get_name(cfg), child_sa->get_name(child_sa)))
1662 {
1663 reqid = child_sa->get_reqid(child_sa);
1664 break;
1665 }
1666 }
1667 children->destroy(children);
1668 }
1669 enumerator->destroy(enumerator);
1670 return reqid;
1671 }
1672
1673 /**
1674 * Perform start actions associated to a child config
1675 */
1676 static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
1677 child_cfg_t *child_cfg)
1678 {
1679 switch (child_cfg->get_start_action(child_cfg))
1680 {
1681 case ACTION_RESTART:
1682 DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
1683 charon->controller->initiate(charon->controller,
1684 peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
1685 NULL, NULL, 0, FALSE);
1686 break;
1687 case ACTION_ROUTE:
1688 DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
1689 switch (child_cfg->get_mode(child_cfg))
1690 {
1691 case MODE_PASS:
1692 case MODE_DROP:
1693 charon->shunts->install(charon->shunts, child_cfg);
1694 break;
1695 default:
1696 charon->traps->install(charon->traps, peer_cfg, child_cfg,
1697 find_reqid(child_cfg));
1698 break;
1699 }
1700 break;
1701 default:
1702 break;
1703 }
1704 }
1705
1706 /**
1707 * Undo start actions associated to a child config
1708 */
1709 static void clear_start_action(private_vici_config_t *this, char *peer_name,
1710 child_cfg_t *child_cfg)
1711 {
1712 enumerator_t *enumerator, *children;
1713 child_sa_t *child_sa;
1714 ike_sa_t *ike_sa;
1715 u_int32_t id = 0, others;
1716 array_t *ids = NULL, *ikeids = NULL;
1717 char *name;
1718
1719 name = child_cfg->get_name(child_cfg);
1720 switch (child_cfg->get_start_action(child_cfg))
1721 {
1722 case ACTION_RESTART:
1723 enumerator = charon->controller->create_ike_sa_enumerator(
1724 charon->controller, TRUE);
1725 while (enumerator->enumerate(enumerator, &ike_sa))
1726 {
1727 if (!streq(ike_sa->get_name(ike_sa), peer_name))
1728 {
1729 continue;
1730 }
1731 others = id = 0;
1732 children = ike_sa->create_child_sa_enumerator(ike_sa);
1733 while (children->enumerate(children, &child_sa))
1734 {
1735 if (child_sa->get_state(child_sa) != CHILD_DELETING)
1736 {
1737 if (streq(name, child_sa->get_name(child_sa)))
1738 {
1739 id = child_sa->get_unique_id(child_sa);
1740 }
1741 else
1742 {
1743 others++;
1744 }
1745 }
1746 }
1747 children->destroy(children);
1748
1749 if (id && !others)
1750 {
1751 /* found matching children only, delete full IKE_SA */
1752 id = ike_sa->get_unique_id(ike_sa);
1753 array_insert_create_value(&ikeids, sizeof(id),
1754 ARRAY_TAIL, &id);
1755 }
1756 else
1757 {
1758 children = ike_sa->create_child_sa_enumerator(ike_sa);
1759 while (children->enumerate(children, &child_sa))
1760 {
1761 if (streq(name, child_sa->get_name(child_sa)))
1762 {
1763 id = child_sa->get_unique_id(child_sa);
1764 array_insert_create_value(&ids, sizeof(id),
1765 ARRAY_TAIL, &id);
1766 }
1767 }
1768 children->destroy(children);
1769 }
1770 }
1771 enumerator->destroy(enumerator);
1772
1773 if (array_count(ids))
1774 {
1775 while (array_remove(ids, ARRAY_HEAD, &id))
1776 {
1777 DBG1(DBG_CFG, "closing '%s' #%u", name, id);
1778 charon->controller->terminate_child(charon->controller,
1779 id, NULL, NULL, 0);
1780 }
1781 array_destroy(ids);
1782 }
1783 if (array_count(ikeids))
1784 {
1785 while (array_remove(ikeids, ARRAY_HEAD, &id))
1786 {
1787 DBG1(DBG_CFG, "closing IKE_SA #%u", id);
1788 charon->controller->terminate_ike(charon->controller,
1789 id, NULL, NULL, 0);
1790 }
1791 array_destroy(ikeids);
1792 }
1793 break;
1794 case ACTION_ROUTE:
1795 DBG1(DBG_CFG, "uninstalling '%s'", name);
1796 switch (child_cfg->get_mode(child_cfg))
1797 {
1798 case MODE_PASS:
1799 case MODE_DROP:
1800 charon->shunts->uninstall(charon->shunts, name);
1801 break;
1802 default:
1803 enumerator = charon->traps->create_enumerator(charon->traps);
1804 while (enumerator->enumerate(enumerator, NULL, &child_sa))
1805 {
1806 if (streq(name, child_sa->get_name(child_sa)))
1807 {
1808 id = child_sa->get_reqid(child_sa);
1809 break;
1810 }
1811 }
1812 enumerator->destroy(enumerator);
1813 if (id)
1814 {
1815 charon->traps->uninstall(charon->traps, id);
1816 }
1817 break;
1818 }
1819 break;
1820 default:
1821 break;
1822 }
1823 }
1824
1825 /**
1826 * Run start actions associated to all child configs of a peer config
1827 */
1828 static void run_start_actions(private_vici_config_t *this, peer_cfg_t *peer_cfg)
1829 {
1830 enumerator_t *enumerator;
1831 child_cfg_t *child_cfg;
1832
1833 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
1834 while (enumerator->enumerate(enumerator, &child_cfg))
1835 {
1836 run_start_action(this, peer_cfg, child_cfg);
1837 }
1838 enumerator->destroy(enumerator);
1839 }
1840
1841 /**
1842 * Undo start actions associated to all child configs of a peer config
1843 */
1844 static void clear_start_actions(private_vici_config_t *this,
1845 peer_cfg_t *peer_cfg)
1846 {
1847 enumerator_t *enumerator;
1848 child_cfg_t *child_cfg;
1849
1850 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
1851 while (enumerator->enumerate(enumerator, &child_cfg))
1852 {
1853 clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
1854 }
1855 enumerator->destroy(enumerator);
1856 }
1857
1858 /**
1859 * Replace children of a peer config by a new config
1860 */
1861 static void replace_children(private_vici_config_t *this,
1862 peer_cfg_t *from, peer_cfg_t *to)
1863 {
1864 enumerator_t *enumerator;
1865 child_cfg_t *child;
1866 bool added;
1867
1868 enumerator = to->replace_child_cfgs(to, from);
1869 while (enumerator->enumerate(enumerator, &child, &added))
1870 {
1871 if (added)
1872 {
1873 run_start_action(this, to, child);
1874 }
1875 else
1876 {
1877 clear_start_action(this, to->get_name(to), child);
1878 }
1879 }
1880 enumerator->destroy(enumerator);
1881 }
1882
1883 /**
1884 * Merge/replace a peer config with existing configs
1885 */
1886 static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
1887 {
1888 enumerator_t *enumerator;
1889 peer_cfg_t *current;
1890 ike_cfg_t *ike_cfg;
1891 bool merged = FALSE;
1892
1893 this->lock->write_lock(this->lock);
1894
1895 enumerator = this->conns->create_enumerator(this->conns);
1896 while (enumerator->enumerate(enumerator, &current))
1897 {
1898 if (streq(peer_cfg->get_name(peer_cfg), current->get_name(current)))
1899 {
1900 ike_cfg = current->get_ike_cfg(current);
1901 if (peer_cfg->equals(peer_cfg, current) &&
1902 ike_cfg->equals(ike_cfg, peer_cfg->get_ike_cfg(peer_cfg)))
1903 {
1904 DBG1(DBG_CFG, "updated vici connection: %s",
1905 peer_cfg->get_name(peer_cfg));
1906 replace_children(this, peer_cfg, current);
1907 peer_cfg->destroy(peer_cfg);
1908 }
1909 else
1910 {
1911 DBG1(DBG_CFG, "replaced vici connection: %s",
1912 peer_cfg->get_name(peer_cfg));
1913 this->conns->remove_at(this->conns, enumerator);
1914 clear_start_actions(this, current);
1915 current->destroy(current);
1916 this->conns->insert_last(this->conns, peer_cfg);
1917 run_start_actions(this, peer_cfg);
1918 }
1919 merged = TRUE;
1920 break;
1921 }
1922 }
1923 enumerator->destroy(enumerator);
1924
1925 if (!merged)
1926 {
1927 DBG1(DBG_CFG, "added vici connection: %s", peer_cfg->get_name(peer_cfg));
1928 this->conns->insert_last(this->conns, peer_cfg);
1929 run_start_actions(this, peer_cfg);
1930 }
1931
1932 this->lock->unlock(this->lock);
1933 }
1934
1935 CALLBACK(config_sn, bool,
1936 request_data_t *request, vici_message_t *message,
1937 vici_parse_context_t *ctx, char *name)
1938 {
1939 peer_data_t peer = {
1940 .request = request,
1941 .local = linked_list_create(),
1942 .remote = linked_list_create(),
1943 .vips = linked_list_create(),
1944 .children = linked_list_create(),
1945 .proposals = linked_list_create(),
1946 .mobike = TRUE,
1947 .send_certreq = TRUE,
1948 .pull = TRUE,
1949 .send_cert = CERT_SEND_IF_ASKED,
1950 .version = IKE_ANY,
1951 .remote_port = IKEV2_UDP_PORT,
1952 .fragmentation = FRAGMENTATION_NO,
1953 .unique = UNIQUE_NO,
1954 .keyingtries = 1,
1955 .rekey_time = LFT_UNDEFINED,
1956 .reauth_time = LFT_UNDEFINED,
1957 .over_time = LFT_UNDEFINED,
1958 .rand_time = LFT_UNDEFINED,
1959 };
1960 enumerator_t *enumerator;
1961 peer_cfg_t *peer_cfg;
1962 ike_cfg_t *ike_cfg;
1963 child_cfg_t *child_cfg;
1964 auth_data_t *auth;
1965 proposal_t *proposal;
1966 host_t *host;
1967 char *str;
1968
1969 DBG2(DBG_CFG, " conn %s:", name);
1970
1971 if (!message->parse(message, ctx, peer_sn, peer_kv, peer_li, &peer))
1972 {
1973 free_peer_data(&peer);
1974 return FALSE;
1975 }
1976
1977 if (peer.local->get_count(peer.local) == 0)
1978 {
1979 INIT(auth,
1980 .cfg = auth_cfg_create(),
1981 );
1982 peer.local->insert_last(peer.local, auth);
1983 }
1984 if (peer.remote->get_count(peer.remote) == 0)
1985 {
1986 INIT(auth,
1987 .cfg = auth_cfg_create(),
1988 );
1989 peer.remote->insert_last(peer.remote, auth);
1990 }
1991 if (peer.proposals->get_count(peer.proposals) == 0)
1992 {
1993 proposal = proposal_create_default(PROTO_IKE);
1994 if (proposal)
1995 {
1996 peer.proposals->insert_last(peer.proposals, proposal);
1997 }
1998 proposal = proposal_create_default_aead(PROTO_IKE);
1999 if (proposal)
2000 {
2001 peer.proposals->insert_last(peer.proposals, proposal);
2002 }
2003 }
2004 if (!peer.local_addrs)
2005 {
2006 peer.local_addrs = strdup("%any");
2007 }
2008 if (!peer.remote_addrs)
2009 {
2010 peer.remote_addrs = strdup("%any");
2011 }
2012 if (!peer.local_port)
2013 {
2014 peer.local_port = charon->socket->get_port(charon->socket, FALSE);
2015 }
2016
2017 if (peer.rekey_time == LFT_UNDEFINED && peer.reauth_time == LFT_UNDEFINED)
2018 {
2019 /* apply a default rekey time if no rekey/reauth time set */
2020 peer.rekey_time = LFT_DEFAULT_IKE_REKEY;
2021 peer.reauth_time = 0;
2022 }
2023 if (peer.rekey_time == LFT_UNDEFINED)
2024 {
2025 peer.rekey_time = 0;
2026 }
2027 if (peer.reauth_time == LFT_UNDEFINED)
2028 {
2029 peer.reauth_time = 0;
2030 }
2031 if (peer.over_time == LFT_UNDEFINED)
2032 {
2033 /* default over_time to 10% of rekey/reauth time if not given */
2034 peer.over_time = max(peer.rekey_time, peer.reauth_time) / 10;
2035 }
2036 if (peer.rand_time == LFT_UNDEFINED)
2037 {
2038 /* default rand_time to over_time if not given, but don't make it
2039 * longer than half of rekey/rauth time */
2040 if (peer.rekey_time && peer.reauth_time)
2041 {
2042 peer.rand_time = min(peer.rekey_time, peer.reauth_time);
2043 }
2044 else
2045 {
2046 peer.rand_time = max(peer.rekey_time, peer.reauth_time);
2047 }
2048 peer.rand_time = min(peer.over_time, peer.rand_time / 2);
2049 }
2050
2051 log_peer_data(&peer);
2052
2053 ike_cfg = ike_cfg_create(peer.version, peer.send_certreq, peer.encap,
2054 peer.local_addrs, peer.local_port,
2055 peer.remote_addrs, peer.remote_port,
2056 peer.fragmentation, 0);
2057 peer_cfg = peer_cfg_create(name, ike_cfg, peer.send_cert, peer.unique,
2058 peer.keyingtries, peer.rekey_time, peer.reauth_time,
2059 peer.rand_time, peer.over_time, peer.mobike,
2060 peer.aggressive, peer.pull,
2061 peer.dpd_delay, peer.dpd_timeout,
2062 FALSE, NULL, NULL);
2063
2064 while (peer.local->remove_first(peer.local,
2065 (void**)&auth) == SUCCESS)
2066 {
2067 peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, TRUE);
2068 auth->cfg = NULL;
2069 free_auth_data(auth);
2070 }
2071 while (peer.remote->remove_first(peer.remote,
2072 (void**)&auth) == SUCCESS)
2073 {
2074 peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, FALSE);
2075 auth->cfg = NULL;
2076 free_auth_data(auth);
2077 }
2078 while (peer.children->remove_first(peer.children,
2079 (void**)&child_cfg) == SUCCESS)
2080 {
2081 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
2082 }
2083 while (peer.proposals->remove_first(peer.proposals,
2084 (void**)&proposal) == SUCCESS)
2085 {
2086 ike_cfg->add_proposal(ike_cfg, proposal);
2087 }
2088 while (peer.vips->remove_first(peer.vips, (void**)&host) == SUCCESS)
2089 {
2090 peer_cfg->add_virtual_ip(peer_cfg, host);
2091 }
2092 if (peer.pools)
2093 {
2094 enumerator = enumerator_create_token(peer.pools, ",", " ");
2095 while (enumerator->enumerate(enumerator, &str))
2096 {
2097 peer_cfg->add_pool(peer_cfg, str);
2098 }
2099 enumerator->destroy(enumerator);
2100 }
2101
2102 free_peer_data(&peer);
2103
2104 merge_config(request->this, peer_cfg);
2105
2106 return TRUE;
2107 }
2108
2109 CALLBACK(load_conn, vici_message_t*,
2110 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2111 {
2112 request_data_t request = {
2113 .this = this,
2114 };
2115
2116 if (!message->parse(message, NULL, config_sn, NULL, NULL, &request))
2117 {
2118 if (request.reply)
2119 {
2120 return request.reply;
2121 }
2122 return create_reply("parsing request failed");
2123 }
2124 return create_reply(NULL);
2125 }
2126
2127 CALLBACK(unload_conn, vici_message_t*,
2128 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2129 {
2130 enumerator_t *enumerator;
2131 peer_cfg_t *cfg;
2132 char *conn_name;
2133 bool found = FALSE;
2134
2135 conn_name = message->get_str(message, NULL, "name");
2136 if (!conn_name)
2137 {
2138 return create_reply("unload: missing connection name");
2139 }
2140
2141 this->lock->write_lock(this->lock);
2142 enumerator = this->conns->create_enumerator(this->conns);
2143 while (enumerator->enumerate(enumerator, &cfg))
2144 {
2145 if (streq(cfg->get_name(cfg), conn_name))
2146 {
2147 this->conns->remove_at(this->conns, enumerator);
2148 clear_start_actions(this, cfg);
2149 cfg->destroy(cfg);
2150 found = TRUE;
2151 break;
2152 }
2153 }
2154 enumerator->destroy(enumerator);
2155 this->lock->unlock(this->lock);
2156
2157 if (!found)
2158 {
2159 return create_reply("unload: connection '%s' not found", conn_name);
2160 }
2161 return create_reply(NULL);
2162 }
2163
2164 CALLBACK(get_conns, vici_message_t*,
2165 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2166 {
2167 vici_builder_t *builder;
2168 enumerator_t *enumerator;
2169 peer_cfg_t *cfg;
2170
2171 builder = vici_builder_create();
2172 builder->begin_list(builder, "conns");
2173
2174 this->lock->read_lock(this->lock);
2175 enumerator = this->conns->create_enumerator(this->conns);
2176 while (enumerator->enumerate(enumerator, &cfg))
2177 {
2178 builder->add_li(builder, "%s", cfg->get_name(cfg));
2179 }
2180 enumerator->destroy(enumerator);
2181 this->lock->unlock(this->lock);
2182
2183 builder->end_list(builder);
2184
2185 return builder->finalize(builder);
2186 }
2187
2188 static void manage_command(private_vici_config_t *this,
2189 char *name, vici_command_cb_t cb, bool reg)
2190 {
2191 this->dispatcher->manage_command(this->dispatcher, name,
2192 reg ? cb : NULL, this);
2193 }
2194
2195 /**
2196 * (Un-)register dispatcher functions
2197 */
2198 static void manage_commands(private_vici_config_t *this, bool reg)
2199 {
2200 manage_command(this, "load-conn", load_conn, reg);
2201 manage_command(this, "unload-conn", unload_conn, reg);
2202 manage_command(this, "get-conns", get_conns, reg);
2203 }
2204
2205 METHOD(vici_config_t, destroy, void,
2206 private_vici_config_t *this)
2207 {
2208 manage_commands(this, FALSE);
2209 this->conns->destroy_offset(this->conns, offsetof(peer_cfg_t, destroy));
2210 this->lock->destroy(this->lock);
2211 free(this);
2212 }
2213
2214 /**
2215 * See header
2216 */
2217 vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
2218 vici_authority_t *authority,
2219 vici_cred_t *cred)
2220 {
2221 private_vici_config_t *this;
2222
2223 INIT(this,
2224 .public = {
2225 .backend = {
2226 .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
2227 .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
2228 .get_peer_cfg_by_name = _get_peer_cfg_by_name,
2229 },
2230 .destroy = _destroy,
2231 },
2232 .dispatcher = dispatcher,
2233 .conns = linked_list_create(),
2234 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
2235 .authority = authority,
2236 .cred = cred,
2237 );
2238
2239 manage_commands(this, TRUE);
2240
2241 return &this->public;
2242 }