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