vici: Make childless initiation of IKE_SAs configurable
[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-2019 Tobias Brunner
6 * Copyright (C) 2015-2018 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 <threading/rwlock_condvar.h>
50 #include <collections/array.h>
51 #include <collections/linked_list.h>
52
53 #include <pubkey_cert.h>
54
55 #include <stdio.h>
56
57 /**
58 * Magic value for an undefined lifetime
59 */
60 #define LFT_UNDEFINED (~(uint64_t)0)
61
62 /**
63 * Default IKE rekey time
64 */
65 #define LFT_DEFAULT_IKE_REKEY_TIME (4 * 60 * 60)
66
67 /**
68 * Default CHILD rekey time
69 */
70 #define LFT_DEFAULT_CHILD_REKEY_TIME (1 * 60 * 60)
71
72 /**
73 * Default CHILD rekey bytes
74 */
75 #define LFT_DEFAULT_CHILD_REKEY_BYTES 0
76
77 /**
78 * Default CHILD rekey packets
79 */
80 #define LFT_DEFAULT_CHILD_REKEY_PACKETS 0
81
82 /**
83 * Undefined replay window
84 */
85 #define REPLAY_UNDEFINED (~(uint32_t)0)
86
87 typedef struct private_vici_config_t private_vici_config_t;
88
89 /**
90 * Private data of an vici_config_t object.
91 */
92 struct private_vici_config_t {
93
94 /**
95 * Public vici_config_t interface.
96 */
97 vici_config_t public;
98
99 /**
100 * Dispatcher
101 */
102 vici_dispatcher_t *dispatcher;
103
104 /**
105 * List of loaded connections, as peer_cfg_t
106 */
107 linked_list_t *conns;
108
109 /**
110 * Lock for conns list
111 */
112 rwlock_t *lock;
113
114 /**
115 * Condvar used to sync running actions
116 */
117 rwlock_condvar_t *condvar;
118
119 /**
120 * True while we run or undo a start action
121 */
122 bool handling_actions;
123
124 /**
125 * Credential backend managed by VICI used for our certificates
126 */
127 vici_cred_t *cred;
128
129 /**
130 * Auxiliary certification authority information
131 */
132 vici_authority_t *authority;
133
134 };
135
136 METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
137 private_vici_config_t *this, identification_t *me, identification_t *other)
138 {
139 this->lock->read_lock(this->lock);
140 return enumerator_create_cleaner(this->conns->create_enumerator(this->conns),
141 (void*)this->lock->unlock, this->lock);
142 }
143
144 CALLBACK(ike_filter, bool,
145 void *data, enumerator_t *orig, va_list args)
146 {
147 peer_cfg_t *cfg;
148 ike_cfg_t **out;
149
150 VA_ARGS_VGET(args, out);
151
152 if (orig->enumerate(orig, &cfg))
153 {
154 *out = cfg->get_ike_cfg(cfg);
155 return TRUE;
156 }
157 return FALSE;
158 }
159
160 METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
161 private_vici_config_t *this, host_t *me, host_t *other)
162 {
163 this->lock->read_lock(this->lock);
164 return enumerator_create_filter(this->conns->create_enumerator(this->conns),
165 ike_filter, this->lock,
166 (void*)this->lock->unlock);
167 }
168
169 METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
170 private_vici_config_t *this, char *name)
171 {
172 peer_cfg_t *current, *found = NULL;
173 enumerator_t *enumerator;
174
175 this->lock->read_lock(this->lock);
176 enumerator = this->conns->create_enumerator(this->conns);
177 while (enumerator->enumerate(enumerator, &current))
178 {
179 if (streq(current->get_name(current), name))
180 {
181 found = current;
182 found->get_ref(found);
183 break;
184 }
185 }
186 enumerator->destroy(enumerator);
187 this->lock->unlock(this->lock);
188
189 return found;
190 }
191
192 /**
193 * Create a (error) reply message
194 */
195 static vici_message_t* create_reply(char *fmt, ...)
196 {
197 vici_builder_t *builder;
198 va_list args;
199
200 builder = vici_builder_create();
201 builder->add_kv(builder, "success", fmt ? "no" : "yes");
202 if (fmt)
203 {
204 va_start(args, fmt);
205 builder->vadd_kv(builder, "errmsg", fmt, args);
206 va_end(args);
207 }
208 return builder->finalize(builder);
209 }
210
211 /**
212 * A rule to parse a key/value or list item
213 */
214 typedef struct {
215 /** name of the key/value or list */
216 char *name;
217 /** function to parse value */
218 bool (*parse)(void *out, chunk_t value);
219 /** result, passed to parse() */
220 void *out;
221 } parse_rule_t;
222
223 /**
224 * Parse key/values using a rule-set
225 */
226 static bool parse_rules(parse_rule_t *rules, int count, char *name,
227 chunk_t value, vici_message_t **reply)
228 {
229 int i;
230
231 for (i = 0; i < count; i++)
232 {
233 if (streq(name, rules[i].name))
234 {
235 if (rules[i].parse(rules[i].out, value))
236 {
237 return TRUE;
238 }
239 *reply = create_reply("invalid value for: %s, config discarded",
240 name);
241 return FALSE;
242 }
243 }
244 *reply = create_reply("unknown option: %s, config discarded", name);
245 return FALSE;
246 }
247
248 /**
249 * Parse callback data, passed to each callback
250 */
251 typedef struct {
252 private_vici_config_t *this;
253 vici_message_t *reply;
254 } request_data_t;
255
256 /**
257 * Certificate data
258 */
259 typedef struct {
260 request_data_t *request;
261 char *handle;
262 uint32_t slot;
263 char *module;
264 char *file;
265 } cert_data_t;
266
267 /**
268 * Clean up certificate data
269 */
270 static void free_cert_data(cert_data_t *data)
271 {
272 free(data->handle);
273 free(data->module);
274 free(data->file);
275 free(data);
276 }
277
278 /**
279 * Auth config data
280 */
281 typedef struct {
282 request_data_t *request;
283 auth_cfg_t *cfg;
284 uint32_t round;
285 } auth_data_t;
286
287 /**
288 * Clean up auth config data
289 */
290 static void free_auth_data(auth_data_t *data)
291 {
292 DESTROY_IF(data->cfg);
293 free(data);
294 }
295
296 /**
297 * Data associated to a peer config
298 */
299 typedef struct {
300 request_data_t *request;
301 uint32_t version;
302 bool aggressive;
303 bool encap;
304 bool mobike;
305 bool send_certreq;
306 bool pull;
307 identification_t *ppk_id;
308 bool ppk_required;
309 cert_policy_t send_cert;
310 uint64_t dpd_delay;
311 uint64_t dpd_timeout;
312 fragmentation_t fragmentation;
313 childless_t childless;
314 unique_policy_t unique;
315 uint32_t keyingtries;
316 uint32_t local_port;
317 uint32_t remote_port;
318 char *local_addrs;
319 char *remote_addrs;
320 linked_list_t *local;
321 linked_list_t *remote;
322 linked_list_t *proposals;
323 linked_list_t *children;
324 linked_list_t *vips;
325 char *pools;
326 uint64_t reauth_time;
327 uint64_t rekey_time;
328 uint64_t over_time;
329 uint64_t rand_time;
330 uint8_t dscp;
331 uint32_t if_id_in;
332 uint32_t if_id_out;
333 #ifdef ME
334 bool mediation;
335 char *mediated_by;
336 identification_t *peer_id;
337 #endif /* ME */
338 } peer_data_t;
339
340 /**
341 * Log relevant auth config data
342 */
343 static void log_auth(auth_cfg_t *auth)
344 {
345 enumerator_t *enumerator;
346 auth_rule_t rule;
347 union {
348 uintptr_t u;
349 identification_t *id;
350 char *str;
351 } v;
352
353 enumerator = auth->create_enumerator(auth);
354 while (enumerator->enumerate(enumerator, &rule, &v))
355 {
356 switch (rule)
357 {
358 case AUTH_RULE_AUTH_CLASS:
359 DBG2(DBG_CFG, " class = %N", auth_class_names, v.u);
360 break;
361 case AUTH_RULE_EAP_TYPE:
362 DBG2(DBG_CFG, " eap-type = %N", eap_type_names, v.u);
363 break;
364 case AUTH_RULE_EAP_VENDOR:
365 DBG2(DBG_CFG, " eap-vendor = %u", v.u);
366 break;
367 case AUTH_RULE_XAUTH_BACKEND:
368 DBG2(DBG_CFG, " xauth = %s", v.str);
369 break;
370 case AUTH_RULE_CRL_VALIDATION:
371 DBG2(DBG_CFG, " revocation = %N", cert_validation_names, v.u);
372 break;
373 case AUTH_RULE_IDENTITY:
374 DBG2(DBG_CFG, " id = %Y", v.id);
375 break;
376 case AUTH_RULE_AAA_IDENTITY:
377 DBG2(DBG_CFG, " aaa_id = %Y", v.id);
378 break;
379 case AUTH_RULE_EAP_IDENTITY:
380 DBG2(DBG_CFG, " eap_id = %Y", v.id);
381 break;
382 case AUTH_RULE_XAUTH_IDENTITY:
383 DBG2(DBG_CFG, " xauth_id = %Y", v.id);
384 break;
385 case AUTH_RULE_GROUP:
386 DBG2(DBG_CFG, " group = %Y", v.id);
387 break;
388 default:
389 break;
390 }
391 }
392 enumerator->destroy(enumerator);
393 }
394
395 /**
396 * Log parsed peer data
397 */
398 static void log_peer_data(peer_data_t *data)
399 {
400 enumerator_t *enumerator;
401 auth_data_t *auth;
402 host_t *host;
403
404 DBG2(DBG_CFG, " version = %u", data->version);
405 DBG2(DBG_CFG, " local_addrs = %s", data->local_addrs);
406 DBG2(DBG_CFG, " remote_addrs = %s", data->remote_addrs);
407 DBG2(DBG_CFG, " local_port = %u", data->local_port);
408 DBG2(DBG_CFG, " remote_port = %u", data->remote_port);
409 DBG2(DBG_CFG, " send_certreq = %u", data->send_certreq);
410 DBG2(DBG_CFG, " send_cert = %N", cert_policy_names, data->send_cert);
411 DBG2(DBG_CFG, " ppk_id = %Y", data->ppk_id);
412 DBG2(DBG_CFG, " ppk_required = %u", data->ppk_required);
413 DBG2(DBG_CFG, " mobike = %u", data->mobike);
414 DBG2(DBG_CFG, " aggressive = %u", data->aggressive);
415 DBG2(DBG_CFG, " dscp = 0x%.2x", data->dscp);
416 DBG2(DBG_CFG, " encap = %u", data->encap);
417 DBG2(DBG_CFG, " dpd_delay = %llu", data->dpd_delay);
418 DBG2(DBG_CFG, " dpd_timeout = %llu", data->dpd_timeout);
419 DBG2(DBG_CFG, " fragmentation = %u", data->fragmentation);
420 DBG2(DBG_CFG, " childless = %u", data->childless);
421 DBG2(DBG_CFG, " unique = %N", unique_policy_names, data->unique);
422 DBG2(DBG_CFG, " keyingtries = %u", data->keyingtries);
423 DBG2(DBG_CFG, " reauth_time = %llu", data->reauth_time);
424 DBG2(DBG_CFG, " rekey_time = %llu", data->rekey_time);
425 DBG2(DBG_CFG, " over_time = %llu", data->over_time);
426 DBG2(DBG_CFG, " rand_time = %llu", data->rand_time);
427 DBG2(DBG_CFG, " proposals = %#P", data->proposals);
428 DBG2(DBG_CFG, " if_id_in = %u", data->if_id_in);
429 DBG2(DBG_CFG, " if_id_out = %u", data->if_id_out);
430 #ifdef ME
431 DBG2(DBG_CFG, " mediation = %u", data->mediation);
432 if (data->mediated_by)
433 {
434 DBG2(DBG_CFG, " mediated_by = %s", data->mediated_by);
435 DBG2(DBG_CFG, " mediation_peer = %Y", data->peer_id);
436 }
437 #endif /* ME */
438
439 if (data->vips->get_count(data->vips))
440 {
441 DBG2(DBG_CFG, " vips:");
442 }
443 enumerator = data->vips->create_enumerator(data->vips);
444 while (enumerator->enumerate(enumerator, &host))
445 {
446 DBG2(DBG_CFG, " %H", host);
447 }
448 enumerator->destroy(enumerator);
449
450 enumerator = data->local->create_enumerator(data->local);
451 while (enumerator->enumerate(enumerator, &auth))
452 {
453 DBG2(DBG_CFG, " local:");
454 log_auth(auth->cfg);
455 }
456 enumerator->destroy(enumerator);
457
458 enumerator = data->remote->create_enumerator(data->remote);
459 while (enumerator->enumerate(enumerator, &auth))
460 {
461 DBG2(DBG_CFG, " remote:");
462 log_auth(auth->cfg);
463 }
464 enumerator->destroy(enumerator);
465 }
466
467 /**
468 * Clean up peer config data
469 */
470 static void free_peer_data(peer_data_t *data)
471 {
472 data->local->destroy_function(data->local, (void*)free_auth_data);
473 data->remote->destroy_function(data->remote, (void*)free_auth_data);
474 data->children->destroy_offset(data->children,
475 offsetof(child_cfg_t, destroy));
476 data->proposals->destroy_offset(data->proposals,
477 offsetof(proposal_t, destroy));
478 data->vips->destroy_offset(data->vips, offsetof(host_t, destroy));
479 free(data->pools);
480 free(data->local_addrs);
481 free(data->remote_addrs);
482 DESTROY_IF(data->ppk_id);
483 #ifdef ME
484 free(data->mediated_by);
485 DESTROY_IF(data->peer_id);
486 #endif /* ME */
487 }
488
489 /**
490 * CHILD config data
491 */
492 typedef struct {
493 request_data_t *request;
494 linked_list_t *proposals;
495 linked_list_t *local_ts;
496 linked_list_t *remote_ts;
497 uint32_t replay_window;
498 child_cfg_create_t cfg;
499 } child_data_t;
500
501 /**
502 * Log parsed CHILD config data
503 */
504 static void log_child_data(child_data_t *data, char *name)
505 {
506 child_cfg_create_t *cfg = &data->cfg;
507
508 #define has_opt(opt) ({ (cfg->options & (opt)) == (opt); })
509 DBG2(DBG_CFG, " child %s:", name);
510 DBG2(DBG_CFG, " rekey_time = %llu", cfg->lifetime.time.rekey);
511 DBG2(DBG_CFG, " life_time = %llu", cfg->lifetime.time.life);
512 DBG2(DBG_CFG, " rand_time = %llu", cfg->lifetime.time.jitter);
513 DBG2(DBG_CFG, " rekey_bytes = %llu", cfg->lifetime.bytes.rekey);
514 DBG2(DBG_CFG, " life_bytes = %llu", cfg->lifetime.bytes.life);
515 DBG2(DBG_CFG, " rand_bytes = %llu", cfg->lifetime.bytes.jitter);
516 DBG2(DBG_CFG, " rekey_packets = %llu", cfg->lifetime.packets.rekey);
517 DBG2(DBG_CFG, " life_packets = %llu", cfg->lifetime.packets.life);
518 DBG2(DBG_CFG, " rand_packets = %llu", cfg->lifetime.packets.jitter);
519 DBG2(DBG_CFG, " updown = %s", cfg->updown);
520 DBG2(DBG_CFG, " hostaccess = %u", has_opt(OPT_HOSTACCESS));
521 DBG2(DBG_CFG, " ipcomp = %u", has_opt(OPT_IPCOMP));
522 DBG2(DBG_CFG, " mode = %N%s", ipsec_mode_names, cfg->mode,
523 has_opt(OPT_PROXY_MODE) ? "_PROXY" : "");
524 DBG2(DBG_CFG, " policies = %u", !has_opt(OPT_NO_POLICIES));
525 DBG2(DBG_CFG, " policies_fwd_out = %u", has_opt(OPT_FWD_OUT_POLICIES));
526 if (data->replay_window != REPLAY_UNDEFINED)
527 {
528 DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
529 }
530 DBG2(DBG_CFG, " dpd_action = %N", action_names, cfg->dpd_action);
531 DBG2(DBG_CFG, " start_action = %N", action_names, cfg->start_action);
532 DBG2(DBG_CFG, " close_action = %N", action_names, cfg->close_action);
533 DBG2(DBG_CFG, " reqid = %u", cfg->reqid);
534 DBG2(DBG_CFG, " tfc = %d", cfg->tfc);
535 DBG2(DBG_CFG, " priority = %d", cfg->priority);
536 DBG2(DBG_CFG, " interface = %s", cfg->interface);
537 DBG2(DBG_CFG, " if_id_in = %u", cfg->if_id_in);
538 DBG2(DBG_CFG, " if_id_out = %u", cfg->if_id_out);
539 DBG2(DBG_CFG, " mark_in = %u/%u",
540 cfg->mark_in.value, cfg->mark_in.mask);
541 DBG2(DBG_CFG, " mark_in_sa = %u", has_opt(OPT_MARK_IN_SA));
542 DBG2(DBG_CFG, " mark_out = %u/%u",
543 cfg->mark_out.value, cfg->mark_out.mask);
544 DBG2(DBG_CFG, " set_mark_in = %u/%u",
545 cfg->set_mark_in.value, cfg->set_mark_in.mask);
546 DBG2(DBG_CFG, " set_mark_out = %u/%u",
547 cfg->set_mark_out.value, cfg->set_mark_out.mask);
548 DBG2(DBG_CFG, " inactivity = %llu", cfg->inactivity);
549 DBG2(DBG_CFG, " proposals = %#P", data->proposals);
550 DBG2(DBG_CFG, " local_ts = %#R", data->local_ts);
551 DBG2(DBG_CFG, " remote_ts = %#R", data->remote_ts);
552 DBG2(DBG_CFG, " hw_offload = %N", hw_offload_names, cfg->hw_offload);
553 DBG2(DBG_CFG, " sha256_96 = %u", has_opt(OPT_SHA256_96));
554 DBG2(DBG_CFG, " copy_df = %u", !has_opt(OPT_NO_COPY_DF));
555 DBG2(DBG_CFG, " copy_ecn = %u", !has_opt(OPT_NO_COPY_ECN));
556 DBG2(DBG_CFG, " copy_dscp = %N", dscp_copy_names, cfg->copy_dscp);
557 }
558
559 /**
560 * Clean up CHILD config data
561 */
562 static void free_child_data(child_data_t *data)
563 {
564 data->proposals->destroy_offset(data->proposals,
565 offsetof(proposal_t, destroy));
566 data->local_ts->destroy_offset(data->local_ts,
567 offsetof(traffic_selector_t, destroy));
568 data->remote_ts->destroy_offset(data->remote_ts,
569 offsetof(traffic_selector_t, destroy));
570 free(data->cfg.updown);
571 free(data->cfg.interface);
572 }
573
574 /**
575 * Common proposal parsing
576 */
577 static bool parse_proposal(linked_list_t *list, protocol_id_t proto, chunk_t v)
578 {
579 char buf[BUF_LEN];
580 proposal_t *proposal;
581
582 if (!vici_stringify(v, buf, sizeof(buf)))
583 {
584 return FALSE;
585 }
586 if (strcaseeq("default", buf))
587 {
588 proposal = proposal_create_default(proto);
589 if (proposal)
590 {
591 list->insert_last(list, proposal);
592 }
593 proposal = proposal_create_default_aead(proto);
594 if (proposal)
595 {
596 list->insert_last(list, proposal);
597 }
598 return TRUE;
599 }
600 proposal = proposal_create_from_string(proto, buf);
601 if (proposal)
602 {
603 list->insert_last(list, proposal);
604 return TRUE;
605 }
606 return FALSE;
607 }
608
609 /**
610 * Parse IKE proposal
611 */
612 CALLBACK(parse_ike_proposal, bool,
613 linked_list_t *out, chunk_t v)
614 {
615 return parse_proposal(out, PROTO_IKE, v);
616 }
617
618 /**
619 * Parse ESP proposal
620 */
621 CALLBACK(parse_esp_proposal, bool,
622 linked_list_t *out, chunk_t v)
623 {
624 return parse_proposal(out, PROTO_ESP, v);
625 }
626
627 /**
628 * Parse AH proposal
629 */
630 CALLBACK(parse_ah_proposal, bool,
631 linked_list_t *out, chunk_t v)
632 {
633 return parse_proposal(out, PROTO_AH, v);
634 }
635
636 /**
637 * Parse a traffic selector
638 */
639 CALLBACK(parse_ts, bool,
640 linked_list_t *out, chunk_t v)
641 {
642 char buf[BUF_LEN], *protoport, *sep, *port = "", *end;
643 traffic_selector_t *ts = NULL;
644 struct protoent *protoent;
645 struct servent *svc;
646 long int p;
647 uint16_t from = 0, to = 0xffff;
648 uint8_t proto = 0;
649
650 if (!vici_stringify(v, buf, sizeof(buf)))
651 {
652 return FALSE;
653 }
654
655 protoport = strchr(buf, '[');
656 if (protoport)
657 {
658 *(protoport++) = '\0';
659
660 sep = strrchr(protoport, ']');
661 if (!sep)
662 {
663 return FALSE;
664 }
665 *sep = '\0';
666
667 sep = strchr(protoport, '/');
668 if (sep)
669 { /* protocol/port */
670 *sep = '\0';
671 port = sep + 1;
672 }
673
674 if (streq(protoport, "any"))
675 {
676 proto = 0;
677 }
678 else
679 {
680 protoent = getprotobyname(protoport);
681 if (protoent)
682 {
683 proto = protoent->p_proto;
684 }
685 else
686 {
687 p = strtol(protoport, &end, 0);
688 if ((*protoport && *end) || p < 0 || p > 0xff)
689 {
690 return FALSE;
691 }
692 proto = (uint8_t)p;
693 }
694 }
695 if (streq(port, "opaque"))
696 {
697 from = 0xffff;
698 to = 0;
699 }
700 else if (*port && !streq(port, "any"))
701 {
702 svc = getservbyname(port, NULL);
703 if (svc)
704 {
705 from = to = ntohs(svc->s_port);
706 }
707 else
708 {
709 p = strtol(port, &end, 0);
710 if (p < 0 || p > 0xffff)
711 {
712 return FALSE;
713 }
714 from = p;
715 if (*end == '-')
716 {
717 port = end + 1;
718 p = strtol(port, &end, 0);
719 if (p < 0 || p > 0xffff)
720 {
721 return FALSE;
722 }
723 }
724 to = p;
725 if (*end)
726 {
727 return FALSE;
728 }
729 }
730 }
731 }
732 if (streq(buf, "dynamic"))
733 {
734 ts = traffic_selector_create_dynamic(proto, from, to);
735 }
736 else if (strchr(buf, '-'))
737 {
738 host_t *lower, *upper;
739 ts_type_t type;
740
741 if (host_create_from_range(buf, &lower, &upper))
742 {
743 type = (lower->get_family(lower) == AF_INET) ?
744 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
745 ts = traffic_selector_create_from_bytes(proto, type,
746 lower->get_address(lower), from,
747 upper->get_address(upper), to);
748 lower->destroy(lower);
749 upper->destroy(upper);
750 }
751 }
752 else
753 {
754 ts = traffic_selector_create_from_cidr(buf, proto, from, to);
755 }
756 if (!ts)
757 {
758 return FALSE;
759 }
760 out->insert_last(out, ts);
761 return TRUE;
762 }
763
764 /**
765 * Parse a string
766 */
767 CALLBACK(parse_string, bool,
768 char **out, chunk_t v)
769 {
770 if (!chunk_printable(v, NULL, ' '))
771 {
772 return FALSE;
773 }
774 free(*out);
775 *out = NULL;
776 if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
777 {
778 return FALSE;
779 }
780 return TRUE;
781 }
782
783 /**
784 * Map a string to an integer
785 */
786 typedef struct {
787 char *str;
788 int d;
789 } enum_map_t;
790
791 /**
792 * Parse a string to an integer mapping
793 */
794 static bool parse_map(enum_map_t *map, int count, int *out, chunk_t v)
795 {
796 char buf[BUF_LEN];
797 int i;
798
799 if (!vici_stringify(v, buf, sizeof(buf)))
800 {
801 return FALSE;
802 }
803 for (i = 0; i < count; i++)
804 {
805 if (strcaseeq(map[i].str, buf))
806 {
807 *out = map[i].d;
808 return TRUE;
809 }
810 }
811 return FALSE;
812 }
813
814 /**
815 * Parse a boolean
816 */
817 CALLBACK(parse_bool, bool,
818 bool *out, chunk_t v)
819 {
820 enum_map_t map[] = {
821 { "yes", TRUE },
822 { "true", TRUE },
823 { "enabled", TRUE },
824 { "1", TRUE },
825 { "no", FALSE },
826 { "false", FALSE },
827 { "disabled", FALSE },
828 { "0", FALSE },
829 };
830 int d;
831
832 if (parse_map(map, countof(map), &d, v))
833 {
834 *out = d;
835 return TRUE;
836 }
837 return FALSE;
838 }
839
840 /**
841 * Parse a ipsec_mode_t
842 */
843 CALLBACK(parse_mode, bool,
844 child_cfg_create_t *cfg, chunk_t v)
845 {
846 enum_map_t map[] = {
847 { "tunnel", MODE_TUNNEL },
848 { "transport", MODE_TRANSPORT },
849 { "transport_proxy", MODE_TRANSPORT },
850 { "beet", MODE_BEET },
851 { "drop", MODE_DROP },
852 { "pass", MODE_PASS },
853 };
854 int d;
855
856 if (parse_map(map, countof(map), &d, v))
857 {
858 cfg->mode = d;
859 if ((d == MODE_TRANSPORT) && (v.len > 9))
860 {
861 cfg->options |= OPT_PROXY_MODE;
862 }
863 return TRUE;
864 }
865 return FALSE;
866 }
867
868 /**
869 * Enable a child_cfg_option_t, the flag controls whether the option is enabled
870 * if the parsed value is TRUE or FALSE.
871 */
872 static bool parse_option(child_cfg_option_t *out, child_cfg_option_t opt,
873 chunk_t v, bool add_if_true)
874 {
875 bool val;
876
877 if (parse_bool(&val, v))
878 {
879 if (val == add_if_true)
880 {
881 *out |= opt;
882 }
883 return TRUE;
884 }
885 return FALSE;
886 }
887
888 /**
889 * Parse OPT_HOSTACCESS option
890 */
891 CALLBACK(parse_opt_haccess, bool,
892 child_cfg_option_t *out, chunk_t v)
893 {
894 return parse_option(out, OPT_HOSTACCESS, v, TRUE);
895 }
896
897 /**
898 * Parse OPT_NO_POLICIES option
899 */
900 CALLBACK(parse_opt_policies, bool,
901 child_cfg_option_t *out, chunk_t v)
902 {
903 return parse_option(out, OPT_NO_POLICIES, v, FALSE);
904 }
905
906 /**
907 * Parse OPT_FWD_OUT_POLICIES option
908 */
909 CALLBACK(parse_opt_fwd_out, bool,
910 child_cfg_option_t *out, chunk_t v)
911 {
912 return parse_option(out, OPT_FWD_OUT_POLICIES, v, TRUE);
913 }
914
915 /**
916 * Parse OPT_IPCOMP option
917 */
918 CALLBACK(parse_opt_ipcomp, bool,
919 child_cfg_option_t *out, chunk_t v)
920 {
921 return parse_option(out, OPT_IPCOMP, v, TRUE);
922 }
923
924 /**
925 * Parse OPT_SHA256_96 option
926 */
927 CALLBACK(parse_opt_sha256_96, bool,
928 child_cfg_option_t *out, chunk_t v)
929 {
930 return parse_option(out, OPT_SHA256_96, v, TRUE);
931 }
932
933 /**
934 * Parse OPT_MARK_IN_SA option
935 */
936 CALLBACK(parse_opt_mark_in, bool,
937 child_cfg_option_t *out, chunk_t v)
938 {
939 return parse_option(out, OPT_MARK_IN_SA, v, TRUE);
940 }
941
942 /**
943 * Parse OPT_NO_COPY_DF option
944 */
945 CALLBACK(parse_opt_copy_df, bool,
946 child_cfg_option_t *out, chunk_t v)
947 {
948 return parse_option(out, OPT_NO_COPY_DF, v, FALSE);
949 }
950
951 /**
952 * Parse OPT_NO_COPY_ECN option
953 */
954 CALLBACK(parse_opt_copy_ecn, bool,
955 child_cfg_option_t *out, chunk_t v)
956 {
957 return parse_option(out, OPT_NO_COPY_ECN, v, FALSE);
958 }
959
960 /**
961 * Parse a dscp_copy_t
962 */
963 CALLBACK(parse_copy_dscp, bool,
964 dscp_copy_t *out, chunk_t v)
965 {
966 enum_map_t map[] = {
967 { "no", DSCP_COPY_NO },
968 { "in", DSCP_COPY_IN_ONLY },
969 { "out", DSCP_COPY_OUT_ONLY },
970 { "yes", DSCP_COPY_YES },
971 };
972 int d;
973
974 if (parse_map(map, countof(map), &d, v))
975 {
976 *out = d;
977 return TRUE;
978 }
979 return FALSE;
980 }
981
982 /**
983 * Parse an action_t
984 */
985 CALLBACK(parse_action, bool,
986 action_t *out, chunk_t v)
987 {
988 enum_map_t map[] = {
989 { "start", ACTION_RESTART },
990 { "restart", ACTION_RESTART },
991 { "route", ACTION_ROUTE },
992 { "trap", ACTION_ROUTE },
993 { "none", ACTION_NONE },
994 { "clear", ACTION_NONE },
995 };
996 int d;
997
998 if (parse_map(map, countof(map), &d, v))
999 {
1000 *out = d;
1001 return TRUE;
1002 }
1003 return FALSE;
1004 }
1005
1006 /**
1007 * Parse an hw_offload_t
1008 */
1009 CALLBACK(parse_hw_offload, bool,
1010 action_t *out, chunk_t v)
1011 {
1012 enum_map_t map[] = {
1013 { "no", HW_OFFLOAD_NO },
1014 { "yes", HW_OFFLOAD_YES },
1015 { "auto", HW_OFFLOAD_AUTO },
1016 };
1017 int d;
1018
1019 if (parse_map(map, countof(map), &d, v))
1020 {
1021 *out = d;
1022 return TRUE;
1023 }
1024 return FALSE;
1025 }
1026
1027 /**
1028 * Parse a uint32_t with the given base
1029 */
1030 static bool parse_uint32_base(uint32_t *out, chunk_t v, int base)
1031 {
1032 char buf[16], *end;
1033 u_long l;
1034
1035 if (!vici_stringify(v, buf, sizeof(buf)))
1036 {
1037 return FALSE;
1038 }
1039 l = strtoul(buf, &end, base);
1040 if (*end == 0)
1041 {
1042 *out = l;
1043 return TRUE;
1044 }
1045 return FALSE;
1046 }
1047
1048 /**
1049 * Parse a uint32_t
1050 */
1051 CALLBACK(parse_uint32, bool,
1052 uint32_t *out, chunk_t v)
1053 {
1054 return parse_uint32_base(out, v, 0);
1055 }
1056
1057 /**
1058 * Parse a uint32_t in binary encoding
1059 */
1060 CALLBACK(parse_uint32_bin, bool,
1061 uint32_t *out, chunk_t v)
1062 {
1063 return parse_uint32_base(out, v, 2);
1064 }
1065
1066 /**
1067 * Parse a uint64_t
1068 */
1069 CALLBACK(parse_uint64, bool,
1070 uint64_t *out, chunk_t v)
1071 {
1072 char buf[16], *end;
1073 unsigned long long l;
1074
1075 if (!vici_stringify(v, buf, sizeof(buf)))
1076 {
1077 return FALSE;
1078 }
1079 l = strtoull(buf, &end, 0);
1080 if (*end == 0)
1081 {
1082 *out = l;
1083 return TRUE;
1084 }
1085 return FALSE;
1086 }
1087
1088 /**
1089 * Parse a relative time
1090 */
1091 CALLBACK(parse_time, bool,
1092 uint64_t *out, chunk_t v)
1093 {
1094 char buf[16], *end;
1095 u_long l;
1096
1097 if (!vici_stringify(v, buf, sizeof(buf)))
1098 {
1099 return FALSE;
1100 }
1101
1102 l = strtoul(buf, &end, 0);
1103 while (*end == ' ')
1104 {
1105 end++;
1106 }
1107 switch (*end)
1108 {
1109 case 'd':
1110 case 'D':
1111 l *= 24;
1112 /* fall */
1113 case 'h':
1114 case 'H':
1115 l *= 60;
1116 /* fall */
1117 case 'm':
1118 case 'M':
1119 l *= 60;
1120 /* fall */
1121 case 's':
1122 case 'S':
1123 end++;
1124 break;
1125 case '\0':
1126 break;
1127 default:
1128 return FALSE;
1129 }
1130 if (*end)
1131 {
1132 return FALSE;
1133 }
1134 *out = l;
1135 return TRUE;
1136 }
1137
1138 /**
1139 * Parse a relative time (32-bit)
1140 */
1141 CALLBACK(parse_time32, bool,
1142 uint32_t *out, chunk_t v)
1143 {
1144 uint64_t time;
1145
1146 if (parse_time(&time, v))
1147 {
1148 *out = time;
1149 return TRUE;
1150 }
1151 return FALSE;
1152 }
1153
1154 /**
1155 * Parse byte volume
1156 */
1157 CALLBACK(parse_bytes, bool,
1158 uint64_t *out, chunk_t v)
1159 {
1160 char buf[16], *end;
1161 unsigned long long l;
1162
1163 if (!vici_stringify(v, buf, sizeof(buf)))
1164 {
1165 return FALSE;
1166 }
1167
1168 l = strtoull(buf, &end, 0);
1169 while (*end == ' ')
1170 {
1171 end++;
1172 }
1173 switch (*end)
1174 {
1175 case 'g':
1176 case 'G':
1177 l *= 1024;
1178 /* fall */
1179 case 'm':
1180 case 'M':
1181 l *= 1024;
1182 /* fall */
1183 case 'k':
1184 case 'K':
1185 l *= 1024;
1186 end++;
1187 break;
1188 case '\0':
1189 break;
1190 default:
1191 return FALSE;
1192 }
1193 if (*end)
1194 {
1195 return FALSE;
1196 }
1197 *out = l;
1198 return TRUE;
1199 }
1200
1201 /**
1202 * Parse a mark_t
1203 */
1204 CALLBACK(parse_mark, bool,
1205 mark_t *out, chunk_t v)
1206 {
1207 char buf[32];
1208
1209 if (!vici_stringify(v, buf, sizeof(buf)))
1210 {
1211 return FALSE;
1212 }
1213 return mark_from_string(buf, MARK_OP_UNIQUE, out);
1214 }
1215
1216 /**
1217 * Parse a mark_t when using it as set_mark.
1218 */
1219 CALLBACK(parse_set_mark, bool,
1220 mark_t *out, chunk_t v)
1221 {
1222 char buf[32];
1223
1224 if (!vici_stringify(v, buf, sizeof(buf)))
1225 {
1226 return FALSE;
1227 }
1228 return mark_from_string(buf, MARK_OP_SAME, out);
1229 }
1230
1231 /**
1232 * Parse interface ID
1233 */
1234 CALLBACK(parse_if_id, bool,
1235 uint32_t *out, chunk_t v)
1236 {
1237 char buf[32];
1238
1239 if (!vici_stringify(v, buf, sizeof(buf)))
1240 {
1241 return FALSE;
1242 }
1243 return if_id_from_string(buf, out);
1244 }
1245
1246 /**
1247 * Parse TFC padding option
1248 */
1249 CALLBACK(parse_tfc, bool,
1250 uint32_t *out, chunk_t v)
1251 {
1252 if (chunk_equals(v, chunk_from_str("mtu")))
1253 {
1254 *out = -1;
1255 return TRUE;
1256 }
1257 return parse_uint32(out, v);
1258 }
1259
1260 /**
1261 * Parse 6-bit DSCP value
1262 */
1263 CALLBACK(parse_dscp, bool,
1264 uint8_t *out, chunk_t v)
1265 {
1266 if (parse_uint32_bin(out, v))
1267 {
1268 *out = *out & 0x3f;
1269 return TRUE;
1270 }
1271 return FALSE;
1272 }
1273
1274 /**
1275 * Parse authentication config
1276 */
1277 CALLBACK(parse_auth, bool,
1278 auth_cfg_t *cfg, chunk_t v)
1279 {
1280 char buf[64], *pos;
1281 eap_vendor_type_t *type;
1282
1283 if (!vici_stringify(v, buf, sizeof(buf)))
1284 {
1285 return FALSE;
1286 }
1287 if (strpfx(buf, "ike:") ||
1288 strpfx(buf, "pubkey") ||
1289 strpfx(buf, "rsa") ||
1290 strpfx(buf, "ecdsa") ||
1291 strpfx(buf, "bliss"))
1292 {
1293 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
1294 cfg->add_pubkey_constraints(cfg, buf, TRUE);
1295 return TRUE;
1296 }
1297 if (strcaseeq(buf, "psk"))
1298 {
1299 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
1300 return TRUE;
1301 }
1302 if (strcasepfx(buf, "xauth"))
1303 {
1304 pos = strchr(buf, '-');
1305 if (pos)
1306 {
1307 cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
1308 }
1309 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
1310 return TRUE;
1311 }
1312 if (strcasepfx(buf, "eap"))
1313 {
1314 char *pos;
1315
1316 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
1317
1318 pos = strchr(buf, ':');
1319 if (pos)
1320 {
1321 *pos = 0;
1322 cfg->add_pubkey_constraints(cfg, pos + 1, FALSE);
1323 }
1324 type = eap_vendor_type_from_string(buf);
1325 if (type)
1326 {
1327 cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
1328 if (type->vendor)
1329 {
1330 cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
1331 }
1332 free(type);
1333 }
1334 return TRUE;
1335 }
1336 return FALSE;
1337 }
1338
1339 /**
1340 * Parse identity; add as auth rule to config
1341 */
1342 static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
1343 {
1344 char buf[BUF_LEN];
1345
1346 if (!vici_stringify(v, buf, sizeof(buf)))
1347 {
1348 return FALSE;
1349 }
1350 cfg->add(cfg, rule, identification_create_from_string(buf));
1351 return TRUE;
1352 }
1353
1354 /**
1355 * Parse IKE identity
1356 */
1357 CALLBACK(parse_ike_id, bool,
1358 auth_cfg_t *cfg, chunk_t v)
1359 {
1360 return parse_id(cfg, AUTH_RULE_IDENTITY, v);
1361 }
1362
1363 /**
1364 * Parse AAA identity
1365 */
1366 CALLBACK(parse_aaa_id, bool,
1367 auth_cfg_t *cfg, chunk_t v)
1368 {
1369 return parse_id(cfg, AUTH_RULE_AAA_IDENTITY, v);
1370 }
1371
1372 /**
1373 * Parse EAP identity
1374 */
1375 CALLBACK(parse_eap_id, bool,
1376 auth_cfg_t *cfg, chunk_t v)
1377 {
1378 return parse_id(cfg, AUTH_RULE_EAP_IDENTITY, v);
1379 }
1380
1381 /**
1382 * Parse XAuth identity
1383 */
1384 CALLBACK(parse_xauth_id, bool,
1385 auth_cfg_t *cfg, chunk_t v)
1386 {
1387 return parse_id(cfg, AUTH_RULE_XAUTH_IDENTITY, v);
1388 }
1389
1390 /**
1391 * Parse group membership
1392 */
1393 CALLBACK(parse_group, bool,
1394 auth_cfg_t *cfg, chunk_t v)
1395 {
1396 return parse_id(cfg, AUTH_RULE_GROUP, v);
1397 }
1398
1399 /**
1400 * Parse certificate policy
1401 */
1402 CALLBACK(parse_cert_policy, bool,
1403 auth_cfg_t *cfg, chunk_t v)
1404 {
1405 char buf[BUF_LEN];
1406
1407 if (!vici_stringify(v, buf, sizeof(buf)))
1408 {
1409 return FALSE;
1410 }
1411 cfg->add(cfg, AUTH_RULE_CERT_POLICY, strdup(buf));
1412 return TRUE;
1413 }
1414
1415 /**
1416 * Add a certificate as auth rule to config
1417 */
1418 static bool add_cert(auth_data_t *auth, auth_rule_t rule, certificate_t *cert)
1419 {
1420 vici_authority_t *authority;
1421 vici_cred_t *cred;
1422
1423 if (rule == AUTH_RULE_SUBJECT_CERT)
1424 {
1425 authority = auth->request->this->authority;
1426 authority->check_for_hash_and_url(authority, cert);
1427 }
1428 cred = auth->request->this->cred;
1429 cert = cred->add_cert(cred, cert);
1430 auth->cfg->add(auth->cfg, rule, cert);
1431 return TRUE;
1432 }
1433
1434 /**
1435 * Parse a certificate; add as auth rule to config
1436 */
1437 static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
1438 {
1439 certificate_t *cert;
1440
1441 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
1442 BUILD_BLOB_PEM, v, BUILD_END);
1443 if (cert)
1444 {
1445 return add_cert(auth, rule, cert);
1446 }
1447 return FALSE;
1448 }
1449
1450 /**
1451 * Parse subject certificates
1452 */
1453 CALLBACK(parse_certs, bool,
1454 auth_data_t *auth, chunk_t v)
1455 {
1456 return parse_cert(auth, AUTH_RULE_SUBJECT_CERT, v);
1457 }
1458
1459 /**
1460 * Parse CA certificates
1461 */
1462 CALLBACK(parse_cacerts, bool,
1463 auth_data_t *auth, chunk_t v)
1464 {
1465 return parse_cert(auth, AUTH_RULE_CA_CERT, v);
1466 }
1467
1468 /**
1469 * Parse raw public keys
1470 */
1471 CALLBACK(parse_pubkeys, bool,
1472 auth_data_t *auth, chunk_t v)
1473 {
1474 vici_cred_t *cred;
1475 certificate_t *cert;
1476
1477 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
1478 BUILD_BLOB_PEM, v, BUILD_END);
1479 if (cert)
1480 {
1481 cred = auth->request->this->cred;
1482 cert = cred->add_cert(cred, cert);
1483 auth->cfg->add(auth->cfg, AUTH_RULE_SUBJECT_CERT, cert);
1484 return TRUE;
1485 }
1486 return FALSE;
1487 }
1488
1489 /**
1490 * Parse revocation status
1491 */
1492 CALLBACK(parse_revocation, bool,
1493 auth_cfg_t *cfg, chunk_t v)
1494 {
1495 enum_map_t map[] = {
1496 { "strict", VALIDATION_GOOD },
1497 { "ifuri", VALIDATION_SKIPPED },
1498 { "relaxed", VALIDATION_FAILED },
1499 };
1500 int d;
1501
1502 if (parse_map(map, countof(map), &d, v))
1503 {
1504 if (d != VALIDATION_FAILED)
1505 {
1506 cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, d);
1507 }
1508 return TRUE;
1509 }
1510 return FALSE;
1511 }
1512
1513 /**
1514 * Parse list items to comma separated strings
1515 */
1516 CALLBACK(parse_stringlist, bool,
1517 char **out, chunk_t v)
1518 {
1519 char *current;
1520
1521 if (!chunk_printable(v, NULL, ' '))
1522 {
1523 return FALSE;
1524 }
1525 current = *out;
1526 if (current)
1527 {
1528 if (asprintf(out, "%s, %.*s", current, (int)v.len, v.ptr) == -1)
1529 {
1530 return FALSE;
1531 }
1532 free(current);
1533 }
1534 else
1535 {
1536 if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
1537 {
1538 return FALSE;
1539 }
1540 }
1541 return TRUE;
1542 }
1543
1544 /**
1545 * Parse an fragmentation_t
1546 */
1547 CALLBACK(parse_frag, bool,
1548 fragmentation_t *out, chunk_t v)
1549 {
1550 enum_map_t map[] = {
1551 { "yes", FRAGMENTATION_YES },
1552 { "accept", FRAGMENTATION_ACCEPT },
1553 { "no", FRAGMENTATION_NO },
1554 { "force", FRAGMENTATION_FORCE },
1555 };
1556 int d;
1557
1558 if (parse_map(map, countof(map), &d, v))
1559 {
1560 *out = d;
1561 return TRUE;
1562 }
1563 return FALSE;
1564 }
1565
1566 /**
1567 * Parse a childless_t
1568 */
1569 CALLBACK(parse_childless, bool,
1570 childless_t *out, chunk_t v)
1571 {
1572 enum_map_t map[] = {
1573 { "allow", CHILDLESS_ALLOW },
1574 { "never", CHILDLESS_NEVER },
1575 { "force", CHILDLESS_FORCE },
1576 };
1577 int d;
1578
1579 if (parse_map(map, countof(map), &d, v))
1580 {
1581 *out = d;
1582 return TRUE;
1583 }
1584 return FALSE;
1585 }
1586
1587 /**
1588 * Parse a cert_policy_t
1589 */
1590 CALLBACK(parse_send_cert, bool,
1591 cert_policy_t *out, chunk_t v)
1592 {
1593 enum_map_t map[] = {
1594 { "ifasked", CERT_SEND_IF_ASKED },
1595 { "always", CERT_ALWAYS_SEND },
1596 { "never", CERT_NEVER_SEND },
1597 };
1598 int d;
1599
1600 if (parse_map(map, countof(map), &d, v))
1601 {
1602 *out = d;
1603 return TRUE;
1604 }
1605 return FALSE;
1606 }
1607
1608 /**
1609 * Parse a unique_policy_t
1610 */
1611 CALLBACK(parse_unique, bool,
1612 unique_policy_t *out, chunk_t v)
1613 {
1614 enum_map_t map[] = {
1615 { "never", UNIQUE_NEVER },
1616 { "no", UNIQUE_NO },
1617 { "replace", UNIQUE_REPLACE },
1618 { "keep", UNIQUE_KEEP },
1619 };
1620 int d;
1621
1622 if (parse_map(map, countof(map), &d, v))
1623 {
1624 *out = d;
1625 return TRUE;
1626 }
1627 return FALSE;
1628 }
1629
1630 /**
1631 * Parse host_t into a list
1632 */
1633 CALLBACK(parse_hosts, bool,
1634 linked_list_t *list, chunk_t v)
1635 {
1636 char buf[64];
1637 host_t *host;
1638
1639 if (!vici_stringify(v, buf, sizeof(buf)))
1640 {
1641 return FALSE;
1642 }
1643 host = host_create_from_string(buf, 0);
1644 if (!host)
1645 {
1646 return FALSE;
1647 }
1648 list->insert_last(list, host);
1649 return TRUE;
1650 }
1651
1652 /**
1653 * Parse peer/ppk ID
1654 */
1655 CALLBACK(parse_peer_id, bool,
1656 identification_t **out, chunk_t v)
1657 {
1658 char buf[BUF_LEN];
1659
1660 if (!vici_stringify(v, buf, sizeof(buf)))
1661 {
1662 return FALSE;
1663 }
1664 *out = identification_create_from_string(buf);
1665 return TRUE;
1666 }
1667
1668
1669 CALLBACK(cert_kv, bool,
1670 cert_data_t *cert, vici_message_t *message, char *name, chunk_t value)
1671 {
1672 parse_rule_t rules[] = {
1673 { "handle", parse_string, &cert->handle },
1674 { "slot", parse_uint32, &cert->slot },
1675 { "module", parse_string, &cert->module },
1676 { "file", parse_string, &cert->file },
1677 };
1678
1679 return parse_rules(rules, countof(rules), name, value,
1680 &cert->request->reply);
1681 }
1682
1683 CALLBACK(child_li, bool,
1684 child_data_t *child, vici_message_t *message, char *name, chunk_t value)
1685 {
1686 parse_rule_t rules[] = {
1687 { "ah_proposals", parse_ah_proposal, child->proposals },
1688 { "esp_proposals", parse_esp_proposal, child->proposals },
1689 { "local_ts", parse_ts, child->local_ts },
1690 { "remote_ts", parse_ts, child->remote_ts },
1691 };
1692
1693 return parse_rules(rules, countof(rules), name, value,
1694 &child->request->reply);
1695 }
1696
1697 CALLBACK(child_kv, bool,
1698 child_data_t *child, vici_message_t *message, char *name, chunk_t value)
1699 {
1700 parse_rule_t rules[] = {
1701 { "updown", parse_string, &child->cfg.updown },
1702 { "hostaccess", parse_opt_haccess, &child->cfg.options },
1703 { "mode", parse_mode, &child->cfg },
1704 { "policies", parse_opt_policies, &child->cfg.options },
1705 { "policies_fwd_out", parse_opt_fwd_out, &child->cfg.options },
1706 { "replay_window", parse_uint32, &child->replay_window },
1707 { "rekey_time", parse_time, &child->cfg.lifetime.time.rekey },
1708 { "life_time", parse_time, &child->cfg.lifetime.time.life },
1709 { "rand_time", parse_time, &child->cfg.lifetime.time.jitter },
1710 { "rekey_bytes", parse_bytes, &child->cfg.lifetime.bytes.rekey },
1711 { "life_bytes", parse_bytes, &child->cfg.lifetime.bytes.life },
1712 { "rand_bytes", parse_bytes, &child->cfg.lifetime.bytes.jitter },
1713 { "rekey_packets", parse_uint64, &child->cfg.lifetime.packets.rekey },
1714 { "life_packets", parse_uint64, &child->cfg.lifetime.packets.life },
1715 { "rand_packets", parse_uint64, &child->cfg.lifetime.packets.jitter },
1716 { "dpd_action", parse_action, &child->cfg.dpd_action },
1717 { "start_action", parse_action, &child->cfg.start_action },
1718 { "close_action", parse_action, &child->cfg.close_action },
1719 { "ipcomp", parse_opt_ipcomp, &child->cfg.options },
1720 { "inactivity", parse_time32, &child->cfg.inactivity },
1721 { "reqid", parse_uint32, &child->cfg.reqid },
1722 { "mark_in", parse_mark, &child->cfg.mark_in },
1723 { "mark_in_sa", parse_opt_mark_in, &child->cfg.options },
1724 { "mark_out", parse_mark, &child->cfg.mark_out },
1725 { "set_mark_in", parse_set_mark, &child->cfg.set_mark_in },
1726 { "set_mark_out", parse_set_mark, &child->cfg.set_mark_out },
1727 { "tfc_padding", parse_tfc, &child->cfg.tfc },
1728 { "priority", parse_uint32, &child->cfg.priority },
1729 { "interface", parse_string, &child->cfg.interface },
1730 { "hw_offload", parse_hw_offload, &child->cfg.hw_offload },
1731 { "sha256_96", parse_opt_sha256_96,&child->cfg.options },
1732 { "copy_df", parse_opt_copy_df, &child->cfg.options },
1733 { "copy_ecn", parse_opt_copy_ecn, &child->cfg.options },
1734 { "copy_dscp", parse_copy_dscp, &child->cfg.copy_dscp },
1735 { "if_id_in", parse_if_id, &child->cfg.if_id_in },
1736 { "if_id_out", parse_if_id, &child->cfg.if_id_out },
1737 };
1738
1739 return parse_rules(rules, countof(rules), name, value,
1740 &child->request->reply);
1741 }
1742
1743 CALLBACK(auth_li, bool,
1744 auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
1745 {
1746 parse_rule_t rules[] = {
1747 { "groups", parse_group, auth->cfg },
1748 { "cert_policy", parse_cert_policy, auth->cfg },
1749 { "certs", parse_certs, auth },
1750 { "cacerts", parse_cacerts, auth },
1751 { "pubkeys", parse_pubkeys, auth },
1752 };
1753
1754 return parse_rules(rules, countof(rules), name, value,
1755 &auth->request->reply);
1756 }
1757
1758 CALLBACK(auth_kv, bool,
1759 auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
1760 {
1761 parse_rule_t rules[] = {
1762 { "auth", parse_auth, auth->cfg },
1763 { "id", parse_ike_id, auth->cfg },
1764 { "aaa_id", parse_aaa_id, auth->cfg },
1765 { "eap_id", parse_eap_id, auth->cfg },
1766 { "xauth_id", parse_xauth_id, auth->cfg },
1767 { "revocation", parse_revocation, auth->cfg },
1768 { "round", parse_uint32, &auth->round },
1769 };
1770
1771 return parse_rules(rules, countof(rules), name, value,
1772 &auth->request->reply);
1773 }
1774
1775 CALLBACK(peer_li, bool,
1776 peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
1777 {
1778 parse_rule_t rules[] = {
1779 { "local_addrs", parse_stringlist, &peer->local_addrs },
1780 { "remote_addrs", parse_stringlist, &peer->remote_addrs },
1781 { "proposals", parse_ike_proposal, peer->proposals },
1782 { "vips", parse_hosts, peer->vips },
1783 { "pools", parse_stringlist, &peer->pools },
1784 };
1785
1786 return parse_rules(rules, countof(rules), name, value,
1787 &peer->request->reply);
1788 }
1789
1790 CALLBACK(peer_kv, bool,
1791 peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
1792 {
1793 parse_rule_t rules[] = {
1794 { "version", parse_uint32, &peer->version },
1795 { "aggressive", parse_bool, &peer->aggressive },
1796 { "pull", parse_bool, &peer->pull },
1797 { "dscp", parse_dscp, &peer->dscp },
1798 { "encap", parse_bool, &peer->encap },
1799 { "mobike", parse_bool, &peer->mobike },
1800 { "dpd_delay", parse_time, &peer->dpd_delay },
1801 { "dpd_timeout", parse_time, &peer->dpd_timeout },
1802 { "fragmentation", parse_frag, &peer->fragmentation },
1803 { "childless", parse_childless, &peer->childless },
1804 { "send_certreq", parse_bool, &peer->send_certreq },
1805 { "send_cert", parse_send_cert, &peer->send_cert },
1806 { "keyingtries", parse_uint32, &peer->keyingtries },
1807 { "unique", parse_unique, &peer->unique },
1808 { "local_port", parse_uint32, &peer->local_port },
1809 { "remote_port", parse_uint32, &peer->remote_port },
1810 { "reauth_time", parse_time, &peer->reauth_time },
1811 { "rekey_time", parse_time, &peer->rekey_time },
1812 { "over_time", parse_time, &peer->over_time },
1813 { "rand_time", parse_time, &peer->rand_time },
1814 { "ppk_id", parse_peer_id, &peer->ppk_id },
1815 { "ppk_required", parse_bool, &peer->ppk_required },
1816 { "if_id_in", parse_if_id, &peer->if_id_in },
1817 { "if_id_out", parse_if_id, &peer->if_id_out },
1818 #ifdef ME
1819 { "mediation", parse_bool, &peer->mediation },
1820 { "mediated_by", parse_string, &peer->mediated_by },
1821 { "mediation_peer", parse_peer_id, &peer->peer_id },
1822 #endif /* ME */
1823 };
1824
1825 return parse_rules(rules, countof(rules), name, value,
1826 &peer->request->reply);
1827 }
1828
1829 CALLBACK(auth_sn, bool,
1830 auth_data_t *auth, vici_message_t *message, vici_parse_context_t *ctx,
1831 char *name)
1832 {
1833 if (strcasepfx(name, "cert") ||
1834 strcasepfx(name, "cacert"))
1835 {
1836 cert_data_t *data;
1837 auth_rule_t rule;
1838 certificate_t *cert;
1839 chunk_t handle;
1840
1841 INIT(data,
1842 .request = auth->request,
1843 .slot = -1,
1844 );
1845
1846 if (!message->parse(message, ctx, NULL, cert_kv, NULL, data))
1847 {
1848 free_cert_data(data);
1849 return FALSE;
1850 }
1851 if (!data->handle && !data->file)
1852 {
1853 auth->request->reply = create_reply("handle or file path missing: "
1854 "%s", name);
1855 free_cert_data(data);
1856 return FALSE;
1857 }
1858 else if (data->handle && data->file)
1859 {
1860 auth->request->reply = create_reply("handle and file path given: "
1861 "%s", name);
1862 free_cert_data(data);
1863 return FALSE;
1864 }
1865
1866 if (data->file)
1867 {
1868 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
1869 BUILD_FROM_FILE, data->file, BUILD_END);
1870 }
1871 else
1872 {
1873 handle = chunk_from_hex(chunk_from_str(data->handle), NULL);
1874 if (data->slot != -1)
1875 {
1876 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
1877 CERT_X509, BUILD_PKCS11_KEYID, handle,
1878 BUILD_PKCS11_SLOT, data->slot,
1879 data->module ? BUILD_PKCS11_MODULE : BUILD_END,
1880 data->module, BUILD_END);
1881 }
1882 else
1883 {
1884 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
1885 CERT_X509, BUILD_PKCS11_KEYID, handle,
1886 data->module ? BUILD_PKCS11_MODULE : BUILD_END,
1887 data->module, BUILD_END);
1888 }
1889 chunk_free(&handle);
1890 }
1891 free_cert_data(data);
1892 if (!cert)
1893 {
1894 auth->request->reply = create_reply("unable to load certificate: "
1895 "%s", name);
1896 return FALSE;
1897 }
1898 rule = strcasepfx(name, "cert") ? AUTH_RULE_SUBJECT_CERT
1899 : AUTH_RULE_CA_CERT;
1900 return add_cert(auth, rule, cert);
1901 }
1902 auth->request->reply = create_reply("invalid section: %s", name);
1903 return FALSE;
1904 }
1905
1906 /**
1907 * Check and update lifetimes
1908 */
1909 static void check_lifetimes(lifetime_cfg_t *lft)
1910 {
1911 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1912 if (lft->time.life == LFT_UNDEFINED)
1913 {
1914 lft->time.life = lft->time.rekey * 110 / 100;
1915 }
1916 if (lft->bytes.life == LFT_UNDEFINED)
1917 {
1918 lft->bytes.life = lft->bytes.rekey * 110 / 100;
1919 }
1920 if (lft->packets.life == LFT_UNDEFINED)
1921 {
1922 lft->packets.life = lft->packets.rekey * 110 / 100;
1923 }
1924 /* if no rand time defined, use difference of hard and soft */
1925 if (lft->time.jitter == LFT_UNDEFINED)
1926 {
1927 lft->time.jitter = lft->time.life -
1928 min(lft->time.life, lft->time.rekey);
1929 }
1930 if (lft->bytes.jitter == LFT_UNDEFINED)
1931 {
1932 lft->bytes.jitter = lft->bytes.life -
1933 min(lft->bytes.life, lft->bytes.rekey);
1934 }
1935 if (lft->packets.jitter == LFT_UNDEFINED)
1936 {
1937 lft->packets.jitter = lft->packets.life -
1938 min(lft->packets.life, lft->packets.rekey);
1939 }
1940 }
1941
1942 CALLBACK(children_sn, bool,
1943 peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
1944 char *name)
1945 {
1946 child_data_t child = {
1947 .request = peer->request,
1948 .proposals = linked_list_create(),
1949 .local_ts = linked_list_create(),
1950 .remote_ts = linked_list_create(),
1951 .replay_window = REPLAY_UNDEFINED,
1952 .cfg = {
1953 .mode = MODE_TUNNEL,
1954 .lifetime = {
1955 .time = {
1956 .rekey = LFT_DEFAULT_CHILD_REKEY_TIME,
1957 .life = LFT_UNDEFINED,
1958 .jitter = LFT_UNDEFINED,
1959 },
1960 .bytes = {
1961 .rekey = LFT_DEFAULT_CHILD_REKEY_BYTES,
1962 .life = LFT_UNDEFINED,
1963 .jitter = LFT_UNDEFINED,
1964 },
1965 .packets = {
1966 .rekey = LFT_DEFAULT_CHILD_REKEY_PACKETS,
1967 .life = LFT_UNDEFINED,
1968 .jitter = LFT_UNDEFINED,
1969 },
1970 },
1971 },
1972 };
1973 child_cfg_t *cfg;
1974 proposal_t *proposal;
1975 traffic_selector_t *ts;
1976
1977 if (!message->parse(message, ctx, NULL, child_kv, child_li, &child))
1978 {
1979 free_child_data(&child);
1980 return FALSE;
1981 }
1982
1983 if (child.local_ts->get_count(child.local_ts) == 0)
1984 {
1985 child.local_ts->insert_last(child.local_ts,
1986 traffic_selector_create_dynamic(0, 0, 65535));
1987 }
1988 if (child.remote_ts->get_count(child.remote_ts) == 0)
1989 {
1990 child.remote_ts->insert_last(child.remote_ts,
1991 traffic_selector_create_dynamic(0, 0, 65535));
1992 }
1993 if (child.proposals->get_count(child.proposals) == 0)
1994 {
1995 proposal = proposal_create_default(PROTO_ESP);
1996 if (proposal)
1997 {
1998 child.proposals->insert_last(child.proposals, proposal);
1999 }
2000 proposal = proposal_create_default_aead(PROTO_ESP);
2001 if (proposal)
2002 {
2003 child.proposals->insert_last(child.proposals, proposal);
2004 }
2005 }
2006
2007 check_lifetimes(&child.cfg.lifetime);
2008
2009 log_child_data(&child, name);
2010
2011 cfg = child_cfg_create(name, &child.cfg);
2012
2013 if (child.replay_window != REPLAY_UNDEFINED)
2014 {
2015 cfg->set_replay_window(cfg, child.replay_window);
2016 }
2017 while (child.local_ts->remove_first(child.local_ts,
2018 (void**)&ts) == SUCCESS)
2019 {
2020 cfg->add_traffic_selector(cfg, TRUE, ts);
2021 }
2022 while (child.remote_ts->remove_first(child.remote_ts,
2023 (void**)&ts) == SUCCESS)
2024 {
2025 cfg->add_traffic_selector(cfg, FALSE, ts);
2026 }
2027 while (child.proposals->remove_first(child.proposals,
2028 (void**)&proposal) == SUCCESS)
2029 {
2030 cfg->add_proposal(cfg, proposal);
2031 }
2032
2033 peer->children->insert_last(peer->children, cfg);
2034
2035 free_child_data(&child);
2036
2037 return TRUE;
2038 }
2039
2040 CALLBACK(peer_sn, bool,
2041 peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
2042 char *name)
2043 {
2044 if (strcaseeq(name, "children"))
2045 {
2046 return message->parse(message, ctx, children_sn, NULL, NULL, peer);
2047 }
2048 if (strcasepfx(name, "local") ||
2049 strcasepfx(name, "remote"))
2050 {
2051 enumerator_t *enumerator;
2052 linked_list_t *auths;
2053 auth_data_t *auth, *current;
2054 auth_rule_t rule;
2055 certificate_t *cert;
2056 pubkey_cert_t *pubkey_cert;
2057 identification_t *id;
2058 bool default_id = FALSE;
2059
2060 INIT(auth,
2061 .request = peer->request,
2062 .cfg = auth_cfg_create(),
2063 );
2064
2065 if (!message->parse(message, ctx, auth_sn, auth_kv, auth_li, auth))
2066 {
2067 free_auth_data(auth);
2068 return FALSE;
2069 }
2070 id = auth->cfg->get(auth->cfg, AUTH_RULE_IDENTITY);
2071
2072 enumerator = auth->cfg->create_enumerator(auth->cfg);
2073 while (enumerator->enumerate(enumerator, &rule, &cert))
2074 {
2075 if (rule == AUTH_RULE_SUBJECT_CERT && !default_id)
2076 {
2077 if (id == NULL)
2078 {
2079 id = cert->get_subject(cert);
2080 DBG1(DBG_CFG, " id not specified, defaulting to"
2081 " cert subject '%Y'", id);
2082 auth->cfg->add(auth->cfg, AUTH_RULE_IDENTITY, id->clone(id));
2083 default_id = TRUE;
2084 }
2085 else if (cert->get_type(cert) == CERT_TRUSTED_PUBKEY &&
2086 id->get_type != ID_ANY)
2087 {
2088 /* set the subject of all raw public keys to the id */
2089 pubkey_cert = (pubkey_cert_t*)cert;
2090 pubkey_cert->set_subject(pubkey_cert, id);
2091 }
2092 }
2093 }
2094 enumerator->destroy(enumerator);
2095
2096 auths = strcasepfx(name, "local") ? peer->local : peer->remote;
2097 enumerator = auths->create_enumerator(auths);
2098 while (enumerator->enumerate(enumerator, &current))
2099 {
2100 if (auth->round < current->round)
2101 {
2102 break;
2103 }
2104 }
2105 auths->insert_before(auths, enumerator, auth);
2106 enumerator->destroy(enumerator);
2107 return TRUE;
2108 }
2109 peer->request->reply = create_reply("invalid section: %s", name);
2110 return FALSE;
2111 }
2112
2113 /**
2114 * Perform start actions associated with a child config
2115 */
2116 static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
2117 child_cfg_t *child_cfg)
2118 {
2119 switch (child_cfg->get_start_action(child_cfg))
2120 {
2121 case ACTION_RESTART:
2122 DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
2123 charon->controller->initiate(charon->controller,
2124 peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
2125 NULL, NULL, 0, FALSE);
2126 break;
2127 case ACTION_ROUTE:
2128 DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
2129 switch (child_cfg->get_mode(child_cfg))
2130 {
2131 case MODE_PASS:
2132 case MODE_DROP:
2133 charon->shunts->install(charon->shunts,
2134 peer_cfg->get_name(peer_cfg), child_cfg);
2135 break;
2136 default:
2137 charon->traps->install(charon->traps, peer_cfg, child_cfg);
2138 break;
2139 }
2140 break;
2141 default:
2142 break;
2143 }
2144 }
2145
2146 /**
2147 * Undo start actions associated with a child config
2148 */
2149 static void clear_start_action(private_vici_config_t *this, char *peer_name,
2150 child_cfg_t *child_cfg)
2151 {
2152 enumerator_t *enumerator, *children;
2153 child_sa_t *child_sa;
2154 ike_sa_t *ike_sa;
2155 uint32_t id = 0, others;
2156 array_t *ids = NULL, *ikeids = NULL;
2157 char *name;
2158
2159 name = child_cfg->get_name(child_cfg);
2160
2161 switch (child_cfg->get_start_action(child_cfg))
2162 {
2163 case ACTION_RESTART:
2164 enumerator = charon->controller->create_ike_sa_enumerator(
2165 charon->controller, TRUE);
2166 while (enumerator->enumerate(enumerator, &ike_sa))
2167 {
2168 if (!streq(ike_sa->get_name(ike_sa), peer_name))
2169 {
2170 continue;
2171 }
2172 others = id = 0;
2173 children = ike_sa->create_child_sa_enumerator(ike_sa);
2174 while (children->enumerate(children, &child_sa))
2175 {
2176 if (child_sa->get_state(child_sa) != CHILD_DELETING &&
2177 child_sa->get_state(child_sa) != CHILD_DELETED)
2178 {
2179 if (streq(name, child_sa->get_name(child_sa)))
2180 {
2181 id = child_sa->get_unique_id(child_sa);
2182 }
2183 else
2184 {
2185 others++;
2186 }
2187 }
2188 }
2189 children->destroy(children);
2190
2191 if (id && !others)
2192 {
2193 /* found matching children only, delete full IKE_SA */
2194 id = ike_sa->get_unique_id(ike_sa);
2195 array_insert_create_value(&ikeids, sizeof(id),
2196 ARRAY_TAIL, &id);
2197 }
2198 else
2199 {
2200 children = ike_sa->create_child_sa_enumerator(ike_sa);
2201 while (children->enumerate(children, &child_sa))
2202 {
2203 if (streq(name, child_sa->get_name(child_sa)))
2204 {
2205 id = child_sa->get_unique_id(child_sa);
2206 array_insert_create_value(&ids, sizeof(id),
2207 ARRAY_TAIL, &id);
2208 }
2209 }
2210 children->destroy(children);
2211 }
2212 }
2213 enumerator->destroy(enumerator);
2214
2215 if (array_count(ids))
2216 {
2217 while (array_remove(ids, ARRAY_HEAD, &id))
2218 {
2219 DBG1(DBG_CFG, "closing '%s' #%u", name, id);
2220 charon->controller->terminate_child(charon->controller,
2221 id, NULL, NULL, 0);
2222 }
2223 array_destroy(ids);
2224 }
2225 if (array_count(ikeids))
2226 {
2227 while (array_remove(ikeids, ARRAY_HEAD, &id))
2228 {
2229 DBG1(DBG_CFG, "closing IKE_SA #%u", id);
2230 charon->controller->terminate_ike(charon->controller, id,
2231 FALSE, NULL, NULL, 0);
2232 }
2233 array_destroy(ikeids);
2234 }
2235 break;
2236 case ACTION_ROUTE:
2237 DBG1(DBG_CFG, "uninstalling '%s'", name);
2238 switch (child_cfg->get_mode(child_cfg))
2239 {
2240 case MODE_PASS:
2241 case MODE_DROP:
2242 charon->shunts->uninstall(charon->shunts, peer_name, name);
2243 break;
2244 default:
2245 charon->traps->uninstall(charon->traps, peer_name, name);
2246 break;
2247 }
2248 break;
2249 default:
2250 break;
2251 }
2252 }
2253
2254 /**
2255 * Run or undo a start actions associated with a child config
2256 */
2257 static void handle_start_action(private_vici_config_t *this,
2258 peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
2259 bool undo)
2260 {
2261 this->handling_actions = TRUE;
2262 this->lock->unlock(this->lock);
2263
2264 if (undo)
2265 {
2266 clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
2267 }
2268 else
2269 {
2270 run_start_action(this, peer_cfg, child_cfg);
2271 }
2272
2273 this->lock->write_lock(this->lock);
2274 this->handling_actions = FALSE;
2275 }
2276
2277 /**
2278 * Run or undo start actions associated with all child configs of a peer config
2279 */
2280 static void handle_start_actions(private_vici_config_t *this,
2281 peer_cfg_t *peer_cfg, bool undo)
2282 {
2283 enumerator_t *enumerator;
2284 child_cfg_t *child_cfg;
2285
2286 this->handling_actions = TRUE;
2287 this->lock->unlock(this->lock);
2288
2289 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
2290 while (enumerator->enumerate(enumerator, &child_cfg))
2291 {
2292 if (undo)
2293 {
2294 clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
2295 }
2296 else
2297 {
2298 run_start_action(this, peer_cfg, child_cfg);
2299 }
2300 }
2301 enumerator->destroy(enumerator);
2302
2303 this->lock->write_lock(this->lock);
2304 this->handling_actions = FALSE;
2305 }
2306
2307 /**
2308 * Replace children of a peer config by a new config
2309 */
2310 static void replace_children(private_vici_config_t *this,
2311 peer_cfg_t *from, peer_cfg_t *to)
2312 {
2313 enumerator_t *enumerator;
2314 child_cfg_t *child;
2315 bool added;
2316
2317 enumerator = to->replace_child_cfgs(to, from);
2318 while (enumerator->enumerate(enumerator, &child, &added))
2319 {
2320 handle_start_action(this, to, child, !added);
2321 }
2322 enumerator->destroy(enumerator);
2323 }
2324
2325 /**
2326 * Merge/replace a peer config with existing configs
2327 */
2328 static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
2329 {
2330 enumerator_t *enumerator;
2331 peer_cfg_t *current;
2332 ike_cfg_t *ike_cfg;
2333 bool merged = FALSE;
2334
2335 this->lock->write_lock(this->lock);
2336 while (this->handling_actions)
2337 {
2338 this->condvar->wait(this->condvar, this->lock);
2339 }
2340
2341 enumerator = this->conns->create_enumerator(this->conns);
2342 while (enumerator->enumerate(enumerator, &current))
2343 {
2344 if (streq(peer_cfg->get_name(peer_cfg), current->get_name(current)))
2345 {
2346 ike_cfg = current->get_ike_cfg(current);
2347 if (peer_cfg->equals(peer_cfg, current) &&
2348 ike_cfg->equals(ike_cfg, peer_cfg->get_ike_cfg(peer_cfg)))
2349 {
2350 DBG1(DBG_CFG, "updated vici connection: %s",
2351 peer_cfg->get_name(peer_cfg));
2352 replace_children(this, peer_cfg, current);
2353 peer_cfg->destroy(peer_cfg);
2354 }
2355 else
2356 {
2357 DBG1(DBG_CFG, "replaced vici connection: %s",
2358 peer_cfg->get_name(peer_cfg));
2359 this->conns->insert_before(this->conns, enumerator, peer_cfg);
2360 this->conns->remove_at(this->conns, enumerator);
2361 handle_start_actions(this, current, TRUE);
2362 handle_start_actions(this, peer_cfg, FALSE);
2363 current->destroy(current);
2364 }
2365 merged = TRUE;
2366 break;
2367 }
2368 }
2369 enumerator->destroy(enumerator);
2370
2371 if (!merged)
2372 {
2373 DBG1(DBG_CFG, "added vici connection: %s", peer_cfg->get_name(peer_cfg));
2374 this->conns->insert_last(this->conns, peer_cfg);
2375 handle_start_actions(this, peer_cfg, FALSE);
2376 }
2377 this->condvar->signal(this->condvar);
2378 this->lock->unlock(this->lock);
2379 }
2380
2381 CALLBACK(config_sn, bool,
2382 request_data_t *request, vici_message_t *message,
2383 vici_parse_context_t *ctx, char *name)
2384 {
2385 peer_data_t peer = {
2386 .request = request,
2387 .local = linked_list_create(),
2388 .remote = linked_list_create(),
2389 .vips = linked_list_create(),
2390 .children = linked_list_create(),
2391 .proposals = linked_list_create(),
2392 .mobike = TRUE,
2393 .send_certreq = TRUE,
2394 .pull = TRUE,
2395 .send_cert = CERT_SEND_IF_ASKED,
2396 .version = IKE_ANY,
2397 .remote_port = IKEV2_UDP_PORT,
2398 .fragmentation = FRAGMENTATION_YES,
2399 .unique = UNIQUE_NO,
2400 .keyingtries = 1,
2401 .rekey_time = LFT_UNDEFINED,
2402 .reauth_time = LFT_UNDEFINED,
2403 .over_time = LFT_UNDEFINED,
2404 .rand_time = LFT_UNDEFINED,
2405 };
2406 enumerator_t *enumerator;
2407 peer_cfg_create_t cfg;
2408 peer_cfg_t *peer_cfg;
2409 ike_cfg_create_t ike;
2410 ike_cfg_t *ike_cfg;
2411 child_cfg_t *child_cfg;
2412 auth_data_t *auth;
2413 proposal_t *proposal;
2414 host_t *host;
2415 char *str;
2416
2417 DBG2(DBG_CFG, " conn %s:", name);
2418
2419 if (!message->parse(message, ctx, peer_sn, peer_kv, peer_li, &peer))
2420 {
2421 free_peer_data(&peer);
2422 return FALSE;
2423 }
2424
2425 if (peer.local->get_count(peer.local) == 0)
2426 {
2427 INIT(auth,
2428 .cfg = auth_cfg_create(),
2429 );
2430 peer.local->insert_last(peer.local, auth);
2431 }
2432 if (peer.remote->get_count(peer.remote) == 0)
2433 {
2434 INIT(auth,
2435 .cfg = auth_cfg_create(),
2436 );
2437 peer.remote->insert_last(peer.remote, auth);
2438 }
2439 if (peer.proposals->get_count(peer.proposals) == 0)
2440 {
2441 proposal = proposal_create_default(PROTO_IKE);
2442 if (proposal)
2443 {
2444 peer.proposals->insert_last(peer.proposals, proposal);
2445 }
2446 proposal = proposal_create_default_aead(PROTO_IKE);
2447 if (proposal)
2448 {
2449 peer.proposals->insert_last(peer.proposals, proposal);
2450 }
2451 }
2452 if (!peer.local_addrs)
2453 {
2454 peer.local_addrs = strdup("%any");
2455 }
2456 if (!peer.remote_addrs)
2457 {
2458 peer.remote_addrs = strdup("%any");
2459 }
2460 if (!peer.local_port)
2461 {
2462 peer.local_port = charon->socket->get_port(charon->socket, FALSE);
2463 }
2464
2465 if (peer.rekey_time == LFT_UNDEFINED && peer.reauth_time == LFT_UNDEFINED)
2466 {
2467 /* apply a default rekey time if no rekey/reauth time set */
2468 peer.rekey_time = LFT_DEFAULT_IKE_REKEY_TIME;
2469 peer.reauth_time = 0;
2470 }
2471 if (peer.rekey_time == LFT_UNDEFINED)
2472 {
2473 peer.rekey_time = 0;
2474 }
2475 if (peer.reauth_time == LFT_UNDEFINED)
2476 {
2477 peer.reauth_time = 0;
2478 }
2479 if (peer.over_time == LFT_UNDEFINED)
2480 {
2481 /* default over_time to 10% of rekey/reauth time if not given */
2482 peer.over_time = max(peer.rekey_time, peer.reauth_time) / 10;
2483 }
2484 if (peer.rand_time == LFT_UNDEFINED)
2485 {
2486 /* default rand_time to over_time if not given, but don't make it
2487 * longer than half of rekey/rauth time */
2488 if (peer.rekey_time && peer.reauth_time)
2489 {
2490 peer.rand_time = min(peer.rekey_time, peer.reauth_time);
2491 }
2492 else
2493 {
2494 peer.rand_time = max(peer.rekey_time, peer.reauth_time);
2495 }
2496 peer.rand_time = min(peer.over_time, peer.rand_time / 2);
2497 }
2498
2499 #ifdef ME
2500 if (peer.mediation && peer.mediated_by)
2501 {
2502 DBG1(DBG_CFG, "a mediation connection cannot be a mediated connection "
2503 "at the same time, config discarded");
2504 free_peer_data(&peer);
2505 return FALSE;
2506 }
2507 if (peer.mediation)
2508 { /* force unique connections for mediation connections */
2509 peer.unique = UNIQUE_REPLACE;
2510 }
2511 else if (peer.mediated_by)
2512 { /* fallback to remote identity of first auth round if peer_id is not
2513 * given explicitly */
2514 auth_cfg_t *cfg;
2515
2516 if (!peer.peer_id &&
2517 peer.remote->get_first(peer.remote, (void**)&cfg) == SUCCESS)
2518 {
2519 peer.peer_id = cfg->get(cfg, AUTH_RULE_IDENTITY);
2520 if (peer.peer_id)
2521 {
2522 peer.peer_id = peer.peer_id->clone(peer.peer_id);
2523 }
2524 else
2525 {
2526 DBG1(DBG_CFG, "mediation peer missing for mediated connection, "
2527 "config discarded");
2528 free_peer_data(&peer);
2529 return FALSE;
2530 }
2531 }
2532 }
2533 #endif /* ME */
2534
2535 log_peer_data(&peer);
2536
2537 ike = (ike_cfg_create_t){
2538 .version = peer.version,
2539 .local = peer.local_addrs,
2540 .local_port = peer.local_port,
2541 .remote = peer.remote_addrs,
2542 .remote_port = peer.remote_port,
2543 .no_certreq = !peer.send_certreq,
2544 .force_encap = peer.encap,
2545 .fragmentation = peer.fragmentation,
2546 .childless = peer.childless,
2547 .dscp = peer.dscp,
2548 };
2549 ike_cfg = ike_cfg_create(&ike);
2550
2551 cfg = (peer_cfg_create_t){
2552 .cert_policy = peer.send_cert,
2553 .unique = peer.unique,
2554 .keyingtries = peer.keyingtries,
2555 .rekey_time = peer.rekey_time,
2556 .reauth_time = peer.reauth_time,
2557 .jitter_time = peer.rand_time,
2558 .over_time = peer.over_time,
2559 .no_mobike = !peer.mobike,
2560 .aggressive = peer.aggressive,
2561 .push_mode = !peer.pull,
2562 .dpd = peer.dpd_delay,
2563 .dpd_timeout = peer.dpd_timeout,
2564 .ppk_id = peer.ppk_id ? peer.ppk_id->clone(peer.ppk_id) : NULL,
2565 .ppk_required = peer.ppk_required,
2566 .if_id_in = peer.if_id_in,
2567 .if_id_out = peer.if_id_out,
2568 };
2569 #ifdef ME
2570 cfg.mediation = peer.mediation;
2571 if (peer.mediated_by)
2572 {
2573 cfg.mediated_by = peer.mediated_by;
2574 if (peer.peer_id)
2575 {
2576 cfg.peer_id = peer.peer_id->clone(peer.peer_id);
2577 }
2578 }
2579 #endif /* ME */
2580 peer_cfg = peer_cfg_create(name, ike_cfg, &cfg);
2581
2582 while (peer.local->remove_first(peer.local,
2583 (void**)&auth) == SUCCESS)
2584 {
2585 peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, TRUE);
2586 auth->cfg = NULL;
2587 free_auth_data(auth);
2588 }
2589 while (peer.remote->remove_first(peer.remote,
2590 (void**)&auth) == SUCCESS)
2591 {
2592 peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, FALSE);
2593 auth->cfg = NULL;
2594 free_auth_data(auth);
2595 }
2596 while (peer.children->remove_first(peer.children,
2597 (void**)&child_cfg) == SUCCESS)
2598 {
2599 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
2600 }
2601 while (peer.proposals->remove_first(peer.proposals,
2602 (void**)&proposal) == SUCCESS)
2603 {
2604 ike_cfg->add_proposal(ike_cfg, proposal);
2605 }
2606 while (peer.vips->remove_first(peer.vips, (void**)&host) == SUCCESS)
2607 {
2608 peer_cfg->add_virtual_ip(peer_cfg, host);
2609 }
2610 if (peer.pools)
2611 {
2612 enumerator = enumerator_create_token(peer.pools, ",", " ");
2613 while (enumerator->enumerate(enumerator, &str))
2614 {
2615 peer_cfg->add_pool(peer_cfg, str);
2616 }
2617 enumerator->destroy(enumerator);
2618 }
2619
2620 free_peer_data(&peer);
2621
2622 merge_config(request->this, peer_cfg);
2623
2624 return TRUE;
2625 }
2626
2627 CALLBACK(load_conn, vici_message_t*,
2628 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2629 {
2630 request_data_t request = {
2631 .this = this,
2632 };
2633
2634 if (!message->parse(message, NULL, config_sn, NULL, NULL, &request))
2635 {
2636 if (request.reply)
2637 {
2638 return request.reply;
2639 }
2640 return create_reply("parsing request failed");
2641 }
2642 return create_reply(NULL);
2643 }
2644
2645 CALLBACK(unload_conn, vici_message_t*,
2646 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2647 {
2648 enumerator_t *enumerator;
2649 peer_cfg_t *cfg;
2650 char *conn_name;
2651 bool found = FALSE;
2652
2653 conn_name = message->get_str(message, NULL, "name");
2654 if (!conn_name)
2655 {
2656 return create_reply("unload: missing connection name");
2657 }
2658
2659 this->lock->write_lock(this->lock);
2660 while (this->handling_actions)
2661 {
2662 this->condvar->wait(this->condvar, this->lock);
2663 }
2664 enumerator = this->conns->create_enumerator(this->conns);
2665 while (enumerator->enumerate(enumerator, &cfg))
2666 {
2667 if (streq(cfg->get_name(cfg), conn_name))
2668 {
2669 this->conns->remove_at(this->conns, enumerator);
2670 handle_start_actions(this, cfg, TRUE);
2671 cfg->destroy(cfg);
2672 found = TRUE;
2673 break;
2674 }
2675 }
2676 enumerator->destroy(enumerator);
2677 this->condvar->signal(this->condvar);
2678 this->lock->unlock(this->lock);
2679
2680 if (!found)
2681 {
2682 return create_reply("unload: connection '%s' not found", conn_name);
2683 }
2684 return create_reply(NULL);
2685 }
2686
2687 CALLBACK(get_conns, vici_message_t*,
2688 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2689 {
2690 vici_builder_t *builder;
2691 enumerator_t *enumerator;
2692 peer_cfg_t *cfg;
2693
2694 builder = vici_builder_create();
2695 builder->begin_list(builder, "conns");
2696
2697 this->lock->read_lock(this->lock);
2698 enumerator = this->conns->create_enumerator(this->conns);
2699 while (enumerator->enumerate(enumerator, &cfg))
2700 {
2701 builder->add_li(builder, "%s", cfg->get_name(cfg));
2702 }
2703 enumerator->destroy(enumerator);
2704 this->lock->unlock(this->lock);
2705
2706 builder->end_list(builder);
2707
2708 return builder->finalize(builder);
2709 }
2710
2711 static void manage_command(private_vici_config_t *this,
2712 char *name, vici_command_cb_t cb, bool reg)
2713 {
2714 this->dispatcher->manage_command(this->dispatcher, name,
2715 reg ? cb : NULL, this);
2716 }
2717
2718 /**
2719 * (Un-)register dispatcher functions
2720 */
2721 static void manage_commands(private_vici_config_t *this, bool reg)
2722 {
2723 manage_command(this, "load-conn", load_conn, reg);
2724 manage_command(this, "unload-conn", unload_conn, reg);
2725 manage_command(this, "get-conns", get_conns, reg);
2726 }
2727
2728 METHOD(vici_config_t, destroy, void,
2729 private_vici_config_t *this)
2730 {
2731 manage_commands(this, FALSE);
2732 this->conns->destroy_offset(this->conns, offsetof(peer_cfg_t, destroy));
2733 this->condvar->destroy(this->condvar);
2734 this->lock->destroy(this->lock);
2735 free(this);
2736 }
2737
2738 /**
2739 * See header
2740 */
2741 vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
2742 vici_authority_t *authority,
2743 vici_cred_t *cred)
2744 {
2745 private_vici_config_t *this;
2746
2747 INIT(this,
2748 .public = {
2749 .backend = {
2750 .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
2751 .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
2752 .get_peer_cfg_by_name = _get_peer_cfg_by_name,
2753 },
2754 .destroy = _destroy,
2755 },
2756 .dispatcher = dispatcher,
2757 .conns = linked_list_create(),
2758 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
2759 .condvar = rwlock_condvar_create(),
2760 .authority = authority,
2761 .cred = cred,
2762 );
2763
2764 manage_commands(this, TRUE);
2765
2766 return &this->public;
2767 }