2 * Copyright (C) 2012-2014 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * HSR 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"
20 #include <threading/mutex.h>
21 #include <utils/lexparser.h>
25 typedef struct private_stroke_config_t private_stroke_config_t
;
28 * private data of stroke_config
30 struct private_stroke_config_t
{
35 stroke_config_t
public;
43 * mutex to lock config list
58 * Virtual IP pool / DNS backend
60 stroke_attribute_t
*attributes
;
63 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
64 private_stroke_config_t
*this, identification_t
*me
, identification_t
*other
)
66 this->mutex
->lock(this->mutex
);
67 return enumerator_create_cleaner(this->list
->create_enumerator(this->list
),
68 (void*)this->mutex
->unlock
, this->mutex
);
71 CALLBACK(ike_filter
, bool,
72 void *data
, enumerator_t
*orig
, va_list args
)
77 VA_ARGS_VGET(args
, out
);
79 if (orig
->enumerate(orig
, &cfg
))
81 *out
= cfg
->get_ike_cfg(cfg
);
87 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
88 private_stroke_config_t
*this, host_t
*me
, host_t
*other
)
90 this->mutex
->lock(this->mutex
);
91 return enumerator_create_filter(this->list
->create_enumerator(this->list
),
92 ike_filter
, this->mutex
,
93 (void*)this->mutex
->unlock
);
96 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
97 private_stroke_config_t
*this, char *name
)
99 enumerator_t
*e1
, *e2
;
100 peer_cfg_t
*current
, *found
= NULL
;
103 this->mutex
->lock(this->mutex
);
104 e1
= this->list
->create_enumerator(this->list
);
105 while (e1
->enumerate(e1
, ¤t
))
107 /* compare peer_cfgs name first */
108 if (streq(current
->get_name(current
), name
))
111 found
->get_ref(found
);
114 /* compare all child_cfg names otherwise */
115 e2
= current
->create_child_cfg_enumerator(current
);
116 while (e2
->enumerate(e2
, &child
))
118 if (streq(child
->get_name(child
), name
))
121 found
->get_ref(found
);
132 this->mutex
->unlock(this->mutex
);
137 * parse a proposal string, either into ike_cfg or child_cfg
139 static bool add_proposals(private_stroke_config_t
*this, char *string
,
140 ike_cfg_t
*ike_cfg
, child_cfg_t
*child_cfg
, protocol_id_t proto
)
146 proposal_t
*proposal
;
148 strict
= string
+ strlen(string
) - 1;
157 while ((single
= strsep(&string
, ",")))
159 proposal
= proposal_create_from_string(proto
, single
);
164 ike_cfg
->add_proposal(ike_cfg
, proposal
);
168 child_cfg
->add_proposal(child_cfg
, proposal
);
172 DBG1(DBG_CFG
, "skipped invalid proposal string: %s", single
);
179 /* add default porposal to the end if not strict */
183 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default(proto
));
184 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default_aead(proto
));
188 child_cfg
->add_proposal(child_cfg
, proposal_create_default(proto
));
189 child_cfg
->add_proposal(child_cfg
, proposal_create_default_aead(proto
));
195 * Check if any addresses in the given string are local
197 static bool is_local(char *address
, bool any_allowed
)
199 enumerator_t
*enumerator
;
204 enumerator
= enumerator_create_token(address
, ",", " ");
205 while (enumerator
->enumerate(enumerator
, &token
))
207 if (!strchr(token
, '/'))
209 host
= host_create_from_dns(token
, 0, 0);
212 if (charon
->kernel
->get_interface(charon
->kernel
, host
, NULL
))
216 else if (any_allowed
&& host
->is_anyaddr(host
))
228 enumerator
->destroy(enumerator
);
233 * Swap ends if indicated by left|right
235 static void swap_ends(stroke_msg_t
*msg
)
237 if (!lib
->settings
->get_bool(lib
->settings
, "%s.plugins.stroke.allow_swap",
243 if (is_local(msg
->add_conn
.other
.address
, FALSE
))
245 stroke_end_t tmp_end
;
247 DBG2(DBG_CFG
, "left is other host, swapping ends");
248 tmp_end
= msg
->add_conn
.me
;
249 msg
->add_conn
.me
= msg
->add_conn
.other
;
250 msg
->add_conn
.other
= tmp_end
;
252 else if (!is_local(msg
->add_conn
.me
.address
, TRUE
))
254 DBG1(DBG_CFG
, "left nor right host is our side, assuming left=local");
259 * Build an IKE config from a stroke message
261 static ike_cfg_t
*build_ike_cfg(private_stroke_config_t
*this, stroke_msg_t
*msg
)
263 ike_cfg_create_t ike
;
265 char me
[256], other
[256];
269 ike
= (ike_cfg_create_t
){
270 .version
= msg
->add_conn
.version
,
271 .local
= msg
->add_conn
.me
.address
,
272 .local_port
= msg
->add_conn
.me
.ikeport
,
273 .remote
= msg
->add_conn
.other
.address
,
274 .remote_port
= msg
->add_conn
.other
.ikeport
,
275 .no_certreq
= msg
->add_conn
.other
.sendcert
== CERT_NEVER_SEND
,
276 .force_encap
= msg
->add_conn
.force_encap
,
277 .fragmentation
= msg
->add_conn
.fragmentation
,
278 .dscp
= msg
->add_conn
.ikedscp
,
280 if (msg
->add_conn
.me
.allow_any
)
282 snprintf(me
, sizeof(me
), "%s,0.0.0.0/0,::/0",
283 msg
->add_conn
.me
.address
);
286 if (msg
->add_conn
.other
.allow_any
)
288 snprintf(other
, sizeof(other
), "%s,0.0.0.0/0,::/0",
289 msg
->add_conn
.other
.address
);
292 if (ike
.local_port
== IKEV2_UDP_PORT
)
294 ike
.local_port
= charon
->socket
->get_port(charon
->socket
, FALSE
);
296 ike_cfg
= ike_cfg_create(&ike
);
298 if (!add_proposals(this, msg
->add_conn
.algorithms
.ike
, ike_cfg
,
301 ike_cfg
->destroy(ike_cfg
);
308 * Add CRL constraint to config
310 static void build_crl_policy(auth_cfg_t
*cfg
, bool local
, int policy
)
312 /* CRL/OCSP policy, for remote config only */
318 /* if yes, we require a GOOD validation */
319 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, VALIDATION_GOOD
);
321 case CRL_STRICT_IFURI
:
322 /* for ifuri, a SKIPPED validation is sufficient */
323 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, VALIDATION_SKIPPED
);
332 * build authentication config
334 static auth_cfg_t
*build_auth_cfg(private_stroke_config_t
*this,
335 stroke_msg_t
*msg
, bool local
, bool primary
)
337 identification_t
*identity
;
338 certificate_t
*certificate
;
339 char *auth
, *id
, *pubkey
, *cert
, *ca
, *groups
;
340 stroke_end_t
*end
, *other_end
;
347 end
= &msg
->add_conn
.me
;
348 other_end
= &msg
->add_conn
.other
;
352 end
= &msg
->add_conn
.other
;
353 other_end
= &msg
->add_conn
.me
;
360 { /* leftid/rightid fallback to address */
365 if (ca
&& streq(ca
, "%same"))
375 { /* leftid2 falls back to leftid */
380 if (ca
&& streq(ca
, "%same"))
385 if (id
&& *id
== '%' && !streq(id
, "%any") && !streq(id
, "%any6"))
386 { /* has only an effect on rightid/2 */
398 { /* no second authentication round, fine. But load certificates
399 * for other purposes (EAP-TLS) */
402 certificate
= this->cred
->load_peer(this->cred
, cert
);
405 certificate
->destroy(certificate
);
412 cfg
= auth_cfg_create();
414 /* add identity and peer certificate */
415 identity
= identification_create_from_string(id
);
418 enumerator_t
*enumerator
;
419 bool has_subject
= FALSE
;
420 certificate_t
*first
= NULL
;
422 enumerator
= enumerator_create_token(cert
, ",", " ");
423 while (enumerator
->enumerate(enumerator
, &cert
))
425 certificate
= this->cred
->load_peer(this->cred
, cert
);
428 cfg
->add(cfg
, AUTH_RULE_SUBJECT_CERT
, certificate
);
433 if (identity
->get_type(identity
) != ID_ANY
&&
434 certificate
->has_subject(certificate
, identity
))
440 enumerator
->destroy(enumerator
);
442 if (first
&& !has_subject
)
444 DBG1(DBG_CFG
, " id '%Y' not confirmed by certificate, "
445 "defaulting to '%Y'", identity
, first
->get_subject(first
));
446 identity
->destroy(identity
);
447 identity
= first
->get_subject(first
);
448 identity
= identity
->clone(identity
);
451 /* add raw RSA public key */
452 pubkey
= end
->rsakey
;
453 if (pubkey
&& !streq(pubkey
, "") && !streq(pubkey
, "%cert"))
455 certificate
= this->cred
->load_pubkey(this->cred
, pubkey
, identity
);
458 cfg
->add(cfg
, AUTH_RULE_SUBJECT_CERT
, certificate
);
461 if (identity
->get_type(identity
) != ID_ANY
)
463 cfg
->add(cfg
, AUTH_RULE_IDENTITY
, identity
);
466 cfg
->add(cfg
, AUTH_RULE_IDENTITY_LOOSE
, TRUE
);
471 identity
->destroy(identity
);
477 identity
= identification_create_from_string(ca
);
478 certificate
= lib
->credmgr
->get_cert(lib
->credmgr
, CERT_X509
,
479 KEY_ANY
, identity
, TRUE
);
480 identity
->destroy(identity
);
483 cfg
->add(cfg
, AUTH_RULE_CA_CERT
, certificate
);
487 DBG1(DBG_CFG
, "CA certificate \"%s\" not found, discarding CA "
493 groups
= primary
? end
->groups
: end
->groups2
;
496 enumerator_t
*enumerator
;
499 enumerator
= enumerator_create_token(groups
, ",", " ");
500 while (enumerator
->enumerate(enumerator
, &group
))
502 cfg
->add(cfg
, AUTH_RULE_GROUP
,
503 identification_create_from_string(group
));
505 enumerator
->destroy(enumerator
);
508 /* certificatePolicies */
509 if (end
->cert_policy
)
511 enumerator_t
*enumerator
;
514 enumerator
= enumerator_create_token(end
->cert_policy
, ",", " ");
515 while (enumerator
->enumerate(enumerator
, &policy
))
517 cfg
->add(cfg
, AUTH_RULE_CERT_POLICY
, strdup(policy
));
519 enumerator
->destroy(enumerator
);
522 /* authentication method (class, actually) */
523 if (strpfx(auth
, "ike:") ||
524 strpfx(auth
, "pubkey") ||
525 strpfx(auth
, "rsa") ||
526 strpfx(auth
, "ecdsa") ||
527 strpfx(auth
, "bliss"))
529 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
530 build_crl_policy(cfg
, local
, msg
->add_conn
.crl_policy
);
531 cfg
->add_pubkey_constraints(cfg
, auth
, TRUE
);
533 else if (streq(auth
, "psk") || streq(auth
, "secret"))
535 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PSK
);
537 else if (strpfx(auth
, "xauth"))
541 pos
= strchr(auth
, '-');
544 cfg
->add(cfg
, AUTH_RULE_XAUTH_BACKEND
, strdup(++pos
));
546 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_XAUTH
);
547 if (msg
->add_conn
.xauth_identity
)
549 cfg
->add(cfg
, AUTH_RULE_XAUTH_IDENTITY
,
550 identification_create_from_string(msg
->add_conn
.xauth_identity
));
553 else if (strpfx(auth
, "eap"))
555 eap_vendor_type_t
*type
;
558 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_EAP
);
559 /* check for public key constraints for EAP-TLS etc. */
560 pos
= strchr(auth
, ':');
564 cfg
->add_pubkey_constraints(cfg
, pos
+ 1, FALSE
);
566 type
= eap_vendor_type_from_string(auth
);
569 cfg
->add(cfg
, AUTH_RULE_EAP_TYPE
, type
->type
);
572 cfg
->add(cfg
, AUTH_RULE_EAP_VENDOR
, type
->vendor
);
577 if (msg
->add_conn
.eap_identity
)
579 if (streq(msg
->add_conn
.eap_identity
, "%identity"))
581 identity
= identification_create_from_encoding(ID_ANY
,
586 identity
= identification_create_from_string(
587 msg
->add_conn
.eap_identity
);
589 cfg
->add(cfg
, AUTH_RULE_EAP_IDENTITY
, identity
);
591 if (msg
->add_conn
.aaa_identity
)
593 cfg
->add(cfg
, AUTH_RULE_AAA_IDENTITY
,
594 identification_create_from_string(msg
->add_conn
.aaa_identity
));
599 if (!streq(auth
, "any"))
601 DBG1(DBG_CFG
, "authentication method %s unknown, fallback to any",
604 build_crl_policy(cfg
, local
, msg
->add_conn
.crl_policy
);
610 * build a mem_pool_t from an address range
612 static mem_pool_t
*create_pool_range(char *str
)
617 if (!host_create_from_range(str
, &from
, &to
))
621 pool
= mem_pool_create_range(str
, from
, to
);
628 * build a peer_cfg from a stroke msg
630 static peer_cfg_t
*build_peer_cfg(private_stroke_config_t
*this,
631 stroke_msg_t
*msg
, ike_cfg_t
*ike_cfg
)
633 peer_cfg_t
*peer_cfg
;
634 auth_cfg_t
*auth_cfg
;
635 peer_cfg_create_t peer
= {
636 .cert_policy
= msg
->add_conn
.me
.sendcert
,
637 .keyingtries
= msg
->add_conn
.rekey
.tries
,
638 .no_mobike
= !msg
->add_conn
.mobike
,
639 .aggressive
= msg
->add_conn
.aggressive
,
640 .push_mode
= msg
->add_conn
.pushmode
,
641 .dpd
= msg
->add_conn
.dpd
.delay
,
642 .dpd_timeout
= msg
->add_conn
.dpd
.timeout
,
646 int handover
= FALSE
;
650 if (msg
->add_conn
.ikeme
.mediation
&& msg
->add_conn
.ikeme
.mediated_by
)
652 DBG1(DBG_CFG
, "a mediation connection cannot be a mediated connection "
653 "at the same time, aborting");
657 if (msg
->add_conn
.ikeme
.mediation
)
659 peer
.mediation
= TRUE
;
660 /* force unique connections for mediation connections */
661 msg
->add_conn
.unique
= 1;
663 else if (msg
->add_conn
.ikeme
.mediated_by
)
665 peer
.mediated_by
= msg
->add_conn
.ikeme
.mediated_by
;
666 if (msg
->add_conn
.ikeme
.peerid
)
668 peer
.peer_id
= identification_create_from_string(
669 msg
->add_conn
.ikeme
.peerid
);
671 else if (msg
->add_conn
.other
.id
)
673 peer
.peer_id
= identification_create_from_string(
674 msg
->add_conn
.other
.id
);
679 peer
.jitter_time
= msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100;
680 peer
.over_time
= msg
->add_conn
.rekey
.margin
;
681 if (msg
->add_conn
.rekey
.reauth
)
683 peer
.reauth_time
= msg
->add_conn
.rekey
.ike_lifetime
- peer
.over_time
;
687 peer
.rekey_time
= msg
->add_conn
.rekey
.ike_lifetime
- peer
.over_time
;
689 switch (msg
->add_conn
.unique
)
692 case 2: /* replace */
693 peer
.unique
= UNIQUE_REPLACE
;
696 peer
.unique
= UNIQUE_KEEP
;
699 peer
.unique
= UNIQUE_NEVER
;
702 peer
.unique
= UNIQUE_NO
;
705 if (msg
->add_conn
.dpd
.action
== 0)
706 { /* dpdaction=none disables DPD */
710 /* other.sourceip is managed in stroke_attributes. If it is set, we define
711 * the pool name as the connection name, which the attribute provider
712 * uses to serve pool addresses. */
713 peer_cfg
= peer_cfg_create(msg
->add_conn
.name
, ike_cfg
, &peer
);
715 if (msg
->add_conn
.other
.sourceip
)
717 enumerator_t
*enumerator
;
720 enumerator
= enumerator_create_token(msg
->add_conn
.other
.sourceip
,
722 while (enumerator
->enumerate(enumerator
, &token
))
724 if (streq(token
, "%modeconfig") || streq(token
, "%modecfg") ||
725 streq(token
, "%config") || streq(token
, "%cfg") ||
726 streq(token
, "%config4") || streq(token
, "%config6"))
728 /* empty pool, uses connection name */
729 this->attributes
->add_pool(this->attributes
,
730 mem_pool_create(msg
->add_conn
.name
, NULL
, 0));
731 peer_cfg
->add_pool(peer_cfg
, msg
->add_conn
.name
);
733 else if (*token
== '%')
735 /* external named pool */
736 peer_cfg
->add_pool(peer_cfg
, token
+ 1);
740 /* in-memory pool, using range or CIDR notation */
745 pool
= create_pool_range(token
);
748 base
= host_create_from_subnet(token
, &bits
);
751 pool
= mem_pool_create(token
, base
, bits
);
757 this->attributes
->add_pool(this->attributes
, pool
);
758 peer_cfg
->add_pool(peer_cfg
, token
);
762 DBG1(DBG_CFG
, "IP pool %s invalid, ignored", token
);
766 enumerator
->destroy(enumerator
);
769 if (msg
->add_conn
.me
.sourceip
&& msg
->add_conn
.other
.sourceip
)
771 DBG1(DBG_CFG
, "'%s' has both left- and rightsourceip, but IKE can "
772 "negotiate one virtual IP only, ignoring local virtual IP",
775 else if (msg
->add_conn
.me
.sourceip
)
777 enumerator_t
*enumerator
;
780 enumerator
= enumerator_create_token(msg
->add_conn
.me
.sourceip
, ",", " ");
781 while (enumerator
->enumerate(enumerator
, &token
))
785 if (streq(token
, "%modeconfig") || streq(token
, "%modecfg") ||
786 streq(token
, "%config") || streq(token
, "%cfg"))
787 { /* try to deduce an address family */
788 if (msg
->add_conn
.me
.subnets
)
789 { /* use the same family as in local subnet, if any */
790 if (strchr(msg
->add_conn
.me
.subnets
, '.'))
792 vip
= host_create_any(AF_INET
);
796 vip
= host_create_any(AF_INET6
);
799 else if (msg
->add_conn
.other
.subnets
)
800 { /* use the same family as in remote subnet, if any */
801 if (strchr(msg
->add_conn
.other
.subnets
, '.'))
803 vip
= host_create_any(AF_INET
);
807 vip
= host_create_any(AF_INET6
);
812 char *addr
, *next
, *hit
;
814 /* guess virtual IP family based on local address. If
815 * multiple addresses are specified, we look at the first
816 * only, as with leftallowany a ::/0 is always appended. */
817 addr
= ike_cfg
->get_my_addr(ike_cfg
);
818 next
= strchr(addr
, ',');
819 hit
= strchr(addr
, ':');
820 if (hit
&& (!next
|| hit
< next
))
822 vip
= host_create_any(AF_INET6
);
826 vip
= host_create_any(AF_INET
);
830 else if (streq(token
, "%config4"))
832 vip
= host_create_any(AF_INET
);
834 else if (streq(token
, "%config6"))
836 vip
= host_create_any(AF_INET6
);
843 DBG1(DBG_CFG
, "Handover detected");
847 vip
= host_create_from_string(token
, 0);
850 DBG1(DBG_CFG
, "ignored invalid subnet token: %s", token
);
856 peer_cfg
->add_virtual_ip(peer_cfg
, vip
);
859 enumerator
->destroy(enumerator
);
862 /* build leftauth= */
863 auth_cfg
= build_auth_cfg(this, msg
, TRUE
, TRUE
);
866 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, TRUE
);
869 { /* we require at least one config on our side */
870 peer_cfg
->destroy(peer_cfg
);
873 /* build leftauth2= */
874 auth_cfg
= build_auth_cfg(this, msg
, TRUE
, FALSE
);
877 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, TRUE
);
879 /* build rightauth= */
880 auth_cfg
= build_auth_cfg(this, msg
, FALSE
, TRUE
);
883 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, FALSE
);
885 /* build rightauth2= */
886 auth_cfg
= build_auth_cfg(this, msg
, FALSE
, FALSE
);
889 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, FALSE
);
893 DBG1(DBG_CFG
, "Operator Type : %d \n", msg
->add_conn
.opr_type
);
894 peer_cfg
->set_operator(peer_cfg
, msg
->add_conn
.opr_type
);
896 DBG1(DBG_CFG
, "Keepalive interval : %d \n", msg
->add_conn
.keepalive_interval
);
897 peer_cfg
->set_keepalive_interval(peer_cfg
, msg
->add_conn
.keepalive_interval
);
899 peer_cfg
->set_interface(peer_cfg
, msg
->add_conn
.interface
);
900 peer_cfg
->set_handover(peer_cfg
, handover
);
901 peer_cfg
->set_use_original_ts(peer_cfg
, msg
->add_conn
.options
& OPT_USE_ORIGINAL_TS
);
902 peer_cfg
->set_do_rekey_on_roam(peer_cfg
, msg
->add_conn
.options
& OPT_DO_REKEY_ON_ROAM
);
903 peer_cfg
->set_retransmit_timeout(peer_cfg
, msg
->add_conn
.retransmit
.timeout
);
904 peer_cfg
->set_retransmit_base(peer_cfg
, msg
->add_conn
.retransmit
.base
);
905 peer_cfg
->set_retransmit_retries(peer_cfg
, msg
->add_conn
.retransmit
.tries
);
906 peer_cfg
->set_retransmit_timeout_handover(peer_cfg
, msg
->add_conn
.retransmit_handover
.timeout
);
907 peer_cfg
->set_retransmit_base_handover(peer_cfg
, msg
->add_conn
.retransmit_handover
.base
);
908 peer_cfg
->set_retransmit_retries_handover(peer_cfg
, msg
->add_conn
.retransmit_handover
.tries
);
914 * Parse a protoport specifier
916 static bool parse_protoport(char *token
, uint16_t *from_port
,
917 uint16_t *to_port
, uint8_t *protocol
)
919 char *sep
, *port
= "", *endptr
;
920 struct protoent
*proto
;
924 sep
= strrchr(token
, ']');
931 sep
= strchr(token
, '/');
933 { /* protocol/port */
938 if (streq(token
, "%any"))
944 proto
= getprotobyname(token
);
947 *protocol
= proto
->p_proto
;
951 p
= strtol(token
, &endptr
, 0);
952 if ((*token
&& *endptr
) || p
< 0 || p
> 0xff)
956 *protocol
= (uint8_t)p
;
959 if (streq(port
, "%any"))
964 else if (streq(port
, "%opaque"))
971 svc
= getservbyname(port
, NULL
);
974 *from_port
= *to_port
= ntohs(svc
->s_port
);
978 p
= strtol(port
, &endptr
, 0);
979 if (p
< 0 || p
> 0xffff)
987 p
= strtol(port
, &endptr
, 0);
988 if (p
< 0 || p
> 0xffff)
1004 * build a traffic selector from a stroke_end
1006 static void add_ts(private_stroke_config_t
*this,
1007 stroke_end_t
*end
, child_cfg_t
*child_cfg
, bool local
)
1009 traffic_selector_t
*ts
;
1010 bool ts_added
= FALSE
;
1014 enumerator_t
*enumerator
;
1016 uint16_t from_port
, to_port
;
1019 enumerator
= enumerator_create_token(end
->subnets
, ",", " ");
1020 while (enumerator
->enumerate(enumerator
, &subnet
))
1022 from_port
= end
->from_port
;
1023 to_port
= end
->to_port
;
1024 proto
= end
->protocol
;
1026 pos
= strchr(subnet
, '[');
1030 if (!parse_protoport(pos
, &from_port
, &to_port
, &proto
))
1032 DBG1(DBG_CFG
, "invalid proto/port: %s, skipped subnet",
1037 if (streq(subnet
, "%dynamic"))
1039 ts
= traffic_selector_create_dynamic(proto
,
1040 from_port
, to_port
);
1044 ts
= traffic_selector_create_from_cidr(subnet
, proto
,
1045 from_port
, to_port
);
1049 child_cfg
->add_traffic_selector(child_cfg
, local
, ts
);
1054 DBG1(DBG_CFG
, "invalid subnet: %s, skipped", subnet
);
1057 enumerator
->destroy(enumerator
);
1061 ts
= traffic_selector_create_dynamic(end
->protocol
,
1062 end
->from_port
, end
->to_port
);
1063 child_cfg
->add_traffic_selector(child_cfg
, local
, ts
);
1068 * map starter magic values to our action type
1070 static action_t
map_action(int starter_action
)
1072 switch (starter_action
)
1075 return ACTION_ROUTE
;
1076 case 3: /* =restart */
1077 return ACTION_RESTART
;
1084 * build a child config from the stroke message
1086 static child_cfg_t
*build_child_cfg(private_stroke_config_t
*this,
1089 child_cfg_t
*child_cfg
;
1091 child_cfg_create_t child
= {
1094 .life
= msg
->add_conn
.rekey
.ipsec_lifetime
,
1095 .rekey
= msg
->add_conn
.rekey
.ipsec_lifetime
- msg
->add_conn
.rekey
.margin
,
1096 .jitter
= msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100
1099 .life
= msg
->add_conn
.rekey
.life_bytes
,
1100 .rekey
= msg
->add_conn
.rekey
.life_bytes
- msg
->add_conn
.rekey
.margin_bytes
,
1101 .jitter
= msg
->add_conn
.rekey
.margin_bytes
* msg
->add_conn
.rekey
.fuzz
/ 100
1104 .life
= msg
->add_conn
.rekey
.life_packets
,
1105 .rekey
= msg
->add_conn
.rekey
.life_packets
- msg
->add_conn
.rekey
.margin_packets
,
1106 .jitter
= msg
->add_conn
.rekey
.margin_packets
* msg
->add_conn
.rekey
.fuzz
/ 100
1110 .value
= msg
->add_conn
.mark_in
.value
,
1111 .mask
= msg
->add_conn
.mark_in
.mask
1114 .value
= msg
->add_conn
.mark_out
.value
,
1115 .mask
= msg
->add_conn
.mark_out
.mask
1117 .reqid
= msg
->add_conn
.reqid
,
1118 .mode
= msg
->add_conn
.mode
,
1119 .options
= (msg
->add_conn
.proxy_mode
? OPT_PROXY_MODE
: 0) |
1120 (msg
->add_conn
.ipcomp
? OPT_IPCOMP
: 0) |
1121 (msg
->add_conn
.me
.hostaccess
? OPT_HOSTACCESS
: 0) |
1122 (msg
->add_conn
.install_policy
? 0 : OPT_NO_POLICIES
) |
1123 (msg
->add_conn
.sha256_96
? OPT_SHA256_96
: 0),
1124 .tfc
= msg
->add_conn
.tfc
,
1125 .inactivity
= msg
->add_conn
.inactivity
,
1126 .dpd_action
= map_action(msg
->add_conn
.dpd
.action
),
1127 .close_action
= map_action(msg
->add_conn
.close_action
),
1128 .updown
= msg
->add_conn
.me
.updown
,
1131 child_cfg
= child_cfg_create(msg
->add_conn
.name
, &child
);
1132 if (msg
->add_conn
.replay_window
!= -1)
1134 child_cfg
->set_replay_window(child_cfg
, msg
->add_conn
.replay_window
);
1136 add_ts(this, &msg
->add_conn
.me
, child_cfg
, TRUE
);
1137 add_ts(this, &msg
->add_conn
.other
, child_cfg
, FALSE
);
1139 if (msg
->add_conn
.algorithms
.ah
)
1141 success
= add_proposals(this, msg
->add_conn
.algorithms
.ah
,
1142 NULL
, child_cfg
, PROTO_AH
);
1146 success
= add_proposals(this, msg
->add_conn
.algorithms
.esp
,
1147 NULL
, child_cfg
, PROTO_ESP
);
1151 child_cfg
->destroy(child_cfg
);
1157 METHOD(stroke_config_t
, add
, void,
1158 private_stroke_config_t
*this, stroke_msg_t
*msg
)
1160 ike_cfg_t
*ike_cfg
, *existing_ike
;
1161 peer_cfg_t
*peer_cfg
, *existing
;
1162 child_cfg_t
*child_cfg
;
1163 enumerator_t
*enumerator
;
1164 bool use_existing
= FALSE
;
1166 ike_cfg
= build_ike_cfg(this, msg
);
1171 peer_cfg
= build_peer_cfg(this, msg
, ike_cfg
);
1174 ike_cfg
->destroy(ike_cfg
);
1178 enumerator
= create_peer_cfg_enumerator(this, NULL
, NULL
);
1179 while (enumerator
->enumerate(enumerator
, &existing
))
1181 existing_ike
= existing
->get_ike_cfg(existing
);
1182 if (existing
->equals(existing
, peer_cfg
) &&
1183 existing_ike
->equals(existing_ike
, peer_cfg
->get_ike_cfg(peer_cfg
)))
1185 use_existing
= TRUE
;
1186 peer_cfg
->destroy(peer_cfg
);
1187 peer_cfg
= existing
;
1188 peer_cfg
->get_ref(peer_cfg
);
1189 DBG1(DBG_CFG
, "added child to existing configuration '%s'",
1190 peer_cfg
->get_name(peer_cfg
));
1194 enumerator
->destroy(enumerator
);
1196 child_cfg
= build_child_cfg(this, msg
);
1199 peer_cfg
->destroy(peer_cfg
);
1202 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
1206 peer_cfg
->destroy(peer_cfg
);
1210 /* add config to backend */
1211 DBG1(DBG_CFG
, "added configuration '%s'", msg
->add_conn
.name
);
1212 this->mutex
->lock(this->mutex
);
1213 this->list
->insert_last(this->list
, peer_cfg
);
1214 this->mutex
->unlock(this->mutex
);
1218 METHOD(stroke_config_t
, del
, void,
1219 private_stroke_config_t
*this, stroke_msg_t
*msg
)
1221 enumerator_t
*enumerator
, *children
;
1224 bool deleted
= FALSE
;
1226 this->mutex
->lock(this->mutex
);
1227 enumerator
= this->list
->create_enumerator(this->list
);
1228 while (enumerator
->enumerate(enumerator
, &peer
))
1232 /* remove any child with such a name */
1233 children
= peer
->create_child_cfg_enumerator(peer
);
1234 while (children
->enumerate(children
, &child
))
1236 if (streq(child
->get_name(child
), msg
->del_conn
.name
))
1238 peer
->remove_child_cfg(peer
, children
);
1239 child
->destroy(child
);
1247 children
->destroy(children
);
1249 /* if peer config has no children anymore, remove it */
1252 this->list
->remove_at(this->list
, enumerator
);
1253 peer
->destroy(peer
);
1256 enumerator
->destroy(enumerator
);
1257 this->mutex
->unlock(this->mutex
);
1261 DBG1(DBG_CFG
, "deleted connection '%s'", msg
->del_conn
.name
);
1265 DBG1(DBG_CFG
, "connection '%s' not found", msg
->del_conn
.name
);
1269 METHOD(stroke_config_t
, set_user_credentials
, void,
1270 private_stroke_config_t
*this, stroke_msg_t
*msg
, FILE *prompt
)
1272 enumerator_t
*enumerator
, *children
, *remote_auth
;
1273 peer_cfg_t
*peer
, *found
= NULL
;
1274 auth_cfg_t
*auth_cfg
, *remote_cfg
;
1275 auth_class_t auth_class
;
1277 identification_t
*id
, *identity
, *gw
= NULL
;
1278 shared_key_type_t type
= SHARED_ANY
;
1279 chunk_t password
= chunk_empty
;
1281 this->mutex
->lock(this->mutex
);
1282 enumerator
= this->list
->create_enumerator(this->list
);
1283 while (enumerator
->enumerate(enumerator
, (void**)&peer
))
1284 { /* find the peer (or child) config with the given name */
1285 if (streq(peer
->get_name(peer
), msg
->user_creds
.name
))
1291 children
= peer
->create_child_cfg_enumerator(peer
);
1292 while (children
->enumerate(children
, &child
))
1294 if (streq(child
->get_name(child
), msg
->user_creds
.name
))
1300 children
->destroy(children
);
1308 enumerator
->destroy(enumerator
);
1312 DBG1(DBG_CFG
, " no config named '%s'", msg
->user_creds
.name
);
1313 fprintf(prompt
, "no config named '%s'\n", msg
->user_creds
.name
);
1314 this->mutex
->unlock(this->mutex
);
1318 id
= identification_create_from_string(msg
->user_creds
.username
);
1319 if (strlen(msg
->user_creds
.username
) == 0 ||
1320 !id
|| id
->get_type(id
) == ID_ANY
)
1322 DBG1(DBG_CFG
, " invalid username '%s'", msg
->user_creds
.username
);
1323 fprintf(prompt
, "invalid username '%s'\n", msg
->user_creds
.username
);
1324 this->mutex
->unlock(this->mutex
);
1329 /* replace/set the username in the first EAP/XAuth auth_cfg, also look for
1330 * a suitable remote ID.
1331 * note that adding the identity here is not fully thread-safe as the
1332 * peer_cfg and in turn the auth_cfg could be in use. for the default use
1333 * case (setting user credentials before upping the connection) this will
1334 * not be a problem, though. */
1335 enumerator
= found
->create_auth_cfg_enumerator(found
, TRUE
);
1336 remote_auth
= found
->create_auth_cfg_enumerator(found
, FALSE
);
1337 while (enumerator
->enumerate(enumerator
, (void**)&auth_cfg
))
1339 if (remote_auth
->enumerate(remote_auth
, (void**)&remote_cfg
))
1340 { /* fall back on rightid, in case aaa_identity is not specified */
1341 identity
= remote_cfg
->get(remote_cfg
, AUTH_RULE_IDENTITY
);
1342 if (identity
&& identity
->get_type(identity
) != ID_ANY
)
1348 auth_class
= (uintptr_t)auth_cfg
->get(auth_cfg
, AUTH_RULE_AUTH_CLASS
);
1349 if (auth_class
== AUTH_CLASS_EAP
|| auth_class
== AUTH_CLASS_XAUTH
)
1351 if (auth_class
== AUTH_CLASS_EAP
)
1353 auth_cfg
->add(auth_cfg
, AUTH_RULE_EAP_IDENTITY
, id
->clone(id
));
1354 /* if aaa_identity is specified use that as remote ID */
1355 identity
= auth_cfg
->get(auth_cfg
, AUTH_RULE_AAA_IDENTITY
);
1356 if (identity
&& identity
->get_type(identity
) != ID_ANY
)
1360 DBG1(DBG_CFG
, " configured EAP-Identity %Y", id
);
1364 auth_cfg
->add(auth_cfg
, AUTH_RULE_XAUTH_IDENTITY
,
1366 DBG1(DBG_CFG
, " configured XAuth username %Y", id
);
1372 enumerator
->destroy(enumerator
);
1373 remote_auth
->destroy(remote_auth
);
1374 /* clone the gw ID before unlocking the mutex */
1379 this->mutex
->unlock(this->mutex
);
1381 if (type
== SHARED_ANY
)
1383 DBG1(DBG_CFG
, " config '%s' unsuitable for user credentials",
1384 msg
->user_creds
.name
);
1385 fprintf(prompt
, "config '%s' unsuitable for user credentials\n",
1386 msg
->user_creds
.name
);
1392 if (msg
->user_creds
.password
)
1396 pass
= msg
->user_creds
.password
;
1397 password
= chunk_clone(chunk_create(pass
, strlen(pass
)));
1398 memwipe(pass
, strlen(pass
));
1401 { /* prompt the user for the password */
1404 fprintf(prompt
, "Password:\n");
1405 if (fgets(buf
, sizeof(buf
), prompt
))
1407 password
= chunk_clone(chunk_create(buf
, strlen(buf
)));
1408 if (password
.len
> 0)
1409 { /* trim trailing \n */
1412 memwipe(buf
, sizeof(buf
));
1418 shared_key_t
*shared
;
1419 linked_list_t
*owners
;
1421 shared
= shared_key_create(type
, password
);
1423 owners
= linked_list_create();
1424 owners
->insert_last(owners
, id
->clone(id
));
1425 if (gw
&& gw
->get_type(gw
) != ID_ANY
)
1427 owners
->insert_last(owners
, gw
->clone(gw
));
1428 DBG1(DBG_CFG
, " added %N secret for %Y %Y", shared_key_type_names
,
1433 DBG1(DBG_CFG
, " added %N secret for %Y", shared_key_type_names
,
1436 this->cred
->add_shared(this->cred
, shared
, owners
);
1437 DBG4(DBG_CFG
, " secret: %#B", &password
);
1440 { /* in case a user answers the password prompt by just pressing enter */
1441 chunk_clear(&password
);
1447 METHOD(stroke_config_t
, destroy
, void,
1448 private_stroke_config_t
*this)
1450 this->list
->destroy_offset(this->list
, offsetof(peer_cfg_t
, destroy
));
1451 this->mutex
->destroy(this->mutex
);
1458 stroke_config_t
*stroke_config_create(stroke_ca_t
*ca
, stroke_cred_t
*cred
,
1459 stroke_attribute_t
*attributes
)
1461 private_stroke_config_t
*this;
1466 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
1467 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
1468 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
1472 .set_user_credentials
= _set_user_credentials
,
1473 .destroy
= _destroy
,
1475 .list
= linked_list_create(),
1476 .mutex
= mutex_create(MUTEX_TYPE_RECURSIVE
),
1479 .attributes
= attributes
,
1482 return &this->public;