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