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