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