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