2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
5 * Copyright (C) 2015-2017 Tobias Brunner
6 * Copyright (C) 2015-2018 Andreas Steffen
7 * HSR Hochschule fuer Technik Rapperswil
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44 #include "vici_config.h"
45 #include "vici_builder.h"
48 #include <threading/rwlock.h>
49 #include <threading/rwlock_condvar.h>
50 #include <collections/array.h>
51 #include <collections/linked_list.h>
53 #include <pubkey_cert.h>
58 * Magic value for an undefined lifetime
60 #define LFT_UNDEFINED (~(uint64_t)0)
63 * Default IKE rekey time
65 #define LFT_DEFAULT_IKE_REKEY_TIME (4 * 60 * 60)
68 * Default CHILD rekey time
70 #define LFT_DEFAULT_CHILD_REKEY_TIME (1 * 60 * 60)
73 * Default CHILD rekey bytes
75 #define LFT_DEFAULT_CHILD_REKEY_BYTES 0
78 * Default CHILD rekey packets
80 #define LFT_DEFAULT_CHILD_REKEY_PACKETS 0
83 * Undefined replay window
85 #define REPLAY_UNDEFINED (~(uint32_t)0)
87 typedef struct private_vici_config_t private_vici_config_t
;
90 * Private data of an vici_config_t object.
92 struct private_vici_config_t
{
95 * Public vici_config_t interface.
102 vici_dispatcher_t
*dispatcher
;
105 * List of loaded connections, as peer_cfg_t
107 linked_list_t
*conns
;
110 * Lock for conns list
115 * Condvar used to sync running actions
117 rwlock_condvar_t
*condvar
;
120 * True while we run or undo a start action
122 bool handling_actions
;
125 * Credential backend managed by VICI used for our certificates
130 * Auxiliary certification authority information
132 vici_authority_t
*authority
;
136 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
137 private_vici_config_t
*this, identification_t
*me
, identification_t
*other
)
139 this->lock
->read_lock(this->lock
);
140 return enumerator_create_cleaner(this->conns
->create_enumerator(this->conns
),
141 (void*)this->lock
->unlock
, this->lock
);
144 CALLBACK(ike_filter
, bool,
145 void *data
, enumerator_t
*orig
, va_list args
)
150 VA_ARGS_VGET(args
, out
);
152 if (orig
->enumerate(orig
, &cfg
))
154 *out
= cfg
->get_ike_cfg(cfg
);
160 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
161 private_vici_config_t
*this, host_t
*me
, host_t
*other
)
163 this->lock
->read_lock(this->lock
);
164 return enumerator_create_filter(this->conns
->create_enumerator(this->conns
),
165 ike_filter
, this->lock
,
166 (void*)this->lock
->unlock
);
169 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
170 private_vici_config_t
*this, char *name
)
172 peer_cfg_t
*current
, *found
= NULL
;
173 enumerator_t
*enumerator
;
175 this->lock
->read_lock(this->lock
);
176 enumerator
= this->conns
->create_enumerator(this->conns
);
177 while (enumerator
->enumerate(enumerator
, ¤t
))
179 if (streq(current
->get_name(current
), name
))
182 found
->get_ref(found
);
186 enumerator
->destroy(enumerator
);
187 this->lock
->unlock(this->lock
);
193 * Create a (error) reply message
195 static vici_message_t
* create_reply(char *fmt
, ...)
197 vici_builder_t
*builder
;
200 builder
= vici_builder_create();
201 builder
->add_kv(builder
, "success", fmt ?
"no" : "yes");
205 builder
->vadd_kv(builder
, "errmsg", fmt
, args
);
208 return builder
->finalize(builder
);
212 * A rule to parse a key/value or list item
215 /** name of the key/value or list */
217 /** function to parse value */
218 bool (*parse
)(void *out
, chunk_t value
);
219 /** result, passed to parse() */
224 * Parse key/values using a rule-set
226 static bool parse_rules(parse_rule_t
*rules
, int count
, char *name
,
227 chunk_t value
, vici_message_t
**reply
)
231 for (i
= 0; i
< count
; i
++)
233 if (streq(name
, rules
[i
].name
))
235 if (rules
[i
].parse(rules
[i
].out
, value
))
239 *reply
= create_reply("invalid value for: %s, config discarded",
244 *reply
= create_reply("unknown option: %s, config discarded", name
);
249 * Parse callback data, passed to each callback
252 private_vici_config_t
*this;
253 vici_message_t
*reply
;
260 request_data_t
*request
;
268 * Clean up certificate data
270 static void free_cert_data(cert_data_t
*data
)
282 request_data_t
*request
;
288 * Clean up auth config data
290 static void free_auth_data(auth_data_t
*data
)
292 DESTROY_IF(data
->cfg
);
297 * Data associated to a peer config
300 request_data_t
*request
;
307 cert_policy_t send_cert
;
309 uint64_t dpd_timeout
;
310 fragmentation_t fragmentation
;
311 unique_policy_t unique
;
312 uint32_t keyingtries
;
314 uint32_t remote_port
;
317 linked_list_t
*local
;
318 linked_list_t
*remote
;
319 linked_list_t
*proposals
;
320 linked_list_t
*children
;
323 uint64_t reauth_time
;
331 identification_t
*peer_id
;
336 * Log relevant auth config data
338 static void log_auth(auth_cfg_t
*auth
)
340 enumerator_t
*enumerator
;
344 identification_t
*id
;
348 enumerator
= auth
->create_enumerator(auth
);
349 while (enumerator
->enumerate(enumerator
, &rule
, &v
))
353 case AUTH_RULE_AUTH_CLASS
:
354 DBG2(DBG_CFG
, " class = %N", auth_class_names
, v
.u
);
356 case AUTH_RULE_EAP_TYPE
:
357 DBG2(DBG_CFG
, " eap-type = %N", eap_type_names
, v
.u
);
359 case AUTH_RULE_EAP_VENDOR
:
360 DBG2(DBG_CFG
, " eap-vendor = %u", v
.u
);
362 case AUTH_RULE_XAUTH_BACKEND
:
363 DBG2(DBG_CFG
, " xauth = %s", v
.str
);
365 case AUTH_RULE_CRL_VALIDATION
:
366 DBG2(DBG_CFG
, " revocation = %N", cert_validation_names
, v
.u
);
368 case AUTH_RULE_IDENTITY
:
369 DBG2(DBG_CFG
, " id = %Y", v
.id
);
371 case AUTH_RULE_AAA_IDENTITY
:
372 DBG2(DBG_CFG
, " aaa_id = %Y", v
.id
);
374 case AUTH_RULE_EAP_IDENTITY
:
375 DBG2(DBG_CFG
, " eap_id = %Y", v
.id
);
377 case AUTH_RULE_XAUTH_IDENTITY
:
378 DBG2(DBG_CFG
, " xauth_id = %Y", v
.id
);
380 case AUTH_RULE_GROUP
:
381 DBG2(DBG_CFG
, " group = %Y", v
.id
);
387 enumerator
->destroy(enumerator
);
391 * Log parsed peer data
393 static void log_peer_data(peer_data_t
*data
)
395 enumerator_t
*enumerator
;
399 DBG2(DBG_CFG
, " version = %u", data
->version
);
400 DBG2(DBG_CFG
, " local_addrs = %s", data
->local_addrs
);
401 DBG2(DBG_CFG
, " remote_addrs = %s", data
->remote_addrs
);
402 DBG2(DBG_CFG
, " local_port = %u", data
->local_port
);
403 DBG2(DBG_CFG
, " remote_port = %u", data
->remote_port
);
404 DBG2(DBG_CFG
, " send_certreq = %u", data
->send_certreq
);
405 DBG2(DBG_CFG
, " send_cert = %N", cert_policy_names
, data
->send_cert
);
406 DBG2(DBG_CFG
, " mobike = %u", data
->mobike
);
407 DBG2(DBG_CFG
, " aggressive = %u", data
->aggressive
);
408 DBG2(DBG_CFG
, " dscp = 0x%.2x", data
->dscp
);
409 DBG2(DBG_CFG
, " encap = %u", data
->encap
);
410 DBG2(DBG_CFG
, " dpd_delay = %llu", data
->dpd_delay
);
411 DBG2(DBG_CFG
, " dpd_timeout = %llu", data
->dpd_timeout
);
412 DBG2(DBG_CFG
, " fragmentation = %u", data
->fragmentation
);
413 DBG2(DBG_CFG
, " unique = %N", unique_policy_names
, data
->unique
);
414 DBG2(DBG_CFG
, " keyingtries = %u", data
->keyingtries
);
415 DBG2(DBG_CFG
, " reauth_time = %llu", data
->reauth_time
);
416 DBG2(DBG_CFG
, " rekey_time = %llu", data
->rekey_time
);
417 DBG2(DBG_CFG
, " over_time = %llu", data
->over_time
);
418 DBG2(DBG_CFG
, " rand_time = %llu", data
->rand_time
);
419 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
421 DBG2(DBG_CFG
, " mediation = %u", data
->mediation
);
422 if (data
->mediated_by
)
424 DBG2(DBG_CFG
, " mediated_by = %s", data
->mediated_by
);
425 DBG2(DBG_CFG
, " mediation_peer = %Y", data
->peer_id
);
429 if (data
->vips
->get_count(data
->vips
))
431 DBG2(DBG_CFG
, " vips:");
433 enumerator
= data
->vips
->create_enumerator(data
->vips
);
434 while (enumerator
->enumerate(enumerator
, &host
))
436 DBG2(DBG_CFG
, " %H", host
);
438 enumerator
->destroy(enumerator
);
440 enumerator
= data
->local
->create_enumerator(data
->local
);
441 while (enumerator
->enumerate(enumerator
, &auth
))
443 DBG2(DBG_CFG
, " local:");
446 enumerator
->destroy(enumerator
);
448 enumerator
= data
->remote
->create_enumerator(data
->remote
);
449 while (enumerator
->enumerate(enumerator
, &auth
))
451 DBG2(DBG_CFG
, " remote:");
454 enumerator
->destroy(enumerator
);
458 * Clean up peer config data
460 static void free_peer_data(peer_data_t
*data
)
462 data
->local
->destroy_function(data
->local
, (void*)free_auth_data
);
463 data
->remote
->destroy_function(data
->remote
, (void*)free_auth_data
);
464 data
->children
->destroy_offset(data
->children
,
465 offsetof(child_cfg_t
, destroy
));
466 data
->proposals
->destroy_offset(data
->proposals
,
467 offsetof(proposal_t
, destroy
));
468 data
->vips
->destroy_offset(data
->vips
, offsetof(host_t
, destroy
));
470 free(data
->local_addrs
);
471 free(data
->remote_addrs
);
473 free(data
->mediated_by
);
474 DESTROY_IF(data
->peer_id
);
482 request_data_t
*request
;
483 linked_list_t
*proposals
;
484 linked_list_t
*local_ts
;
485 linked_list_t
*remote_ts
;
486 uint32_t replay_window
;
487 child_cfg_create_t cfg
;
491 * Log parsed CHILD config data
493 static void log_child_data(child_data_t
*data
, char *name
)
495 child_cfg_create_t
*cfg
= &data
->cfg
;
497 #define has_opt(opt) ({ (cfg->options & (opt)) == (opt); })
498 DBG2(DBG_CFG
, " child %s:", name
);
499 DBG2(DBG_CFG
, " rekey_time = %llu", cfg
->lifetime
.time
.rekey
);
500 DBG2(DBG_CFG
, " life_time = %llu", cfg
->lifetime
.time
.life
);
501 DBG2(DBG_CFG
, " rand_time = %llu", cfg
->lifetime
.time
.jitter
);
502 DBG2(DBG_CFG
, " rekey_bytes = %llu", cfg
->lifetime
.bytes
.rekey
);
503 DBG2(DBG_CFG
, " life_bytes = %llu", cfg
->lifetime
.bytes
.life
);
504 DBG2(DBG_CFG
, " rand_bytes = %llu", cfg
->lifetime
.bytes
.jitter
);
505 DBG2(DBG_CFG
, " rekey_packets = %llu", cfg
->lifetime
.packets
.rekey
);
506 DBG2(DBG_CFG
, " life_packets = %llu", cfg
->lifetime
.packets
.life
);
507 DBG2(DBG_CFG
, " rand_packets = %llu", cfg
->lifetime
.packets
.jitter
);
508 DBG2(DBG_CFG
, " updown = %s", cfg
->updown
);
509 DBG2(DBG_CFG
, " hostaccess = %u", has_opt(OPT_HOSTACCESS
));
510 DBG2(DBG_CFG
, " ipcomp = %u", has_opt(OPT_IPCOMP
));
511 DBG2(DBG_CFG
, " mode = %N%s", ipsec_mode_names
, cfg
->mode
,
512 has_opt(OPT_PROXY_MODE
) ?
"_PROXY" : "");
513 DBG2(DBG_CFG
, " policies = %u", !has_opt(OPT_NO_POLICIES
));
514 DBG2(DBG_CFG
, " policies_fwd_out = %u", has_opt(OPT_FWD_OUT_POLICIES
));
515 if (data
->replay_window
!= REPLAY_UNDEFINED
)
517 DBG2(DBG_CFG
, " replay_window = %u", data
->replay_window
);
519 DBG2(DBG_CFG
, " dpd_action = %N", action_names
, cfg
->dpd_action
);
520 DBG2(DBG_CFG
, " start_action = %N", action_names
, cfg
->start_action
);
521 DBG2(DBG_CFG
, " close_action = %N", action_names
, cfg
->close_action
);
522 DBG2(DBG_CFG
, " reqid = %u", cfg
->reqid
);
523 DBG2(DBG_CFG
, " tfc = %d", cfg
->tfc
);
524 DBG2(DBG_CFG
, " priority = %d", cfg
->priority
);
525 DBG2(DBG_CFG
, " interface = %s", cfg
->interface
);
526 DBG2(DBG_CFG
, " mark_in = %u/%u",
527 cfg
->mark_in
.value
, cfg
->mark_in
.mask
);
528 DBG2(DBG_CFG
, " mark_in_sa = %u", has_opt(OPT_MARK_IN_SA
));
529 DBG2(DBG_CFG
, " mark_out = %u/%u",
530 cfg
->mark_out
.value
, cfg
->mark_out
.mask
);
531 DBG2(DBG_CFG
, " inactivity = %llu", cfg
->inactivity
);
532 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
533 DBG2(DBG_CFG
, " local_ts = %#R", data
->local_ts
);
534 DBG2(DBG_CFG
, " remote_ts = %#R", data
->remote_ts
);
535 DBG2(DBG_CFG
, " hw_offload = %N", hw_offload_names
, cfg
->hw_offload
);
536 DBG2(DBG_CFG
, " sha256_96 = %u", has_opt(OPT_SHA256_96
));
537 DBG2(DBG_CFG
, " copy_df = %u", !has_opt(OPT_NO_COPY_DF
));
538 DBG2(DBG_CFG
, " copy_ecn = %u", !has_opt(OPT_NO_COPY_ECN
));
542 * Clean up CHILD config data
544 static void free_child_data(child_data_t
*data
)
546 data
->proposals
->destroy_offset(data
->proposals
,
547 offsetof(proposal_t
, destroy
));
548 data
->local_ts
->destroy_offset(data
->local_ts
,
549 offsetof(traffic_selector_t
, destroy
));
550 data
->remote_ts
->destroy_offset(data
->remote_ts
,
551 offsetof(traffic_selector_t
, destroy
));
552 free(data
->cfg
.updown
);
553 free(data
->cfg
.interface
);
557 * Common proposal parsing
559 static bool parse_proposal(linked_list_t
*list
, protocol_id_t proto
, chunk_t v
)
562 proposal_t
*proposal
;
564 if (!vici_stringify(v
, buf
, sizeof(buf
)))
568 if (strcaseeq("default", buf
))
570 proposal
= proposal_create_default(proto
);
573 list
->insert_last(list
, proposal
);
575 proposal
= proposal_create_default_aead(proto
);
578 list
->insert_last(list
, proposal
);
582 proposal
= proposal_create_from_string(proto
, buf
);
585 list
->insert_last(list
, proposal
);
594 CALLBACK(parse_ike_proposal
, bool,
595 linked_list_t
*out
, chunk_t v
)
597 return parse_proposal(out
, PROTO_IKE
, v
);
603 CALLBACK(parse_esp_proposal
, bool,
604 linked_list_t
*out
, chunk_t v
)
606 return parse_proposal(out
, PROTO_ESP
, v
);
612 CALLBACK(parse_ah_proposal
, bool,
613 linked_list_t
*out
, chunk_t v
)
615 return parse_proposal(out
, PROTO_AH
, v
);
619 * Parse a traffic selector
621 CALLBACK(parse_ts
, bool,
622 linked_list_t
*out
, chunk_t v
)
624 char buf
[BUF_LEN
], *protoport
, *sep
, *port
= "", *end
;
625 traffic_selector_t
*ts
= NULL
;
626 struct protoent
*protoent
;
629 uint16_t from
= 0, to
= 0xffff;
632 if (!vici_stringify(v
, buf
, sizeof(buf
)))
637 protoport
= strchr(buf
, '[');
640 *(protoport
++) = '\0';
642 sep
= strrchr(protoport
, ']');
649 sep
= strchr(protoport
, '/');
651 { /* protocol/port */
656 if (streq(protoport
, "any"))
662 protoent
= getprotobyname(protoport
);
665 proto
= protoent
->p_proto
;
669 p
= strtol(protoport
, &end
, 0);
670 if ((*protoport
&& *end
) || p
< 0 || p
> 0xff)
677 if (streq(port
, "opaque"))
682 else if (*port
&& !streq(port
, "any"))
684 svc
= getservbyname(port
, NULL
);
687 from
= to
= ntohs(svc
->s_port
);
691 p
= strtol(port
, &end
, 0);
692 if (p
< 0 || p
> 0xffff)
700 p
= strtol(port
, &end
, 0);
701 if (p
< 0 || p
> 0xffff)
714 if (streq(buf
, "dynamic"))
716 ts
= traffic_selector_create_dynamic(proto
, from
, to
);
718 else if (strchr(buf
, '-'))
720 host_t
*lower
, *upper
;
723 if (host_create_from_range(buf
, &lower
, &upper
))
725 type
= (lower
->get_family(lower
) == AF_INET
) ?
726 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
;
727 ts
= traffic_selector_create_from_bytes(proto
, type
,
728 lower
->get_address(lower
), from
,
729 upper
->get_address(upper
), to
);
730 lower
->destroy(lower
);
731 upper
->destroy(upper
);
736 ts
= traffic_selector_create_from_cidr(buf
, proto
, from
, to
);
742 out
->insert_last(out
, ts
);
749 CALLBACK(parse_string
, bool,
750 char **out
, chunk_t v
)
752 if (!chunk_printable(v
, NULL
, ' '))
758 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
766 * Map a string to an integer
774 * Parse a string to an integer mapping
776 static bool parse_map(enum_map_t
*map
, int count
, int *out
, chunk_t v
)
781 if (!vici_stringify(v
, buf
, sizeof(buf
)))
785 for (i
= 0; i
< count
; i
++)
787 if (strcaseeq(map
[i
].str
, buf
))
799 CALLBACK(parse_bool
, bool,
800 bool *out
, chunk_t v
)
809 { "disabled", FALSE
},
814 if (parse_map(map
, countof(map
), &d
, v
))
823 * Parse a ipsec_mode_t
825 CALLBACK(parse_mode
, bool,
826 child_cfg_create_t
*cfg
, chunk_t v
)
829 { "tunnel", MODE_TUNNEL
},
830 { "transport", MODE_TRANSPORT
},
831 { "transport_proxy", MODE_TRANSPORT
},
832 { "beet", MODE_BEET
},
833 { "drop", MODE_DROP
},
834 { "pass", MODE_PASS
},
838 if (parse_map(map
, countof(map
), &d
, v
))
841 if ((d
== MODE_TRANSPORT
) && (v
.len
> 9))
843 cfg
->options
|= OPT_PROXY_MODE
;
851 * Enable a child_cfg_option_t, the flag controls whether the option is enabled
852 * if the parsed value is TRUE or FALSE.
854 static bool parse_option(child_cfg_option_t
*out
, child_cfg_option_t opt
,
855 chunk_t v
, bool add_if_true
)
859 if (parse_bool(&val
, v
))
861 if (val
== add_if_true
)
871 * Parse OPT_HOSTACCESS option
873 CALLBACK(parse_opt_haccess
, bool,
874 child_cfg_option_t
*out
, chunk_t v
)
876 return parse_option(out
, OPT_HOSTACCESS
, v
, TRUE
);
880 * Parse OPT_NO_POLICIES option
882 CALLBACK(parse_opt_policies
, bool,
883 child_cfg_option_t
*out
, chunk_t v
)
885 return parse_option(out
, OPT_NO_POLICIES
, v
, FALSE
);
889 * Parse OPT_FWD_OUT_POLICIES option
891 CALLBACK(parse_opt_fwd_out
, bool,
892 child_cfg_option_t
*out
, chunk_t v
)
894 return parse_option(out
, OPT_FWD_OUT_POLICIES
, v
, TRUE
);
898 * Parse OPT_IPCOMP option
900 CALLBACK(parse_opt_ipcomp
, bool,
901 child_cfg_option_t
*out
, chunk_t v
)
903 return parse_option(out
, OPT_IPCOMP
, v
, TRUE
);
907 * Parse OPT_SHA256_96 option
909 CALLBACK(parse_opt_sha256_96
, bool,
910 child_cfg_option_t
*out
, chunk_t v
)
912 return parse_option(out
, OPT_SHA256_96
, v
, TRUE
);
916 * Parse OPT_MARK_IN_SA option
918 CALLBACK(parse_opt_mark_in
, bool,
919 child_cfg_option_t
*out
, chunk_t v
)
921 return parse_option(out
, OPT_MARK_IN_SA
, v
, TRUE
);
925 * Parse OPT_NO_COPY_DF option
927 CALLBACK(parse_opt_copy_df
, bool,
928 child_cfg_option_t
*out
, chunk_t v
)
930 return parse_option(out
, OPT_NO_COPY_DF
, v
, FALSE
);
934 * Parse OPT_NO_COPY_ECN option
936 CALLBACK(parse_opt_copy_ecn
, bool,
937 child_cfg_option_t
*out
, chunk_t v
)
939 return parse_option(out
, OPT_NO_COPY_ECN
, v
, FALSE
);
945 CALLBACK(parse_action
, bool,
946 action_t
*out
, chunk_t v
)
949 { "start", ACTION_RESTART
},
950 { "restart", ACTION_RESTART
},
951 { "route", ACTION_ROUTE
},
952 { "trap", ACTION_ROUTE
},
953 { "none", ACTION_NONE
},
954 { "clear", ACTION_NONE
},
958 if (parse_map(map
, countof(map
), &d
, v
))
967 * Parse an hw_offload_t
969 CALLBACK(parse_hw_offload
, bool,
970 action_t
*out
, chunk_t v
)
973 { "no", HW_OFFLOAD_NO
},
974 { "yes", HW_OFFLOAD_YES
},
975 { "auto", HW_OFFLOAD_AUTO
},
979 if (parse_map(map
, countof(map
), &d
, v
))
988 * Parse a uint32_t with the given base
990 static bool parse_uint32_base(uint32_t *out
, chunk_t v
, int base
)
995 if (!vici_stringify(v
, buf
, sizeof(buf
)))
999 l
= strtoul(buf
, &end
, base
);
1011 CALLBACK(parse_uint32
, bool,
1012 uint32_t *out
, chunk_t v
)
1014 return parse_uint32_base(out
, v
, 0);
1018 * Parse a uint32_t in binary encoding
1020 CALLBACK(parse_uint32_bin
, bool,
1021 uint32_t *out
, chunk_t v
)
1023 return parse_uint32_base(out
, v
, 2);
1029 CALLBACK(parse_uint64
, bool,
1030 uint64_t *out
, chunk_t v
)
1033 unsigned long long l
;
1035 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1039 l
= strtoull(buf
, &end
, 0);
1049 * Parse a relative time
1051 CALLBACK(parse_time
, bool,
1052 uint64_t *out
, chunk_t v
)
1057 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1062 l
= strtoul(buf
, &end
, 0);
1101 CALLBACK(parse_bytes
, bool,
1102 uint64_t *out
, chunk_t v
)
1105 unsigned long long l
;
1107 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1112 l
= strtoull(buf
, &end
, 0);
1148 CALLBACK(parse_mark
, bool,
1149 mark_t
*out
, chunk_t v
)
1153 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1157 return mark_from_string(buf
, out
);
1161 * Parse TFC padding option
1163 CALLBACK(parse_tfc
, bool,
1164 uint32_t *out
, chunk_t v
)
1166 if (chunk_equals(v
, chunk_from_str("mtu")))
1171 return parse_uint32(out
, v
);
1175 * Parse 6-bit DSCP value
1177 CALLBACK(parse_dscp
, bool,
1178 uint8_t *out
, chunk_t v
)
1180 if (parse_uint32_bin(out
, v
))
1189 * Parse authentication config
1191 CALLBACK(parse_auth
, bool,
1192 auth_cfg_t
*cfg
, chunk_t v
)
1195 eap_vendor_type_t
*type
;
1197 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1201 if (strpfx(buf
, "ike:") ||
1202 strpfx(buf
, "pubkey") ||
1203 strpfx(buf
, "rsa") ||
1204 strpfx(buf
, "ecdsa") ||
1205 strpfx(buf
, "bliss"))
1207 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
1208 cfg
->add_pubkey_constraints(cfg
, buf
, TRUE
);
1211 if (strcaseeq(buf
, "psk"))
1213 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PSK
);
1216 if (strcasepfx(buf
, "xauth"))
1218 pos
= strchr(buf
, '-');
1221 cfg
->add(cfg
, AUTH_RULE_XAUTH_BACKEND
, strdup(++pos
));
1223 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_XAUTH
);
1226 if (strcasepfx(buf
, "eap"))
1230 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_EAP
);
1232 pos
= strchr(buf
, ':');
1236 cfg
->add_pubkey_constraints(cfg
, pos
+ 1, FALSE
);
1238 type
= eap_vendor_type_from_string(buf
);
1241 cfg
->add(cfg
, AUTH_RULE_EAP_TYPE
, type
->type
);
1244 cfg
->add(cfg
, AUTH_RULE_EAP_VENDOR
, type
->vendor
);
1254 * Parse identity; add as auth rule to config
1256 static bool parse_id(auth_cfg_t
*cfg
, auth_rule_t rule
, chunk_t v
)
1260 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1264 cfg
->add(cfg
, rule
, identification_create_from_string(buf
));
1269 * Parse IKE identity
1271 CALLBACK(parse_ike_id
, bool,
1272 auth_cfg_t
*cfg
, chunk_t v
)
1274 return parse_id(cfg
, AUTH_RULE_IDENTITY
, v
);
1278 * Parse AAA identity
1280 CALLBACK(parse_aaa_id
, bool,
1281 auth_cfg_t
*cfg
, chunk_t v
)
1283 return parse_id(cfg
, AUTH_RULE_AAA_IDENTITY
, v
);
1287 * Parse EAP identity
1289 CALLBACK(parse_eap_id
, bool,
1290 auth_cfg_t
*cfg
, chunk_t v
)
1292 return parse_id(cfg
, AUTH_RULE_EAP_IDENTITY
, v
);
1296 * Parse XAuth identity
1298 CALLBACK(parse_xauth_id
, bool,
1299 auth_cfg_t
*cfg
, chunk_t v
)
1301 return parse_id(cfg
, AUTH_RULE_XAUTH_IDENTITY
, v
);
1305 * Parse group membership
1307 CALLBACK(parse_group
, bool,
1308 auth_cfg_t
*cfg
, chunk_t v
)
1310 return parse_id(cfg
, AUTH_RULE_GROUP
, v
);
1314 * Parse certificate policy
1316 CALLBACK(parse_cert_policy
, bool,
1317 auth_cfg_t
*cfg
, chunk_t v
)
1321 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1325 cfg
->add(cfg
, AUTH_RULE_CERT_POLICY
, strdup(buf
));
1330 * Add a certificate as auth rule to config
1332 static bool add_cert(auth_data_t
*auth
, auth_rule_t rule
, certificate_t
*cert
)
1334 vici_authority_t
*authority
;
1337 if (rule
== AUTH_RULE_SUBJECT_CERT
)
1339 authority
= auth
->request
->this->authority
;
1340 authority
->check_for_hash_and_url(authority
, cert
);
1342 cred
= auth
->request
->this->cred
;
1343 cert
= cred
->add_cert(cred
, cert
);
1344 auth
->cfg
->add(auth
->cfg
, rule
, cert
);
1349 * Parse a certificate; add as auth rule to config
1351 static bool parse_cert(auth_data_t
*auth
, auth_rule_t rule
, chunk_t v
)
1353 certificate_t
*cert
;
1355 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
1356 BUILD_BLOB_PEM
, v
, BUILD_END
);
1359 return add_cert(auth
, rule
, cert
);
1365 * Parse subject certificates
1367 CALLBACK(parse_certs
, bool,
1368 auth_data_t
*auth
, chunk_t v
)
1370 return parse_cert(auth
, AUTH_RULE_SUBJECT_CERT
, v
);
1374 * Parse CA certificates
1376 CALLBACK(parse_cacerts
, bool,
1377 auth_data_t
*auth
, chunk_t v
)
1379 return parse_cert(auth
, AUTH_RULE_CA_CERT
, v
);
1383 * Parse raw public keys
1385 CALLBACK(parse_pubkeys
, bool,
1386 auth_data_t
*auth
, chunk_t v
)
1389 certificate_t
*cert
;
1391 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_TRUSTED_PUBKEY
,
1392 BUILD_BLOB_PEM
, v
, BUILD_END
);
1395 cred
= auth
->request
->this->cred
;
1396 cert
= cred
->add_cert(cred
, cert
);
1397 auth
->cfg
->add(auth
->cfg
, AUTH_RULE_SUBJECT_CERT
, cert
);
1404 * Parse revocation status
1406 CALLBACK(parse_revocation
, bool,
1407 auth_cfg_t
*cfg
, chunk_t v
)
1409 enum_map_t map
[] = {
1410 { "strict", VALIDATION_GOOD
},
1411 { "ifuri", VALIDATION_SKIPPED
},
1412 { "relaxed", VALIDATION_FAILED
},
1416 if (parse_map(map
, countof(map
), &d
, v
))
1418 if (d
!= VALIDATION_FAILED
)
1420 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, d
);
1428 * Parse list items to comma separated strings
1430 CALLBACK(parse_stringlist
, bool,
1431 char **out
, chunk_t v
)
1435 if (!chunk_printable(v
, NULL
, ' '))
1442 if (asprintf(out
, "%s, %.*s", current
, (int)v
.len
, v
.ptr
) == -1)
1450 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
1459 * Parse an fragmentation_t
1461 CALLBACK(parse_frag
, bool,
1462 fragmentation_t
*out
, chunk_t v
)
1464 enum_map_t map
[] = {
1465 { "yes", FRAGMENTATION_YES
},
1466 { "accept", FRAGMENTATION_ACCEPT
},
1467 { "no", FRAGMENTATION_NO
},
1468 { "force", FRAGMENTATION_FORCE
},
1472 if (parse_map(map
, countof(map
), &d
, v
))
1481 * Parse a cert_policy_t
1483 CALLBACK(parse_send_cert
, bool,
1484 cert_policy_t
*out
, chunk_t v
)
1486 enum_map_t map
[] = {
1487 { "ifasked", CERT_SEND_IF_ASKED
},
1488 { "always", CERT_ALWAYS_SEND
},
1489 { "never", CERT_NEVER_SEND
},
1493 if (parse_map(map
, countof(map
), &d
, v
))
1502 * Parse a unique_policy_t
1504 CALLBACK(parse_unique
, bool,
1505 unique_policy_t
*out
, chunk_t v
)
1507 enum_map_t map
[] = {
1508 { "never", UNIQUE_NEVER
},
1509 { "no", UNIQUE_NO
},
1510 { "replace", UNIQUE_REPLACE
},
1511 { "keep", UNIQUE_KEEP
},
1515 if (parse_map(map
, countof(map
), &d
, v
))
1524 * Parse host_t into a list
1526 CALLBACK(parse_hosts
, bool,
1527 linked_list_t
*list
, chunk_t v
)
1532 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1536 host
= host_create_from_string(buf
, 0);
1541 list
->insert_last(list
, host
);
1549 CALLBACK(parse_peer_id
, bool,
1550 identification_t
**out
, chunk_t v
)
1554 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1558 *out
= identification_create_from_string(buf
);
1563 CALLBACK(cert_kv
, bool,
1564 cert_data_t
*cert
, vici_message_t
*message
, char *name
, chunk_t value
)
1566 parse_rule_t rules
[] = {
1567 { "handle", parse_string
, &cert
->handle
},
1568 { "slot", parse_uint32
, &cert
->slot
},
1569 { "module", parse_string
, &cert
->module
},
1570 { "file", parse_string
, &cert
->file
},
1573 return parse_rules(rules
, countof(rules
), name
, value
,
1574 &cert
->request
->reply
);
1577 CALLBACK(child_li
, bool,
1578 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1580 parse_rule_t rules
[] = {
1581 { "ah_proposals", parse_ah_proposal
, child
->proposals
},
1582 { "esp_proposals", parse_esp_proposal
, child
->proposals
},
1583 { "local_ts", parse_ts
, child
->local_ts
},
1584 { "remote_ts", parse_ts
, child
->remote_ts
},
1587 return parse_rules(rules
, countof(rules
), name
, value
,
1588 &child
->request
->reply
);
1591 CALLBACK(child_kv
, bool,
1592 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1594 parse_rule_t rules
[] = {
1595 { "updown", parse_string
, &child
->cfg
.updown
},
1596 { "hostaccess", parse_opt_haccess
, &child
->cfg
.options
},
1597 { "mode", parse_mode
, &child
->cfg
},
1598 { "policies", parse_opt_policies
, &child
->cfg
.options
},
1599 { "policies_fwd_out", parse_opt_fwd_out
, &child
->cfg
.options
},
1600 { "replay_window", parse_uint32
, &child
->replay_window
},
1601 { "rekey_time", parse_time
, &child
->cfg
.lifetime
.time
.rekey
},
1602 { "life_time", parse_time
, &child
->cfg
.lifetime
.time
.life
},
1603 { "rand_time", parse_time
, &child
->cfg
.lifetime
.time
.jitter
},
1604 { "rekey_bytes", parse_bytes
, &child
->cfg
.lifetime
.bytes
.rekey
},
1605 { "life_bytes", parse_bytes
, &child
->cfg
.lifetime
.bytes
.life
},
1606 { "rand_bytes", parse_bytes
, &child
->cfg
.lifetime
.bytes
.jitter
},
1607 { "rekey_packets", parse_uint64
, &child
->cfg
.lifetime
.packets
.rekey
},
1608 { "life_packets", parse_uint64
, &child
->cfg
.lifetime
.packets
.life
},
1609 { "rand_packets", parse_uint64
, &child
->cfg
.lifetime
.packets
.jitter
},
1610 { "dpd_action", parse_action
, &child
->cfg
.dpd_action
},
1611 { "start_action", parse_action
, &child
->cfg
.start_action
},
1612 { "close_action", parse_action
, &child
->cfg
.close_action
},
1613 { "ipcomp", parse_opt_ipcomp
, &child
->cfg
.options
},
1614 { "inactivity", parse_time
, &child
->cfg
.inactivity
},
1615 { "reqid", parse_uint32
, &child
->cfg
.reqid
},
1616 { "mark_in", parse_mark
, &child
->cfg
.mark_in
},
1617 { "mark_in_sa", parse_opt_mark_in
, &child
->cfg
.options
},
1618 { "mark_out", parse_mark
, &child
->cfg
.mark_out
},
1619 { "tfc_padding", parse_tfc
, &child
->cfg
.tfc
},
1620 { "priority", parse_uint32
, &child
->cfg
.priority
},
1621 { "interface", parse_string
, &child
->cfg
.interface
},
1622 { "hw_offload", parse_hw_offload
, &child
->cfg
.hw_offload
},
1623 { "sha256_96", parse_opt_sha256_96
,&child
->cfg
.options
},
1624 { "copy_df", parse_opt_copy_df
, &child
->cfg
.options
},
1625 { "copy_ecn", parse_opt_copy_ecn
, &child
->cfg
.options
},
1628 return parse_rules(rules
, countof(rules
), name
, value
,
1629 &child
->request
->reply
);
1632 CALLBACK(auth_li
, bool,
1633 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1635 parse_rule_t rules
[] = {
1636 { "groups", parse_group
, auth
->cfg
},
1637 { "cert_policy", parse_cert_policy
, auth
->cfg
},
1638 { "certs", parse_certs
, auth
},
1639 { "cacerts", parse_cacerts
, auth
},
1640 { "pubkeys", parse_pubkeys
, auth
},
1643 return parse_rules(rules
, countof(rules
), name
, value
,
1644 &auth
->request
->reply
);
1647 CALLBACK(auth_kv
, bool,
1648 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1650 parse_rule_t rules
[] = {
1651 { "auth", parse_auth
, auth
->cfg
},
1652 { "id", parse_ike_id
, auth
->cfg
},
1653 { "aaa_id", parse_aaa_id
, auth
->cfg
},
1654 { "eap_id", parse_eap_id
, auth
->cfg
},
1655 { "xauth_id", parse_xauth_id
, auth
->cfg
},
1656 { "revocation", parse_revocation
, auth
->cfg
},
1657 { "round", parse_uint32
, &auth
->round
},
1660 return parse_rules(rules
, countof(rules
), name
, value
,
1661 &auth
->request
->reply
);
1664 CALLBACK(peer_li
, bool,
1665 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1667 parse_rule_t rules
[] = {
1668 { "local_addrs", parse_stringlist
, &peer
->local_addrs
},
1669 { "remote_addrs", parse_stringlist
, &peer
->remote_addrs
},
1670 { "proposals", parse_ike_proposal
, peer
->proposals
},
1671 { "vips", parse_hosts
, peer
->vips
},
1672 { "pools", parse_stringlist
, &peer
->pools
},
1675 return parse_rules(rules
, countof(rules
), name
, value
,
1676 &peer
->request
->reply
);
1679 CALLBACK(peer_kv
, bool,
1680 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1682 parse_rule_t rules
[] = {
1683 { "version", parse_uint32
, &peer
->version
},
1684 { "aggressive", parse_bool
, &peer
->aggressive
},
1685 { "pull", parse_bool
, &peer
->pull
},
1686 { "dscp", parse_dscp
, &peer
->dscp
},
1687 { "encap", parse_bool
, &peer
->encap
},
1688 { "mobike", parse_bool
, &peer
->mobike
},
1689 { "dpd_delay", parse_time
, &peer
->dpd_delay
},
1690 { "dpd_timeout", parse_time
, &peer
->dpd_timeout
},
1691 { "fragmentation", parse_frag
, &peer
->fragmentation
},
1692 { "send_certreq", parse_bool
, &peer
->send_certreq
},
1693 { "send_cert", parse_send_cert
, &peer
->send_cert
},
1694 { "keyingtries", parse_uint32
, &peer
->keyingtries
},
1695 { "unique", parse_unique
, &peer
->unique
},
1696 { "local_port", parse_uint32
, &peer
->local_port
},
1697 { "remote_port", parse_uint32
, &peer
->remote_port
},
1698 { "reauth_time", parse_time
, &peer
->reauth_time
},
1699 { "rekey_time", parse_time
, &peer
->rekey_time
},
1700 { "over_time", parse_time
, &peer
->over_time
},
1701 { "rand_time", parse_time
, &peer
->rand_time
},
1703 { "mediation", parse_bool
, &peer
->mediation
},
1704 { "mediated_by", parse_string
, &peer
->mediated_by
},
1705 { "mediation_peer", parse_peer_id
, &peer
->peer_id
},
1709 return parse_rules(rules
, countof(rules
), name
, value
,
1710 &peer
->request
->reply
);
1713 CALLBACK(auth_sn
, bool,
1714 auth_data_t
*auth
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1717 if (strcasepfx(name
, "cert") ||
1718 strcasepfx(name
, "cacert"))
1722 certificate_t
*cert
;
1726 .request
= auth
->request
,
1730 if (!message
->parse(message
, ctx
, NULL
, cert_kv
, NULL
, data
))
1732 free_cert_data(data
);
1735 if (!data
->handle
&& !data
->file
)
1737 auth
->request
->reply
= create_reply("handle or file path missing: "
1739 free_cert_data(data
);
1742 else if (data
->handle
&& data
->file
)
1744 auth
->request
->reply
= create_reply("handle and file path given: "
1746 free_cert_data(data
);
1752 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
1753 BUILD_FROM_FILE
, data
->file
, BUILD_END
);
1757 handle
= chunk_from_hex(chunk_from_str(data
->handle
), NULL
);
1758 if (data
->slot
!= -1)
1760 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
1761 CERT_X509
, BUILD_PKCS11_KEYID
, handle
,
1762 BUILD_PKCS11_SLOT
, data
->slot
,
1763 data
->module ? BUILD_PKCS11_MODULE
: BUILD_END
,
1764 data
->module
, BUILD_END
);
1768 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
1769 CERT_X509
, BUILD_PKCS11_KEYID
, handle
,
1770 data
->module ? BUILD_PKCS11_MODULE
: BUILD_END
,
1771 data
->module
, BUILD_END
);
1773 chunk_free(&handle
);
1775 free_cert_data(data
);
1778 auth
->request
->reply
= create_reply("unable to load certificate: "
1782 rule
= strcasepfx(name
, "cert") ? AUTH_RULE_SUBJECT_CERT
1783 : AUTH_RULE_CA_CERT
;
1784 return add_cert(auth
, rule
, cert
);
1786 auth
->request
->reply
= create_reply("invalid section: %s", name
);
1791 * Check and update lifetimes
1793 static void check_lifetimes(lifetime_cfg_t
*lft
)
1795 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1796 if (lft
->time
.life
== LFT_UNDEFINED
)
1798 lft
->time
.life
= lft
->time
.rekey
* 110 / 100;
1800 if (lft
->bytes
.life
== LFT_UNDEFINED
)
1802 lft
->bytes
.life
= lft
->bytes
.rekey
* 110 / 100;
1804 if (lft
->packets
.life
== LFT_UNDEFINED
)
1806 lft
->packets
.life
= lft
->packets
.rekey
* 110 / 100;
1808 /* if no rand time defined, use difference of hard and soft */
1809 if (lft
->time
.jitter
== LFT_UNDEFINED
)
1811 lft
->time
.jitter
= lft
->time
.life
-
1812 min(lft
->time
.life
, lft
->time
.rekey
);
1814 if (lft
->bytes
.jitter
== LFT_UNDEFINED
)
1816 lft
->bytes
.jitter
= lft
->bytes
.life
-
1817 min(lft
->bytes
.life
, lft
->bytes
.rekey
);
1819 if (lft
->packets
.jitter
== LFT_UNDEFINED
)
1821 lft
->packets
.jitter
= lft
->packets
.life
-
1822 min(lft
->packets
.life
, lft
->packets
.rekey
);
1826 CALLBACK(children_sn
, bool,
1827 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1830 child_data_t child
= {
1831 .request
= peer
->request
,
1832 .proposals
= linked_list_create(),
1833 .local_ts
= linked_list_create(),
1834 .remote_ts
= linked_list_create(),
1835 .replay_window
= REPLAY_UNDEFINED
,
1837 .mode
= MODE_TUNNEL
,
1840 .rekey
= LFT_DEFAULT_CHILD_REKEY_TIME
,
1841 .life
= LFT_UNDEFINED
,
1842 .jitter
= LFT_UNDEFINED
,
1845 .rekey
= LFT_DEFAULT_CHILD_REKEY_BYTES
,
1846 .life
= LFT_UNDEFINED
,
1847 .jitter
= LFT_UNDEFINED
,
1850 .rekey
= LFT_DEFAULT_CHILD_REKEY_PACKETS
,
1851 .life
= LFT_UNDEFINED
,
1852 .jitter
= LFT_UNDEFINED
,
1858 proposal_t
*proposal
;
1859 traffic_selector_t
*ts
;
1861 if (!message
->parse(message
, ctx
, NULL
, child_kv
, child_li
, &child
))
1863 free_child_data(&child
);
1867 if (child
.local_ts
->get_count(child
.local_ts
) == 0)
1869 child
.local_ts
->insert_last(child
.local_ts
,
1870 traffic_selector_create_dynamic(0, 0, 65535));
1872 if (child
.remote_ts
->get_count(child
.remote_ts
) == 0)
1874 child
.remote_ts
->insert_last(child
.remote_ts
,
1875 traffic_selector_create_dynamic(0, 0, 65535));
1877 if (child
.proposals
->get_count(child
.proposals
) == 0)
1879 proposal
= proposal_create_default(PROTO_ESP
);
1882 child
.proposals
->insert_last(child
.proposals
, proposal
);
1884 proposal
= proposal_create_default_aead(PROTO_ESP
);
1887 child
.proposals
->insert_last(child
.proposals
, proposal
);
1891 check_lifetimes(&child
.cfg
.lifetime
);
1893 log_child_data(&child
, name
);
1895 cfg
= child_cfg_create(name
, &child
.cfg
);
1897 if (child
.replay_window
!= REPLAY_UNDEFINED
)
1899 cfg
->set_replay_window(cfg
, child
.replay_window
);
1901 while (child
.local_ts
->remove_first(child
.local_ts
,
1902 (void**)&ts
) == SUCCESS
)
1904 cfg
->add_traffic_selector(cfg
, TRUE
, ts
);
1906 while (child
.remote_ts
->remove_first(child
.remote_ts
,
1907 (void**)&ts
) == SUCCESS
)
1909 cfg
->add_traffic_selector(cfg
, FALSE
, ts
);
1911 while (child
.proposals
->remove_first(child
.proposals
,
1912 (void**)&proposal
) == SUCCESS
)
1914 cfg
->add_proposal(cfg
, proposal
);
1917 peer
->children
->insert_last(peer
->children
, cfg
);
1919 free_child_data(&child
);
1924 CALLBACK(peer_sn
, bool,
1925 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1928 if (strcaseeq(name
, "children"))
1930 return message
->parse(message
, ctx
, children_sn
, NULL
, NULL
, peer
);
1932 if (strcasepfx(name
, "local") ||
1933 strcasepfx(name
, "remote"))
1935 enumerator_t
*enumerator
;
1936 linked_list_t
*auths
;
1937 auth_data_t
*auth
, *current
;
1939 certificate_t
*cert
;
1940 pubkey_cert_t
*pubkey_cert
;
1941 identification_t
*id
;
1942 bool default_id
= FALSE
;
1945 .request
= peer
->request
,
1946 .cfg
= auth_cfg_create(),
1949 if (!message
->parse(message
, ctx
, auth_sn
, auth_kv
, auth_li
, auth
))
1951 free_auth_data(auth
);
1954 id
= auth
->cfg
->get(auth
->cfg
, AUTH_RULE_IDENTITY
);
1956 enumerator
= auth
->cfg
->create_enumerator(auth
->cfg
);
1957 while (enumerator
->enumerate(enumerator
, &rule
, &cert
))
1959 if (rule
== AUTH_RULE_SUBJECT_CERT
&& !default_id
)
1963 id
= cert
->get_subject(cert
);
1964 DBG1(DBG_CFG
, " id not specified, defaulting to"
1965 " cert subject '%Y'", id
);
1966 auth
->cfg
->add(auth
->cfg
, AUTH_RULE_IDENTITY
, id
->clone(id
));
1969 else if (cert
->get_type(cert
) == CERT_TRUSTED_PUBKEY
&&
1970 id
->get_type
!= ID_ANY
)
1972 /* set the subject of all raw public keys to the id */
1973 pubkey_cert
= (pubkey_cert_t
*)cert
;
1974 pubkey_cert
->set_subject(pubkey_cert
, id
);
1978 enumerator
->destroy(enumerator
);
1980 auths
= strcasepfx(name
, "local") ? peer
->local
: peer
->remote
;
1981 enumerator
= auths
->create_enumerator(auths
);
1982 while (enumerator
->enumerate(enumerator
, ¤t
))
1984 if (auth
->round
< current
->round
)
1989 auths
->insert_before(auths
, enumerator
, auth
);
1990 enumerator
->destroy(enumerator
);
1993 peer
->request
->reply
= create_reply("invalid section: %s", name
);
1998 * Perform start actions associated with a child config
2000 static void run_start_action(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
,
2001 child_cfg_t
*child_cfg
)
2003 switch (child_cfg
->get_start_action(child_cfg
))
2005 case ACTION_RESTART
:
2006 DBG1(DBG_CFG
, "initiating '%s'", child_cfg
->get_name(child_cfg
));
2007 charon
->controller
->initiate(charon
->controller
,
2008 peer_cfg
->get_ref(peer_cfg
), child_cfg
->get_ref(child_cfg
),
2009 NULL
, NULL
, 0, FALSE
);
2012 DBG1(DBG_CFG
, "installing '%s'", child_cfg
->get_name(child_cfg
));
2013 switch (child_cfg
->get_mode(child_cfg
))
2017 charon
->shunts
->install(charon
->shunts
,
2018 peer_cfg
->get_name(peer_cfg
), child_cfg
);
2021 charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
);
2031 * Undo start actions associated with a child config
2033 static void clear_start_action(private_vici_config_t
*this, char *peer_name
,
2034 child_cfg_t
*child_cfg
)
2036 enumerator_t
*enumerator
, *children
;
2037 child_sa_t
*child_sa
;
2039 uint32_t id
= 0, others
;
2040 array_t
*ids
= NULL
, *ikeids
= NULL
;
2043 name
= child_cfg
->get_name(child_cfg
);
2045 switch (child_cfg
->get_start_action(child_cfg
))
2047 case ACTION_RESTART
:
2048 enumerator
= charon
->controller
->create_ike_sa_enumerator(
2049 charon
->controller
, TRUE
);
2050 while (enumerator
->enumerate(enumerator
, &ike_sa
))
2052 if (!streq(ike_sa
->get_name(ike_sa
), peer_name
))
2057 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
2058 while (children
->enumerate(children
, &child_sa
))
2060 if (child_sa
->get_state(child_sa
) != CHILD_DELETING
&&
2061 child_sa
->get_state(child_sa
) != CHILD_DELETED
)
2063 if (streq(name
, child_sa
->get_name(child_sa
)))
2065 id
= child_sa
->get_unique_id(child_sa
);
2073 children
->destroy(children
);
2077 /* found matching children only, delete full IKE_SA */
2078 id
= ike_sa
->get_unique_id(ike_sa
);
2079 array_insert_create_value(&ikeids
, sizeof(id
),
2084 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
2085 while (children
->enumerate(children
, &child_sa
))
2087 if (streq(name
, child_sa
->get_name(child_sa
)))
2089 id
= child_sa
->get_unique_id(child_sa
);
2090 array_insert_create_value(&ids
, sizeof(id
),
2094 children
->destroy(children
);
2097 enumerator
->destroy(enumerator
);
2099 if (array_count(ids
))
2101 while (array_remove(ids
, ARRAY_HEAD
, &id
))
2103 DBG1(DBG_CFG
, "closing '%s' #%u", name
, id
);
2104 charon
->controller
->terminate_child(charon
->controller
,
2109 if (array_count(ikeids
))
2111 while (array_remove(ikeids
, ARRAY_HEAD
, &id
))
2113 DBG1(DBG_CFG
, "closing IKE_SA #%u", id
);
2114 charon
->controller
->terminate_ike(charon
->controller
, FALSE
,
2117 array_destroy(ikeids
);
2121 DBG1(DBG_CFG
, "uninstalling '%s'", name
);
2122 switch (child_cfg
->get_mode(child_cfg
))
2126 charon
->shunts
->uninstall(charon
->shunts
, peer_name
, name
);
2129 charon
->traps
->uninstall(charon
->traps
, peer_name
, name
);
2139 * Run or undo a start actions associated with a child config
2141 static void handle_start_action(private_vici_config_t
*this,
2142 peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
2145 this->handling_actions
= TRUE
;
2146 this->lock
->unlock(this->lock
);
2150 clear_start_action(this, peer_cfg
->get_name(peer_cfg
), child_cfg
);
2154 run_start_action(this, peer_cfg
, child_cfg
);
2157 this->lock
->write_lock(this->lock
);
2158 this->handling_actions
= FALSE
;
2162 * Run or undo start actions associated with all child configs of a peer config
2164 static void handle_start_actions(private_vici_config_t
*this,
2165 peer_cfg_t
*peer_cfg
, bool undo
)
2167 enumerator_t
*enumerator
;
2168 child_cfg_t
*child_cfg
;
2170 this->handling_actions
= TRUE
;
2171 this->lock
->unlock(this->lock
);
2173 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
2174 while (enumerator
->enumerate(enumerator
, &child_cfg
))
2178 clear_start_action(this, peer_cfg
->get_name(peer_cfg
), child_cfg
);
2182 run_start_action(this, peer_cfg
, child_cfg
);
2185 enumerator
->destroy(enumerator
);
2187 this->lock
->write_lock(this->lock
);
2188 this->handling_actions
= FALSE
;
2192 * Replace children of a peer config by a new config
2194 static void replace_children(private_vici_config_t
*this,
2195 peer_cfg_t
*from
, peer_cfg_t
*to
)
2197 enumerator_t
*enumerator
;
2201 enumerator
= to
->replace_child_cfgs(to
, from
);
2202 while (enumerator
->enumerate(enumerator
, &child
, &added
))
2204 handle_start_action(this, to
, child
, !added
);
2206 enumerator
->destroy(enumerator
);
2210 * Merge/replace a peer config with existing configs
2212 static void merge_config(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
)
2214 enumerator_t
*enumerator
;
2215 peer_cfg_t
*current
;
2217 bool merged
= FALSE
;
2219 this->lock
->write_lock(this->lock
);
2220 while (this->handling_actions
)
2222 this->condvar
->wait(this->condvar
, this->lock
);
2225 enumerator
= this->conns
->create_enumerator(this->conns
);
2226 while (enumerator
->enumerate(enumerator
, ¤t
))
2228 if (streq(peer_cfg
->get_name(peer_cfg
), current
->get_name(current
)))
2230 ike_cfg
= current
->get_ike_cfg(current
);
2231 if (peer_cfg
->equals(peer_cfg
, current
) &&
2232 ike_cfg
->equals(ike_cfg
, peer_cfg
->get_ike_cfg(peer_cfg
)))
2234 DBG1(DBG_CFG
, "updated vici connection: %s",
2235 peer_cfg
->get_name(peer_cfg
));
2236 replace_children(this, peer_cfg
, current
);
2237 peer_cfg
->destroy(peer_cfg
);
2241 DBG1(DBG_CFG
, "replaced vici connection: %s",
2242 peer_cfg
->get_name(peer_cfg
));
2243 this->conns
->insert_before(this->conns
, enumerator
, peer_cfg
);
2244 this->conns
->remove_at(this->conns
, enumerator
);
2245 handle_start_actions(this, current
, TRUE
);
2246 handle_start_actions(this, peer_cfg
, FALSE
);
2247 current
->destroy(current
);
2253 enumerator
->destroy(enumerator
);
2257 DBG1(DBG_CFG
, "added vici connection: %s", peer_cfg
->get_name(peer_cfg
));
2258 this->conns
->insert_last(this->conns
, peer_cfg
);
2259 handle_start_actions(this, peer_cfg
, FALSE
);
2261 this->condvar
->signal(this->condvar
);
2262 this->lock
->unlock(this->lock
);
2265 CALLBACK(config_sn
, bool,
2266 request_data_t
*request
, vici_message_t
*message
,
2267 vici_parse_context_t
*ctx
, char *name
)
2269 peer_data_t peer
= {
2271 .local
= linked_list_create(),
2272 .remote
= linked_list_create(),
2273 .vips
= linked_list_create(),
2274 .children
= linked_list_create(),
2275 .proposals
= linked_list_create(),
2277 .send_certreq
= TRUE
,
2279 .send_cert
= CERT_SEND_IF_ASKED
,
2281 .remote_port
= IKEV2_UDP_PORT
,
2282 .fragmentation
= FRAGMENTATION_YES
,
2283 .unique
= UNIQUE_NO
,
2285 .rekey_time
= LFT_UNDEFINED
,
2286 .reauth_time
= LFT_UNDEFINED
,
2287 .over_time
= LFT_UNDEFINED
,
2288 .rand_time
= LFT_UNDEFINED
,
2290 enumerator_t
*enumerator
;
2291 peer_cfg_create_t cfg
;
2292 peer_cfg_t
*peer_cfg
;
2294 child_cfg_t
*child_cfg
;
2296 proposal_t
*proposal
;
2300 DBG2(DBG_CFG
, " conn %s:", name
);
2302 if (!message
->parse(message
, ctx
, peer_sn
, peer_kv
, peer_li
, &peer
))
2304 free_peer_data(&peer
);
2308 if (peer
.local
->get_count(peer
.local
) == 0)
2311 .cfg
= auth_cfg_create(),
2313 peer
.local
->insert_last(peer
.local
, auth
);
2315 if (peer
.remote
->get_count(peer
.remote
) == 0)
2318 .cfg
= auth_cfg_create(),
2320 peer
.remote
->insert_last(peer
.remote
, auth
);
2322 if (peer
.proposals
->get_count(peer
.proposals
) == 0)
2324 proposal
= proposal_create_default(PROTO_IKE
);
2327 peer
.proposals
->insert_last(peer
.proposals
, proposal
);
2329 proposal
= proposal_create_default_aead(PROTO_IKE
);
2332 peer
.proposals
->insert_last(peer
.proposals
, proposal
);
2335 if (!peer
.local_addrs
)
2337 peer
.local_addrs
= strdup("%any");
2339 if (!peer
.remote_addrs
)
2341 peer
.remote_addrs
= strdup("%any");
2343 if (!peer
.local_port
)
2345 peer
.local_port
= charon
->socket
->get_port(charon
->socket
, FALSE
);
2348 if (peer
.rekey_time
== LFT_UNDEFINED
&& peer
.reauth_time
== LFT_UNDEFINED
)
2350 /* apply a default rekey time if no rekey/reauth time set */
2351 peer
.rekey_time
= LFT_DEFAULT_IKE_REKEY_TIME
;
2352 peer
.reauth_time
= 0;
2354 if (peer
.rekey_time
== LFT_UNDEFINED
)
2356 peer
.rekey_time
= 0;
2358 if (peer
.reauth_time
== LFT_UNDEFINED
)
2360 peer
.reauth_time
= 0;
2362 if (peer
.over_time
== LFT_UNDEFINED
)
2364 /* default over_time to 10% of rekey/reauth time if not given */
2365 peer
.over_time
= max(peer
.rekey_time
, peer
.reauth_time
) / 10;
2367 if (peer
.rand_time
== LFT_UNDEFINED
)
2369 /* default rand_time to over_time if not given, but don't make it
2370 * longer than half of rekey/rauth time */
2371 if (peer
.rekey_time
&& peer
.reauth_time
)
2373 peer
.rand_time
= min(peer
.rekey_time
, peer
.reauth_time
);
2377 peer
.rand_time
= max(peer
.rekey_time
, peer
.reauth_time
);
2379 peer
.rand_time
= min(peer
.over_time
, peer
.rand_time
/ 2);
2383 if (peer
.mediation
&& peer
.mediated_by
)
2385 DBG1(DBG_CFG
, "a mediation connection cannot be a mediated connection "
2386 "at the same time, config discarded");
2387 free_peer_data(&peer
);
2391 { /* force unique connections for mediation connections */
2392 peer
.unique
= UNIQUE_REPLACE
;
2394 else if (peer
.mediated_by
)
2395 { /* fallback to remote identity of first auth round if peer_id is not
2396 * given explicitly */
2399 if (!peer
.peer_id
&&
2400 peer
.remote
->get_first(peer
.remote
, (void**)&cfg
) == SUCCESS
)
2402 peer
.peer_id
= cfg
->get(cfg
, AUTH_RULE_IDENTITY
);
2405 peer
.peer_id
= peer
.peer_id
->clone(peer
.peer_id
);
2409 DBG1(DBG_CFG
, "mediation peer missing for mediated connection, "
2410 "config discarded");
2411 free_peer_data(&peer
);
2418 log_peer_data(&peer
);
2420 ike_cfg
= ike_cfg_create(peer
.version
, peer
.send_certreq
, peer
.encap
,
2421 peer
.local_addrs
, peer
.local_port
,
2422 peer
.remote_addrs
, peer
.remote_port
,
2423 peer
.fragmentation
, peer
.dscp
);
2425 cfg
= (peer_cfg_create_t
){
2426 .cert_policy
= peer
.send_cert
,
2427 .unique
= peer
.unique
,
2428 .keyingtries
= peer
.keyingtries
,
2429 .rekey_time
= peer
.rekey_time
,
2430 .reauth_time
= peer
.reauth_time
,
2431 .jitter_time
= peer
.rand_time
,
2432 .over_time
= peer
.over_time
,
2433 .no_mobike
= !peer
.mobike
,
2434 .aggressive
= peer
.aggressive
,
2435 .push_mode
= !peer
.pull
,
2436 .dpd
= peer
.dpd_delay
,
2437 .dpd_timeout
= peer
.dpd_timeout
,
2440 cfg
.mediation
= peer
.mediation
;
2441 if (peer
.mediated_by
)
2443 cfg
.mediated_by
= peer
.mediated_by
;
2444 cfg
.peer_id
= peer
.peer_id
->clone(peer
.peer_id
);
2447 peer_cfg
= peer_cfg_create(name
, ike_cfg
, &cfg
);
2449 while (peer
.local
->remove_first(peer
.local
,
2450 (void**)&auth
) == SUCCESS
)
2452 peer_cfg
->add_auth_cfg(peer_cfg
, auth
->cfg
, TRUE
);
2454 free_auth_data(auth
);
2456 while (peer
.remote
->remove_first(peer
.remote
,
2457 (void**)&auth
) == SUCCESS
)
2459 peer_cfg
->add_auth_cfg(peer_cfg
, auth
->cfg
, FALSE
);
2461 free_auth_data(auth
);
2463 while (peer
.children
->remove_first(peer
.children
,
2464 (void**)&child_cfg
) == SUCCESS
)
2466 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
2468 while (peer
.proposals
->remove_first(peer
.proposals
,
2469 (void**)&proposal
) == SUCCESS
)
2471 ike_cfg
->add_proposal(ike_cfg
, proposal
);
2473 while (peer
.vips
->remove_first(peer
.vips
, (void**)&host
) == SUCCESS
)
2475 peer_cfg
->add_virtual_ip(peer_cfg
, host
);
2479 enumerator
= enumerator_create_token(peer
.pools
, ",", " ");
2480 while (enumerator
->enumerate(enumerator
, &str
))
2482 peer_cfg
->add_pool(peer_cfg
, str
);
2484 enumerator
->destroy(enumerator
);
2487 free_peer_data(&peer
);
2489 merge_config(request
->this, peer_cfg
);
2494 CALLBACK(load_conn
, vici_message_t
*,
2495 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2497 request_data_t request
= {
2501 if (!message
->parse(message
, NULL
, config_sn
, NULL
, NULL
, &request
))
2505 return request
.reply
;
2507 return create_reply("parsing request failed");
2509 return create_reply(NULL
);
2512 CALLBACK(unload_conn
, vici_message_t
*,
2513 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2515 enumerator_t
*enumerator
;
2520 conn_name
= message
->get_str(message
, NULL
, "name");
2523 return create_reply("unload: missing connection name");
2526 this->lock
->write_lock(this->lock
);
2527 while (this->handling_actions
)
2529 this->condvar
->wait(this->condvar
, this->lock
);
2531 enumerator
= this->conns
->create_enumerator(this->conns
);
2532 while (enumerator
->enumerate(enumerator
, &cfg
))
2534 if (streq(cfg
->get_name(cfg
), conn_name
))
2536 this->conns
->remove_at(this->conns
, enumerator
);
2537 handle_start_actions(this, cfg
, TRUE
);
2543 enumerator
->destroy(enumerator
);
2544 this->condvar
->signal(this->condvar
);
2545 this->lock
->unlock(this->lock
);
2549 return create_reply("unload: connection '%s' not found", conn_name
);
2551 return create_reply(NULL
);
2554 CALLBACK(get_conns
, vici_message_t
*,
2555 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2557 vici_builder_t
*builder
;
2558 enumerator_t
*enumerator
;
2561 builder
= vici_builder_create();
2562 builder
->begin_list(builder
, "conns");
2564 this->lock
->read_lock(this->lock
);
2565 enumerator
= this->conns
->create_enumerator(this->conns
);
2566 while (enumerator
->enumerate(enumerator
, &cfg
))
2568 builder
->add_li(builder
, "%s", cfg
->get_name(cfg
));
2570 enumerator
->destroy(enumerator
);
2571 this->lock
->unlock(this->lock
);
2573 builder
->end_list(builder
);
2575 return builder
->finalize(builder
);
2578 static void manage_command(private_vici_config_t
*this,
2579 char *name
, vici_command_cb_t cb
, bool reg
)
2581 this->dispatcher
->manage_command(this->dispatcher
, name
,
2582 reg ? cb
: NULL
, this);
2586 * (Un-)register dispatcher functions
2588 static void manage_commands(private_vici_config_t
*this, bool reg
)
2590 manage_command(this, "load-conn", load_conn
, reg
);
2591 manage_command(this, "unload-conn", unload_conn
, reg
);
2592 manage_command(this, "get-conns", get_conns
, reg
);
2595 METHOD(vici_config_t
, destroy
, void,
2596 private_vici_config_t
*this)
2598 manage_commands(this, FALSE
);
2599 this->conns
->destroy_offset(this->conns
, offsetof(peer_cfg_t
, destroy
));
2600 this->condvar
->destroy(this->condvar
);
2601 this->lock
->destroy(this->lock
);
2608 vici_config_t
*vici_config_create(vici_dispatcher_t
*dispatcher
,
2609 vici_authority_t
*authority
,
2612 private_vici_config_t
*this;
2617 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
2618 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
2619 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
2621 .destroy
= _destroy
,
2623 .dispatcher
= dispatcher
,
2624 .conns
= linked_list_create(),
2625 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
2626 .condvar
= rwlock_condvar_create(),
2627 .authority
= authority
,
2631 manage_commands(this, TRUE
);
2633 return &this->public;