2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "stroke_config.h"
21 #include <threading/mutex.h>
22 #include <utils/lexparser.h>
24 typedef struct private_stroke_config_t private_stroke_config_t
;
27 * private data of stroke_config
29 struct private_stroke_config_t
{
34 stroke_config_t
public;
42 * mutex to lock config list
57 * Virtual IP pool / DNS backend
59 stroke_attribute_t
*attributes
;
62 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
63 private_stroke_config_t
*this, identification_t
*me
, identification_t
*other
)
65 this->mutex
->lock(this->mutex
);
66 return enumerator_create_cleaner(this->list
->create_enumerator(this->list
),
67 (void*)this->mutex
->unlock
, this->mutex
);
71 * filter function for ike configs
73 static bool ike_filter(void *data
, peer_cfg_t
**in
, ike_cfg_t
**out
)
75 *out
= (*in
)->get_ike_cfg(*in
);
79 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
80 private_stroke_config_t
*this, host_t
*me
, host_t
*other
)
82 this->mutex
->lock(this->mutex
);
83 return enumerator_create_filter(this->list
->create_enumerator(this->list
),
84 (void*)ike_filter
, this->mutex
,
85 (void*)this->mutex
->unlock
);
88 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
89 private_stroke_config_t
*this, char *name
)
91 enumerator_t
*e1
, *e2
;
92 peer_cfg_t
*current
, *found
= NULL
;
95 this->mutex
->lock(this->mutex
);
96 e1
= this->list
->create_enumerator(this->list
);
97 while (e1
->enumerate(e1
, ¤t
))
99 /* compare peer_cfgs name first */
100 if (streq(current
->get_name(current
), name
))
103 found
->get_ref(found
);
106 /* compare all child_cfg names otherwise */
107 e2
= current
->create_child_cfg_enumerator(current
);
108 while (e2
->enumerate(e2
, &child
))
110 if (streq(child
->get_name(child
), name
))
113 found
->get_ref(found
);
124 this->mutex
->unlock(this->mutex
);
129 * parse a proposal string, either into ike_cfg or child_cfg
131 static void add_proposals(private_stroke_config_t
*this, char *string
,
132 ike_cfg_t
*ike_cfg
, child_cfg_t
*child_cfg
)
138 proposal_t
*proposal
;
139 protocol_id_t proto
= PROTO_ESP
;
145 strict
= string
+ strlen(string
) - 1;
154 while ((single
= strsep(&string
, ",")))
156 proposal
= proposal_create_from_string(proto
, single
);
161 ike_cfg
->add_proposal(ike_cfg
, proposal
);
165 child_cfg
->add_proposal(child_cfg
, proposal
);
169 DBG1(DBG_CFG
, "skipped invalid proposal string: %s", single
);
175 /* add default porposal to the end if not strict */
179 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default(PROTO_IKE
));
183 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
188 * Build an IKE config from a stroke message
190 static ike_cfg_t
*build_ike_cfg(private_stroke_config_t
*this, stroke_msg_t
*msg
)
192 stroke_end_t tmp_end
;
197 host
= host_create_from_dns(msg
->add_conn
.other
.address
, 0, 0);
200 if (hydra
->kernel_interface
->get_interface(hydra
->kernel_interface
,
203 DBG2(DBG_CFG
, "left is other host, swapping ends");
204 tmp_end
= msg
->add_conn
.me
;
205 msg
->add_conn
.me
= msg
->add_conn
.other
;
206 msg
->add_conn
.other
= tmp_end
;
212 host
= host_create_from_dns(msg
->add_conn
.me
.address
, 0, 0);
215 if (!hydra
->kernel_interface
->get_interface(
216 hydra
->kernel_interface
, host
, NULL
))
218 DBG1(DBG_CFG
, "left nor right host is our side, "
219 "assuming left=local");
225 ikeport
= msg
->add_conn
.me
.ikeport
;
226 ikeport
= (ikeport
== IKEV2_UDP_PORT
) ?
227 charon
->socket
->get_port(charon
->socket
, FALSE
) : ikeport
;
228 ike_cfg
= ike_cfg_create(msg
->add_conn
.version
,
229 msg
->add_conn
.other
.sendcert
!= CERT_NEVER_SEND
,
230 msg
->add_conn
.force_encap
,
231 msg
->add_conn
.me
.address
,
232 msg
->add_conn
.me
.allow_any
,
234 msg
->add_conn
.other
.address
,
235 msg
->add_conn
.other
.allow_any
,
236 msg
->add_conn
.other
.ikeport
,
237 msg
->add_conn
.fragmentation
,
238 msg
->add_conn
.ikedscp
);
239 add_proposals(this, msg
->add_conn
.algorithms
.ike
, ike_cfg
, NULL
);
244 * Add CRL constraint to config
246 static void build_crl_policy(auth_cfg_t
*cfg
, bool local
, int policy
)
248 /* CRL/OCSP policy, for remote config only */
254 /* if yes, we require a GOOD validation */
255 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, VALIDATION_GOOD
);
257 case CRL_STRICT_IFURI
:
258 /* for ifuri, a SKIPPED validation is sufficient */
259 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, VALIDATION_SKIPPED
);
268 * Parse public key / signature strength constraints
270 static void parse_pubkey_constraints(char *auth
, auth_cfg_t
*cfg
)
272 enumerator_t
*enumerator
;
273 bool rsa
= FALSE
, ecdsa
= FALSE
, rsa_len
= FALSE
, ecdsa_len
= FALSE
;
277 enumerator
= enumerator_create_token(auth
, "-", "");
278 while (enumerator
->enumerate(enumerator
, &token
))
284 signature_scheme_t scheme
;
287 { "md5", SIGN_RSA_EMSA_PKCS1_MD5
, KEY_RSA
, },
288 { "sha1", SIGN_RSA_EMSA_PKCS1_SHA1
, KEY_RSA
, },
289 { "sha224", SIGN_RSA_EMSA_PKCS1_SHA224
, KEY_RSA
, },
290 { "sha256", SIGN_RSA_EMSA_PKCS1_SHA256
, KEY_RSA
, },
291 { "sha384", SIGN_RSA_EMSA_PKCS1_SHA384
, KEY_RSA
, },
292 { "sha512", SIGN_RSA_EMSA_PKCS1_SHA512
, KEY_RSA
, },
293 { "sha1", SIGN_ECDSA_WITH_SHA1_DER
, KEY_ECDSA
, },
294 { "sha256", SIGN_ECDSA_WITH_SHA256_DER
, KEY_ECDSA
, },
295 { "sha384", SIGN_ECDSA_WITH_SHA384_DER
, KEY_ECDSA
, },
296 { "sha512", SIGN_ECDSA_WITH_SHA512_DER
, KEY_ECDSA
, },
297 { "sha256", SIGN_ECDSA_256
, KEY_ECDSA
, },
298 { "sha384", SIGN_ECDSA_384
, KEY_ECDSA
, },
299 { "sha512", SIGN_ECDSA_521
, KEY_ECDSA
, },
302 if (rsa_len
|| ecdsa_len
)
303 { /* expecting a key strength token */
304 strength
= atoi(token
);
309 cfg
->add(cfg
, AUTH_RULE_RSA_STRENGTH
, (uintptr_t)strength
);
313 cfg
->add(cfg
, AUTH_RULE_ECDSA_STRENGTH
, (uintptr_t)strength
);
316 rsa_len
= ecdsa_len
= FALSE
;
322 if (streq(token
, "rsa"))
324 rsa
= rsa_len
= TRUE
;
327 if (streq(token
, "ecdsa"))
329 ecdsa
= ecdsa_len
= TRUE
;
332 if (streq(token
, "pubkey"))
337 for (i
= 0; i
< countof(schemes
); i
++)
339 if (streq(schemes
[i
].name
, token
))
341 /* for each matching string, allow the scheme, if:
342 * - it is an RSA scheme, and we enforced RSA
343 * - it is an ECDSA scheme, and we enforced ECDSA
344 * - it is not a key type specific scheme
346 if ((rsa
&& schemes
[i
].key
== KEY_RSA
) ||
347 (ecdsa
&& schemes
[i
].key
== KEY_ECDSA
) ||
350 cfg
->add(cfg
, AUTH_RULE_SIGNATURE_SCHEME
,
351 (uintptr_t)schemes
[i
].scheme
);
358 DBG1(DBG_CFG
, "ignoring invalid auth token: '%s'", token
);
361 enumerator
->destroy(enumerator
);
365 * build authentication config
367 static auth_cfg_t
*build_auth_cfg(private_stroke_config_t
*this,
368 stroke_msg_t
*msg
, bool local
, bool primary
)
370 identification_t
*identity
;
371 certificate_t
*certificate
;
372 char *auth
, *id
, *pubkey
, *cert
, *ca
, *groups
;
373 stroke_end_t
*end
, *other_end
;
380 end
= &msg
->add_conn
.me
;
381 other_end
= &msg
->add_conn
.other
;
385 end
= &msg
->add_conn
.other
;
386 other_end
= &msg
->add_conn
.me
;
393 { /* leftid/rightid fallback to address */
398 if (ca
&& streq(ca
, "%same"))
408 { /* leftid2 falls back to leftid */
413 if (ca
&& streq(ca
, "%same"))
418 if (id
&& *id
== '%' && !streq(id
, "%any") && !streq(id
, "%any6"))
419 { /* has only an effect on rightid/2 */
431 { /* no second authentication round, fine. But load certificates
432 * for other purposes (EAP-TLS) */
435 certificate
= this->cred
->load_peer(this->cred
, cert
);
438 certificate
->destroy(certificate
);
445 cfg
= auth_cfg_create();
447 /* add identity and peer certificate */
448 identity
= identification_create_from_string(id
);
451 enumerator_t
*enumerator
;
452 bool has_subject
= FALSE
;
453 certificate_t
*first
= NULL
;
455 enumerator
= enumerator_create_token(cert
, ",", " ");
456 while (enumerator
->enumerate(enumerator
, &cert
))
458 certificate
= this->cred
->load_peer(this->cred
, cert
);
463 this->ca
->check_for_hash_and_url(this->ca
, certificate
);
465 cfg
->add(cfg
, AUTH_RULE_SUBJECT_CERT
, certificate
);
470 if (identity
->get_type(identity
) != ID_ANY
&&
471 certificate
->has_subject(certificate
, identity
))
477 enumerator
->destroy(enumerator
);
479 if (first
&& !has_subject
)
481 DBG1(DBG_CFG
, " id '%Y' not confirmed by certificate, "
482 "defaulting to '%Y'", identity
, first
->get_subject(first
));
483 identity
->destroy(identity
);
484 identity
= first
->get_subject(first
);
485 identity
= identity
->clone(identity
);
488 /* add raw RSA public key */
489 pubkey
= end
->rsakey
;
490 if (pubkey
&& !streq(pubkey
, "") && !streq(pubkey
, "%cert"))
492 certificate
= this->cred
->load_pubkey(this->cred
, pubkey
, identity
);
495 cfg
->add(cfg
, AUTH_RULE_SUBJECT_CERT
, certificate
);
498 if (identity
->get_type(identity
) != ID_ANY
)
500 cfg
->add(cfg
, AUTH_RULE_IDENTITY
, identity
);
503 cfg
->add(cfg
, AUTH_RULE_IDENTITY_LOOSE
, TRUE
);
508 identity
->destroy(identity
);
514 identity
= identification_create_from_string(ca
);
515 certificate
= lib
->credmgr
->get_cert(lib
->credmgr
, CERT_X509
,
516 KEY_ANY
, identity
, TRUE
);
517 identity
->destroy(identity
);
520 cfg
->add(cfg
, AUTH_RULE_CA_CERT
, certificate
);
524 DBG1(DBG_CFG
, "CA certificate \"%s\" not found, discarding CA "
530 groups
= primary
? end
->groups
: end
->groups2
;
533 enumerator_t
*enumerator
;
536 enumerator
= enumerator_create_token(groups
, ",", " ");
537 while (enumerator
->enumerate(enumerator
, &group
))
539 cfg
->add(cfg
, AUTH_RULE_GROUP
,
540 identification_create_from_string(group
));
542 enumerator
->destroy(enumerator
);
545 /* certificatePolicies */
546 if (end
->cert_policy
)
548 enumerator_t
*enumerator
;
551 enumerator
= enumerator_create_token(end
->cert_policy
, ",", " ");
552 while (enumerator
->enumerate(enumerator
, &policy
))
554 cfg
->add(cfg
, AUTH_RULE_CERT_POLICY
, strdup(policy
));
556 enumerator
->destroy(enumerator
);
559 /* authentication metod (class, actually) */
560 if (strneq(auth
, "pubkey", strlen("pubkey")) ||
561 strneq(auth
, "rsa", strlen("rsa")) ||
562 strneq(auth
, "ecdsa", strlen("ecdsa")))
564 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
565 build_crl_policy(cfg
, local
, msg
->add_conn
.crl_policy
);
567 parse_pubkey_constraints(auth
, cfg
);
569 else if (streq(auth
, "psk") || streq(auth
, "secret"))
571 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PSK
);
573 else if (strneq(auth
, "xauth", 5))
577 pos
= strchr(auth
, '-');
580 cfg
->add(cfg
, AUTH_RULE_XAUTH_BACKEND
, strdup(++pos
));
582 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_XAUTH
);
583 if (msg
->add_conn
.xauth_identity
)
585 cfg
->add(cfg
, AUTH_RULE_XAUTH_IDENTITY
,
586 identification_create_from_string(msg
->add_conn
.xauth_identity
));
589 else if (strneq(auth
, "eap", 3))
591 eap_vendor_type_t
*type
;
593 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_EAP
);
595 type
= eap_vendor_type_from_string(auth
);
598 cfg
->add(cfg
, AUTH_RULE_EAP_TYPE
, type
->type
);
601 cfg
->add(cfg
, AUTH_RULE_EAP_VENDOR
, type
->vendor
);
606 if (msg
->add_conn
.eap_identity
)
608 if (streq(msg
->add_conn
.eap_identity
, "%identity"))
610 identity
= identification_create_from_encoding(ID_ANY
,
615 identity
= identification_create_from_string(
616 msg
->add_conn
.eap_identity
);
618 cfg
->add(cfg
, AUTH_RULE_EAP_IDENTITY
, identity
);
620 if (msg
->add_conn
.aaa_identity
)
622 cfg
->add(cfg
, AUTH_RULE_AAA_IDENTITY
,
623 identification_create_from_string(msg
->add_conn
.aaa_identity
));
628 if (!streq(auth
, "any"))
630 DBG1(DBG_CFG
, "authentication method %s unknown, fallback to any",
633 build_crl_policy(cfg
, local
, msg
->add_conn
.crl_policy
);
639 * build a peer_cfg from a stroke msg
641 static peer_cfg_t
*build_peer_cfg(private_stroke_config_t
*this,
642 stroke_msg_t
*msg
, ike_cfg_t
*ike_cfg
)
644 identification_t
*peer_id
= NULL
;
645 peer_cfg_t
*mediated_by
= NULL
;
646 unique_policy_t unique
;
647 u_int32_t rekey
= 0, reauth
= 0, over
, jitter
;
648 peer_cfg_t
*peer_cfg
;
649 auth_cfg_t
*auth_cfg
;
652 if (msg
->add_conn
.ikeme
.mediation
&& msg
->add_conn
.ikeme
.mediated_by
)
654 DBG1(DBG_CFG
, "a mediation connection cannot be a mediated connection "
655 "at the same time, aborting");
659 if (msg
->add_conn
.ikeme
.mediation
)
661 /* force unique connections for mediation connections */
662 msg
->add_conn
.unique
= 1;
665 if (msg
->add_conn
.ikeme
.mediated_by
)
667 mediated_by
= charon
->backends
->get_peer_cfg_by_name(charon
->backends
,
668 msg
->add_conn
.ikeme
.mediated_by
);
671 DBG1(DBG_CFG
, "mediation connection '%s' not found, aborting",
672 msg
->add_conn
.ikeme
.mediated_by
);
675 if (!mediated_by
->is_mediation(mediated_by
))
677 DBG1(DBG_CFG
, "connection '%s' as referred to by '%s' is "
678 "no mediation connection, aborting",
679 msg
->add_conn
.ikeme
.mediated_by
, msg
->add_conn
.name
);
680 mediated_by
->destroy(mediated_by
);
683 if (msg
->add_conn
.ikeme
.peerid
)
685 peer_id
= identification_create_from_string(msg
->add_conn
.ikeme
.peerid
);
687 else if (msg
->add_conn
.other
.id
)
689 peer_id
= identification_create_from_string(msg
->add_conn
.other
.id
);
694 jitter
= msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100;
695 over
= msg
->add_conn
.rekey
.margin
;
696 if (msg
->add_conn
.rekey
.reauth
)
698 reauth
= msg
->add_conn
.rekey
.ike_lifetime
- over
;
702 rekey
= msg
->add_conn
.rekey
.ike_lifetime
- over
;
704 switch (msg
->add_conn
.unique
)
707 case 2: /* replace */
708 unique
= UNIQUE_REPLACE
;
711 unique
= UNIQUE_KEEP
;
714 unique
= UNIQUE_NEVER
;
720 if (msg
->add_conn
.dpd
.action
== 0)
721 { /* dpdaction=none disables DPD */
722 msg
->add_conn
.dpd
.delay
= 0;
725 /* other.sourceip is managed in stroke_attributes. If it is set, we define
726 * the pool name as the connection name, which the attribute provider
727 * uses to serve pool addresses. */
728 peer_cfg
= peer_cfg_create(msg
->add_conn
.name
, ike_cfg
,
729 msg
->add_conn
.me
.sendcert
, unique
,
730 msg
->add_conn
.rekey
.tries
, rekey
, reauth
, jitter
, over
,
731 msg
->add_conn
.mobike
, msg
->add_conn
.aggressive
,
732 msg
->add_conn
.dpd
.delay
, msg
->add_conn
.dpd
.timeout
,
733 msg
->add_conn
.ikeme
.mediation
, mediated_by
, peer_id
);
735 if (msg
->add_conn
.other
.sourceip
)
737 enumerator_t
*enumerator
;
740 enumerator
= enumerator_create_token(msg
->add_conn
.other
.sourceip
,
742 while (enumerator
->enumerate(enumerator
, &token
))
744 if (streq(token
, "%modeconfig") || streq(token
, "%modecfg") ||
745 streq(token
, "%config") || streq(token
, "%cfg") ||
746 streq(token
, "%config4") || streq(token
, "%config6"))
748 /* empty pool, uses connection name */
749 this->attributes
->add_pool(this->attributes
,
750 mem_pool_create(msg
->add_conn
.name
, NULL
, 0));
751 peer_cfg
->add_pool(peer_cfg
, msg
->add_conn
.name
);
753 else if (*token
== '%')
755 /* external named pool */
756 peer_cfg
->add_pool(peer_cfg
, token
+ 1);
760 /* in-memory pool, named using CIDR notation */
764 base
= host_create_from_subnet(token
, &bits
);
767 this->attributes
->add_pool(this->attributes
,
768 mem_pool_create(token
, base
, bits
));
769 peer_cfg
->add_pool(peer_cfg
, token
);
774 DBG1(DBG_CFG
, "IP pool %s invalid, ignored", token
);
778 enumerator
->destroy(enumerator
);
781 if (msg
->add_conn
.me
.sourceip
)
783 enumerator_t
*enumerator
;
786 enumerator
= enumerator_create_token(msg
->add_conn
.me
.sourceip
, ",", " ");
787 while (enumerator
->enumerate(enumerator
, &token
))
791 if (streq(token
, "%modeconfig") || streq(token
, "%modecfg") ||
792 streq(token
, "%config") || streq(token
, "%cfg"))
793 { /* try to deduce an address family */
794 if (msg
->add_conn
.me
.subnets
)
795 { /* use the same family as in local subnet, if any */
796 if (strchr(msg
->add_conn
.me
.subnets
, '.'))
798 vip
= host_create_any(AF_INET
);
802 vip
= host_create_any(AF_INET6
);
805 else if (msg
->add_conn
.other
.subnets
)
806 { /* use the same family as in remote subnet, if any */
807 if (strchr(msg
->add_conn
.other
.subnets
, '.'))
809 vip
= host_create_any(AF_INET
);
813 vip
= host_create_any(AF_INET6
);
818 if (strchr(ike_cfg
->get_my_addr(ike_cfg
, NULL
), ':'))
820 vip
= host_create_any(AF_INET6
);
824 vip
= host_create_any(AF_INET
);
828 else if (streq(token
, "%config4"))
830 vip
= host_create_any(AF_INET
);
832 else if (streq(token
, "%config6"))
834 vip
= host_create_any(AF_INET6
);
838 vip
= host_create_from_string(token
, 0);
841 DBG1(DBG_CFG
, "ignored invalid subnet token: %s", token
);
847 peer_cfg
->add_virtual_ip(peer_cfg
, vip
);
850 enumerator
->destroy(enumerator
);
853 /* build leftauth= */
854 auth_cfg
= build_auth_cfg(this, msg
, TRUE
, TRUE
);
857 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, TRUE
);
860 { /* we require at least one config on our side */
861 peer_cfg
->destroy(peer_cfg
);
864 /* build leftauth2= */
865 auth_cfg
= build_auth_cfg(this, msg
, TRUE
, FALSE
);
868 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, TRUE
);
870 /* build rightauth= */
871 auth_cfg
= build_auth_cfg(this, msg
, FALSE
, TRUE
);
874 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, FALSE
);
876 /* build rightauth2= */
877 auth_cfg
= build_auth_cfg(this, msg
, FALSE
, FALSE
);
880 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, FALSE
);
886 * build a traffic selector from a stroke_end
888 static void add_ts(private_stroke_config_t
*this,
889 stroke_end_t
*end
, child_cfg_t
*child_cfg
, bool local
)
891 traffic_selector_t
*ts
;
895 ts
= traffic_selector_create_dynamic(end
->protocol
,
896 end
->from_port
, end
->to_port
);
897 child_cfg
->add_traffic_selector(child_cfg
, local
, ts
);
905 net
= host_create_from_string(end
->address
, 0);
908 ts
= traffic_selector_create_from_subnet(net
, 0, end
->protocol
,
909 end
->from_port
, end
->to_port
);
910 child_cfg
->add_traffic_selector(child_cfg
, local
, ts
);
915 enumerator_t
*enumerator
;
918 enumerator
= enumerator_create_token(end
->subnets
, ",", " ");
919 while (enumerator
->enumerate(enumerator
, &subnet
))
921 ts
= traffic_selector_create_from_cidr(subnet
, end
->protocol
,
922 end
->from_port
, end
->to_port
);
925 child_cfg
->add_traffic_selector(child_cfg
, local
, ts
);
929 DBG1(DBG_CFG
, "invalid subnet: %s, skipped", subnet
);
932 enumerator
->destroy(enumerator
);
938 * map starter magic values to our action type
940 static action_t
map_action(int starter_action
)
942 switch (starter_action
)
946 case 3: /* =restart */
947 return ACTION_RESTART
;
954 * build a child config from the stroke message
956 static child_cfg_t
*build_child_cfg(private_stroke_config_t
*this,
959 child_cfg_t
*child_cfg
;
960 lifetime_cfg_t lifetime
= {
962 .life
= msg
->add_conn
.rekey
.ipsec_lifetime
,
963 .rekey
= msg
->add_conn
.rekey
.ipsec_lifetime
- msg
->add_conn
.rekey
.margin
,
964 .jitter
= msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100
967 .life
= msg
->add_conn
.rekey
.life_bytes
,
968 .rekey
= msg
->add_conn
.rekey
.life_bytes
- msg
->add_conn
.rekey
.margin_bytes
,
969 .jitter
= msg
->add_conn
.rekey
.margin_bytes
* msg
->add_conn
.rekey
.fuzz
/ 100
972 .life
= msg
->add_conn
.rekey
.life_packets
,
973 .rekey
= msg
->add_conn
.rekey
.life_packets
- msg
->add_conn
.rekey
.margin_packets
,
974 .jitter
= msg
->add_conn
.rekey
.margin_packets
* msg
->add_conn
.rekey
.fuzz
/ 100
978 .value
= msg
->add_conn
.mark_in
.value
,
979 .mask
= msg
->add_conn
.mark_in
.mask
982 .value
= msg
->add_conn
.mark_out
.value
,
983 .mask
= msg
->add_conn
.mark_out
.mask
986 child_cfg
= child_cfg_create(
987 msg
->add_conn
.name
, &lifetime
, msg
->add_conn
.me
.updown
,
988 msg
->add_conn
.me
.hostaccess
, msg
->add_conn
.mode
, ACTION_NONE
,
989 map_action(msg
->add_conn
.dpd
.action
),
990 map_action(msg
->add_conn
.close_action
), msg
->add_conn
.ipcomp
,
991 msg
->add_conn
.inactivity
, msg
->add_conn
.reqid
,
992 &mark_in
, &mark_out
, msg
->add_conn
.tfc
);
993 child_cfg
->set_mipv6_options(child_cfg
, msg
->add_conn
.proxy_mode
,
994 msg
->add_conn
.install_policy
);
995 add_ts(this, &msg
->add_conn
.me
, child_cfg
, TRUE
);
996 add_ts(this, &msg
->add_conn
.other
, child_cfg
, FALSE
);
998 add_proposals(this, msg
->add_conn
.algorithms
.esp
, NULL
, child_cfg
);
1003 METHOD(stroke_config_t
, add
, void,
1004 private_stroke_config_t
*this, stroke_msg_t
*msg
)
1006 ike_cfg_t
*ike_cfg
, *existing_ike
;
1007 peer_cfg_t
*peer_cfg
, *existing
;
1008 child_cfg_t
*child_cfg
;
1009 enumerator_t
*enumerator
;
1010 bool use_existing
= FALSE
;
1012 ike_cfg
= build_ike_cfg(this, msg
);
1017 peer_cfg
= build_peer_cfg(this, msg
, ike_cfg
);
1020 ike_cfg
->destroy(ike_cfg
);
1024 enumerator
= create_peer_cfg_enumerator(this, NULL
, NULL
);
1025 while (enumerator
->enumerate(enumerator
, &existing
))
1027 existing_ike
= existing
->get_ike_cfg(existing
);
1028 if (existing
->equals(existing
, peer_cfg
) &&
1029 existing_ike
->equals(existing_ike
, peer_cfg
->get_ike_cfg(peer_cfg
)))
1031 use_existing
= TRUE
;
1032 peer_cfg
->destroy(peer_cfg
);
1033 peer_cfg
= existing
;
1034 peer_cfg
->get_ref(peer_cfg
);
1035 DBG1(DBG_CFG
, "added child to existing configuration '%s'",
1036 peer_cfg
->get_name(peer_cfg
));
1040 enumerator
->destroy(enumerator
);
1042 child_cfg
= build_child_cfg(this, msg
);
1045 peer_cfg
->destroy(peer_cfg
);
1048 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
1052 peer_cfg
->destroy(peer_cfg
);
1056 /* add config to backend */
1057 DBG1(DBG_CFG
, "added configuration '%s'", msg
->add_conn
.name
);
1058 this->mutex
->lock(this->mutex
);
1059 this->list
->insert_last(this->list
, peer_cfg
);
1060 this->mutex
->unlock(this->mutex
);
1064 METHOD(stroke_config_t
, del
, void,
1065 private_stroke_config_t
*this, stroke_msg_t
*msg
)
1067 enumerator_t
*enumerator
, *children
;
1070 bool deleted
= FALSE
;
1072 this->mutex
->lock(this->mutex
);
1073 enumerator
= this->list
->create_enumerator(this->list
);
1074 while (enumerator
->enumerate(enumerator
, (void**)&peer
))
1078 /* remove any child with such a name */
1079 children
= peer
->create_child_cfg_enumerator(peer
);
1080 while (children
->enumerate(children
, &child
))
1082 if (streq(child
->get_name(child
), msg
->del_conn
.name
))
1084 peer
->remove_child_cfg(peer
, children
);
1085 child
->destroy(child
);
1093 children
->destroy(children
);
1095 /* if peer config matches, or has no children anymore, remove it */
1096 if (!keep
|| streq(peer
->get_name(peer
), msg
->del_conn
.name
))
1098 this->list
->remove_at(this->list
, enumerator
);
1099 peer
->destroy(peer
);
1103 enumerator
->destroy(enumerator
);
1104 this->mutex
->unlock(this->mutex
);
1108 DBG1(DBG_CFG
, "deleted connection '%s'", msg
->del_conn
.name
);
1112 DBG1(DBG_CFG
, "connection '%s' not found", msg
->del_conn
.name
);
1116 METHOD(stroke_config_t
, set_user_credentials
, void,
1117 private_stroke_config_t
*this, stroke_msg_t
*msg
, FILE *prompt
)
1119 enumerator_t
*enumerator
, *children
, *remote_auth
;
1120 peer_cfg_t
*peer
, *found
= NULL
;
1121 auth_cfg_t
*auth_cfg
, *remote_cfg
;
1122 auth_class_t auth_class
;
1124 identification_t
*id
, *identity
, *gw
= NULL
;
1125 shared_key_type_t type
= SHARED_ANY
;
1126 chunk_t password
= chunk_empty
;
1128 this->mutex
->lock(this->mutex
);
1129 enumerator
= this->list
->create_enumerator(this->list
);
1130 while (enumerator
->enumerate(enumerator
, (void**)&peer
))
1131 { /* find the peer (or child) config with the given name */
1132 if (streq(peer
->get_name(peer
), msg
->user_creds
.name
))
1138 children
= peer
->create_child_cfg_enumerator(peer
);
1139 while (children
->enumerate(children
, &child
))
1141 if (streq(child
->get_name(child
), msg
->user_creds
.name
))
1147 children
->destroy(children
);
1155 enumerator
->destroy(enumerator
);
1159 DBG1(DBG_CFG
, " no config named '%s'", msg
->user_creds
.name
);
1160 fprintf(prompt
, "no config named '%s'\n", msg
->user_creds
.name
);
1161 this->mutex
->unlock(this->mutex
);
1165 id
= identification_create_from_string(msg
->user_creds
.username
);
1166 if (strlen(msg
->user_creds
.username
) == 0 ||
1167 !id
|| id
->get_type(id
) == ID_ANY
)
1169 DBG1(DBG_CFG
, " invalid username '%s'", msg
->user_creds
.username
);
1170 fprintf(prompt
, "invalid username '%s'\n", msg
->user_creds
.username
);
1171 this->mutex
->unlock(this->mutex
);
1176 /* replace/set the username in the first EAP/XAuth auth_cfg, also look for
1177 * a suitable remote ID.
1178 * note that adding the identity here is not fully thread-safe as the
1179 * peer_cfg and in turn the auth_cfg could be in use. for the default use
1180 * case (setting user credentials before upping the connection) this will
1181 * not be a problem, though. */
1182 enumerator
= found
->create_auth_cfg_enumerator(found
, TRUE
);
1183 remote_auth
= found
->create_auth_cfg_enumerator(found
, FALSE
);
1184 while (enumerator
->enumerate(enumerator
, (void**)&auth_cfg
))
1186 if (remote_auth
->enumerate(remote_auth
, (void**)&remote_cfg
))
1187 { /* fall back on rightid, in case aaa_identity is not specified */
1188 identity
= remote_cfg
->get(remote_cfg
, AUTH_RULE_IDENTITY
);
1189 if (identity
&& identity
->get_type(identity
) != ID_ANY
)
1195 auth_class
= (uintptr_t)auth_cfg
->get(auth_cfg
, AUTH_RULE_AUTH_CLASS
);
1196 if (auth_class
== AUTH_CLASS_EAP
|| auth_class
== AUTH_CLASS_XAUTH
)
1198 if (auth_class
== AUTH_CLASS_EAP
)
1200 auth_cfg
->add(auth_cfg
, AUTH_RULE_EAP_IDENTITY
, id
->clone(id
));
1201 /* if aaa_identity is specified use that as remote ID */
1202 identity
= auth_cfg
->get(auth_cfg
, AUTH_RULE_AAA_IDENTITY
);
1203 if (identity
&& identity
->get_type(identity
) != ID_ANY
)
1207 DBG1(DBG_CFG
, " configured EAP-Identity %Y", id
);
1211 auth_cfg
->add(auth_cfg
, AUTH_RULE_XAUTH_IDENTITY
,
1213 DBG1(DBG_CFG
, " configured XAuth username %Y", id
);
1219 enumerator
->destroy(enumerator
);
1220 remote_auth
->destroy(remote_auth
);
1221 /* clone the gw ID before unlocking the mutex */
1226 this->mutex
->unlock(this->mutex
);
1228 if (type
== SHARED_ANY
)
1230 DBG1(DBG_CFG
, " config '%s' unsuitable for user credentials",
1231 msg
->user_creds
.name
);
1232 fprintf(prompt
, "config '%s' unsuitable for user credentials\n",
1233 msg
->user_creds
.name
);
1239 if (msg
->user_creds
.password
)
1243 pass
= msg
->user_creds
.password
;
1244 password
= chunk_clone(chunk_create(pass
, strlen(pass
)));
1245 memwipe(pass
, strlen(pass
));
1248 { /* prompt the user for the password */
1251 fprintf(prompt
, "Password:\n");
1252 if (fgets(buf
, sizeof(buf
), prompt
))
1254 password
= chunk_clone(chunk_create(buf
, strlen(buf
)));
1255 if (password
.len
> 0)
1256 { /* trim trailing \n */
1259 memwipe(buf
, sizeof(buf
));
1265 shared_key_t
*shared
;
1266 linked_list_t
*owners
;
1268 shared
= shared_key_create(type
, password
);
1270 owners
= linked_list_create();
1271 owners
->insert_last(owners
, id
->clone(id
));
1272 if (gw
&& gw
->get_type(gw
) != ID_ANY
)
1274 owners
->insert_last(owners
, gw
->clone(gw
));
1275 DBG1(DBG_CFG
, " added %N secret for %Y %Y", shared_key_type_names
,
1280 DBG1(DBG_CFG
, " added %N secret for %Y", shared_key_type_names
,
1283 this->cred
->add_shared(this->cred
, shared
, owners
);
1284 DBG4(DBG_CFG
, " secret: %#B", &password
);
1287 { /* in case a user answers the password prompt by just pressing enter */
1288 chunk_clear(&password
);
1294 METHOD(stroke_config_t
, destroy
, void,
1295 private_stroke_config_t
*this)
1297 this->list
->destroy_offset(this->list
, offsetof(peer_cfg_t
, destroy
));
1298 this->mutex
->destroy(this->mutex
);
1305 stroke_config_t
*stroke_config_create(stroke_ca_t
*ca
, stroke_cred_t
*cred
,
1306 stroke_attribute_t
*attributes
)
1308 private_stroke_config_t
*this;
1313 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
1314 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
1315 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
1319 .set_user_credentials
= _set_user_credentials
,
1320 .destroy
= _destroy
,
1322 .list
= linked_list_create(),
1323 .mutex
= mutex_create(MUTEX_TYPE_RECURSIVE
),
1326 .attributes
= attributes
,
1329 return &this->public;