Apply pubkey and signature constraints in vici plugin
[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 Andreas Steffen
6 * HSR Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 /*
20 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
21 *
22 * Permission is hereby granted, free of charge, to any person obtaining a copy
23 * of this software and associated documentation files (the "Software"), to deal
24 * in the Software without restriction, including without limitation the rights
25 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26 * copies of the Software, and to permit persons to whom the Software is
27 * furnished to do so, subject to the following conditions:
28 *
29 * The above copyright notice and this permission notice shall be included in
30 * all copies or substantial portions of the Software.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38 * THE SOFTWARE.
39 */
40
41 #define _GNU_SOURCE
42
43 #include "vici_config.h"
44 #include "vici_builder.h"
45
46 #include <daemon.h>
47 #include <threading/rwlock.h>
48 #include <collections/array.h>
49 #include <collections/linked_list.h>
50
51 #include <stdio.h>
52
53 /**
54 * Magic value for an undefined lifetime
55 */
56 #define LFT_UNDEFINED (~(u_int64_t)0)
57
58 /**
59 * Default IKE rekey time
60 */
61 #define LFT_DEFAULT_IKE_REKEY (4 * 60 * 60)
62
63 /**
64 * Default CHILD rekey time
65 */
66 #define LFT_DEFAULT_CHILD_REKEY (1 * 60 * 60)
67
68 /**
69 * Undefined replay window
70 */
71 #define REPLAY_UNDEFINED (~(u_int32_t)0)
72
73 typedef struct private_vici_config_t private_vici_config_t;
74
75 /**
76 * Private data of an vici_config_t object.
77 */
78 struct private_vici_config_t {
79
80 /**
81 * Public vici_config_t interface.
82 */
83 vici_config_t public;
84
85 /**
86 * Dispatcher
87 */
88 vici_dispatcher_t *dispatcher;
89
90 /**
91 * List of loaded connections, as peer_cfg_t
92 */
93 linked_list_t *conns;
94
95 /**
96 * Lock for conns list
97 */
98 rwlock_t *lock;
99
100 /**
101 * Auxiliary certification authority information
102 */
103 vici_authority_t *authority;
104
105 };
106
107 METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
108 private_vici_config_t *this, identification_t *me, identification_t *other)
109 {
110 this->lock->read_lock(this->lock);
111 return enumerator_create_cleaner(this->conns->create_enumerator(this->conns),
112 (void*)this->lock->unlock, this->lock);
113 }
114
115 /**
116 * Enumerator filter function for ike configs
117 */
118 static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
119 {
120 *out = (*in)->get_ike_cfg(*in);
121 return TRUE;
122 }
123
124 METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
125 private_vici_config_t *this, host_t *me, host_t *other)
126 {
127 this->lock->read_lock(this->lock);
128 return enumerator_create_filter(this->conns->create_enumerator(this->conns),
129 (void*)ike_filter, this->lock,
130 (void*)this->lock->unlock);
131 }
132
133 METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
134 private_vici_config_t *this, char *name)
135 {
136 peer_cfg_t *current, *found = NULL;
137 enumerator_t *enumerator;
138
139 this->lock->read_lock(this->lock);
140 enumerator = this->conns->create_enumerator(this->conns);
141 while (enumerator->enumerate(enumerator, &current))
142 {
143 if (streq(current->get_name(current), name))
144 {
145 found = current;
146 found->get_ref(found);
147 break;
148 }
149 }
150 enumerator->destroy(enumerator);
151 this->lock->unlock(this->lock);
152
153 return found;
154 }
155
156 /**
157 * Create a (error) reply message
158 */
159 static vici_message_t* create_reply(char *fmt, ...)
160 {
161 vici_builder_t *builder;
162 va_list args;
163
164 builder = vici_builder_create();
165 builder->add_kv(builder, "success", fmt ? "no" : "yes");
166 if (fmt)
167 {
168 va_start(args, fmt);
169 builder->vadd_kv(builder, "errmsg", fmt, args);
170 va_end(args);
171 }
172 return builder->finalize(builder);
173 }
174
175 /**
176 * A rule to parse a key/value or list item
177 */
178 typedef struct {
179 /** name of the key/value or list */
180 char *name;
181 /** function to parse value */
182 bool (*parse)(void *out, chunk_t value);
183 /** result, passed to parse() */
184 void *out;
185 } parse_rule_t;
186
187 /**
188 * Parse key/values using a rule-set
189 */
190 static bool parse_rules(parse_rule_t *rules, int count, char *name,
191 chunk_t value, vici_message_t **reply)
192 {
193 int i;
194
195 for (i = 0; i < count; i++)
196 {
197 if (streq(name, rules[i].name))
198 {
199 if (rules[i].parse(rules[i].out, value))
200 {
201 return TRUE;
202 }
203 *reply = create_reply("invalid value for: %s, config discarded",
204 name);
205 return FALSE;
206 }
207 }
208 *reply = create_reply("unknown option: %s, config discarded", name);
209 return FALSE;
210 }
211
212 /**
213 * Parse callback data, passed to each callback
214 */
215 typedef struct {
216 private_vici_config_t *this;
217 vici_message_t *reply;
218 } request_data_t;
219
220 /**
221 * Data associated to a peer config
222 */
223 typedef struct {
224 request_data_t *request;
225 u_int32_t version;
226 bool aggressive;
227 bool encap;
228 bool mobike;
229 bool send_certreq;
230 bool pull;
231 cert_policy_t send_cert;
232 u_int64_t dpd_delay;
233 u_int64_t dpd_timeout;
234 fragmentation_t fragmentation;
235 unique_policy_t unique;
236 u_int32_t keyingtries;
237 u_int32_t local_port;
238 u_int32_t remote_port;
239 char *local_addrs;
240 char *remote_addrs;
241 linked_list_t *local;
242 linked_list_t *remote;
243 linked_list_t *proposals;
244 linked_list_t *children;
245 linked_list_t *vips;
246 char *pools;
247 u_int64_t reauth_time;
248 u_int64_t rekey_time;
249 u_int64_t over_time;
250 u_int64_t rand_time;
251 } peer_data_t;
252
253 /**
254 * Log relevant auth config data
255 */
256 static void log_auth(auth_cfg_t *auth)
257 {
258 enumerator_t *enumerator;
259 auth_rule_t rule;
260 union {
261 uintptr_t u;
262 identification_t *id;
263 char *str;
264 } v;
265
266 enumerator = auth->create_enumerator(auth);
267 while (enumerator->enumerate(enumerator, &rule, &v))
268 {
269 switch (rule)
270 {
271 case AUTH_RULE_AUTH_CLASS:
272 DBG2(DBG_CFG, " class = %N", auth_class_names, v.u);
273 break;
274 case AUTH_RULE_EAP_TYPE:
275 DBG2(DBG_CFG, " eap-type = %N", eap_type_names, v.u);
276 break;
277 case AUTH_RULE_EAP_VENDOR:
278 DBG2(DBG_CFG, " eap-vendor = %u", v.u);
279 break;
280 case AUTH_RULE_XAUTH_BACKEND:
281 DBG2(DBG_CFG, " xauth = %s", v.str);
282 break;
283 case AUTH_RULE_CRL_VALIDATION:
284 DBG2(DBG_CFG, " revocation = %N", cert_validation_names, v.u);
285 break;
286 case AUTH_RULE_IDENTITY:
287 DBG2(DBG_CFG, " id = %Y", v.id);
288 break;
289 case AUTH_RULE_AAA_IDENTITY:
290 DBG2(DBG_CFG, " aaa_id = %Y", v.id);
291 break;
292 case AUTH_RULE_EAP_IDENTITY:
293 DBG2(DBG_CFG, " eap_id = %Y", v.id);
294 break;
295 case AUTH_RULE_XAUTH_IDENTITY:
296 DBG2(DBG_CFG, " xauth_id = %Y", v.id);
297 break;
298 case AUTH_RULE_GROUP:
299 DBG2(DBG_CFG, " group = %Y", v.id);
300 break;
301 default:
302 break;
303 }
304 }
305 enumerator->destroy(enumerator);
306 }
307
308 /**
309 * Log parsed peer data
310 */
311 static void log_peer_data(peer_data_t *data)
312 {
313 enumerator_t *enumerator;
314 auth_cfg_t *auth;
315 host_t *host;
316
317 DBG2(DBG_CFG, " version = %u", data->version);
318 DBG2(DBG_CFG, " local_addrs = %s", data->local_addrs);
319 DBG2(DBG_CFG, " remote_addrs = %s", data->remote_addrs);
320 DBG2(DBG_CFG, " local_port = %u", data->local_port);
321 DBG2(DBG_CFG, " remote_port = %u", data->remote_port);
322 DBG2(DBG_CFG, " send_certreq = %u", data->send_certreq);
323 DBG2(DBG_CFG, " send_cert = %N", cert_policy_names, data->send_cert);
324 DBG2(DBG_CFG, " mobike = %u", data->mobike);
325 DBG2(DBG_CFG, " aggressive = %u", data->aggressive);
326 DBG2(DBG_CFG, " encap = %u", data->encap);
327 DBG2(DBG_CFG, " dpd_delay = %llu", data->dpd_delay);
328 DBG2(DBG_CFG, " dpd_timeout = %llu", data->dpd_timeout);
329 DBG2(DBG_CFG, " fragmentation = %u", data->fragmentation);
330 DBG2(DBG_CFG, " unique = %N", unique_policy_names, data->unique);
331 DBG2(DBG_CFG, " keyingtries = %u", data->keyingtries);
332 DBG2(DBG_CFG, " reauth_time = %llu", data->reauth_time);
333 DBG2(DBG_CFG, " rekey_time = %llu", data->rekey_time);
334 DBG2(DBG_CFG, " over_time = %llu", data->over_time);
335 DBG2(DBG_CFG, " rand_time = %llu", data->rand_time);
336 DBG2(DBG_CFG, " proposals = %#P", data->proposals);
337
338 if (data->vips->get_count(data->vips))
339 {
340 DBG2(DBG_CFG, " vips:");
341 }
342 enumerator = data->vips->create_enumerator(data->vips);
343 while (enumerator->enumerate(enumerator, &host))
344 {
345 DBG2(DBG_CFG, " %H", host);
346 }
347 enumerator->destroy(enumerator);
348
349 enumerator = data->local->create_enumerator(data->local);
350 while (enumerator->enumerate(enumerator, &auth))
351 {
352 DBG2(DBG_CFG, " local:");
353 log_auth(auth);
354 }
355 enumerator->destroy(enumerator);
356
357 enumerator = data->remote->create_enumerator(data->remote);
358 while (enumerator->enumerate(enumerator, &auth))
359 {
360 DBG2(DBG_CFG, " remote:");
361 log_auth(auth);
362 }
363 enumerator->destroy(enumerator);
364 }
365
366 /**
367 * Clean up peer config data
368 */
369 static void free_peer_data(peer_data_t *data)
370 {
371 data->local->destroy_offset(data->local,
372 offsetof(auth_cfg_t, destroy));
373 data->remote->destroy_offset(data->remote,
374 offsetof(auth_cfg_t, destroy));
375 data->children->destroy_offset(data->children,
376 offsetof(child_cfg_t, destroy));
377 data->proposals->destroy_offset(data->proposals,
378 offsetof(proposal_t, destroy));
379 data->vips->destroy_offset(data->vips, offsetof(host_t, destroy));
380 free(data->pools);
381 free(data->local_addrs);
382 free(data->remote_addrs);
383 }
384
385 /**
386 * CHILD config data
387 */
388 typedef struct {
389 request_data_t *request;
390 lifetime_cfg_t lft;
391 char* updown;
392 bool hostaccess;
393 bool ipcomp;
394 bool policies;
395 ipsec_mode_t mode;
396 u_int32_t replay_window;
397 action_t dpd_action;
398 action_t start_action;
399 action_t close_action;
400 u_int32_t reqid;
401 u_int32_t tfc;
402 mark_t mark_in;
403 mark_t mark_out;
404 u_int64_t inactivity;
405 linked_list_t *proposals;
406 linked_list_t *local_ts;
407 linked_list_t *remote_ts;
408 } child_data_t;
409
410 /**
411 * Log parsed CHILD config data
412 */
413 static void log_child_data(child_data_t *data, char *name)
414 {
415 DBG2(DBG_CFG, " child %s:", name);
416 DBG2(DBG_CFG, " rekey_time = %llu", data->lft.time.rekey);
417 DBG2(DBG_CFG, " life_time = %llu", data->lft.time.life);
418 DBG2(DBG_CFG, " rand_time = %llu", data->lft.time.jitter);
419 DBG2(DBG_CFG, " rekey_bytes = %llu", data->lft.bytes.rekey);
420 DBG2(DBG_CFG, " life_bytes = %llu", data->lft.bytes.life);
421 DBG2(DBG_CFG, " rand_bytes = %llu", data->lft.bytes.jitter);
422 DBG2(DBG_CFG, " rekey_packets = %llu", data->lft.packets.rekey);
423 DBG2(DBG_CFG, " life_packets = %llu", data->lft.packets.life);
424 DBG2(DBG_CFG, " rand_packets = %llu", data->lft.packets.jitter);
425 DBG2(DBG_CFG, " updown = %s", data->updown);
426 DBG2(DBG_CFG, " hostaccess = %u", data->hostaccess);
427 DBG2(DBG_CFG, " ipcomp = %u", data->ipcomp);
428 DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, data->mode);
429 DBG2(DBG_CFG, " policies = %u", data->policies);
430 if (data->replay_window != REPLAY_UNDEFINED)
431 {
432 DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
433 }
434 DBG2(DBG_CFG, " dpd_action = %N", action_names, data->dpd_action);
435 DBG2(DBG_CFG, " start_action = %N", action_names, data->start_action);
436 DBG2(DBG_CFG, " close_action = %N", action_names, data->close_action);
437 DBG2(DBG_CFG, " reqid = %u", data->reqid);
438 DBG2(DBG_CFG, " tfc = %d", data->tfc);
439 DBG2(DBG_CFG, " mark_in = %u/%u",
440 data->mark_in.value, data->mark_in.mask);
441 DBG2(DBG_CFG, " mark_out = %u/%u",
442 data->mark_out.value, data->mark_out.mask);
443 DBG2(DBG_CFG, " inactivity = %llu", data->inactivity);
444 DBG2(DBG_CFG, " proposals = %#P", data->proposals);
445 DBG2(DBG_CFG, " local_ts = %#R", data->local_ts);
446 DBG2(DBG_CFG, " remote_ts = %#R", data->remote_ts);
447 }
448
449 /**
450 * Clean up CHILD config data
451 */
452 static void free_child_data(child_data_t *data)
453 {
454 data->proposals->destroy_offset(data->proposals,
455 offsetof(proposal_t, destroy));
456 data->local_ts->destroy_offset(data->local_ts,
457 offsetof(traffic_selector_t, destroy));
458 data->remote_ts->destroy_offset(data->remote_ts,
459 offsetof(traffic_selector_t, destroy));
460 free(data->updown);
461 }
462
463 /**
464 * Auth config data
465 */
466 typedef struct {
467 request_data_t *request;
468 auth_cfg_t *cfg;
469 } auth_data_t;
470
471 /**
472 * Common proposal parsing
473 */
474 static bool parse_proposal(linked_list_t *list, protocol_id_t proto, chunk_t v)
475 {
476 char buf[128];
477 proposal_t *proposal;
478
479 if (!vici_stringify(v, buf, sizeof(buf)))
480 {
481 return FALSE;
482 }
483 if (strcaseeq("default", buf))
484 {
485 proposal = proposal_create_default(proto);
486 if (proposal)
487 {
488 list->insert_last(list, proposal);
489 }
490 proposal = proposal_create_default_aead(proto);
491 if (proposal)
492 {
493 list->insert_last(list, proposal);
494 }
495 return TRUE;
496 }
497 proposal = proposal_create_from_string(proto, buf);
498 if (proposal)
499 {
500 list->insert_last(list, proposal);
501 return TRUE;
502 }
503 return FALSE;
504 }
505
506 /**
507 * Parse IKE proposal
508 */
509 CALLBACK(parse_ike_proposal, bool,
510 linked_list_t *out, chunk_t v)
511 {
512 return parse_proposal(out, PROTO_IKE, v);
513 }
514
515 /**
516 * Parse ESP proposal
517 */
518 CALLBACK(parse_esp_proposal, bool,
519 linked_list_t *out, chunk_t v)
520 {
521 return parse_proposal(out, PROTO_ESP, v);
522 }
523
524 /**
525 * Parse AH proposal
526 */
527 CALLBACK(parse_ah_proposal, bool,
528 linked_list_t *out, chunk_t v)
529 {
530 return parse_proposal(out, PROTO_AH, v);
531 }
532
533 /**
534 * Parse a traffic selector
535 */
536 CALLBACK(parse_ts, bool,
537 linked_list_t *out, chunk_t v)
538 {
539 char buf[128], *protoport, *sep, *port = "", *end;
540 traffic_selector_t *ts;
541 struct protoent *protoent;
542 struct servent *svc;
543 long int p;
544 u_int16_t from = 0, to = 0xffff;
545 u_int8_t proto = 0;
546
547 if (!vici_stringify(v, buf, sizeof(buf)))
548 {
549 return FALSE;
550 }
551
552 protoport = strchr(buf, '[');
553 if (protoport)
554 {
555 *(protoport++) = '\0';
556
557 sep = strrchr(protoport, ']');
558 if (!sep)
559 {
560 return FALSE;
561 }
562 *sep = '\0';
563
564 sep = strchr(protoport, '/');
565 if (sep)
566 { /* protocol/port */
567 *sep = '\0';
568 port = sep + 1;
569 }
570
571 if (streq(protoport, "any"))
572 {
573 proto = 0;
574 }
575 else
576 {
577 protoent = getprotobyname(protoport);
578 if (protoent)
579 {
580 proto = protoent->p_proto;
581 }
582 else
583 {
584 p = strtol(protoport, &end, 0);
585 if ((*protoport && *end) || p < 0 || p > 0xff)
586 {
587 return FALSE;
588 }
589 proto = (u_int8_t)p;
590 }
591 }
592 if (streq(port, "opaque"))
593 {
594 from = 0xffff;
595 to = 0;
596 }
597 else if (*port && !streq(port, "any"))
598 {
599 svc = getservbyname(port, NULL);
600 if (svc)
601 {
602 from = to = ntohs(svc->s_port);
603 }
604 else
605 {
606 p = strtol(port, &end, 0);
607 if (p < 0 || p > 0xffff)
608 {
609 return FALSE;
610 }
611 from = p;
612 if (*end == '-')
613 {
614 port = end + 1;
615 p = strtol(port, &end, 0);
616 if (p < 0 || p > 0xffff)
617 {
618 return FALSE;
619 }
620 }
621 to = p;
622 if (*end)
623 {
624 return FALSE;
625 }
626 }
627 }
628 }
629 if (streq(buf, "dynamic"))
630 {
631 ts = traffic_selector_create_dynamic(proto, from, to);
632 }
633 else
634 {
635 ts = traffic_selector_create_from_cidr(buf, proto, from, to);
636 }
637 if (!ts)
638 {
639 return FALSE;
640 }
641 out->insert_last(out, ts);
642 return TRUE;
643 }
644
645 /**
646 * Parse a string
647 */
648 CALLBACK(parse_string, bool,
649 char **out, chunk_t v)
650 {
651 if (!chunk_printable(v, NULL, ' '))
652 {
653 return FALSE;
654 }
655 free(*out);
656 *out = NULL;
657 if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
658 {
659 return FALSE;
660 }
661 return TRUE;
662 }
663
664 /**
665 * Map a string to an integer
666 */
667 typedef struct {
668 char *str;
669 int d;
670 } enum_map_t;
671
672 /**
673 * Parse a string to an integer mapping
674 */
675 static bool parse_map(enum_map_t *map, int count, int *out, chunk_t v)
676 {
677 char buf[128];
678 int i;
679
680 if (!vici_stringify(v, buf, sizeof(buf)))
681 {
682 return FALSE;
683 }
684 for (i = 0; i < count; i++)
685 {
686 if (strcaseeq(map[i].str, buf))
687 {
688 *out = map[i].d;
689 return TRUE;
690 }
691 }
692 return FALSE;
693 }
694
695 /**
696 * Parse a boolean
697 */
698 CALLBACK(parse_bool, bool,
699 bool *out, chunk_t v)
700 {
701 enum_map_t map[] = {
702 { "yes", TRUE },
703 { "true", TRUE },
704 { "enabled", TRUE },
705 { "1", TRUE },
706 { "no", FALSE },
707 { "false", FALSE },
708 { "disabled", FALSE },
709 { "0", FALSE },
710 };
711 int d;
712
713 if (parse_map(map, countof(map), &d, v))
714 {
715 *out = d;
716 return TRUE;
717 }
718 return FALSE;
719 }
720
721 /**
722 * Parse a ipsec_mode_t
723 */
724 CALLBACK(parse_mode, bool,
725 ipsec_mode_t *out, chunk_t v)
726 {
727 enum_map_t map[] = {
728 { "tunnel", MODE_TUNNEL },
729 { "transport", MODE_TRANSPORT },
730 { "beet", MODE_BEET },
731 { "drop", MODE_DROP },
732 { "pass", MODE_PASS },
733 };
734 int d;
735
736 if (parse_map(map, countof(map), &d, v))
737 {
738 *out = d;
739 return TRUE;
740 }
741 return FALSE;
742 }
743
744 /**
745 * Parse an action_t
746 */
747 CALLBACK(parse_action, bool,
748 action_t *out, chunk_t v)
749 {
750 enum_map_t map[] = {
751 { "start", ACTION_RESTART },
752 { "restart", ACTION_RESTART },
753 { "route", ACTION_ROUTE },
754 { "trap", ACTION_ROUTE },
755 { "none", ACTION_NONE },
756 { "clear", ACTION_NONE },
757 };
758 int d;
759
760 if (parse_map(map, countof(map), &d, v))
761 {
762 *out = d;
763 return TRUE;
764 }
765 return FALSE;
766 }
767
768 /**
769 * Parse a u_int32_t
770 */
771 CALLBACK(parse_uint32, bool,
772 u_int32_t *out, chunk_t v)
773 {
774 char buf[16], *end;
775 u_long l;
776
777 if (!vici_stringify(v, buf, sizeof(buf)))
778 {
779 return FALSE;
780 }
781 l = strtoul(buf, &end, 0);
782 if (*end == 0)
783 {
784 *out = l;
785 return TRUE;
786 }
787 return FALSE;
788 }
789
790 /**
791 * Parse a u_int64_t
792 */
793 CALLBACK(parse_uint64, bool,
794 u_int64_t *out, chunk_t v)
795 {
796 char buf[16], *end;
797 unsigned long long l;
798
799 if (!vici_stringify(v, buf, sizeof(buf)))
800 {
801 return FALSE;
802 }
803 l = strtoull(buf, &end, 0);
804 if (*end == 0)
805 {
806 *out = l;
807 return TRUE;
808 }
809 return FALSE;
810 }
811
812 /**
813 * Parse a relative time
814 */
815 CALLBACK(parse_time, bool,
816 u_int64_t *out, chunk_t v)
817 {
818 char buf[16], *end;
819 u_long l;
820
821 if (!vici_stringify(v, buf, sizeof(buf)))
822 {
823 return FALSE;
824 }
825
826 l = strtoul(buf, &end, 0);
827 while (*end == ' ')
828 {
829 end++;
830 }
831 switch (*end)
832 {
833 case 'd':
834 case 'D':
835 l *= 24;
836 /* fall */
837 case 'h':
838 case 'H':
839 l *= 60;
840 /* fall */
841 case 'm':
842 case 'M':
843 l *= 60;
844 /* fall */
845 case 's':
846 case 'S':
847 end++;
848 break;
849 case '\0':
850 break;
851 default:
852 return FALSE;
853 }
854 if (*end)
855 {
856 return FALSE;
857 }
858 *out = l;
859 return TRUE;
860 }
861
862 /**
863 * Parse byte volume
864 */
865 CALLBACK(parse_bytes, bool,
866 u_int64_t *out, chunk_t v)
867 {
868 char buf[16], *end;
869 unsigned long long l;
870
871 if (!vici_stringify(v, buf, sizeof(buf)))
872 {
873 return FALSE;
874 }
875
876 l = strtoull(buf, &end, 0);
877 while (*end == ' ')
878 {
879 end++;
880 }
881 switch (*end)
882 {
883 case 'g':
884 case 'G':
885 l *= 1024;
886 /* fall */
887 case 'm':
888 case 'M':
889 l *= 1024;
890 /* fall */
891 case 'k':
892 case 'K':
893 l *= 1024;
894 end++;
895 break;
896 case '\0':
897 break;
898 default:
899 return FALSE;
900 }
901 if (*end)
902 {
903 return FALSE;
904 }
905 *out = l;
906 return TRUE;
907 }
908
909 /**
910 * Parse a mark_t
911 */
912 CALLBACK(parse_mark, bool,
913 mark_t *out, chunk_t v)
914 {
915 char buf[32];
916
917 if (!vici_stringify(v, buf, sizeof(buf)))
918 {
919 return FALSE;
920 }
921 return mark_from_string(buf, out);
922 }
923
924 /**
925 * Parse TFC padding option
926 */
927 CALLBACK(parse_tfc, bool,
928 u_int32_t *out, chunk_t v)
929 {
930 if (chunk_equals(v, chunk_from_str("mtu")))
931 {
932 *out = -1;
933 return TRUE;
934 }
935 return parse_uint32(out, v);
936 }
937
938 /**
939 * Parse authentication config
940 */
941 CALLBACK(parse_auth, bool,
942 auth_cfg_t *cfg, chunk_t v)
943 {
944 char buf[64], *pos;
945 eap_vendor_type_t *type;
946
947 if (!vici_stringify(v, buf, sizeof(buf)))
948 {
949 return FALSE;
950 }
951 if (strpfx(buf, "pubkey") ||
952 strpfx(buf, "rsa") ||
953 strpfx(buf, "ecdsa") ||
954 strpfx(buf, "bliss"))
955 {
956 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
957 cfg->add_pubkey_constraints(cfg, buf);
958 return TRUE;
959 }
960 if (strcaseeq(buf, "psk"))
961 {
962 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
963 return TRUE;
964 }
965 if (strcasepfx(buf, "xauth"))
966 {
967 pos = strchr(buf, '-');
968 if (pos)
969 {
970 cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
971 }
972 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
973 return TRUE;
974 }
975 if (strcasepfx(buf, "eap"))
976 {
977 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
978
979 type = eap_vendor_type_from_string(buf);
980 if (type)
981 {
982 cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
983 if (type->vendor)
984 {
985 cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
986 }
987 free(type);
988 }
989 return TRUE;
990 }
991 return FALSE;
992 }
993
994 /**
995 * Parse identity; add as auth rule to config
996 */
997 static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
998 {
999 char buf[256];
1000
1001 if (!vici_stringify(v, buf, sizeof(buf)))
1002 {
1003 return FALSE;
1004 }
1005 cfg->add(cfg, rule, identification_create_from_string(buf));
1006 return TRUE;
1007 }
1008
1009 /**
1010 * Parse IKE identity
1011 */
1012 CALLBACK(parse_ike_id, bool,
1013 auth_cfg_t *cfg, chunk_t v)
1014 {
1015 return parse_id(cfg, AUTH_RULE_IDENTITY, v);
1016 }
1017
1018 /**
1019 * Parse AAA identity
1020 */
1021 CALLBACK(parse_aaa_id, bool,
1022 auth_cfg_t *cfg, chunk_t v)
1023 {
1024 return parse_id(cfg, AUTH_RULE_AAA_IDENTITY, v);
1025 }
1026
1027 /**
1028 * Parse EAP identity
1029 */
1030 CALLBACK(parse_eap_id, bool,
1031 auth_cfg_t *cfg, chunk_t v)
1032 {
1033 return parse_id(cfg, AUTH_RULE_EAP_IDENTITY, v);
1034 }
1035
1036 /**
1037 * Parse XAuth identity
1038 */
1039 CALLBACK(parse_xauth_id, bool,
1040 auth_cfg_t *cfg, chunk_t v)
1041 {
1042 return parse_id(cfg, AUTH_RULE_XAUTH_IDENTITY, v);
1043 }
1044
1045 /**
1046 * Parse group membership
1047 */
1048 CALLBACK(parse_group, bool,
1049 auth_cfg_t *cfg, chunk_t v)
1050 {
1051 return parse_id(cfg, AUTH_RULE_GROUP, v);
1052 }
1053
1054 /**
1055 * Parse a certificate; add as auth rule to config
1056 */
1057 static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
1058 {
1059 vici_authority_t *authority;
1060 certificate_t *cert;
1061
1062 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
1063 BUILD_BLOB_PEM, v, BUILD_END);
1064 if (cert)
1065 {
1066 if (rule == AUTH_RULE_SUBJECT_CERT)
1067 {
1068 authority = auth->request->this->authority;
1069 authority->check_for_hash_and_url(authority, cert);
1070 }
1071 auth->cfg->add(auth->cfg, rule, cert);
1072 return TRUE;
1073 }
1074 return FALSE;
1075 }
1076
1077 /**
1078 * Parse subject certificates
1079 */
1080 CALLBACK(parse_certs, bool,
1081 auth_data_t *auth, chunk_t v)
1082 {
1083 return parse_cert(auth, AUTH_RULE_SUBJECT_CERT, v);
1084 }
1085
1086 /**
1087 * Parse CA certificates
1088 */
1089 CALLBACK(parse_cacerts, bool,
1090 auth_data_t *auth, chunk_t v)
1091 {
1092 return parse_cert(auth, AUTH_RULE_CA_CERT, v);
1093 }
1094
1095 /**
1096 * Parse revocation status
1097 */
1098 CALLBACK(parse_revocation, bool,
1099 auth_cfg_t *cfg, chunk_t v)
1100 {
1101 enum_map_t map[] = {
1102 { "strict", VALIDATION_GOOD },
1103 { "ifuri", VALIDATION_SKIPPED },
1104 { "relaxed", VALIDATION_FAILED },
1105 };
1106 int d;
1107
1108 if (parse_map(map, countof(map), &d, v))
1109 {
1110 if (d != VALIDATION_FAILED)
1111 {
1112 cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, d);
1113 }
1114 return TRUE;
1115 }
1116 return FALSE;
1117 }
1118
1119 /**
1120 * Parse list items to comma separated strings
1121 */
1122 CALLBACK(parse_stringlist, bool,
1123 char **out, chunk_t v)
1124 {
1125 char *current;
1126
1127 if (!chunk_printable(v, NULL, ' '))
1128 {
1129 return FALSE;
1130 }
1131 current = *out;
1132 if (current)
1133 {
1134 if (asprintf(out, "%s, %.*s", current, (int)v.len, v.ptr) == -1)
1135 {
1136 return FALSE;
1137 }
1138 free(current);
1139 }
1140 else
1141 {
1142 if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
1143 {
1144 return FALSE;
1145 }
1146 }
1147 return TRUE;
1148 }
1149
1150 /**
1151 * Parse an fragmentation_t
1152 */
1153 CALLBACK(parse_frag, bool,
1154 fragmentation_t *out, chunk_t v)
1155 {
1156 enum_map_t map[] = {
1157 { "yes", FRAGMENTATION_YES },
1158 { "no", FRAGMENTATION_NO },
1159 { "force", FRAGMENTATION_FORCE },
1160 };
1161 int d;
1162
1163 if (parse_map(map, countof(map), &d, v))
1164 {
1165 *out = d;
1166 return TRUE;
1167 }
1168 return FALSE;
1169 }
1170
1171 /**
1172 * Parse a cert_policy_t
1173 */
1174 CALLBACK(parse_send_cert, bool,
1175 cert_policy_t *out, chunk_t v)
1176 {
1177 enum_map_t map[] = {
1178 { "ifasked", CERT_SEND_IF_ASKED },
1179 { "always", CERT_ALWAYS_SEND },
1180 { "never", CERT_NEVER_SEND },
1181 };
1182 int d;
1183
1184 if (parse_map(map, countof(map), &d, v))
1185 {
1186 *out = d;
1187 return TRUE;
1188 }
1189 return FALSE;
1190 }
1191
1192 /**
1193 * Parse a unique_policy_t
1194 */
1195 CALLBACK(parse_unique, bool,
1196 unique_policy_t *out, chunk_t v)
1197 {
1198 enum_map_t map[] = {
1199 { "never", UNIQUE_NEVER },
1200 { "no", UNIQUE_NO },
1201 { "replace", UNIQUE_REPLACE },
1202 { "keep", UNIQUE_KEEP },
1203 };
1204 int d;
1205
1206 if (parse_map(map, countof(map), &d, v))
1207 {
1208 *out = d;
1209 return TRUE;
1210 }
1211 return FALSE;
1212 }
1213
1214 /**
1215 * Parse host_t into a list
1216 */
1217 CALLBACK(parse_hosts, bool,
1218 linked_list_t *list, chunk_t v)
1219 {
1220 char buf[64];
1221 host_t *host;
1222
1223 if (!vici_stringify(v, buf, sizeof(buf)))
1224 {
1225 return FALSE;
1226 }
1227 host = host_create_from_string(buf, 0);
1228 if (!host)
1229 {
1230 return FALSE;
1231 }
1232 list->insert_last(list, host);
1233 return TRUE;
1234 }
1235
1236 CALLBACK(child_li, bool,
1237 child_data_t *child, vici_message_t *message, char *name, chunk_t value)
1238 {
1239 parse_rule_t rules[] = {
1240 { "ah_proposals", parse_ah_proposal, child->proposals },
1241 { "esp_proposals", parse_esp_proposal, child->proposals },
1242 { "local_ts", parse_ts, child->local_ts },
1243 { "remote_ts", parse_ts, child->remote_ts },
1244 };
1245
1246 return parse_rules(rules, countof(rules), name, value,
1247 &child->request->reply);
1248 }
1249
1250 CALLBACK(child_kv, bool,
1251 child_data_t *child, vici_message_t *message, char *name, chunk_t value)
1252 {
1253 parse_rule_t rules[] = {
1254 { "updown", parse_string, &child->updown },
1255 { "hostaccess", parse_bool, &child->hostaccess },
1256 { "mode", parse_mode, &child->mode },
1257 { "policies", parse_bool, &child->policies },
1258 { "replay_window", parse_uint32, &child->replay_window },
1259 { "rekey_time", parse_time, &child->lft.time.rekey },
1260 { "life_time", parse_time, &child->lft.time.life },
1261 { "rand_time", parse_time, &child->lft.time.jitter },
1262 { "rekey_bytes", parse_bytes, &child->lft.bytes.rekey },
1263 { "life_bytes", parse_bytes, &child->lft.bytes.life },
1264 { "rand_bytes", parse_bytes, &child->lft.bytes.jitter },
1265 { "rekey_packets", parse_uint64, &child->lft.packets.rekey },
1266 { "life_packets", parse_uint64, &child->lft.packets.life },
1267 { "rand_packets", parse_uint64, &child->lft.packets.jitter },
1268 { "dpd_action", parse_action, &child->dpd_action },
1269 { "start_action", parse_action, &child->start_action },
1270 { "close_action", parse_action, &child->close_action },
1271 { "ipcomp", parse_bool, &child->ipcomp },
1272 { "inactivity", parse_time, &child->inactivity },
1273 { "reqid", parse_uint32, &child->reqid },
1274 { "mark_in", parse_mark, &child->mark_in },
1275 { "mark_out", parse_mark, &child->mark_out },
1276 { "tfc_padding", parse_tfc, &child->tfc },
1277 };
1278
1279 return parse_rules(rules, countof(rules), name, value,
1280 &child->request->reply);
1281 }
1282
1283 CALLBACK(auth_li, bool,
1284 auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
1285 {
1286 parse_rule_t rules[] = {
1287 { "groups", parse_group, auth->cfg },
1288 { "certs", parse_certs, auth },
1289 { "cacerts", parse_cacerts, auth },
1290 };
1291
1292 return parse_rules(rules, countof(rules), name, value,
1293 &auth->request->reply);
1294 }
1295
1296 CALLBACK(auth_kv, bool,
1297 auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
1298 {
1299 parse_rule_t rules[] = {
1300 { "auth", parse_auth, auth->cfg },
1301 { "id", parse_ike_id, auth->cfg },
1302 { "aaa_id", parse_aaa_id, auth->cfg },
1303 { "eap_id", parse_eap_id, auth->cfg },
1304 { "xauth_id", parse_xauth_id, auth->cfg },
1305 { "revocation", parse_revocation, auth->cfg },
1306 };
1307
1308 return parse_rules(rules, countof(rules), name, value,
1309 &auth->request->reply);
1310 }
1311
1312 CALLBACK(peer_li, bool,
1313 peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
1314 {
1315 parse_rule_t rules[] = {
1316 { "local_addrs", parse_stringlist, &peer->local_addrs },
1317 { "remote_addrs", parse_stringlist, &peer->remote_addrs },
1318 { "proposals", parse_ike_proposal, peer->proposals },
1319 { "vips", parse_hosts, peer->vips },
1320 { "pools", parse_stringlist, &peer->pools },
1321 };
1322
1323 return parse_rules(rules, countof(rules), name, value,
1324 &peer->request->reply);
1325 }
1326
1327 CALLBACK(peer_kv, bool,
1328 peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
1329 {
1330 parse_rule_t rules[] = {
1331 { "version", parse_uint32, &peer->version },
1332 { "aggressive", parse_bool, &peer->aggressive },
1333 { "pull", parse_bool, &peer->pull },
1334 { "encap", parse_bool, &peer->encap },
1335 { "mobike", parse_bool, &peer->mobike },
1336 { "dpd_delay", parse_time, &peer->dpd_delay },
1337 { "dpd_timeout", parse_time, &peer->dpd_timeout },
1338 { "fragmentation", parse_frag, &peer->fragmentation },
1339 { "send_certreq", parse_bool, &peer->send_certreq },
1340 { "send_cert", parse_send_cert, &peer->send_cert },
1341 { "keyingtries", parse_uint32, &peer->keyingtries },
1342 { "unique", parse_unique, &peer->unique },
1343 { "local_port", parse_uint32, &peer->local_port },
1344 { "remote_port", parse_uint32, &peer->remote_port },
1345 { "reauth_time", parse_time, &peer->reauth_time },
1346 { "rekey_time", parse_time, &peer->rekey_time },
1347 { "over_time", parse_time, &peer->over_time },
1348 { "rand_time", parse_time, &peer->rand_time },
1349 };
1350
1351 return parse_rules(rules, countof(rules), name, value,
1352 &peer->request->reply);
1353 }
1354
1355 CALLBACK(children_sn, bool,
1356 peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
1357 char *name)
1358 {
1359 child_data_t child = {
1360 .request = peer->request,
1361 .proposals = linked_list_create(),
1362 .local_ts = linked_list_create(),
1363 .remote_ts = linked_list_create(),
1364 .mode = MODE_TUNNEL,
1365 .policies = TRUE,
1366 .replay_window = REPLAY_UNDEFINED,
1367 .dpd_action = ACTION_NONE,
1368 .start_action = ACTION_NONE,
1369 .close_action = ACTION_NONE,
1370 .lft = {
1371 .time = {
1372 .rekey = LFT_DEFAULT_CHILD_REKEY,
1373 .life = LFT_UNDEFINED,
1374 .jitter = LFT_UNDEFINED,
1375 },
1376 .bytes = {
1377 .rekey = LFT_UNDEFINED,
1378 .life = LFT_UNDEFINED,
1379 .jitter = LFT_UNDEFINED,
1380 },
1381 .packets = {
1382 .rekey = LFT_UNDEFINED,
1383 .life = LFT_UNDEFINED,
1384 .jitter = LFT_UNDEFINED,
1385 },
1386 }
1387 };
1388 child_cfg_t *cfg;
1389 proposal_t *proposal;
1390 traffic_selector_t *ts;
1391
1392 if (!message->parse(message, ctx, NULL, child_kv, child_li, &child))
1393 {
1394 free_child_data(&child);
1395 return FALSE;
1396 }
1397
1398 if (child.local_ts->get_count(child.local_ts) == 0)
1399 {
1400 child.local_ts->insert_last(child.local_ts,
1401 traffic_selector_create_dynamic(0, 0, 65535));
1402 }
1403 if (child.remote_ts->get_count(child.remote_ts) == 0)
1404 {
1405 child.remote_ts->insert_last(child.remote_ts,
1406 traffic_selector_create_dynamic(0, 0, 65535));
1407 }
1408 if (child.proposals->get_count(child.proposals) == 0)
1409 {
1410 proposal = proposal_create_default(PROTO_ESP);
1411 if (proposal)
1412 {
1413 child.proposals->insert_last(child.proposals, proposal);
1414 }
1415 proposal = proposal_create_default_aead(PROTO_ESP);
1416 if (proposal)
1417 {
1418 child.proposals->insert_last(child.proposals, proposal);
1419 }
1420 }
1421
1422 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1423 if (child.lft.time.life == LFT_UNDEFINED)
1424 {
1425 child.lft.time.life = child.lft.time.rekey * 110 / 100;
1426 }
1427 if (child.lft.bytes.life == LFT_UNDEFINED)
1428 {
1429 child.lft.bytes.life = child.lft.bytes.rekey * 110 / 100;
1430 }
1431 if (child.lft.packets.life == LFT_UNDEFINED)
1432 {
1433 child.lft.packets.life = child.lft.packets.rekey * 110 / 100;
1434 }
1435 /* if no soft lifetime specified, add one at hard lifetime - 10% */
1436 if (child.lft.bytes.rekey == LFT_UNDEFINED)
1437 {
1438 child.lft.bytes.rekey = child.lft.bytes.life * 90 / 100;
1439 }
1440 if (child.lft.packets.rekey == LFT_UNDEFINED)
1441 {
1442 child.lft.packets.rekey = child.lft.packets.life * 90 / 100;
1443 }
1444 /* if no rand time defined, use difference of hard and soft */
1445 if (child.lft.time.jitter == LFT_UNDEFINED)
1446 {
1447 child.lft.time.jitter = child.lft.time.life -
1448 min(child.lft.time.life, child.lft.time.rekey);
1449 }
1450 if (child.lft.bytes.jitter == LFT_UNDEFINED)
1451 {
1452 child.lft.bytes.jitter = child.lft.bytes.life -
1453 min(child.lft.bytes.life, child.lft.bytes.rekey);
1454 }
1455 if (child.lft.packets.jitter == LFT_UNDEFINED)
1456 {
1457 child.lft.packets.jitter = child.lft.packets.life -
1458 min(child.lft.packets.life, child.lft.packets.rekey);
1459 }
1460
1461 log_child_data(&child, name);
1462
1463 cfg = child_cfg_create(name, &child.lft, child.updown,
1464 child.hostaccess, child.mode, child.start_action,
1465 child.dpd_action, child.close_action, child.ipcomp,
1466 child.inactivity, child.reqid, &child.mark_in,
1467 &child.mark_out, child.tfc);
1468
1469 cfg->set_mipv6_options(cfg, FALSE, child.policies);
1470
1471 if (child.replay_window != REPLAY_UNDEFINED)
1472 {
1473 cfg->set_replay_window(cfg, child.replay_window);
1474 }
1475 while (child.local_ts->remove_first(child.local_ts,
1476 (void**)&ts) == SUCCESS)
1477 {
1478 cfg->add_traffic_selector(cfg, TRUE, ts);
1479 }
1480 while (child.remote_ts->remove_first(child.remote_ts,
1481 (void**)&ts) == SUCCESS)
1482 {
1483 cfg->add_traffic_selector(cfg, FALSE, ts);
1484 }
1485 while (child.proposals->remove_first(child.proposals,
1486 (void**)&proposal) == SUCCESS)
1487 {
1488 cfg->add_proposal(cfg, proposal);
1489 }
1490
1491 peer->children->insert_last(peer->children, cfg);
1492
1493 free_child_data(&child);
1494
1495 return TRUE;
1496 }
1497
1498 CALLBACK(peer_sn, bool,
1499 peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
1500 char *name)
1501 {
1502 if (strcaseeq(name, "children"))
1503 {
1504 return message->parse(message, ctx, children_sn, NULL, NULL, peer);
1505 }
1506 if (strcasepfx(name, "local") ||
1507 strcasepfx(name, "remote"))
1508 {
1509 auth_data_t auth = {
1510 .request = peer->request,
1511 .cfg = auth_cfg_create(),
1512 };
1513
1514 if (!message->parse(message, ctx, NULL, auth_kv, auth_li, &auth))
1515 {
1516 auth.cfg->destroy(auth.cfg);
1517 return FALSE;
1518 }
1519
1520 if (!auth.cfg->get(auth.cfg, AUTH_RULE_IDENTITY))
1521 {
1522 identification_t *id;
1523 certificate_t *cert;
1524
1525 cert = auth.cfg->get(auth.cfg, AUTH_RULE_SUBJECT_CERT);
1526 if (cert)
1527 {
1528 id = cert->get_subject(cert);
1529 DBG1(DBG_CFG, " id not specified, defaulting to cert id '%Y'",
1530 id);
1531 auth.cfg->add(auth.cfg, AUTH_RULE_IDENTITY, id->clone(id));
1532 }
1533 }
1534
1535 if (strcasepfx(name, "local"))
1536 {
1537 peer->local->insert_last(peer->local, auth.cfg);
1538 }
1539 else
1540 {
1541 peer->remote->insert_last(peer->remote, auth.cfg);
1542 }
1543 return TRUE;
1544 }
1545 peer->request->reply = create_reply("invalid section: %s", name);
1546 return FALSE;
1547 }
1548
1549 /**
1550 * Find reqid of an existing CHILD_SA
1551 */
1552 static u_int32_t find_reqid(child_cfg_t *cfg)
1553 {
1554 enumerator_t *enumerator, *children;
1555 child_sa_t *child_sa;
1556 ike_sa_t *ike_sa;
1557 u_int32_t reqid;
1558
1559 reqid = charon->traps->find_reqid(charon->traps, cfg);
1560 if (reqid)
1561 { /* already trapped */
1562 return reqid;
1563 }
1564
1565 enumerator = charon->controller->create_ike_sa_enumerator(
1566 charon->controller, TRUE);
1567 while (!reqid && enumerator->enumerate(enumerator, &ike_sa))
1568 {
1569 children = ike_sa->create_child_sa_enumerator(ike_sa);
1570 while (children->enumerate(children, &child_sa))
1571 {
1572 if (streq(cfg->get_name(cfg), child_sa->get_name(child_sa)))
1573 {
1574 reqid = child_sa->get_reqid(child_sa);
1575 break;
1576 }
1577 }
1578 children->destroy(children);
1579 }
1580 enumerator->destroy(enumerator);
1581 return reqid;
1582 }
1583
1584 /**
1585 * Perform start actions associated to a child config
1586 */
1587 static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
1588 child_cfg_t *child_cfg)
1589 {
1590 switch (child_cfg->get_start_action(child_cfg))
1591 {
1592 case ACTION_RESTART:
1593 DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
1594 charon->controller->initiate(charon->controller,
1595 peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
1596 NULL, NULL, 0, FALSE);
1597 break;
1598 case ACTION_ROUTE:
1599 DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
1600 switch (child_cfg->get_mode(child_cfg))
1601 {
1602 case MODE_PASS:
1603 case MODE_DROP:
1604 charon->shunts->install(charon->shunts, child_cfg);
1605 break;
1606 default:
1607 charon->traps->install(charon->traps, peer_cfg, child_cfg,
1608 find_reqid(child_cfg));
1609 break;
1610 }
1611 break;
1612 default:
1613 break;
1614 }
1615 }
1616
1617 /**
1618 * Undo start actions associated to a child config
1619 */
1620 static void clear_start_action(private_vici_config_t *this, char *peer_name,
1621 child_cfg_t *child_cfg)
1622 {
1623 enumerator_t *enumerator, *children;
1624 child_sa_t *child_sa;
1625 ike_sa_t *ike_sa;
1626 u_int32_t id = 0, others;
1627 array_t *ids = NULL, *ikeids = NULL;
1628 char *name;
1629
1630 name = child_cfg->get_name(child_cfg);
1631 switch (child_cfg->get_start_action(child_cfg))
1632 {
1633 case ACTION_RESTART:
1634 enumerator = charon->controller->create_ike_sa_enumerator(
1635 charon->controller, TRUE);
1636 while (enumerator->enumerate(enumerator, &ike_sa))
1637 {
1638 if (!streq(ike_sa->get_name(ike_sa), peer_name))
1639 {
1640 continue;
1641 }
1642 others = id = 0;
1643 children = ike_sa->create_child_sa_enumerator(ike_sa);
1644 while (children->enumerate(children, &child_sa))
1645 {
1646 if (child_sa->get_state(child_sa) != CHILD_DELETING)
1647 {
1648 if (streq(name, child_sa->get_name(child_sa)))
1649 {
1650 id = child_sa->get_unique_id(child_sa);
1651 }
1652 else
1653 {
1654 others++;
1655 }
1656 }
1657 }
1658 children->destroy(children);
1659
1660 if (id && !others)
1661 {
1662 /* found matching children only, delete full IKE_SA */
1663 id = ike_sa->get_unique_id(ike_sa);
1664 array_insert_create_value(&ikeids, sizeof(id),
1665 ARRAY_TAIL, &id);
1666 }
1667 else
1668 {
1669 children = ike_sa->create_child_sa_enumerator(ike_sa);
1670 while (children->enumerate(children, &child_sa))
1671 {
1672 if (streq(name, child_sa->get_name(child_sa)))
1673 {
1674 id = child_sa->get_unique_id(child_sa);
1675 array_insert_create_value(&ids, sizeof(id),
1676 ARRAY_TAIL, &id);
1677 }
1678 }
1679 children->destroy(children);
1680 }
1681 }
1682 enumerator->destroy(enumerator);
1683
1684 if (array_count(ids))
1685 {
1686 while (array_remove(ids, ARRAY_HEAD, &id))
1687 {
1688 DBG1(DBG_CFG, "closing '%s' #%u", name, id);
1689 charon->controller->terminate_child(charon->controller,
1690 id, NULL, NULL, 0);
1691 }
1692 array_destroy(ids);
1693 }
1694 if (array_count(ikeids))
1695 {
1696 while (array_remove(ikeids, ARRAY_HEAD, &id))
1697 {
1698 DBG1(DBG_CFG, "closing IKE_SA #%u", id);
1699 charon->controller->terminate_ike(charon->controller,
1700 id, NULL, NULL, 0);
1701 }
1702 array_destroy(ikeids);
1703 }
1704 break;
1705 case ACTION_ROUTE:
1706 DBG1(DBG_CFG, "uninstalling '%s'", name);
1707 switch (child_cfg->get_mode(child_cfg))
1708 {
1709 case MODE_PASS:
1710 case MODE_DROP:
1711 charon->shunts->uninstall(charon->shunts, name);
1712 break;
1713 default:
1714 enumerator = charon->traps->create_enumerator(charon->traps);
1715 while (enumerator->enumerate(enumerator, NULL, &child_sa))
1716 {
1717 if (streq(name, child_sa->get_name(child_sa)))
1718 {
1719 id = child_sa->get_reqid(child_sa);
1720 break;
1721 }
1722 }
1723 enumerator->destroy(enumerator);
1724 if (id)
1725 {
1726 charon->traps->uninstall(charon->traps, id);
1727 }
1728 break;
1729 }
1730 break;
1731 default:
1732 break;
1733 }
1734 }
1735
1736 /**
1737 * Run start actions associated to all child configs of a peer config
1738 */
1739 static void run_start_actions(private_vici_config_t *this, peer_cfg_t *peer_cfg)
1740 {
1741 enumerator_t *enumerator;
1742 child_cfg_t *child_cfg;
1743
1744 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
1745 while (enumerator->enumerate(enumerator, &child_cfg))
1746 {
1747 run_start_action(this, peer_cfg, child_cfg);
1748 }
1749 enumerator->destroy(enumerator);
1750 }
1751
1752 /**
1753 * Undo start actions associated to all child configs of a peer config
1754 */
1755 static void clear_start_actions(private_vici_config_t *this,
1756 peer_cfg_t *peer_cfg)
1757 {
1758 enumerator_t *enumerator;
1759 child_cfg_t *child_cfg;
1760
1761 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
1762 while (enumerator->enumerate(enumerator, &child_cfg))
1763 {
1764 clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
1765 }
1766 enumerator->destroy(enumerator);
1767 }
1768
1769 /**
1770 * Replace children of a peer config by a new config
1771 */
1772 static void replace_children(private_vici_config_t *this,
1773 peer_cfg_t *from, peer_cfg_t *to)
1774 {
1775 enumerator_t *enumerator;
1776 child_cfg_t *child;
1777
1778 enumerator = to->create_child_cfg_enumerator(to);
1779 while (enumerator->enumerate(enumerator, &child))
1780 {
1781 to->remove_child_cfg(to, enumerator);
1782 clear_start_action(this, to->get_name(to), child);
1783 child->destroy(child);
1784 }
1785 enumerator->destroy(enumerator);
1786
1787 enumerator = from->create_child_cfg_enumerator(from);
1788 while (enumerator->enumerate(enumerator, &child))
1789 {
1790 from->remove_child_cfg(from, enumerator);
1791 to->add_child_cfg(to, child);
1792 run_start_action(this, to, child);
1793 }
1794 enumerator->destroy(enumerator);
1795 }
1796
1797 /**
1798 * Merge/replace a peer config with existing configs
1799 */
1800 static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
1801 {
1802 enumerator_t *enumerator;
1803 peer_cfg_t *current;
1804 ike_cfg_t *ike_cfg;
1805 bool merged = FALSE;
1806
1807 this->lock->write_lock(this->lock);
1808
1809 enumerator = this->conns->create_enumerator(this->conns);
1810 while (enumerator->enumerate(enumerator, &current))
1811 {
1812 if (streq(peer_cfg->get_name(peer_cfg), current->get_name(current)))
1813 {
1814 ike_cfg = current->get_ike_cfg(current);
1815 if (peer_cfg->equals(peer_cfg, current) &&
1816 ike_cfg->equals(ike_cfg, peer_cfg->get_ike_cfg(peer_cfg)))
1817 {
1818 DBG1(DBG_CFG, "updated vici connection: %s",
1819 peer_cfg->get_name(peer_cfg));
1820 replace_children(this, peer_cfg, current);
1821 peer_cfg->destroy(peer_cfg);
1822 }
1823 else
1824 {
1825 DBG1(DBG_CFG, "replaced vici connection: %s",
1826 peer_cfg->get_name(peer_cfg));
1827 this->conns->remove_at(this->conns, enumerator);
1828 clear_start_actions(this, current);
1829 current->destroy(current);
1830 this->conns->insert_last(this->conns, peer_cfg);
1831 run_start_actions(this, peer_cfg);
1832 }
1833 merged = TRUE;
1834 break;
1835 }
1836 }
1837 enumerator->destroy(enumerator);
1838
1839 if (!merged)
1840 {
1841 DBG1(DBG_CFG, "added vici connection: %s", peer_cfg->get_name(peer_cfg));
1842 this->conns->insert_last(this->conns, peer_cfg);
1843 run_start_actions(this, peer_cfg);
1844 }
1845
1846 this->lock->unlock(this->lock);
1847 }
1848
1849 CALLBACK(config_sn, bool,
1850 request_data_t *request, vici_message_t *message,
1851 vici_parse_context_t *ctx, char *name)
1852 {
1853 peer_data_t peer = {
1854 .request = request,
1855 .local = linked_list_create(),
1856 .remote = linked_list_create(),
1857 .vips = linked_list_create(),
1858 .children = linked_list_create(),
1859 .proposals = linked_list_create(),
1860 .mobike = TRUE,
1861 .send_certreq = TRUE,
1862 .pull = TRUE,
1863 .send_cert = CERT_SEND_IF_ASKED,
1864 .version = IKE_ANY,
1865 .remote_port = IKEV2_UDP_PORT,
1866 .fragmentation = FRAGMENTATION_NO,
1867 .unique = UNIQUE_NO,
1868 .keyingtries = 1,
1869 .rekey_time = LFT_UNDEFINED,
1870 .reauth_time = LFT_UNDEFINED,
1871 .over_time = LFT_UNDEFINED,
1872 .rand_time = LFT_UNDEFINED,
1873 };
1874 enumerator_t *enumerator;
1875 peer_cfg_t *peer_cfg;
1876 ike_cfg_t *ike_cfg;
1877 child_cfg_t *child_cfg;
1878 auth_cfg_t *auth_cfg;
1879 proposal_t *proposal;
1880 host_t *host;
1881 char *str;
1882
1883 DBG2(DBG_CFG, " conn %s:", name);
1884
1885 if (!message->parse(message, ctx, peer_sn, peer_kv, peer_li, &peer))
1886 {
1887 free_peer_data(&peer);
1888 return FALSE;
1889 }
1890
1891 if (peer.local->get_count(peer.local) == 0)
1892 {
1893 auth_cfg = auth_cfg_create();
1894 peer.local->insert_last(peer.local, auth_cfg);
1895 }
1896 if (peer.remote->get_count(peer.remote) == 0)
1897 {
1898 auth_cfg = auth_cfg_create();
1899 peer.remote->insert_last(peer.remote, auth_cfg);
1900 }
1901 if (peer.proposals->get_count(peer.proposals) == 0)
1902 {
1903 proposal = proposal_create_default(PROTO_IKE);
1904 if (proposal)
1905 {
1906 peer.proposals->insert_last(peer.proposals, proposal);
1907 }
1908 proposal = proposal_create_default_aead(PROTO_IKE);
1909 if (proposal)
1910 {
1911 peer.proposals->insert_last(peer.proposals, proposal);
1912 }
1913 }
1914 if (!peer.local_addrs)
1915 {
1916 peer.local_addrs = strdup("%any");
1917 }
1918 if (!peer.remote_addrs)
1919 {
1920 peer.remote_addrs = strdup("%any");
1921 }
1922 if (!peer.local_port)
1923 {
1924 peer.local_port = charon->socket->get_port(charon->socket, FALSE);
1925 }
1926
1927 if (peer.rekey_time == LFT_UNDEFINED && peer.reauth_time == LFT_UNDEFINED)
1928 {
1929 /* apply a default rekey time if no rekey/reauth time set */
1930 peer.rekey_time = LFT_DEFAULT_IKE_REKEY;
1931 peer.reauth_time = 0;
1932 }
1933 if (peer.rekey_time == LFT_UNDEFINED)
1934 {
1935 peer.rekey_time = 0;
1936 }
1937 if (peer.reauth_time == LFT_UNDEFINED)
1938 {
1939 peer.reauth_time = 0;
1940 }
1941 if (peer.over_time == LFT_UNDEFINED)
1942 {
1943 /* default over_time to 10% of rekey/reauth time if not given */
1944 peer.over_time = max(peer.rekey_time, peer.reauth_time) / 10;
1945 }
1946 if (peer.rand_time == LFT_UNDEFINED)
1947 {
1948 /* default rand_time to over_time if not given, but don't make it
1949 * longer than half of rekey/rauth time */
1950 if (peer.rekey_time && peer.reauth_time)
1951 {
1952 peer.rand_time = min(peer.rekey_time, peer.reauth_time);
1953 }
1954 else
1955 {
1956 peer.rand_time = max(peer.rekey_time, peer.reauth_time);
1957 }
1958 peer.rand_time = min(peer.over_time, peer.rand_time / 2);
1959 }
1960
1961 log_peer_data(&peer);
1962
1963 ike_cfg = ike_cfg_create(peer.version, peer.send_certreq, peer.encap,
1964 peer.local_addrs, peer.local_port,
1965 peer.remote_addrs, peer.remote_port,
1966 peer.fragmentation, 0);
1967 peer_cfg = peer_cfg_create(name, ike_cfg, peer.send_cert, peer.unique,
1968 peer.keyingtries, peer.rekey_time, peer.reauth_time,
1969 peer.rand_time, peer.over_time, peer.mobike,
1970 peer.aggressive, peer.pull,
1971 peer.dpd_delay, peer.dpd_timeout,
1972 FALSE, NULL, NULL);
1973
1974 while (peer.local->remove_first(peer.local,
1975 (void**)&auth_cfg) == SUCCESS)
1976 {
1977 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
1978 }
1979 while (peer.remote->remove_first(peer.remote,
1980 (void**)&auth_cfg) == SUCCESS)
1981 {
1982 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
1983 }
1984 while (peer.children->remove_first(peer.children,
1985 (void**)&child_cfg) == SUCCESS)
1986 {
1987 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
1988 }
1989 while (peer.proposals->remove_first(peer.proposals,
1990 (void**)&proposal) == SUCCESS)
1991 {
1992 ike_cfg->add_proposal(ike_cfg, proposal);
1993 }
1994 while (peer.vips->remove_first(peer.vips, (void**)&host) == SUCCESS)
1995 {
1996 peer_cfg->add_virtual_ip(peer_cfg, host);
1997 }
1998 if (peer.pools)
1999 {
2000 enumerator = enumerator_create_token(peer.pools, ",", " ");
2001 while (enumerator->enumerate(enumerator, &str))
2002 {
2003 peer_cfg->add_pool(peer_cfg, str);
2004 }
2005 enumerator->destroy(enumerator);
2006 }
2007
2008 free_peer_data(&peer);
2009
2010 merge_config(request->this, peer_cfg);
2011
2012 return TRUE;
2013 }
2014
2015 CALLBACK(load_conn, vici_message_t*,
2016 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2017 {
2018 request_data_t request = {
2019 .this = this,
2020 };
2021
2022 if (!message->parse(message, NULL, config_sn, NULL, NULL, &request))
2023 {
2024 if (request.reply)
2025 {
2026 return request.reply;
2027 }
2028 return create_reply("parsing request failed");
2029 }
2030 return create_reply(NULL);
2031 }
2032
2033 CALLBACK(unload_conn, vici_message_t*,
2034 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2035 {
2036 enumerator_t *enumerator;
2037 peer_cfg_t *cfg;
2038 char *conn_name;
2039 bool found = FALSE;
2040
2041 conn_name = message->get_str(message, NULL, "name");
2042 if (!conn_name)
2043 {
2044 return create_reply("unload: missing connection name");
2045 }
2046
2047 this->lock->write_lock(this->lock);
2048 enumerator = this->conns->create_enumerator(this->conns);
2049 while (enumerator->enumerate(enumerator, &cfg))
2050 {
2051 if (streq(cfg->get_name(cfg), conn_name))
2052 {
2053 this->conns->remove_at(this->conns, enumerator);
2054 clear_start_actions(this, cfg);
2055 cfg->destroy(cfg);
2056 found = TRUE;
2057 break;
2058 }
2059 }
2060 enumerator->destroy(enumerator);
2061 this->lock->unlock(this->lock);
2062
2063 if (!found)
2064 {
2065 return create_reply("unload: connection '%s' not found", conn_name);
2066 }
2067 return create_reply(NULL);
2068 }
2069
2070 CALLBACK(get_conns, vici_message_t*,
2071 private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
2072 {
2073 vici_builder_t *builder;
2074 enumerator_t *enumerator;
2075 peer_cfg_t *cfg;
2076
2077 builder = vici_builder_create();
2078 builder->begin_list(builder, "conns");
2079
2080 this->lock->read_lock(this->lock);
2081 enumerator = this->conns->create_enumerator(this->conns);
2082 while (enumerator->enumerate(enumerator, &cfg))
2083 {
2084 builder->add_li(builder, "%s", cfg->get_name(cfg));
2085 }
2086 enumerator->destroy(enumerator);
2087 this->lock->unlock(this->lock);
2088
2089 builder->end_list(builder);
2090
2091 return builder->finalize(builder);
2092 }
2093
2094 static void manage_command(private_vici_config_t *this,
2095 char *name, vici_command_cb_t cb, bool reg)
2096 {
2097 this->dispatcher->manage_command(this->dispatcher, name,
2098 reg ? cb : NULL, this);
2099 }
2100
2101 /**
2102 * (Un-)register dispatcher functions
2103 */
2104 static void manage_commands(private_vici_config_t *this, bool reg)
2105 {
2106 manage_command(this, "load-conn", load_conn, reg);
2107 manage_command(this, "unload-conn", unload_conn, reg);
2108 manage_command(this, "get-conns", get_conns, reg);
2109 }
2110
2111 METHOD(vici_config_t, destroy, void,
2112 private_vici_config_t *this)
2113 {
2114 manage_commands(this, FALSE);
2115 this->conns->destroy_offset(this->conns, offsetof(peer_cfg_t, destroy));
2116 this->lock->destroy(this->lock);
2117 free(this);
2118 }
2119
2120 /**
2121 * See header
2122 */
2123 vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
2124 vici_authority_t *authority)
2125 {
2126 private_vici_config_t *this;
2127
2128 INIT(this,
2129 .public = {
2130 .backend = {
2131 .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
2132 .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
2133 .get_peer_cfg_by_name = _get_peer_cfg_by_name,
2134 },
2135 .destroy = _destroy,
2136 },
2137 .dispatcher = dispatcher,
2138 .conns = linked_list_create(),
2139 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
2140 .authority = authority,
2141 );
2142
2143 manage_commands(this, TRUE);
2144
2145 return &this->public;
2146 }