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