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>
51 #include <pubkey_cert.h>
56 * Magic value for an undefined lifetime
58 #define LFT_UNDEFINED (~(u_int64_t)0)
61 * Default IKE rekey time
63 #define LFT_DEFAULT_IKE_REKEY (4 * 60 * 60)
66 * Default CHILD rekey time
68 #define LFT_DEFAULT_CHILD_REKEY (1 * 60 * 60)
71 * Undefined replay window
73 #define REPLAY_UNDEFINED (~(u_int32_t)0)
75 typedef struct private_vici_config_t private_vici_config_t
;
78 * Private data of an vici_config_t object.
80 struct private_vici_config_t
{
83 * Public vici_config_t interface.
90 vici_dispatcher_t
*dispatcher
;
93 * List of loaded connections, as peer_cfg_t
103 * Credential backend managed by VICI used for our certificates
108 * Auxiliary certification authority information
110 vici_authority_t
*authority
;
114 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
115 private_vici_config_t
*this, identification_t
*me
, identification_t
*other
)
117 this->lock
->read_lock(this->lock
);
118 return enumerator_create_cleaner(this->conns
->create_enumerator(this->conns
),
119 (void*)this->lock
->unlock
, this->lock
);
123 * Enumerator filter function for ike configs
125 static bool ike_filter(void *data
, peer_cfg_t
**in
, ike_cfg_t
**out
)
127 *out
= (*in
)->get_ike_cfg(*in
);
131 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
132 private_vici_config_t
*this, host_t
*me
, host_t
*other
)
134 this->lock
->read_lock(this->lock
);
135 return enumerator_create_filter(this->conns
->create_enumerator(this->conns
),
136 (void*)ike_filter
, this->lock
,
137 (void*)this->lock
->unlock
);
140 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
141 private_vici_config_t
*this, char *name
)
143 peer_cfg_t
*current
, *found
= NULL
;
144 enumerator_t
*enumerator
;
146 this->lock
->read_lock(this->lock
);
147 enumerator
= this->conns
->create_enumerator(this->conns
);
148 while (enumerator
->enumerate(enumerator
, ¤t
))
150 if (streq(current
->get_name(current
), name
))
153 found
->get_ref(found
);
157 enumerator
->destroy(enumerator
);
158 this->lock
->unlock(this->lock
);
164 * Create a (error) reply message
166 static vici_message_t
* create_reply(char *fmt
, ...)
168 vici_builder_t
*builder
;
171 builder
= vici_builder_create();
172 builder
->add_kv(builder
, "success", fmt
? "no" : "yes");
176 builder
->vadd_kv(builder
, "errmsg", fmt
, args
);
179 return builder
->finalize(builder
);
183 * A rule to parse a key/value or list item
186 /** name of the key/value or list */
188 /** function to parse value */
189 bool (*parse
)(void *out
, chunk_t value
);
190 /** result, passed to parse() */
195 * Parse key/values using a rule-set
197 static bool parse_rules(parse_rule_t
*rules
, int count
, char *name
,
198 chunk_t value
, vici_message_t
**reply
)
202 for (i
= 0; i
< count
; i
++)
204 if (streq(name
, rules
[i
].name
))
206 if (rules
[i
].parse(rules
[i
].out
, value
))
210 *reply
= create_reply("invalid value for: %s, config discarded",
215 *reply
= create_reply("unknown option: %s, config discarded", name
);
220 * Parse callback data, passed to each callback
223 private_vici_config_t
*this;
224 vici_message_t
*reply
;
228 * Data associated to a peer config
231 request_data_t
*request
;
238 cert_policy_t send_cert
;
240 u_int64_t dpd_timeout
;
241 fragmentation_t fragmentation
;
242 unique_policy_t unique
;
243 u_int32_t keyingtries
;
244 u_int32_t local_port
;
245 u_int32_t remote_port
;
248 linked_list_t
*local
;
249 linked_list_t
*remote
;
250 linked_list_t
*proposals
;
251 linked_list_t
*children
;
254 u_int64_t reauth_time
;
255 u_int64_t rekey_time
;
261 * Log relevant auth config data
263 static void log_auth(auth_cfg_t
*auth
)
265 enumerator_t
*enumerator
;
269 identification_t
*id
;
273 enumerator
= auth
->create_enumerator(auth
);
274 while (enumerator
->enumerate(enumerator
, &rule
, &v
))
278 case AUTH_RULE_AUTH_CLASS
:
279 DBG2(DBG_CFG
, " class = %N", auth_class_names
, v
.u
);
281 case AUTH_RULE_EAP_TYPE
:
282 DBG2(DBG_CFG
, " eap-type = %N", eap_type_names
, v
.u
);
284 case AUTH_RULE_EAP_VENDOR
:
285 DBG2(DBG_CFG
, " eap-vendor = %u", v
.u
);
287 case AUTH_RULE_XAUTH_BACKEND
:
288 DBG2(DBG_CFG
, " xauth = %s", v
.str
);
290 case AUTH_RULE_CRL_VALIDATION
:
291 DBG2(DBG_CFG
, " revocation = %N", cert_validation_names
, v
.u
);
293 case AUTH_RULE_IDENTITY
:
294 DBG2(DBG_CFG
, " id = %Y", v
.id
);
296 case AUTH_RULE_AAA_IDENTITY
:
297 DBG2(DBG_CFG
, " aaa_id = %Y", v
.id
);
299 case AUTH_RULE_EAP_IDENTITY
:
300 DBG2(DBG_CFG
, " eap_id = %Y", v
.id
);
302 case AUTH_RULE_XAUTH_IDENTITY
:
303 DBG2(DBG_CFG
, " xauth_id = %Y", v
.id
);
305 case AUTH_RULE_GROUP
:
306 DBG2(DBG_CFG
, " group = %Y", v
.id
);
312 enumerator
->destroy(enumerator
);
316 * Log parsed peer data
318 static void log_peer_data(peer_data_t
*data
)
320 enumerator_t
*enumerator
;
324 DBG2(DBG_CFG
, " version = %u", data
->version
);
325 DBG2(DBG_CFG
, " local_addrs = %s", data
->local_addrs
);
326 DBG2(DBG_CFG
, " remote_addrs = %s", data
->remote_addrs
);
327 DBG2(DBG_CFG
, " local_port = %u", data
->local_port
);
328 DBG2(DBG_CFG
, " remote_port = %u", data
->remote_port
);
329 DBG2(DBG_CFG
, " send_certreq = %u", data
->send_certreq
);
330 DBG2(DBG_CFG
, " send_cert = %N", cert_policy_names
, data
->send_cert
);
331 DBG2(DBG_CFG
, " mobike = %u", data
->mobike
);
332 DBG2(DBG_CFG
, " aggressive = %u", data
->aggressive
);
333 DBG2(DBG_CFG
, " encap = %u", data
->encap
);
334 DBG2(DBG_CFG
, " dpd_delay = %llu", data
->dpd_delay
);
335 DBG2(DBG_CFG
, " dpd_timeout = %llu", data
->dpd_timeout
);
336 DBG2(DBG_CFG
, " fragmentation = %u", data
->fragmentation
);
337 DBG2(DBG_CFG
, " unique = %N", unique_policy_names
, data
->unique
);
338 DBG2(DBG_CFG
, " keyingtries = %u", data
->keyingtries
);
339 DBG2(DBG_CFG
, " reauth_time = %llu", data
->reauth_time
);
340 DBG2(DBG_CFG
, " rekey_time = %llu", data
->rekey_time
);
341 DBG2(DBG_CFG
, " over_time = %llu", data
->over_time
);
342 DBG2(DBG_CFG
, " rand_time = %llu", data
->rand_time
);
343 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
345 if (data
->vips
->get_count(data
->vips
))
347 DBG2(DBG_CFG
, " vips:");
349 enumerator
= data
->vips
->create_enumerator(data
->vips
);
350 while (enumerator
->enumerate(enumerator
, &host
))
352 DBG2(DBG_CFG
, " %H", host
);
354 enumerator
->destroy(enumerator
);
356 enumerator
= data
->local
->create_enumerator(data
->local
);
357 while (enumerator
->enumerate(enumerator
, &auth
))
359 DBG2(DBG_CFG
, " local:");
362 enumerator
->destroy(enumerator
);
364 enumerator
= data
->remote
->create_enumerator(data
->remote
);
365 while (enumerator
->enumerate(enumerator
, &auth
))
367 DBG2(DBG_CFG
, " remote:");
370 enumerator
->destroy(enumerator
);
374 * Clean up peer config data
376 static void free_peer_data(peer_data_t
*data
)
378 data
->local
->destroy_offset(data
->local
,
379 offsetof(auth_cfg_t
, destroy
));
380 data
->remote
->destroy_offset(data
->remote
,
381 offsetof(auth_cfg_t
, destroy
));
382 data
->children
->destroy_offset(data
->children
,
383 offsetof(child_cfg_t
, destroy
));
384 data
->proposals
->destroy_offset(data
->proposals
,
385 offsetof(proposal_t
, destroy
));
386 data
->vips
->destroy_offset(data
->vips
, offsetof(host_t
, destroy
));
388 free(data
->local_addrs
);
389 free(data
->remote_addrs
);
396 request_data_t
*request
;
403 u_int32_t replay_window
;
405 action_t start_action
;
406 action_t close_action
;
411 u_int64_t inactivity
;
412 linked_list_t
*proposals
;
413 linked_list_t
*local_ts
;
414 linked_list_t
*remote_ts
;
418 * Log parsed CHILD config data
420 static void log_child_data(child_data_t
*data
, char *name
)
422 DBG2(DBG_CFG
, " child %s:", name
);
423 DBG2(DBG_CFG
, " rekey_time = %llu", data
->lft
.time
.rekey
);
424 DBG2(DBG_CFG
, " life_time = %llu", data
->lft
.time
.life
);
425 DBG2(DBG_CFG
, " rand_time = %llu", data
->lft
.time
.jitter
);
426 DBG2(DBG_CFG
, " rekey_bytes = %llu", data
->lft
.bytes
.rekey
);
427 DBG2(DBG_CFG
, " life_bytes = %llu", data
->lft
.bytes
.life
);
428 DBG2(DBG_CFG
, " rand_bytes = %llu", data
->lft
.bytes
.jitter
);
429 DBG2(DBG_CFG
, " rekey_packets = %llu", data
->lft
.packets
.rekey
);
430 DBG2(DBG_CFG
, " life_packets = %llu", data
->lft
.packets
.life
);
431 DBG2(DBG_CFG
, " rand_packets = %llu", data
->lft
.packets
.jitter
);
432 DBG2(DBG_CFG
, " updown = %s", data
->updown
);
433 DBG2(DBG_CFG
, " hostaccess = %u", data
->hostaccess
);
434 DBG2(DBG_CFG
, " ipcomp = %u", data
->ipcomp
);
435 DBG2(DBG_CFG
, " mode = %N", ipsec_mode_names
, data
->mode
);
436 DBG2(DBG_CFG
, " policies = %u", data
->policies
);
437 if (data
->replay_window
!= REPLAY_UNDEFINED
)
439 DBG2(DBG_CFG
, " replay_window = %u", data
->replay_window
);
441 DBG2(DBG_CFG
, " dpd_action = %N", action_names
, data
->dpd_action
);
442 DBG2(DBG_CFG
, " start_action = %N", action_names
, data
->start_action
);
443 DBG2(DBG_CFG
, " close_action = %N", action_names
, data
->close_action
);
444 DBG2(DBG_CFG
, " reqid = %u", data
->reqid
);
445 DBG2(DBG_CFG
, " tfc = %d", data
->tfc
);
446 DBG2(DBG_CFG
, " mark_in = %u/%u",
447 data
->mark_in
.value
, data
->mark_in
.mask
);
448 DBG2(DBG_CFG
, " mark_out = %u/%u",
449 data
->mark_out
.value
, data
->mark_out
.mask
);
450 DBG2(DBG_CFG
, " inactivity = %llu", data
->inactivity
);
451 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
452 DBG2(DBG_CFG
, " local_ts = %#R", data
->local_ts
);
453 DBG2(DBG_CFG
, " remote_ts = %#R", data
->remote_ts
);
457 * Clean up CHILD config data
459 static void free_child_data(child_data_t
*data
)
461 data
->proposals
->destroy_offset(data
->proposals
,
462 offsetof(proposal_t
, destroy
));
463 data
->local_ts
->destroy_offset(data
->local_ts
,
464 offsetof(traffic_selector_t
, destroy
));
465 data
->remote_ts
->destroy_offset(data
->remote_ts
,
466 offsetof(traffic_selector_t
, destroy
));
474 request_data_t
*request
;
479 * Common proposal parsing
481 static bool parse_proposal(linked_list_t
*list
, protocol_id_t proto
, chunk_t v
)
484 proposal_t
*proposal
;
486 if (!vici_stringify(v
, buf
, sizeof(buf
)))
490 if (strcaseeq("default", buf
))
492 proposal
= proposal_create_default(proto
);
495 list
->insert_last(list
, proposal
);
497 proposal
= proposal_create_default_aead(proto
);
500 list
->insert_last(list
, proposal
);
504 proposal
= proposal_create_from_string(proto
, buf
);
507 list
->insert_last(list
, proposal
);
516 CALLBACK(parse_ike_proposal
, bool,
517 linked_list_t
*out
, chunk_t v
)
519 return parse_proposal(out
, PROTO_IKE
, v
);
525 CALLBACK(parse_esp_proposal
, bool,
526 linked_list_t
*out
, chunk_t v
)
528 return parse_proposal(out
, PROTO_ESP
, v
);
534 CALLBACK(parse_ah_proposal
, bool,
535 linked_list_t
*out
, chunk_t v
)
537 return parse_proposal(out
, PROTO_AH
, v
);
541 * Parse a traffic selector
543 CALLBACK(parse_ts
, bool,
544 linked_list_t
*out
, chunk_t v
)
546 char buf
[128], *protoport
, *sep
, *port
= "", *end
;
547 traffic_selector_t
*ts
;
548 struct protoent
*protoent
;
551 u_int16_t from
= 0, to
= 0xffff;
554 if (!vici_stringify(v
, buf
, sizeof(buf
)))
559 protoport
= strchr(buf
, '[');
562 *(protoport
++) = '\0';
564 sep
= strrchr(protoport
, ']');
571 sep
= strchr(protoport
, '/');
573 { /* protocol/port */
578 if (streq(protoport
, "any"))
584 protoent
= getprotobyname(protoport
);
587 proto
= protoent
->p_proto
;
591 p
= strtol(protoport
, &end
, 0);
592 if ((*protoport
&& *end
) || p
< 0 || p
> 0xff)
599 if (streq(port
, "opaque"))
604 else if (*port
&& !streq(port
, "any"))
606 svc
= getservbyname(port
, NULL
);
609 from
= to
= ntohs(svc
->s_port
);
613 p
= strtol(port
, &end
, 0);
614 if (p
< 0 || p
> 0xffff)
622 p
= strtol(port
, &end
, 0);
623 if (p
< 0 || p
> 0xffff)
636 if (streq(buf
, "dynamic"))
638 ts
= traffic_selector_create_dynamic(proto
, from
, to
);
642 ts
= traffic_selector_create_from_cidr(buf
, proto
, from
, to
);
648 out
->insert_last(out
, ts
);
655 CALLBACK(parse_string
, bool,
656 char **out
, chunk_t v
)
658 if (!chunk_printable(v
, NULL
, ' '))
664 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
672 * Map a string to an integer
680 * Parse a string to an integer mapping
682 static bool parse_map(enum_map_t
*map
, int count
, int *out
, chunk_t v
)
687 if (!vici_stringify(v
, buf
, sizeof(buf
)))
691 for (i
= 0; i
< count
; i
++)
693 if (strcaseeq(map
[i
].str
, buf
))
705 CALLBACK(parse_bool
, bool,
706 bool *out
, chunk_t v
)
715 { "disabled", FALSE
},
720 if (parse_map(map
, countof(map
), &d
, v
))
729 * Parse a ipsec_mode_t
731 CALLBACK(parse_mode
, bool,
732 ipsec_mode_t
*out
, chunk_t v
)
735 { "tunnel", MODE_TUNNEL
},
736 { "transport", MODE_TRANSPORT
},
737 { "beet", MODE_BEET
},
738 { "drop", MODE_DROP
},
739 { "pass", MODE_PASS
},
743 if (parse_map(map
, countof(map
), &d
, v
))
754 CALLBACK(parse_action
, bool,
755 action_t
*out
, chunk_t v
)
758 { "start", ACTION_RESTART
},
759 { "restart", ACTION_RESTART
},
760 { "route", ACTION_ROUTE
},
761 { "trap", ACTION_ROUTE
},
762 { "none", ACTION_NONE
},
763 { "clear", ACTION_NONE
},
767 if (parse_map(map
, countof(map
), &d
, v
))
778 CALLBACK(parse_uint32
, bool,
779 u_int32_t
*out
, chunk_t v
)
784 if (!vici_stringify(v
, buf
, sizeof(buf
)))
788 l
= strtoul(buf
, &end
, 0);
800 CALLBACK(parse_uint64
, bool,
801 u_int64_t
*out
, chunk_t v
)
804 unsigned long long l
;
806 if (!vici_stringify(v
, buf
, sizeof(buf
)))
810 l
= strtoull(buf
, &end
, 0);
820 * Parse a relative time
822 CALLBACK(parse_time
, bool,
823 u_int64_t
*out
, chunk_t v
)
828 if (!vici_stringify(v
, buf
, sizeof(buf
)))
833 l
= strtoul(buf
, &end
, 0);
872 CALLBACK(parse_bytes
, bool,
873 u_int64_t
*out
, chunk_t v
)
876 unsigned long long l
;
878 if (!vici_stringify(v
, buf
, sizeof(buf
)))
883 l
= strtoull(buf
, &end
, 0);
919 CALLBACK(parse_mark
, bool,
920 mark_t
*out
, chunk_t v
)
924 if (!vici_stringify(v
, buf
, sizeof(buf
)))
928 return mark_from_string(buf
, out
);
932 * Parse TFC padding option
934 CALLBACK(parse_tfc
, bool,
935 u_int32_t
*out
, chunk_t v
)
937 if (chunk_equals(v
, chunk_from_str("mtu")))
942 return parse_uint32(out
, v
);
946 * Parse authentication config
948 CALLBACK(parse_auth
, bool,
949 auth_cfg_t
*cfg
, chunk_t v
)
952 eap_vendor_type_t
*type
;
954 if (!vici_stringify(v
, buf
, sizeof(buf
)))
958 if (strpfx(buf
, "ike:") ||
959 strpfx(buf
, "pubkey") ||
960 strpfx(buf
, "rsa") ||
961 strpfx(buf
, "ecdsa") ||
962 strpfx(buf
, "bliss"))
964 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
965 cfg
->add_pubkey_constraints(cfg
, buf
, TRUE
);
968 if (strcaseeq(buf
, "psk"))
970 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PSK
);
973 if (strcasepfx(buf
, "xauth"))
975 pos
= strchr(buf
, '-');
978 cfg
->add(cfg
, AUTH_RULE_XAUTH_BACKEND
, strdup(++pos
));
980 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_XAUTH
);
983 if (strcasepfx(buf
, "eap"))
985 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_EAP
);
987 type
= eap_vendor_type_from_string(buf
);
990 cfg
->add(cfg
, AUTH_RULE_EAP_TYPE
, type
->type
);
993 cfg
->add(cfg
, AUTH_RULE_EAP_VENDOR
, type
->vendor
);
1003 * Parse identity; add as auth rule to config
1005 static bool parse_id(auth_cfg_t
*cfg
, auth_rule_t rule
, chunk_t v
)
1009 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1013 cfg
->add(cfg
, rule
, identification_create_from_string(buf
));
1018 * Parse IKE identity
1020 CALLBACK(parse_ike_id
, bool,
1021 auth_cfg_t
*cfg
, chunk_t v
)
1023 return parse_id(cfg
, AUTH_RULE_IDENTITY
, v
);
1027 * Parse AAA identity
1029 CALLBACK(parse_aaa_id
, bool,
1030 auth_cfg_t
*cfg
, chunk_t v
)
1032 return parse_id(cfg
, AUTH_RULE_AAA_IDENTITY
, v
);
1036 * Parse EAP identity
1038 CALLBACK(parse_eap_id
, bool,
1039 auth_cfg_t
*cfg
, chunk_t v
)
1041 return parse_id(cfg
, AUTH_RULE_EAP_IDENTITY
, v
);
1045 * Parse XAuth identity
1047 CALLBACK(parse_xauth_id
, bool,
1048 auth_cfg_t
*cfg
, chunk_t v
)
1050 return parse_id(cfg
, AUTH_RULE_XAUTH_IDENTITY
, v
);
1054 * Parse group membership
1056 CALLBACK(parse_group
, bool,
1057 auth_cfg_t
*cfg
, chunk_t v
)
1059 return parse_id(cfg
, AUTH_RULE_GROUP
, v
);
1063 * Parse a certificate; add as auth rule to config
1065 static bool parse_cert(auth_data_t
*auth
, auth_rule_t rule
, chunk_t v
)
1067 vici_authority_t
*authority
;
1069 certificate_t
*cert
;
1071 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
1072 BUILD_BLOB_PEM
, v
, BUILD_END
);
1075 if (rule
== AUTH_RULE_SUBJECT_CERT
)
1077 authority
= auth
->request
->this->authority
;
1078 authority
->check_for_hash_and_url(authority
, cert
);
1080 cred
= auth
->request
->this->cred
;
1081 cert
= cred
->add_cert(cred
, cert
);
1082 auth
->cfg
->add(auth
->cfg
, rule
, cert
);
1089 * Parse subject certificates
1091 CALLBACK(parse_certs
, bool,
1092 auth_data_t
*auth
, chunk_t v
)
1094 return parse_cert(auth
, AUTH_RULE_SUBJECT_CERT
, v
);
1098 * Parse CA certificates
1100 CALLBACK(parse_cacerts
, bool,
1101 auth_data_t
*auth
, chunk_t v
)
1103 return parse_cert(auth
, AUTH_RULE_CA_CERT
, v
);
1107 * Parse raw public keys
1109 CALLBACK(parse_pubkeys
, bool,
1110 auth_data_t
*auth
, chunk_t v
)
1113 certificate_t
*cert
;
1115 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_TRUSTED_PUBKEY
,
1116 BUILD_BLOB_PEM
, v
, BUILD_END
);
1119 cred
= auth
->request
->this->cred
;
1120 cert
= cred
->add_cert(cred
, cert
);
1121 auth
->cfg
->add(auth
->cfg
, AUTH_RULE_SUBJECT_CERT
, cert
);
1128 * Parse revocation status
1130 CALLBACK(parse_revocation
, bool,
1131 auth_cfg_t
*cfg
, chunk_t v
)
1133 enum_map_t map
[] = {
1134 { "strict", VALIDATION_GOOD
},
1135 { "ifuri", VALIDATION_SKIPPED
},
1136 { "relaxed", VALIDATION_FAILED
},
1140 if (parse_map(map
, countof(map
), &d
, v
))
1142 if (d
!= VALIDATION_FAILED
)
1144 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, d
);
1152 * Parse list items to comma separated strings
1154 CALLBACK(parse_stringlist
, bool,
1155 char **out
, chunk_t v
)
1159 if (!chunk_printable(v
, NULL
, ' '))
1166 if (asprintf(out
, "%s, %.*s", current
, (int)v
.len
, v
.ptr
) == -1)
1174 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
1183 * Parse an fragmentation_t
1185 CALLBACK(parse_frag
, bool,
1186 fragmentation_t
*out
, chunk_t v
)
1188 enum_map_t map
[] = {
1189 { "yes", FRAGMENTATION_YES
},
1190 { "no", FRAGMENTATION_NO
},
1191 { "force", FRAGMENTATION_FORCE
},
1195 if (parse_map(map
, countof(map
), &d
, v
))
1204 * Parse a cert_policy_t
1206 CALLBACK(parse_send_cert
, bool,
1207 cert_policy_t
*out
, chunk_t v
)
1209 enum_map_t map
[] = {
1210 { "ifasked", CERT_SEND_IF_ASKED
},
1211 { "always", CERT_ALWAYS_SEND
},
1212 { "never", CERT_NEVER_SEND
},
1216 if (parse_map(map
, countof(map
), &d
, v
))
1225 * Parse a unique_policy_t
1227 CALLBACK(parse_unique
, bool,
1228 unique_policy_t
*out
, chunk_t v
)
1230 enum_map_t map
[] = {
1231 { "never", UNIQUE_NEVER
},
1232 { "no", UNIQUE_NO
},
1233 { "replace", UNIQUE_REPLACE
},
1234 { "keep", UNIQUE_KEEP
},
1238 if (parse_map(map
, countof(map
), &d
, v
))
1247 * Parse host_t into a list
1249 CALLBACK(parse_hosts
, bool,
1250 linked_list_t
*list
, chunk_t v
)
1255 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1259 host
= host_create_from_string(buf
, 0);
1264 list
->insert_last(list
, host
);
1268 CALLBACK(child_li
, bool,
1269 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1271 parse_rule_t rules
[] = {
1272 { "ah_proposals", parse_ah_proposal
, child
->proposals
},
1273 { "esp_proposals", parse_esp_proposal
, child
->proposals
},
1274 { "local_ts", parse_ts
, child
->local_ts
},
1275 { "remote_ts", parse_ts
, child
->remote_ts
},
1278 return parse_rules(rules
, countof(rules
), name
, value
,
1279 &child
->request
->reply
);
1282 CALLBACK(child_kv
, bool,
1283 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1285 parse_rule_t rules
[] = {
1286 { "updown", parse_string
, &child
->updown
},
1287 { "hostaccess", parse_bool
, &child
->hostaccess
},
1288 { "mode", parse_mode
, &child
->mode
},
1289 { "policies", parse_bool
, &child
->policies
},
1290 { "replay_window", parse_uint32
, &child
->replay_window
},
1291 { "rekey_time", parse_time
, &child
->lft
.time
.rekey
},
1292 { "life_time", parse_time
, &child
->lft
.time
.life
},
1293 { "rand_time", parse_time
, &child
->lft
.time
.jitter
},
1294 { "rekey_bytes", parse_bytes
, &child
->lft
.bytes
.rekey
},
1295 { "life_bytes", parse_bytes
, &child
->lft
.bytes
.life
},
1296 { "rand_bytes", parse_bytes
, &child
->lft
.bytes
.jitter
},
1297 { "rekey_packets", parse_uint64
, &child
->lft
.packets
.rekey
},
1298 { "life_packets", parse_uint64
, &child
->lft
.packets
.life
},
1299 { "rand_packets", parse_uint64
, &child
->lft
.packets
.jitter
},
1300 { "dpd_action", parse_action
, &child
->dpd_action
},
1301 { "start_action", parse_action
, &child
->start_action
},
1302 { "close_action", parse_action
, &child
->close_action
},
1303 { "ipcomp", parse_bool
, &child
->ipcomp
},
1304 { "inactivity", parse_time
, &child
->inactivity
},
1305 { "reqid", parse_uint32
, &child
->reqid
},
1306 { "mark_in", parse_mark
, &child
->mark_in
},
1307 { "mark_out", parse_mark
, &child
->mark_out
},
1308 { "tfc_padding", parse_tfc
, &child
->tfc
},
1311 return parse_rules(rules
, countof(rules
), name
, value
,
1312 &child
->request
->reply
);
1315 CALLBACK(auth_li
, bool,
1316 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1318 parse_rule_t rules
[] = {
1319 { "groups", parse_group
, auth
->cfg
},
1320 { "certs", parse_certs
, auth
},
1321 { "cacerts", parse_cacerts
, auth
},
1322 { "pubkeys", parse_pubkeys
, auth
},
1325 return parse_rules(rules
, countof(rules
), name
, value
,
1326 &auth
->request
->reply
);
1329 CALLBACK(auth_kv
, bool,
1330 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1332 parse_rule_t rules
[] = {
1333 { "auth", parse_auth
, auth
->cfg
},
1334 { "id", parse_ike_id
, auth
->cfg
},
1335 { "aaa_id", parse_aaa_id
, auth
->cfg
},
1336 { "eap_id", parse_eap_id
, auth
->cfg
},
1337 { "xauth_id", parse_xauth_id
, auth
->cfg
},
1338 { "revocation", parse_revocation
, auth
->cfg
},
1341 return parse_rules(rules
, countof(rules
), name
, value
,
1342 &auth
->request
->reply
);
1345 CALLBACK(peer_li
, bool,
1346 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1348 parse_rule_t rules
[] = {
1349 { "local_addrs", parse_stringlist
, &peer
->local_addrs
},
1350 { "remote_addrs", parse_stringlist
, &peer
->remote_addrs
},
1351 { "proposals", parse_ike_proposal
, peer
->proposals
},
1352 { "vips", parse_hosts
, peer
->vips
},
1353 { "pools", parse_stringlist
, &peer
->pools
},
1356 return parse_rules(rules
, countof(rules
), name
, value
,
1357 &peer
->request
->reply
);
1360 CALLBACK(peer_kv
, bool,
1361 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1363 parse_rule_t rules
[] = {
1364 { "version", parse_uint32
, &peer
->version
},
1365 { "aggressive", parse_bool
, &peer
->aggressive
},
1366 { "pull", parse_bool
, &peer
->pull
},
1367 { "encap", parse_bool
, &peer
->encap
},
1368 { "mobike", parse_bool
, &peer
->mobike
},
1369 { "dpd_delay", parse_time
, &peer
->dpd_delay
},
1370 { "dpd_timeout", parse_time
, &peer
->dpd_timeout
},
1371 { "fragmentation", parse_frag
, &peer
->fragmentation
},
1372 { "send_certreq", parse_bool
, &peer
->send_certreq
},
1373 { "send_cert", parse_send_cert
, &peer
->send_cert
},
1374 { "keyingtries", parse_uint32
, &peer
->keyingtries
},
1375 { "unique", parse_unique
, &peer
->unique
},
1376 { "local_port", parse_uint32
, &peer
->local_port
},
1377 { "remote_port", parse_uint32
, &peer
->remote_port
},
1378 { "reauth_time", parse_time
, &peer
->reauth_time
},
1379 { "rekey_time", parse_time
, &peer
->rekey_time
},
1380 { "over_time", parse_time
, &peer
->over_time
},
1381 { "rand_time", parse_time
, &peer
->rand_time
},
1384 return parse_rules(rules
, countof(rules
), name
, value
,
1385 &peer
->request
->reply
);
1388 CALLBACK(children_sn
, bool,
1389 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1392 child_data_t child
= {
1393 .request
= peer
->request
,
1394 .proposals
= linked_list_create(),
1395 .local_ts
= linked_list_create(),
1396 .remote_ts
= linked_list_create(),
1397 .mode
= MODE_TUNNEL
,
1399 .replay_window
= REPLAY_UNDEFINED
,
1400 .dpd_action
= ACTION_NONE
,
1401 .start_action
= ACTION_NONE
,
1402 .close_action
= ACTION_NONE
,
1405 .rekey
= LFT_DEFAULT_CHILD_REKEY
,
1406 .life
= LFT_UNDEFINED
,
1407 .jitter
= LFT_UNDEFINED
,
1410 .rekey
= LFT_UNDEFINED
,
1411 .life
= LFT_UNDEFINED
,
1412 .jitter
= LFT_UNDEFINED
,
1415 .rekey
= LFT_UNDEFINED
,
1416 .life
= LFT_UNDEFINED
,
1417 .jitter
= LFT_UNDEFINED
,
1422 proposal_t
*proposal
;
1423 traffic_selector_t
*ts
;
1425 if (!message
->parse(message
, ctx
, NULL
, child_kv
, child_li
, &child
))
1427 free_child_data(&child
);
1431 if (child
.local_ts
->get_count(child
.local_ts
) == 0)
1433 child
.local_ts
->insert_last(child
.local_ts
,
1434 traffic_selector_create_dynamic(0, 0, 65535));
1436 if (child
.remote_ts
->get_count(child
.remote_ts
) == 0)
1438 child
.remote_ts
->insert_last(child
.remote_ts
,
1439 traffic_selector_create_dynamic(0, 0, 65535));
1441 if (child
.proposals
->get_count(child
.proposals
) == 0)
1443 proposal
= proposal_create_default(PROTO_ESP
);
1446 child
.proposals
->insert_last(child
.proposals
, proposal
);
1448 proposal
= proposal_create_default_aead(PROTO_ESP
);
1451 child
.proposals
->insert_last(child
.proposals
, proposal
);
1455 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1456 if (child
.lft
.time
.life
== LFT_UNDEFINED
)
1458 child
.lft
.time
.life
= child
.lft
.time
.rekey
* 110 / 100;
1460 if (child
.lft
.bytes
.life
== LFT_UNDEFINED
)
1462 child
.lft
.bytes
.life
= child
.lft
.bytes
.rekey
* 110 / 100;
1464 if (child
.lft
.packets
.life
== LFT_UNDEFINED
)
1466 child
.lft
.packets
.life
= child
.lft
.packets
.rekey
* 110 / 100;
1468 /* if no soft lifetime specified, add one at hard lifetime - 10% */
1469 if (child
.lft
.bytes
.rekey
== LFT_UNDEFINED
)
1471 child
.lft
.bytes
.rekey
= child
.lft
.bytes
.life
* 90 / 100;
1473 if (child
.lft
.packets
.rekey
== LFT_UNDEFINED
)
1475 child
.lft
.packets
.rekey
= child
.lft
.packets
.life
* 90 / 100;
1477 /* if no rand time defined, use difference of hard and soft */
1478 if (child
.lft
.time
.jitter
== LFT_UNDEFINED
)
1480 child
.lft
.time
.jitter
= child
.lft
.time
.life
-
1481 min(child
.lft
.time
.life
, child
.lft
.time
.rekey
);
1483 if (child
.lft
.bytes
.jitter
== LFT_UNDEFINED
)
1485 child
.lft
.bytes
.jitter
= child
.lft
.bytes
.life
-
1486 min(child
.lft
.bytes
.life
, child
.lft
.bytes
.rekey
);
1488 if (child
.lft
.packets
.jitter
== LFT_UNDEFINED
)
1490 child
.lft
.packets
.jitter
= child
.lft
.packets
.life
-
1491 min(child
.lft
.packets
.life
, child
.lft
.packets
.rekey
);
1494 log_child_data(&child
, name
);
1496 cfg
= child_cfg_create(name
, &child
.lft
, child
.updown
,
1497 child
.hostaccess
, child
.mode
, child
.start_action
,
1498 child
.dpd_action
, child
.close_action
, child
.ipcomp
,
1499 child
.inactivity
, child
.reqid
, &child
.mark_in
,
1500 &child
.mark_out
, child
.tfc
);
1502 cfg
->set_mipv6_options(cfg
, FALSE
, child
.policies
);
1504 if (child
.replay_window
!= REPLAY_UNDEFINED
)
1506 cfg
->set_replay_window(cfg
, child
.replay_window
);
1508 while (child
.local_ts
->remove_first(child
.local_ts
,
1509 (void**)&ts
) == SUCCESS
)
1511 cfg
->add_traffic_selector(cfg
, TRUE
, ts
);
1513 while (child
.remote_ts
->remove_first(child
.remote_ts
,
1514 (void**)&ts
) == SUCCESS
)
1516 cfg
->add_traffic_selector(cfg
, FALSE
, ts
);
1518 while (child
.proposals
->remove_first(child
.proposals
,
1519 (void**)&proposal
) == SUCCESS
)
1521 cfg
->add_proposal(cfg
, proposal
);
1524 peer
->children
->insert_last(peer
->children
, cfg
);
1526 free_child_data(&child
);
1531 CALLBACK(peer_sn
, bool,
1532 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1535 if (strcaseeq(name
, "children"))
1537 return message
->parse(message
, ctx
, children_sn
, NULL
, NULL
, peer
);
1539 if (strcasepfx(name
, "local") ||
1540 strcasepfx(name
, "remote"))
1542 auth_data_t auth
= {
1543 .request
= peer
->request
,
1544 .cfg
= auth_cfg_create(),
1547 certificate_t
*cert
;
1548 pubkey_cert_t
*pubkey_cert
;
1549 identification_t
*id
;
1550 enumerator_t
*enumerator
;
1551 bool default_id
= FALSE
;
1553 if (!message
->parse(message
, ctx
, NULL
, auth_kv
, auth_li
, &auth
))
1555 auth
.cfg
->destroy(auth
.cfg
);
1558 id
= auth
.cfg
->get(auth
.cfg
, AUTH_RULE_IDENTITY
);
1560 enumerator
= auth
.cfg
->create_enumerator(auth
.cfg
);
1561 while (enumerator
->enumerate(enumerator
, &rule
, &cert
))
1563 if (rule
== AUTH_RULE_SUBJECT_CERT
&& !default_id
)
1567 id
= cert
->get_subject(cert
);
1568 DBG1(DBG_CFG
, " id not specified, defaulting to"
1569 " cert subject '%Y'", id
);
1570 auth
.cfg
->add(auth
.cfg
, AUTH_RULE_IDENTITY
, id
->clone(id
));
1573 else if (cert
->get_type(cert
) == CERT_TRUSTED_PUBKEY
&&
1574 id
->get_type
!= ID_ANY
)
1576 /* set the subject of all raw public keys to the id */
1577 pubkey_cert
= (pubkey_cert_t
*)cert
;
1578 pubkey_cert
->set_subject(pubkey_cert
, id
);
1582 enumerator
->destroy(enumerator
);
1584 if (strcasepfx(name
, "local"))
1586 peer
->local
->insert_last(peer
->local
, auth
.cfg
);
1590 peer
->remote
->insert_last(peer
->remote
, auth
.cfg
);
1594 peer
->request
->reply
= create_reply("invalid section: %s", name
);
1599 * Find reqid of an existing CHILD_SA
1601 static u_int32_t
find_reqid(child_cfg_t
*cfg
)
1603 enumerator_t
*enumerator
, *children
;
1604 child_sa_t
*child_sa
;
1608 reqid
= charon
->traps
->find_reqid(charon
->traps
, cfg
);
1610 { /* already trapped */
1614 enumerator
= charon
->controller
->create_ike_sa_enumerator(
1615 charon
->controller
, TRUE
);
1616 while (!reqid
&& enumerator
->enumerate(enumerator
, &ike_sa
))
1618 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
1619 while (children
->enumerate(children
, &child_sa
))
1621 if (streq(cfg
->get_name(cfg
), child_sa
->get_name(child_sa
)))
1623 reqid
= child_sa
->get_reqid(child_sa
);
1627 children
->destroy(children
);
1629 enumerator
->destroy(enumerator
);
1634 * Perform start actions associated to a child config
1636 static void run_start_action(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
,
1637 child_cfg_t
*child_cfg
)
1639 switch (child_cfg
->get_start_action(child_cfg
))
1641 case ACTION_RESTART
:
1642 DBG1(DBG_CFG
, "initiating '%s'", child_cfg
->get_name(child_cfg
));
1643 charon
->controller
->initiate(charon
->controller
,
1644 peer_cfg
->get_ref(peer_cfg
), child_cfg
->get_ref(child_cfg
),
1645 NULL
, NULL
, 0, FALSE
);
1648 DBG1(DBG_CFG
, "installing '%s'", child_cfg
->get_name(child_cfg
));
1649 switch (child_cfg
->get_mode(child_cfg
))
1653 charon
->shunts
->install(charon
->shunts
, child_cfg
);
1656 charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
,
1657 find_reqid(child_cfg
));
1667 * Undo start actions associated to a child config
1669 static void clear_start_action(private_vici_config_t
*this, char *peer_name
,
1670 child_cfg_t
*child_cfg
)
1672 enumerator_t
*enumerator
, *children
;
1673 child_sa_t
*child_sa
;
1675 u_int32_t id
= 0, others
;
1676 array_t
*ids
= NULL
, *ikeids
= NULL
;
1679 name
= child_cfg
->get_name(child_cfg
);
1680 switch (child_cfg
->get_start_action(child_cfg
))
1682 case ACTION_RESTART
:
1683 enumerator
= charon
->controller
->create_ike_sa_enumerator(
1684 charon
->controller
, TRUE
);
1685 while (enumerator
->enumerate(enumerator
, &ike_sa
))
1687 if (!streq(ike_sa
->get_name(ike_sa
), peer_name
))
1692 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
1693 while (children
->enumerate(children
, &child_sa
))
1695 if (child_sa
->get_state(child_sa
) != CHILD_DELETING
)
1697 if (streq(name
, child_sa
->get_name(child_sa
)))
1699 id
= child_sa
->get_unique_id(child_sa
);
1707 children
->destroy(children
);
1711 /* found matching children only, delete full IKE_SA */
1712 id
= ike_sa
->get_unique_id(ike_sa
);
1713 array_insert_create_value(&ikeids
, sizeof(id
),
1718 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
1719 while (children
->enumerate(children
, &child_sa
))
1721 if (streq(name
, child_sa
->get_name(child_sa
)))
1723 id
= child_sa
->get_unique_id(child_sa
);
1724 array_insert_create_value(&ids
, sizeof(id
),
1728 children
->destroy(children
);
1731 enumerator
->destroy(enumerator
);
1733 if (array_count(ids
))
1735 while (array_remove(ids
, ARRAY_HEAD
, &id
))
1737 DBG1(DBG_CFG
, "closing '%s' #%u", name
, id
);
1738 charon
->controller
->terminate_child(charon
->controller
,
1743 if (array_count(ikeids
))
1745 while (array_remove(ikeids
, ARRAY_HEAD
, &id
))
1747 DBG1(DBG_CFG
, "closing IKE_SA #%u", id
);
1748 charon
->controller
->terminate_ike(charon
->controller
,
1751 array_destroy(ikeids
);
1755 DBG1(DBG_CFG
, "uninstalling '%s'", name
);
1756 switch (child_cfg
->get_mode(child_cfg
))
1760 charon
->shunts
->uninstall(charon
->shunts
, name
);
1763 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
1764 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
1766 if (streq(name
, child_sa
->get_name(child_sa
)))
1768 id
= child_sa
->get_reqid(child_sa
);
1772 enumerator
->destroy(enumerator
);
1775 charon
->traps
->uninstall(charon
->traps
, id
);
1786 * Run start actions associated to all child configs of a peer config
1788 static void run_start_actions(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
)
1790 enumerator_t
*enumerator
;
1791 child_cfg_t
*child_cfg
;
1793 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
1794 while (enumerator
->enumerate(enumerator
, &child_cfg
))
1796 run_start_action(this, peer_cfg
, child_cfg
);
1798 enumerator
->destroy(enumerator
);
1802 * Undo start actions associated to all child configs of a peer config
1804 static void clear_start_actions(private_vici_config_t
*this,
1805 peer_cfg_t
*peer_cfg
)
1807 enumerator_t
*enumerator
;
1808 child_cfg_t
*child_cfg
;
1810 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
1811 while (enumerator
->enumerate(enumerator
, &child_cfg
))
1813 clear_start_action(this, peer_cfg
->get_name(peer_cfg
), child_cfg
);
1815 enumerator
->destroy(enumerator
);
1819 * Replace children of a peer config by a new config
1821 static void replace_children(private_vici_config_t
*this,
1822 peer_cfg_t
*from
, peer_cfg_t
*to
)
1824 enumerator_t
*enumerator
;
1827 enumerator
= to
->create_child_cfg_enumerator(to
);
1828 while (enumerator
->enumerate(enumerator
, &child
))
1830 to
->remove_child_cfg(to
, enumerator
);
1831 clear_start_action(this, to
->get_name(to
), child
);
1832 child
->destroy(child
);
1834 enumerator
->destroy(enumerator
);
1836 enumerator
= from
->create_child_cfg_enumerator(from
);
1837 while (enumerator
->enumerate(enumerator
, &child
))
1839 from
->remove_child_cfg(from
, enumerator
);
1840 to
->add_child_cfg(to
, child
);
1841 run_start_action(this, to
, child
);
1843 enumerator
->destroy(enumerator
);
1847 * Merge/replace a peer config with existing configs
1849 static void merge_config(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
)
1851 enumerator_t
*enumerator
;
1852 peer_cfg_t
*current
;
1854 bool merged
= FALSE
;
1856 this->lock
->write_lock(this->lock
);
1858 enumerator
= this->conns
->create_enumerator(this->conns
);
1859 while (enumerator
->enumerate(enumerator
, ¤t
))
1861 if (streq(peer_cfg
->get_name(peer_cfg
), current
->get_name(current
)))
1863 ike_cfg
= current
->get_ike_cfg(current
);
1864 if (peer_cfg
->equals(peer_cfg
, current
) &&
1865 ike_cfg
->equals(ike_cfg
, peer_cfg
->get_ike_cfg(peer_cfg
)))
1867 DBG1(DBG_CFG
, "updated vici connection: %s",
1868 peer_cfg
->get_name(peer_cfg
));
1869 replace_children(this, peer_cfg
, current
);
1870 peer_cfg
->destroy(peer_cfg
);
1874 DBG1(DBG_CFG
, "replaced vici connection: %s",
1875 peer_cfg
->get_name(peer_cfg
));
1876 this->conns
->remove_at(this->conns
, enumerator
);
1877 clear_start_actions(this, current
);
1878 current
->destroy(current
);
1879 this->conns
->insert_last(this->conns
, peer_cfg
);
1880 run_start_actions(this, peer_cfg
);
1886 enumerator
->destroy(enumerator
);
1890 DBG1(DBG_CFG
, "added vici connection: %s", peer_cfg
->get_name(peer_cfg
));
1891 this->conns
->insert_last(this->conns
, peer_cfg
);
1892 run_start_actions(this, peer_cfg
);
1895 this->lock
->unlock(this->lock
);
1898 CALLBACK(config_sn
, bool,
1899 request_data_t
*request
, vici_message_t
*message
,
1900 vici_parse_context_t
*ctx
, char *name
)
1902 peer_data_t peer
= {
1904 .local
= linked_list_create(),
1905 .remote
= linked_list_create(),
1906 .vips
= linked_list_create(),
1907 .children
= linked_list_create(),
1908 .proposals
= linked_list_create(),
1910 .send_certreq
= TRUE
,
1912 .send_cert
= CERT_SEND_IF_ASKED
,
1914 .remote_port
= IKEV2_UDP_PORT
,
1915 .fragmentation
= FRAGMENTATION_NO
,
1916 .unique
= UNIQUE_NO
,
1918 .rekey_time
= LFT_UNDEFINED
,
1919 .reauth_time
= LFT_UNDEFINED
,
1920 .over_time
= LFT_UNDEFINED
,
1921 .rand_time
= LFT_UNDEFINED
,
1923 enumerator_t
*enumerator
;
1924 peer_cfg_t
*peer_cfg
;
1926 child_cfg_t
*child_cfg
;
1927 auth_cfg_t
*auth_cfg
;
1928 proposal_t
*proposal
;
1932 DBG2(DBG_CFG
, " conn %s:", name
);
1934 if (!message
->parse(message
, ctx
, peer_sn
, peer_kv
, peer_li
, &peer
))
1936 free_peer_data(&peer
);
1940 if (peer
.local
->get_count(peer
.local
) == 0)
1942 auth_cfg
= auth_cfg_create();
1943 peer
.local
->insert_last(peer
.local
, auth_cfg
);
1945 if (peer
.remote
->get_count(peer
.remote
) == 0)
1947 auth_cfg
= auth_cfg_create();
1948 peer
.remote
->insert_last(peer
.remote
, auth_cfg
);
1950 if (peer
.proposals
->get_count(peer
.proposals
) == 0)
1952 proposal
= proposal_create_default(PROTO_IKE
);
1955 peer
.proposals
->insert_last(peer
.proposals
, proposal
);
1957 proposal
= proposal_create_default_aead(PROTO_IKE
);
1960 peer
.proposals
->insert_last(peer
.proposals
, proposal
);
1963 if (!peer
.local_addrs
)
1965 peer
.local_addrs
= strdup("%any");
1967 if (!peer
.remote_addrs
)
1969 peer
.remote_addrs
= strdup("%any");
1971 if (!peer
.local_port
)
1973 peer
.local_port
= charon
->socket
->get_port(charon
->socket
, FALSE
);
1976 if (peer
.rekey_time
== LFT_UNDEFINED
&& peer
.reauth_time
== LFT_UNDEFINED
)
1978 /* apply a default rekey time if no rekey/reauth time set */
1979 peer
.rekey_time
= LFT_DEFAULT_IKE_REKEY
;
1980 peer
.reauth_time
= 0;
1982 if (peer
.rekey_time
== LFT_UNDEFINED
)
1984 peer
.rekey_time
= 0;
1986 if (peer
.reauth_time
== LFT_UNDEFINED
)
1988 peer
.reauth_time
= 0;
1990 if (peer
.over_time
== LFT_UNDEFINED
)
1992 /* default over_time to 10% of rekey/reauth time if not given */
1993 peer
.over_time
= max(peer
.rekey_time
, peer
.reauth_time
) / 10;
1995 if (peer
.rand_time
== LFT_UNDEFINED
)
1997 /* default rand_time to over_time if not given, but don't make it
1998 * longer than half of rekey/rauth time */
1999 if (peer
.rekey_time
&& peer
.reauth_time
)
2001 peer
.rand_time
= min(peer
.rekey_time
, peer
.reauth_time
);
2005 peer
.rand_time
= max(peer
.rekey_time
, peer
.reauth_time
);
2007 peer
.rand_time
= min(peer
.over_time
, peer
.rand_time
/ 2);
2010 log_peer_data(&peer
);
2012 ike_cfg
= ike_cfg_create(peer
.version
, peer
.send_certreq
, peer
.encap
,
2013 peer
.local_addrs
, peer
.local_port
,
2014 peer
.remote_addrs
, peer
.remote_port
,
2015 peer
.fragmentation
, 0);
2016 peer_cfg
= peer_cfg_create(name
, ike_cfg
, peer
.send_cert
, peer
.unique
,
2017 peer
.keyingtries
, peer
.rekey_time
, peer
.reauth_time
,
2018 peer
.rand_time
, peer
.over_time
, peer
.mobike
,
2019 peer
.aggressive
, peer
.pull
,
2020 peer
.dpd_delay
, peer
.dpd_timeout
,
2023 while (peer
.local
->remove_first(peer
.local
,
2024 (void**)&auth_cfg
) == SUCCESS
)
2026 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, TRUE
);
2028 while (peer
.remote
->remove_first(peer
.remote
,
2029 (void**)&auth_cfg
) == SUCCESS
)
2031 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, FALSE
);
2033 while (peer
.children
->remove_first(peer
.children
,
2034 (void**)&child_cfg
) == SUCCESS
)
2036 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
2038 while (peer
.proposals
->remove_first(peer
.proposals
,
2039 (void**)&proposal
) == SUCCESS
)
2041 ike_cfg
->add_proposal(ike_cfg
, proposal
);
2043 while (peer
.vips
->remove_first(peer
.vips
, (void**)&host
) == SUCCESS
)
2045 peer_cfg
->add_virtual_ip(peer_cfg
, host
);
2049 enumerator
= enumerator_create_token(peer
.pools
, ",", " ");
2050 while (enumerator
->enumerate(enumerator
, &str
))
2052 peer_cfg
->add_pool(peer_cfg
, str
);
2054 enumerator
->destroy(enumerator
);
2057 free_peer_data(&peer
);
2059 merge_config(request
->this, peer_cfg
);
2064 CALLBACK(load_conn
, vici_message_t
*,
2065 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2067 request_data_t request
= {
2071 if (!message
->parse(message
, NULL
, config_sn
, NULL
, NULL
, &request
))
2075 return request
.reply
;
2077 return create_reply("parsing request failed");
2079 return create_reply(NULL
);
2082 CALLBACK(unload_conn
, vici_message_t
*,
2083 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2085 enumerator_t
*enumerator
;
2090 conn_name
= message
->get_str(message
, NULL
, "name");
2093 return create_reply("unload: missing connection name");
2096 this->lock
->write_lock(this->lock
);
2097 enumerator
= this->conns
->create_enumerator(this->conns
);
2098 while (enumerator
->enumerate(enumerator
, &cfg
))
2100 if (streq(cfg
->get_name(cfg
), conn_name
))
2102 this->conns
->remove_at(this->conns
, enumerator
);
2103 clear_start_actions(this, cfg
);
2109 enumerator
->destroy(enumerator
);
2110 this->lock
->unlock(this->lock
);
2114 return create_reply("unload: connection '%s' not found", conn_name
);
2116 return create_reply(NULL
);
2119 CALLBACK(get_conns
, vici_message_t
*,
2120 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2122 vici_builder_t
*builder
;
2123 enumerator_t
*enumerator
;
2126 builder
= vici_builder_create();
2127 builder
->begin_list(builder
, "conns");
2129 this->lock
->read_lock(this->lock
);
2130 enumerator
= this->conns
->create_enumerator(this->conns
);
2131 while (enumerator
->enumerate(enumerator
, &cfg
))
2133 builder
->add_li(builder
, "%s", cfg
->get_name(cfg
));
2135 enumerator
->destroy(enumerator
);
2136 this->lock
->unlock(this->lock
);
2138 builder
->end_list(builder
);
2140 return builder
->finalize(builder
);
2143 static void manage_command(private_vici_config_t
*this,
2144 char *name
, vici_command_cb_t cb
, bool reg
)
2146 this->dispatcher
->manage_command(this->dispatcher
, name
,
2147 reg
? cb
: NULL
, this);
2151 * (Un-)register dispatcher functions
2153 static void manage_commands(private_vici_config_t
*this, bool reg
)
2155 manage_command(this, "load-conn", load_conn
, reg
);
2156 manage_command(this, "unload-conn", unload_conn
, reg
);
2157 manage_command(this, "get-conns", get_conns
, reg
);
2160 METHOD(vici_config_t
, destroy
, void,
2161 private_vici_config_t
*this)
2163 manage_commands(this, FALSE
);
2164 this->conns
->destroy_offset(this->conns
, offsetof(peer_cfg_t
, destroy
));
2165 this->lock
->destroy(this->lock
);
2172 vici_config_t
*vici_config_create(vici_dispatcher_t
*dispatcher
,
2173 vici_authority_t
*authority
,
2176 private_vici_config_t
*this;
2181 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
2182 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
2183 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
2185 .destroy
= _destroy
,
2187 .dispatcher
= dispatcher
,
2188 .conns
= linked_list_create(),
2189 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
2190 .authority
= authority
,
2194 manage_commands(this, TRUE
);
2196 return &this->public;