2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
5 * Copyright (C) 2015 Andreas Steffen
6 * HSR Hochschule fuer Technik Rapperswil
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>.
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
20 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
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:
29 * The above copyright notice and this permission notice shall be included in
30 * all copies or substantial portions of the Software.
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
43 #include "vici_config.h"
44 #include "vici_builder.h"
47 #include <threading/rwlock.h>
48 #include <collections/array.h>
49 #include <collections/linked_list.h>
54 * Magic value for an undefined lifetime
56 #define LFT_UNDEFINED (~(u_int64_t)0)
59 * Default IKE rekey time
61 #define LFT_DEFAULT_IKE_REKEY (4 * 60 * 60)
64 * Default CHILD rekey time
66 #define LFT_DEFAULT_CHILD_REKEY (1 * 60 * 60)
69 * Undefined replay window
71 #define REPLAY_UNDEFINED (~(u_int32_t)0)
73 typedef struct private_vici_config_t private_vici_config_t
;
76 * Private data of an vici_config_t object.
78 struct private_vici_config_t
{
81 * Public vici_config_t interface.
88 vici_dispatcher_t
*dispatcher
;
91 * List of loaded connections, as peer_cfg_t
101 * Auxiliary certification authority information
103 vici_authority_t
*authority
;
107 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
108 private_vici_config_t
*this, identification_t
*me
, identification_t
*other
)
110 this->lock
->read_lock(this->lock
);
111 return enumerator_create_cleaner(this->conns
->create_enumerator(this->conns
),
112 (void*)this->lock
->unlock
, this->lock
);
116 * Enumerator filter function for ike configs
118 static bool ike_filter(void *data
, peer_cfg_t
**in
, ike_cfg_t
**out
)
120 *out
= (*in
)->get_ike_cfg(*in
);
124 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
125 private_vici_config_t
*this, host_t
*me
, host_t
*other
)
127 this->lock
->read_lock(this->lock
);
128 return enumerator_create_filter(this->conns
->create_enumerator(this->conns
),
129 (void*)ike_filter
, this->lock
,
130 (void*)this->lock
->unlock
);
133 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
134 private_vici_config_t
*this, char *name
)
136 peer_cfg_t
*current
, *found
= NULL
;
137 enumerator_t
*enumerator
;
139 this->lock
->read_lock(this->lock
);
140 enumerator
= this->conns
->create_enumerator(this->conns
);
141 while (enumerator
->enumerate(enumerator
, ¤t
))
143 if (streq(current
->get_name(current
), name
))
146 found
->get_ref(found
);
150 enumerator
->destroy(enumerator
);
151 this->lock
->unlock(this->lock
);
157 * Create a (error) reply message
159 static vici_message_t
* create_reply(char *fmt
, ...)
161 vici_builder_t
*builder
;
164 builder
= vici_builder_create();
165 builder
->add_kv(builder
, "success", fmt
? "no" : "yes");
169 builder
->vadd_kv(builder
, "errmsg", fmt
, args
);
172 return builder
->finalize(builder
);
176 * A rule to parse a key/value or list item
179 /** name of the key/value or list */
181 /** function to parse value */
182 bool (*parse
)(void *out
, chunk_t value
);
183 /** result, passed to parse() */
188 * Parse key/values using a rule-set
190 static bool parse_rules(parse_rule_t
*rules
, int count
, char *name
,
191 chunk_t value
, vici_message_t
**reply
)
195 for (i
= 0; i
< count
; i
++)
197 if (streq(name
, rules
[i
].name
))
199 if (rules
[i
].parse(rules
[i
].out
, value
))
203 *reply
= create_reply("invalid value for: %s, config discarded",
208 *reply
= create_reply("unknown option: %s, config discarded", name
);
213 * Parse callback data, passed to each callback
216 private_vici_config_t
*this;
217 vici_message_t
*reply
;
221 * Data associated to a peer config
224 request_data_t
*request
;
231 cert_policy_t send_cert
;
233 u_int64_t dpd_timeout
;
234 fragmentation_t fragmentation
;
235 unique_policy_t unique
;
236 u_int32_t keyingtries
;
237 u_int32_t local_port
;
238 u_int32_t remote_port
;
241 linked_list_t
*local
;
242 linked_list_t
*remote
;
243 linked_list_t
*proposals
;
244 linked_list_t
*children
;
247 u_int64_t reauth_time
;
248 u_int64_t rekey_time
;
254 * Log relevant auth config data
256 static void log_auth(auth_cfg_t
*auth
)
258 enumerator_t
*enumerator
;
262 identification_t
*id
;
266 enumerator
= auth
->create_enumerator(auth
);
267 while (enumerator
->enumerate(enumerator
, &rule
, &v
))
271 case AUTH_RULE_AUTH_CLASS
:
272 DBG2(DBG_CFG
, " class = %N", auth_class_names
, v
.u
);
274 case AUTH_RULE_EAP_TYPE
:
275 DBG2(DBG_CFG
, " eap-type = %N", eap_type_names
, v
.u
);
277 case AUTH_RULE_EAP_VENDOR
:
278 DBG2(DBG_CFG
, " eap-vendor = %u", v
.u
);
280 case AUTH_RULE_XAUTH_BACKEND
:
281 DBG2(DBG_CFG
, " xauth = %s", v
.str
);
283 case AUTH_RULE_CRL_VALIDATION
:
284 DBG2(DBG_CFG
, " revocation = %N", cert_validation_names
, v
.u
);
286 case AUTH_RULE_IDENTITY
:
287 DBG2(DBG_CFG
, " id = %Y", v
.id
);
289 case AUTH_RULE_AAA_IDENTITY
:
290 DBG2(DBG_CFG
, " aaa_id = %Y", v
.id
);
292 case AUTH_RULE_EAP_IDENTITY
:
293 DBG2(DBG_CFG
, " eap_id = %Y", v
.id
);
295 case AUTH_RULE_XAUTH_IDENTITY
:
296 DBG2(DBG_CFG
, " xauth_id = %Y", v
.id
);
298 case AUTH_RULE_GROUP
:
299 DBG2(DBG_CFG
, " group = %Y", v
.id
);
305 enumerator
->destroy(enumerator
);
309 * Log parsed peer data
311 static void log_peer_data(peer_data_t
*data
)
313 enumerator_t
*enumerator
;
317 DBG2(DBG_CFG
, " version = %u", data
->version
);
318 DBG2(DBG_CFG
, " local_addrs = %s", data
->local_addrs
);
319 DBG2(DBG_CFG
, " remote_addrs = %s", data
->remote_addrs
);
320 DBG2(DBG_CFG
, " local_port = %u", data
->local_port
);
321 DBG2(DBG_CFG
, " remote_port = %u", data
->remote_port
);
322 DBG2(DBG_CFG
, " send_certreq = %u", data
->send_certreq
);
323 DBG2(DBG_CFG
, " send_cert = %N", cert_policy_names
, data
->send_cert
);
324 DBG2(DBG_CFG
, " mobike = %u", data
->mobike
);
325 DBG2(DBG_CFG
, " aggressive = %u", data
->aggressive
);
326 DBG2(DBG_CFG
, " encap = %u", data
->encap
);
327 DBG2(DBG_CFG
, " dpd_delay = %llu", data
->dpd_delay
);
328 DBG2(DBG_CFG
, " dpd_timeout = %llu", data
->dpd_timeout
);
329 DBG2(DBG_CFG
, " fragmentation = %u", data
->fragmentation
);
330 DBG2(DBG_CFG
, " unique = %N", unique_policy_names
, data
->unique
);
331 DBG2(DBG_CFG
, " keyingtries = %u", data
->keyingtries
);
332 DBG2(DBG_CFG
, " reauth_time = %llu", data
->reauth_time
);
333 DBG2(DBG_CFG
, " rekey_time = %llu", data
->rekey_time
);
334 DBG2(DBG_CFG
, " over_time = %llu", data
->over_time
);
335 DBG2(DBG_CFG
, " rand_time = %llu", data
->rand_time
);
336 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
338 if (data
->vips
->get_count(data
->vips
))
340 DBG2(DBG_CFG
, " vips:");
342 enumerator
= data
->vips
->create_enumerator(data
->vips
);
343 while (enumerator
->enumerate(enumerator
, &host
))
345 DBG2(DBG_CFG
, " %H", host
);
347 enumerator
->destroy(enumerator
);
349 enumerator
= data
->local
->create_enumerator(data
->local
);
350 while (enumerator
->enumerate(enumerator
, &auth
))
352 DBG2(DBG_CFG
, " local:");
355 enumerator
->destroy(enumerator
);
357 enumerator
= data
->remote
->create_enumerator(data
->remote
);
358 while (enumerator
->enumerate(enumerator
, &auth
))
360 DBG2(DBG_CFG
, " remote:");
363 enumerator
->destroy(enumerator
);
367 * Clean up peer config data
369 static void free_peer_data(peer_data_t
*data
)
371 data
->local
->destroy_offset(data
->local
,
372 offsetof(auth_cfg_t
, destroy
));
373 data
->remote
->destroy_offset(data
->remote
,
374 offsetof(auth_cfg_t
, destroy
));
375 data
->children
->destroy_offset(data
->children
,
376 offsetof(child_cfg_t
, destroy
));
377 data
->proposals
->destroy_offset(data
->proposals
,
378 offsetof(proposal_t
, destroy
));
379 data
->vips
->destroy_offset(data
->vips
, offsetof(host_t
, destroy
));
381 free(data
->local_addrs
);
382 free(data
->remote_addrs
);
389 request_data_t
*request
;
396 u_int32_t replay_window
;
398 action_t start_action
;
399 action_t close_action
;
404 u_int64_t inactivity
;
405 linked_list_t
*proposals
;
406 linked_list_t
*local_ts
;
407 linked_list_t
*remote_ts
;
411 * Log parsed CHILD config data
413 static void log_child_data(child_data_t
*data
, char *name
)
415 DBG2(DBG_CFG
, " child %s:", name
);
416 DBG2(DBG_CFG
, " rekey_time = %llu", data
->lft
.time
.rekey
);
417 DBG2(DBG_CFG
, " life_time = %llu", data
->lft
.time
.life
);
418 DBG2(DBG_CFG
, " rand_time = %llu", data
->lft
.time
.jitter
);
419 DBG2(DBG_CFG
, " rekey_bytes = %llu", data
->lft
.bytes
.rekey
);
420 DBG2(DBG_CFG
, " life_bytes = %llu", data
->lft
.bytes
.life
);
421 DBG2(DBG_CFG
, " rand_bytes = %llu", data
->lft
.bytes
.jitter
);
422 DBG2(DBG_CFG
, " rekey_packets = %llu", data
->lft
.packets
.rekey
);
423 DBG2(DBG_CFG
, " life_packets = %llu", data
->lft
.packets
.life
);
424 DBG2(DBG_CFG
, " rand_packets = %llu", data
->lft
.packets
.jitter
);
425 DBG2(DBG_CFG
, " updown = %s", data
->updown
);
426 DBG2(DBG_CFG
, " hostaccess = %u", data
->hostaccess
);
427 DBG2(DBG_CFG
, " ipcomp = %u", data
->ipcomp
);
428 DBG2(DBG_CFG
, " mode = %N", ipsec_mode_names
, data
->mode
);
429 DBG2(DBG_CFG
, " policies = %u", data
->policies
);
430 if (data
->replay_window
!= REPLAY_UNDEFINED
)
432 DBG2(DBG_CFG
, " replay_window = %u", data
->replay_window
);
434 DBG2(DBG_CFG
, " dpd_action = %N", action_names
, data
->dpd_action
);
435 DBG2(DBG_CFG
, " start_action = %N", action_names
, data
->start_action
);
436 DBG2(DBG_CFG
, " close_action = %N", action_names
, data
->close_action
);
437 DBG2(DBG_CFG
, " reqid = %u", data
->reqid
);
438 DBG2(DBG_CFG
, " tfc = %d", data
->tfc
);
439 DBG2(DBG_CFG
, " mark_in = %u/%u",
440 data
->mark_in
.value
, data
->mark_in
.mask
);
441 DBG2(DBG_CFG
, " mark_out = %u/%u",
442 data
->mark_out
.value
, data
->mark_out
.mask
);
443 DBG2(DBG_CFG
, " inactivity = %llu", data
->inactivity
);
444 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
445 DBG2(DBG_CFG
, " local_ts = %#R", data
->local_ts
);
446 DBG2(DBG_CFG
, " remote_ts = %#R", data
->remote_ts
);
450 * Clean up CHILD config data
452 static void free_child_data(child_data_t
*data
)
454 data
->proposals
->destroy_offset(data
->proposals
,
455 offsetof(proposal_t
, destroy
));
456 data
->local_ts
->destroy_offset(data
->local_ts
,
457 offsetof(traffic_selector_t
, destroy
));
458 data
->remote_ts
->destroy_offset(data
->remote_ts
,
459 offsetof(traffic_selector_t
, destroy
));
467 request_data_t
*request
;
472 * Common proposal parsing
474 static bool parse_proposal(linked_list_t
*list
, protocol_id_t proto
, chunk_t v
)
477 proposal_t
*proposal
;
479 if (!vici_stringify(v
, buf
, sizeof(buf
)))
483 if (strcaseeq("default", buf
))
485 proposal
= proposal_create_default(proto
);
488 list
->insert_last(list
, proposal
);
490 proposal
= proposal_create_default_aead(proto
);
493 list
->insert_last(list
, proposal
);
497 proposal
= proposal_create_from_string(proto
, buf
);
500 list
->insert_last(list
, proposal
);
509 CALLBACK(parse_ike_proposal
, bool,
510 linked_list_t
*out
, chunk_t v
)
512 return parse_proposal(out
, PROTO_IKE
, v
);
518 CALLBACK(parse_esp_proposal
, bool,
519 linked_list_t
*out
, chunk_t v
)
521 return parse_proposal(out
, PROTO_ESP
, v
);
527 CALLBACK(parse_ah_proposal
, bool,
528 linked_list_t
*out
, chunk_t v
)
530 return parse_proposal(out
, PROTO_AH
, v
);
534 * Parse a traffic selector
536 CALLBACK(parse_ts
, bool,
537 linked_list_t
*out
, chunk_t v
)
539 char buf
[128], *protoport
, *sep
, *port
= "", *end
;
540 traffic_selector_t
*ts
;
541 struct protoent
*protoent
;
544 u_int16_t from
= 0, to
= 0xffff;
547 if (!vici_stringify(v
, buf
, sizeof(buf
)))
552 protoport
= strchr(buf
, '[');
555 *(protoport
++) = '\0';
557 sep
= strrchr(protoport
, ']');
564 sep
= strchr(protoport
, '/');
566 { /* protocol/port */
571 if (streq(protoport
, "any"))
577 protoent
= getprotobyname(protoport
);
580 proto
= protoent
->p_proto
;
584 p
= strtol(protoport
, &end
, 0);
585 if ((*protoport
&& *end
) || p
< 0 || p
> 0xff)
592 if (streq(port
, "opaque"))
597 else if (*port
&& !streq(port
, "any"))
599 svc
= getservbyname(port
, NULL
);
602 from
= to
= ntohs(svc
->s_port
);
606 p
= strtol(port
, &end
, 0);
607 if (p
< 0 || p
> 0xffff)
615 p
= strtol(port
, &end
, 0);
616 if (p
< 0 || p
> 0xffff)
629 if (streq(buf
, "dynamic"))
631 ts
= traffic_selector_create_dynamic(proto
, from
, to
);
635 ts
= traffic_selector_create_from_cidr(buf
, proto
, from
, to
);
641 out
->insert_last(out
, ts
);
648 CALLBACK(parse_string
, bool,
649 char **out
, chunk_t v
)
651 if (!chunk_printable(v
, NULL
, ' '))
657 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
665 * Map a string to an integer
673 * Parse a string to an integer mapping
675 static bool parse_map(enum_map_t
*map
, int count
, int *out
, chunk_t v
)
680 if (!vici_stringify(v
, buf
, sizeof(buf
)))
684 for (i
= 0; i
< count
; i
++)
686 if (strcaseeq(map
[i
].str
, buf
))
698 CALLBACK(parse_bool
, bool,
699 bool *out
, chunk_t v
)
708 { "disabled", FALSE
},
713 if (parse_map(map
, countof(map
), &d
, v
))
722 * Parse a ipsec_mode_t
724 CALLBACK(parse_mode
, bool,
725 ipsec_mode_t
*out
, chunk_t v
)
728 { "tunnel", MODE_TUNNEL
},
729 { "transport", MODE_TRANSPORT
},
730 { "beet", MODE_BEET
},
731 { "drop", MODE_DROP
},
732 { "pass", MODE_PASS
},
736 if (parse_map(map
, countof(map
), &d
, v
))
747 CALLBACK(parse_action
, bool,
748 action_t
*out
, chunk_t v
)
751 { "start", ACTION_RESTART
},
752 { "restart", ACTION_RESTART
},
753 { "route", ACTION_ROUTE
},
754 { "trap", ACTION_ROUTE
},
755 { "none", ACTION_NONE
},
756 { "clear", ACTION_NONE
},
760 if (parse_map(map
, countof(map
), &d
, v
))
771 CALLBACK(parse_uint32
, bool,
772 u_int32_t
*out
, chunk_t v
)
777 if (!vici_stringify(v
, buf
, sizeof(buf
)))
781 l
= strtoul(buf
, &end
, 0);
793 CALLBACK(parse_uint64
, bool,
794 u_int64_t
*out
, chunk_t v
)
797 unsigned long long l
;
799 if (!vici_stringify(v
, buf
, sizeof(buf
)))
803 l
= strtoull(buf
, &end
, 0);
813 * Parse a relative time
815 CALLBACK(parse_time
, bool,
816 u_int64_t
*out
, chunk_t v
)
821 if (!vici_stringify(v
, buf
, sizeof(buf
)))
826 l
= strtoul(buf
, &end
, 0);
865 CALLBACK(parse_bytes
, bool,
866 u_int64_t
*out
, chunk_t v
)
869 unsigned long long l
;
871 if (!vici_stringify(v
, buf
, sizeof(buf
)))
876 l
= strtoull(buf
, &end
, 0);
912 CALLBACK(parse_mark
, bool,
913 mark_t
*out
, chunk_t v
)
917 if (!vici_stringify(v
, buf
, sizeof(buf
)))
921 return mark_from_string(buf
, out
);
925 * Parse TFC padding option
927 CALLBACK(parse_tfc
, bool,
928 u_int32_t
*out
, chunk_t v
)
930 if (chunk_equals(v
, chunk_from_str("mtu")))
935 return parse_uint32(out
, v
);
939 * Parse authentication config
941 CALLBACK(parse_auth
, bool,
942 auth_cfg_t
*cfg
, chunk_t v
)
945 eap_vendor_type_t
*type
;
947 if (!vici_stringify(v
, buf
, sizeof(buf
)))
951 if (strcaseeq(buf
, "pubkey"))
953 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
956 if (strcaseeq(buf
, "psk"))
958 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PSK
);
961 if (strcasepfx(buf
, "xauth"))
963 pos
= strchr(buf
, '-');
966 cfg
->add(cfg
, AUTH_RULE_XAUTH_BACKEND
, strdup(++pos
));
968 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_XAUTH
);
971 if (strcasepfx(buf
, "eap"))
973 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_EAP
);
975 type
= eap_vendor_type_from_string(buf
);
978 cfg
->add(cfg
, AUTH_RULE_EAP_TYPE
, type
->type
);
981 cfg
->add(cfg
, AUTH_RULE_EAP_VENDOR
, type
->vendor
);
991 * Parse identity; add as auth rule to config
993 static bool parse_id(auth_cfg_t
*cfg
, auth_rule_t rule
, chunk_t v
)
997 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1001 cfg
->add(cfg
, rule
, identification_create_from_string(buf
));
1006 * Parse IKE identity
1008 CALLBACK(parse_ike_id
, bool,
1009 auth_cfg_t
*cfg
, chunk_t v
)
1011 return parse_id(cfg
, AUTH_RULE_IDENTITY
, v
);
1015 * Parse AAA identity
1017 CALLBACK(parse_aaa_id
, bool,
1018 auth_cfg_t
*cfg
, chunk_t v
)
1020 return parse_id(cfg
, AUTH_RULE_AAA_IDENTITY
, v
);
1024 * Parse EAP identity
1026 CALLBACK(parse_eap_id
, bool,
1027 auth_cfg_t
*cfg
, chunk_t v
)
1029 return parse_id(cfg
, AUTH_RULE_EAP_IDENTITY
, v
);
1033 * Parse XAuth identity
1035 CALLBACK(parse_xauth_id
, bool,
1036 auth_cfg_t
*cfg
, chunk_t v
)
1038 return parse_id(cfg
, AUTH_RULE_XAUTH_IDENTITY
, v
);
1042 * Parse group membership
1044 CALLBACK(parse_group
, bool,
1045 auth_cfg_t
*cfg
, chunk_t v
)
1047 return parse_id(cfg
, AUTH_RULE_GROUP
, v
);
1051 * Parse a certificate; add as auth rule to config
1053 static bool parse_cert(auth_data_t
*auth
, auth_rule_t rule
, chunk_t v
)
1055 vici_authority_t
*authority
;
1056 certificate_t
*cert
;
1058 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
1059 BUILD_BLOB_PEM
, v
, BUILD_END
);
1062 if (rule
== AUTH_RULE_SUBJECT_CERT
)
1064 authority
= auth
->request
->this->authority
;
1065 authority
->check_for_hash_and_url(authority
, cert
);
1067 auth
->cfg
->add(auth
->cfg
, rule
, cert
);
1074 * Parse subject certificates
1076 CALLBACK(parse_certs
, bool,
1077 auth_data_t
*auth
, chunk_t v
)
1079 return parse_cert(auth
, AUTH_RULE_SUBJECT_CERT
, v
);
1083 * Parse CA certificates
1085 CALLBACK(parse_cacerts
, bool,
1086 auth_data_t
*auth
, chunk_t v
)
1088 return parse_cert(auth
, AUTH_RULE_CA_CERT
, v
);
1092 * Parse revocation status
1094 CALLBACK(parse_revocation
, bool,
1095 auth_cfg_t
*cfg
, chunk_t v
)
1097 enum_map_t map
[] = {
1098 { "strict", VALIDATION_GOOD
},
1099 { "ifuri", VALIDATION_SKIPPED
},
1100 { "relaxed", VALIDATION_FAILED
},
1104 if (parse_map(map
, countof(map
), &d
, v
))
1106 if (d
!= VALIDATION_FAILED
)
1108 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, d
);
1116 * Parse list items to comma separated strings
1118 CALLBACK(parse_stringlist
, bool,
1119 char **out
, chunk_t v
)
1123 if (!chunk_printable(v
, NULL
, ' '))
1130 if (asprintf(out
, "%s, %.*s", current
, (int)v
.len
, v
.ptr
) == -1)
1138 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
1147 * Parse an fragmentation_t
1149 CALLBACK(parse_frag
, bool,
1150 fragmentation_t
*out
, chunk_t v
)
1152 enum_map_t map
[] = {
1153 { "yes", FRAGMENTATION_YES
},
1154 { "no", FRAGMENTATION_NO
},
1155 { "force", FRAGMENTATION_FORCE
},
1159 if (parse_map(map
, countof(map
), &d
, v
))
1168 * Parse a cert_policy_t
1170 CALLBACK(parse_send_cert
, bool,
1171 cert_policy_t
*out
, chunk_t v
)
1173 enum_map_t map
[] = {
1174 { "ifasked", CERT_SEND_IF_ASKED
},
1175 { "always", CERT_ALWAYS_SEND
},
1176 { "never", CERT_NEVER_SEND
},
1180 if (parse_map(map
, countof(map
), &d
, v
))
1189 * Parse a unique_policy_t
1191 CALLBACK(parse_unique
, bool,
1192 unique_policy_t
*out
, chunk_t v
)
1194 enum_map_t map
[] = {
1195 { "never", UNIQUE_NEVER
},
1196 { "no", UNIQUE_NO
},
1197 { "replace", UNIQUE_REPLACE
},
1198 { "keep", UNIQUE_KEEP
},
1202 if (parse_map(map
, countof(map
), &d
, v
))
1211 * Parse host_t into a list
1213 CALLBACK(parse_hosts
, bool,
1214 linked_list_t
*list
, chunk_t v
)
1219 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1223 host
= host_create_from_string(buf
, 0);
1228 list
->insert_last(list
, host
);
1232 CALLBACK(child_li
, bool,
1233 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1235 parse_rule_t rules
[] = {
1236 { "ah_proposals", parse_ah_proposal
, child
->proposals
},
1237 { "esp_proposals", parse_esp_proposal
, child
->proposals
},
1238 { "local_ts", parse_ts
, child
->local_ts
},
1239 { "remote_ts", parse_ts
, child
->remote_ts
},
1242 return parse_rules(rules
, countof(rules
), name
, value
,
1243 &child
->request
->reply
);
1246 CALLBACK(child_kv
, bool,
1247 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1249 parse_rule_t rules
[] = {
1250 { "updown", parse_string
, &child
->updown
},
1251 { "hostaccess", parse_bool
, &child
->hostaccess
},
1252 { "mode", parse_mode
, &child
->mode
},
1253 { "policies", parse_bool
, &child
->policies
},
1254 { "replay_window", parse_uint32
, &child
->replay_window
},
1255 { "rekey_time", parse_time
, &child
->lft
.time
.rekey
},
1256 { "life_time", parse_time
, &child
->lft
.time
.life
},
1257 { "rand_time", parse_time
, &child
->lft
.time
.jitter
},
1258 { "rekey_bytes", parse_bytes
, &child
->lft
.bytes
.rekey
},
1259 { "life_bytes", parse_bytes
, &child
->lft
.bytes
.life
},
1260 { "rand_bytes", parse_bytes
, &child
->lft
.bytes
.jitter
},
1261 { "rekey_packets", parse_uint64
, &child
->lft
.packets
.rekey
},
1262 { "life_packets", parse_uint64
, &child
->lft
.packets
.life
},
1263 { "rand_packets", parse_uint64
, &child
->lft
.packets
.jitter
},
1264 { "dpd_action", parse_action
, &child
->dpd_action
},
1265 { "start_action", parse_action
, &child
->start_action
},
1266 { "close_action", parse_action
, &child
->close_action
},
1267 { "ipcomp", parse_bool
, &child
->ipcomp
},
1268 { "inactivity", parse_time
, &child
->inactivity
},
1269 { "reqid", parse_uint32
, &child
->reqid
},
1270 { "mark_in", parse_mark
, &child
->mark_in
},
1271 { "mark_out", parse_mark
, &child
->mark_out
},
1272 { "tfc_padding", parse_tfc
, &child
->tfc
},
1275 return parse_rules(rules
, countof(rules
), name
, value
,
1276 &child
->request
->reply
);
1279 CALLBACK(auth_li
, bool,
1280 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1282 parse_rule_t rules
[] = {
1283 { "groups", parse_group
, auth
->cfg
},
1284 { "certs", parse_certs
, auth
},
1285 { "cacerts", parse_cacerts
, auth
},
1288 return parse_rules(rules
, countof(rules
), name
, value
,
1289 &auth
->request
->reply
);
1292 CALLBACK(auth_kv
, bool,
1293 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1295 parse_rule_t rules
[] = {
1296 { "auth", parse_auth
, auth
->cfg
},
1297 { "id", parse_ike_id
, auth
->cfg
},
1298 { "aaa_id", parse_aaa_id
, auth
->cfg
},
1299 { "eap_id", parse_eap_id
, auth
->cfg
},
1300 { "xauth_id", parse_xauth_id
, auth
->cfg
},
1301 { "revocation", parse_revocation
, auth
->cfg
},
1304 return parse_rules(rules
, countof(rules
), name
, value
,
1305 &auth
->request
->reply
);
1308 CALLBACK(peer_li
, bool,
1309 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1311 parse_rule_t rules
[] = {
1312 { "local_addrs", parse_stringlist
, &peer
->local_addrs
},
1313 { "remote_addrs", parse_stringlist
, &peer
->remote_addrs
},
1314 { "proposals", parse_ike_proposal
, peer
->proposals
},
1315 { "vips", parse_hosts
, peer
->vips
},
1316 { "pools", parse_stringlist
, &peer
->pools
},
1319 return parse_rules(rules
, countof(rules
), name
, value
,
1320 &peer
->request
->reply
);
1323 CALLBACK(peer_kv
, bool,
1324 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1326 parse_rule_t rules
[] = {
1327 { "version", parse_uint32
, &peer
->version
},
1328 { "aggressive", parse_bool
, &peer
->aggressive
},
1329 { "pull", parse_bool
, &peer
->pull
},
1330 { "encap", parse_bool
, &peer
->encap
},
1331 { "mobike", parse_bool
, &peer
->mobike
},
1332 { "dpd_delay", parse_time
, &peer
->dpd_delay
},
1333 { "dpd_timeout", parse_time
, &peer
->dpd_timeout
},
1334 { "fragmentation", parse_frag
, &peer
->fragmentation
},
1335 { "send_certreq", parse_bool
, &peer
->send_certreq
},
1336 { "send_cert", parse_send_cert
, &peer
->send_cert
},
1337 { "keyingtries", parse_uint32
, &peer
->keyingtries
},
1338 { "unique", parse_unique
, &peer
->unique
},
1339 { "local_port", parse_uint32
, &peer
->local_port
},
1340 { "remote_port", parse_uint32
, &peer
->remote_port
},
1341 { "reauth_time", parse_time
, &peer
->reauth_time
},
1342 { "rekey_time", parse_time
, &peer
->rekey_time
},
1343 { "over_time", parse_time
, &peer
->over_time
},
1344 { "rand_time", parse_time
, &peer
->rand_time
},
1347 return parse_rules(rules
, countof(rules
), name
, value
,
1348 &peer
->request
->reply
);
1351 CALLBACK(children_sn
, bool,
1352 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1355 child_data_t child
= {
1356 .request
= peer
->request
,
1357 .proposals
= linked_list_create(),
1358 .local_ts
= linked_list_create(),
1359 .remote_ts
= linked_list_create(),
1360 .mode
= MODE_TUNNEL
,
1362 .replay_window
= REPLAY_UNDEFINED
,
1363 .dpd_action
= ACTION_NONE
,
1364 .start_action
= ACTION_NONE
,
1365 .close_action
= ACTION_NONE
,
1368 .rekey
= LFT_DEFAULT_CHILD_REKEY
,
1369 .life
= LFT_UNDEFINED
,
1370 .jitter
= LFT_UNDEFINED
,
1373 .rekey
= LFT_UNDEFINED
,
1374 .life
= LFT_UNDEFINED
,
1375 .jitter
= LFT_UNDEFINED
,
1378 .rekey
= LFT_UNDEFINED
,
1379 .life
= LFT_UNDEFINED
,
1380 .jitter
= LFT_UNDEFINED
,
1385 proposal_t
*proposal
;
1386 traffic_selector_t
*ts
;
1388 if (!message
->parse(message
, ctx
, NULL
, child_kv
, child_li
, &child
))
1390 free_child_data(&child
);
1394 if (child
.local_ts
->get_count(child
.local_ts
) == 0)
1396 child
.local_ts
->insert_last(child
.local_ts
,
1397 traffic_selector_create_dynamic(0, 0, 65535));
1399 if (child
.remote_ts
->get_count(child
.remote_ts
) == 0)
1401 child
.remote_ts
->insert_last(child
.remote_ts
,
1402 traffic_selector_create_dynamic(0, 0, 65535));
1404 if (child
.proposals
->get_count(child
.proposals
) == 0)
1406 proposal
= proposal_create_default(PROTO_ESP
);
1409 child
.proposals
->insert_last(child
.proposals
, proposal
);
1411 proposal
= proposal_create_default_aead(PROTO_ESP
);
1414 child
.proposals
->insert_last(child
.proposals
, proposal
);
1418 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1419 if (child
.lft
.time
.life
== LFT_UNDEFINED
)
1421 child
.lft
.time
.life
= child
.lft
.time
.rekey
* 110 / 100;
1423 if (child
.lft
.bytes
.life
== LFT_UNDEFINED
)
1425 child
.lft
.bytes
.life
= child
.lft
.bytes
.rekey
* 110 / 100;
1427 if (child
.lft
.packets
.life
== LFT_UNDEFINED
)
1429 child
.lft
.packets
.life
= child
.lft
.packets
.rekey
* 110 / 100;
1431 /* if no soft lifetime specified, add one at hard lifetime - 10% */
1432 if (child
.lft
.bytes
.rekey
== LFT_UNDEFINED
)
1434 child
.lft
.bytes
.rekey
= child
.lft
.bytes
.life
* 90 / 100;
1436 if (child
.lft
.packets
.rekey
== LFT_UNDEFINED
)
1438 child
.lft
.packets
.rekey
= child
.lft
.packets
.life
* 90 / 100;
1440 /* if no rand time defined, use difference of hard and soft */
1441 if (child
.lft
.time
.jitter
== LFT_UNDEFINED
)
1443 child
.lft
.time
.jitter
= child
.lft
.time
.life
-
1444 min(child
.lft
.time
.life
, child
.lft
.time
.rekey
);
1446 if (child
.lft
.bytes
.jitter
== LFT_UNDEFINED
)
1448 child
.lft
.bytes
.jitter
= child
.lft
.bytes
.life
-
1449 min(child
.lft
.bytes
.life
, child
.lft
.bytes
.rekey
);
1451 if (child
.lft
.packets
.jitter
== LFT_UNDEFINED
)
1453 child
.lft
.packets
.jitter
= child
.lft
.packets
.life
-
1454 min(child
.lft
.packets
.life
, child
.lft
.packets
.rekey
);
1457 log_child_data(&child
, name
);
1459 cfg
= child_cfg_create(name
, &child
.lft
, child
.updown
,
1460 child
.hostaccess
, child
.mode
, child
.start_action
,
1461 child
.dpd_action
, child
.close_action
, child
.ipcomp
,
1462 child
.inactivity
, child
.reqid
, &child
.mark_in
,
1463 &child
.mark_out
, child
.tfc
);
1465 cfg
->set_mipv6_options(cfg
, FALSE
, child
.policies
);
1467 if (child
.replay_window
!= REPLAY_UNDEFINED
)
1469 cfg
->set_replay_window(cfg
, child
.replay_window
);
1471 while (child
.local_ts
->remove_first(child
.local_ts
,
1472 (void**)&ts
) == SUCCESS
)
1474 cfg
->add_traffic_selector(cfg
, TRUE
, ts
);
1476 while (child
.remote_ts
->remove_first(child
.remote_ts
,
1477 (void**)&ts
) == SUCCESS
)
1479 cfg
->add_traffic_selector(cfg
, FALSE
, ts
);
1481 while (child
.proposals
->remove_first(child
.proposals
,
1482 (void**)&proposal
) == SUCCESS
)
1484 cfg
->add_proposal(cfg
, proposal
);
1487 peer
->children
->insert_last(peer
->children
, cfg
);
1489 free_child_data(&child
);
1494 CALLBACK(peer_sn
, bool,
1495 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1498 if (strcaseeq(name
, "children"))
1500 return message
->parse(message
, ctx
, children_sn
, NULL
, NULL
, peer
);
1502 if (strcasepfx(name
, "local") ||
1503 strcasepfx(name
, "remote"))
1505 auth_data_t auth
= {
1506 .request
= peer
->request
,
1507 .cfg
= auth_cfg_create(),
1510 if (!message
->parse(message
, ctx
, NULL
, auth_kv
, auth_li
, &auth
))
1512 auth
.cfg
->destroy(auth
.cfg
);
1516 if (!auth
.cfg
->get(auth
.cfg
, AUTH_RULE_IDENTITY
))
1518 identification_t
*id
;
1519 certificate_t
*cert
;
1521 cert
= auth
.cfg
->get(auth
.cfg
, AUTH_RULE_SUBJECT_CERT
);
1524 id
= cert
->get_subject(cert
);
1525 DBG1(DBG_CFG
, " id not specified, defaulting to cert id '%Y'",
1527 auth
.cfg
->add(auth
.cfg
, AUTH_RULE_IDENTITY
, id
->clone(id
));
1531 if (strcasepfx(name
, "local"))
1533 peer
->local
->insert_last(peer
->local
, auth
.cfg
);
1537 peer
->remote
->insert_last(peer
->remote
, auth
.cfg
);
1541 peer
->request
->reply
= create_reply("invalid section: %s", name
);
1546 * Find reqid of an existing CHILD_SA
1548 static u_int32_t
find_reqid(child_cfg_t
*cfg
)
1550 enumerator_t
*enumerator
, *children
;
1551 child_sa_t
*child_sa
;
1555 reqid
= charon
->traps
->find_reqid(charon
->traps
, cfg
);
1557 { /* already trapped */
1561 enumerator
= charon
->controller
->create_ike_sa_enumerator(
1562 charon
->controller
, TRUE
);
1563 while (!reqid
&& enumerator
->enumerate(enumerator
, &ike_sa
))
1565 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
1566 while (children
->enumerate(children
, &child_sa
))
1568 if (streq(cfg
->get_name(cfg
), child_sa
->get_name(child_sa
)))
1570 reqid
= child_sa
->get_reqid(child_sa
);
1574 children
->destroy(children
);
1576 enumerator
->destroy(enumerator
);
1581 * Perform start actions associated to a child config
1583 static void run_start_action(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
,
1584 child_cfg_t
*child_cfg
)
1586 switch (child_cfg
->get_start_action(child_cfg
))
1588 case ACTION_RESTART
:
1589 DBG1(DBG_CFG
, "initiating '%s'", child_cfg
->get_name(child_cfg
));
1590 charon
->controller
->initiate(charon
->controller
,
1591 peer_cfg
->get_ref(peer_cfg
), child_cfg
->get_ref(child_cfg
),
1592 NULL
, NULL
, 0, FALSE
);
1595 DBG1(DBG_CFG
, "installing '%s'", child_cfg
->get_name(child_cfg
));
1596 switch (child_cfg
->get_mode(child_cfg
))
1600 charon
->shunts
->install(charon
->shunts
, child_cfg
);
1603 charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
,
1604 find_reqid(child_cfg
));
1614 * Undo start actions associated to a child config
1616 static void clear_start_action(private_vici_config_t
*this,
1617 child_cfg_t
*child_cfg
)
1619 enumerator_t
*enumerator
, *children
;
1620 child_sa_t
*child_sa
;
1622 u_int32_t id
= 0, *del
;
1623 array_t
*ids
= NULL
;
1626 name
= child_cfg
->get_name(child_cfg
);
1627 switch (child_cfg
->get_start_action(child_cfg
))
1629 case ACTION_RESTART
:
1630 enumerator
= charon
->controller
->create_ike_sa_enumerator(
1631 charon
->controller
, TRUE
);
1632 while (enumerator
->enumerate(enumerator
, &ike_sa
))
1634 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
1635 while (children
->enumerate(children
, &child_sa
))
1637 if (streq(name
, child_sa
->get_name(child_sa
)))
1639 id
= child_sa
->get_unique_id(child_sa
);
1640 array_insert_create(&ids
, ARRAY_TAIL
, &id
);
1643 children
->destroy(children
);
1645 enumerator
->destroy(enumerator
);
1647 if (array_count(ids
))
1649 while (array_remove(ids
, ARRAY_HEAD
, &del
))
1651 DBG1(DBG_CFG
, "closing '%s' #%u", name
, *del
);
1652 charon
->controller
->terminate_child(charon
->controller
,
1653 *del
, NULL
, NULL
, 0);
1659 DBG1(DBG_CFG
, "uninstalling '%s'", name
);
1660 switch (child_cfg
->get_mode(child_cfg
))
1664 charon
->shunts
->uninstall(charon
->shunts
, name
);
1667 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
1668 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
1670 if (streq(name
, child_sa
->get_name(child_sa
)))
1672 id
= child_sa
->get_reqid(child_sa
);
1676 enumerator
->destroy(enumerator
);
1679 charon
->traps
->uninstall(charon
->traps
, id
);
1690 * Run start actions associated to all child configs of a peer config
1692 static void run_start_actions(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
)
1694 enumerator_t
*enumerator
;
1695 child_cfg_t
*child_cfg
;
1697 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
1698 while (enumerator
->enumerate(enumerator
, &child_cfg
))
1700 run_start_action(this, peer_cfg
, child_cfg
);
1702 enumerator
->destroy(enumerator
);
1706 * Undo start actions associated to all child configs of a peer config
1708 static void clear_start_actions(private_vici_config_t
*this,
1709 peer_cfg_t
*peer_cfg
)
1711 enumerator_t
*enumerator
;
1712 child_cfg_t
*child_cfg
;
1714 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
1715 while (enumerator
->enumerate(enumerator
, &child_cfg
))
1717 clear_start_action(this, child_cfg
);
1719 enumerator
->destroy(enumerator
);
1723 * Replace children of a peer config by a new config
1725 static void replace_children(private_vici_config_t
*this,
1726 peer_cfg_t
*from
, peer_cfg_t
*to
)
1728 enumerator_t
*enumerator
;
1731 enumerator
= to
->create_child_cfg_enumerator(to
);
1732 while (enumerator
->enumerate(enumerator
, &child
))
1734 to
->remove_child_cfg(to
, enumerator
);
1735 clear_start_action(this, child
);
1736 child
->destroy(child
);
1738 enumerator
->destroy(enumerator
);
1740 enumerator
= from
->create_child_cfg_enumerator(from
);
1741 while (enumerator
->enumerate(enumerator
, &child
))
1743 from
->remove_child_cfg(from
, enumerator
);
1744 to
->add_child_cfg(to
, child
);
1745 run_start_action(this, to
, child
);
1747 enumerator
->destroy(enumerator
);
1751 * Merge/replace a peer config with existing configs
1753 static void merge_config(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
)
1755 enumerator_t
*enumerator
;
1756 peer_cfg_t
*current
;
1758 bool merged
= FALSE
;
1760 this->lock
->write_lock(this->lock
);
1762 enumerator
= this->conns
->create_enumerator(this->conns
);
1763 while (enumerator
->enumerate(enumerator
, ¤t
))
1765 if (streq(peer_cfg
->get_name(peer_cfg
), current
->get_name(current
)))
1767 ike_cfg
= current
->get_ike_cfg(current
);
1768 if (peer_cfg
->equals(peer_cfg
, current
) &&
1769 ike_cfg
->equals(ike_cfg
, peer_cfg
->get_ike_cfg(peer_cfg
)))
1771 DBG1(DBG_CFG
, "updated vici connection: %s",
1772 peer_cfg
->get_name(peer_cfg
));
1773 replace_children(this, peer_cfg
, current
);
1774 peer_cfg
->destroy(peer_cfg
);
1778 DBG1(DBG_CFG
, "replaced vici connection: %s",
1779 peer_cfg
->get_name(peer_cfg
));
1780 this->conns
->remove_at(this->conns
, enumerator
);
1781 clear_start_actions(this, current
);
1782 current
->destroy(current
);
1783 this->conns
->insert_last(this->conns
, peer_cfg
);
1784 run_start_actions(this, peer_cfg
);
1790 enumerator
->destroy(enumerator
);
1794 DBG1(DBG_CFG
, "added vici connection: %s", peer_cfg
->get_name(peer_cfg
));
1795 this->conns
->insert_last(this->conns
, peer_cfg
);
1796 run_start_actions(this, peer_cfg
);
1799 this->lock
->unlock(this->lock
);
1802 CALLBACK(config_sn
, bool,
1803 request_data_t
*request
, vici_message_t
*message
,
1804 vici_parse_context_t
*ctx
, char *name
)
1806 peer_data_t peer
= {
1808 .local
= linked_list_create(),
1809 .remote
= linked_list_create(),
1810 .vips
= linked_list_create(),
1811 .children
= linked_list_create(),
1812 .proposals
= linked_list_create(),
1814 .send_certreq
= TRUE
,
1816 .send_cert
= CERT_SEND_IF_ASKED
,
1818 .remote_port
= IKEV2_UDP_PORT
,
1819 .fragmentation
= FRAGMENTATION_NO
,
1820 .unique
= UNIQUE_NO
,
1822 .rekey_time
= LFT_UNDEFINED
,
1823 .reauth_time
= LFT_UNDEFINED
,
1824 .over_time
= LFT_UNDEFINED
,
1825 .rand_time
= LFT_UNDEFINED
,
1827 enumerator_t
*enumerator
;
1828 peer_cfg_t
*peer_cfg
;
1830 child_cfg_t
*child_cfg
;
1831 auth_cfg_t
*auth_cfg
;
1832 proposal_t
*proposal
;
1836 DBG2(DBG_CFG
, " conn %s:", name
);
1838 if (!message
->parse(message
, ctx
, peer_sn
, peer_kv
, peer_li
, &peer
))
1840 free_peer_data(&peer
);
1844 if (peer
.local
->get_count(peer
.local
) == 0)
1846 free_peer_data(&peer
);
1847 peer
.request
->reply
= create_reply("missing local auth config");
1850 if (peer
.remote
->get_count(peer
.remote
) == 0)
1852 auth_cfg
= auth_cfg_create();
1853 peer
.remote
->insert_last(peer
.remote
, auth_cfg
);
1855 if (peer
.proposals
->get_count(peer
.proposals
) == 0)
1857 proposal
= proposal_create_default(PROTO_IKE
);
1860 peer
.proposals
->insert_last(peer
.proposals
, proposal
);
1862 proposal
= proposal_create_default_aead(PROTO_IKE
);
1865 peer
.proposals
->insert_last(peer
.proposals
, proposal
);
1868 if (!peer
.local_addrs
)
1870 peer
.local_addrs
= strdup("%any");
1872 if (!peer
.remote_addrs
)
1874 peer
.remote_addrs
= strdup("%any");
1876 if (!peer
.local_port
)
1878 peer
.local_port
= charon
->socket
->get_port(charon
->socket
, FALSE
);
1881 if (peer
.rekey_time
== LFT_UNDEFINED
&& peer
.reauth_time
== LFT_UNDEFINED
)
1883 /* apply a default rekey time if no rekey/reauth time set */
1884 peer
.rekey_time
= LFT_DEFAULT_IKE_REKEY
;
1885 peer
.reauth_time
= 0;
1887 if (peer
.rekey_time
== LFT_UNDEFINED
)
1889 peer
.rekey_time
= 0;
1891 if (peer
.reauth_time
== LFT_UNDEFINED
)
1893 peer
.reauth_time
= 0;
1895 if (peer
.over_time
== LFT_UNDEFINED
)
1897 /* default over_time to 10% of rekey/reauth time if not given */
1898 peer
.over_time
= max(peer
.rekey_time
, peer
.reauth_time
) / 10;
1900 if (peer
.rand_time
== LFT_UNDEFINED
)
1902 /* default rand_time to over_time if not given, but don't make it
1903 * longer than half of rekey/rauth time */
1904 if (peer
.rekey_time
&& peer
.reauth_time
)
1906 peer
.rand_time
= min(peer
.rekey_time
, peer
.reauth_time
);
1910 peer
.rand_time
= max(peer
.rekey_time
, peer
.reauth_time
);
1912 peer
.rand_time
= min(peer
.over_time
, peer
.rand_time
/ 2);
1915 log_peer_data(&peer
);
1917 ike_cfg
= ike_cfg_create(peer
.version
, peer
.send_certreq
, peer
.encap
,
1918 peer
.local_addrs
, peer
.local_port
,
1919 peer
.remote_addrs
, peer
.remote_port
,
1920 peer
.fragmentation
, 0);
1921 peer_cfg
= peer_cfg_create(name
, ike_cfg
, peer
.send_cert
, peer
.unique
,
1922 peer
.keyingtries
, peer
.rekey_time
, peer
.reauth_time
,
1923 peer
.rand_time
, peer
.over_time
, peer
.mobike
,
1924 peer
.aggressive
, peer
.pull
,
1925 peer
.dpd_delay
, peer
.dpd_timeout
,
1928 while (peer
.local
->remove_first(peer
.local
,
1929 (void**)&auth_cfg
) == SUCCESS
)
1931 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, TRUE
);
1933 while (peer
.remote
->remove_first(peer
.remote
,
1934 (void**)&auth_cfg
) == SUCCESS
)
1936 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, FALSE
);
1938 while (peer
.children
->remove_first(peer
.children
,
1939 (void**)&child_cfg
) == SUCCESS
)
1941 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
1943 while (peer
.proposals
->remove_first(peer
.proposals
,
1944 (void**)&proposal
) == SUCCESS
)
1946 ike_cfg
->add_proposal(ike_cfg
, proposal
);
1948 while (peer
.vips
->remove_first(peer
.vips
, (void**)&host
) == SUCCESS
)
1950 peer_cfg
->add_virtual_ip(peer_cfg
, host
);
1954 enumerator
= enumerator_create_token(peer
.pools
, ",", " ");
1955 while (enumerator
->enumerate(enumerator
, &str
))
1957 peer_cfg
->add_pool(peer_cfg
, str
);
1959 enumerator
->destroy(enumerator
);
1962 free_peer_data(&peer
);
1964 merge_config(request
->this, peer_cfg
);
1969 CALLBACK(load_conn
, vici_message_t
*,
1970 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
1972 request_data_t request
= {
1976 if (!message
->parse(message
, NULL
, config_sn
, NULL
, NULL
, &request
))
1980 return request
.reply
;
1982 return create_reply("parsing request failed");
1984 return create_reply(NULL
);
1987 CALLBACK(unload_conn
, vici_message_t
*,
1988 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
1990 enumerator_t
*enumerator
;
1995 conn_name
= message
->get_str(message
, NULL
, "name");
1998 return create_reply("unload: missing connection name");
2001 this->lock
->write_lock(this->lock
);
2002 enumerator
= this->conns
->create_enumerator(this->conns
);
2003 while (enumerator
->enumerate(enumerator
, &cfg
))
2005 if (streq(cfg
->get_name(cfg
), conn_name
))
2007 this->conns
->remove_at(this->conns
, enumerator
);
2013 enumerator
->destroy(enumerator
);
2014 this->lock
->unlock(this->lock
);
2018 return create_reply("unload: connection '%s' not found", conn_name
);
2020 return create_reply(NULL
);
2023 CALLBACK(get_conns
, vici_message_t
*,
2024 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2026 vici_builder_t
*builder
;
2027 enumerator_t
*enumerator
;
2030 builder
= vici_builder_create();
2031 builder
->begin_list(builder
, "conns");
2033 this->lock
->read_lock(this->lock
);
2034 enumerator
= this->conns
->create_enumerator(this->conns
);
2035 while (enumerator
->enumerate(enumerator
, &cfg
))
2037 builder
->add_li(builder
, "%s", cfg
->get_name(cfg
));
2039 enumerator
->destroy(enumerator
);
2040 this->lock
->unlock(this->lock
);
2042 builder
->end_list(builder
);
2044 return builder
->finalize(builder
);
2047 static void manage_command(private_vici_config_t
*this,
2048 char *name
, vici_command_cb_t cb
, bool reg
)
2050 this->dispatcher
->manage_command(this->dispatcher
, name
,
2051 reg
? cb
: NULL
, this);
2055 * (Un-)register dispatcher functions
2057 static void manage_commands(private_vici_config_t
*this, bool reg
)
2059 manage_command(this, "load-conn", load_conn
, reg
);
2060 manage_command(this, "unload-conn", unload_conn
, reg
);
2061 manage_command(this, "get-conns", get_conns
, reg
);
2064 METHOD(vici_config_t
, destroy
, void,
2065 private_vici_config_t
*this)
2067 manage_commands(this, FALSE
);
2068 this->conns
->destroy_offset(this->conns
, offsetof(peer_cfg_t
, destroy
));
2069 this->lock
->destroy(this->lock
);
2076 vici_config_t
*vici_config_create(vici_dispatcher_t
*dispatcher
,
2077 vici_authority_t
*authority
)
2079 private_vici_config_t
*this;
2084 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
2085 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
2086 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
2088 .destroy
= _destroy
,
2090 .dispatcher
= dispatcher
,
2091 .conns
= linked_list_create(),
2092 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
2093 .authority
= authority
,
2096 manage_commands(this, TRUE
);
2098 return &this->public;