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