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