Make it easy to check if an address is locally usable via changed get_interface(...
[strongswan.git] / src / libcharon / plugins / stroke / stroke_config.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 */
16
17 #include "stroke_config.h"
18
19 #include <hydra.h>
20 #include <daemon.h>
21 #include <threading/mutex.h>
22 #include <utils/lexparser.h>
23
24 typedef struct private_stroke_config_t private_stroke_config_t;
25
26 /**
27 * private data of stroke_config
28 */
29 struct private_stroke_config_t {
30
31 /**
32 * public functions
33 */
34 stroke_config_t public;
35
36 /**
37 * list of peer_cfg_t
38 */
39 linked_list_t *list;
40
41 /**
42 * mutex to lock config list
43 */
44 mutex_t *mutex;
45
46 /**
47 * ca sections
48 */
49 stroke_ca_t *ca;
50
51 /**
52 * credentials
53 */
54 stroke_cred_t *cred;
55
56 /**
57 * Virtual IP pool / DNS backend
58 */
59 stroke_attribute_t *attributes;
60 };
61
62 METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
63 private_stroke_config_t *this, identification_t *me, identification_t *other)
64 {
65 this->mutex->lock(this->mutex);
66 return enumerator_create_cleaner(this->list->create_enumerator(this->list),
67 (void*)this->mutex->unlock, this->mutex);
68 }
69
70 /**
71 * filter function for ike configs
72 */
73 static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
74 {
75 *out = (*in)->get_ike_cfg(*in);
76 return TRUE;
77 }
78
79 METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
80 private_stroke_config_t *this, host_t *me, host_t *other)
81 {
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);
86 }
87
88 METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
89 private_stroke_config_t *this, char *name)
90 {
91 enumerator_t *e1, *e2;
92 peer_cfg_t *current, *found = NULL;
93 child_cfg_t *child;
94
95 this->mutex->lock(this->mutex);
96 e1 = this->list->create_enumerator(this->list);
97 while (e1->enumerate(e1, &current))
98 {
99 /* compare peer_cfgs name first */
100 if (streq(current->get_name(current), name))
101 {
102 found = current;
103 found->get_ref(found);
104 break;
105 }
106 /* compare all child_cfg names otherwise */
107 e2 = current->create_child_cfg_enumerator(current);
108 while (e2->enumerate(e2, &child))
109 {
110 if (streq(child->get_name(child), name))
111 {
112 found = current;
113 found->get_ref(found);
114 break;
115 }
116 }
117 e2->destroy(e2);
118 if (found)
119 {
120 break;
121 }
122 }
123 e1->destroy(e1);
124 this->mutex->unlock(this->mutex);
125 return found;
126 }
127
128 /**
129 * parse a proposal string, either into ike_cfg or child_cfg
130 */
131 static void add_proposals(private_stroke_config_t *this, char *string,
132 ike_cfg_t *ike_cfg, child_cfg_t *child_cfg)
133 {
134 if (string)
135 {
136 char *single;
137 char *strict;
138 proposal_t *proposal;
139 protocol_id_t proto = PROTO_ESP;
140
141 if (ike_cfg)
142 {
143 proto = PROTO_IKE;
144 }
145 strict = string + strlen(string) - 1;
146 if (*strict == '!')
147 {
148 *strict = '\0';
149 }
150 else
151 {
152 strict = NULL;
153 }
154 while ((single = strsep(&string, ",")))
155 {
156 proposal = proposal_create_from_string(proto, single);
157 if (proposal)
158 {
159 if (ike_cfg)
160 {
161 ike_cfg->add_proposal(ike_cfg, proposal);
162 }
163 else
164 {
165 child_cfg->add_proposal(child_cfg, proposal);
166 }
167 continue;
168 }
169 DBG1(DBG_CFG, "skipped invalid proposal string: %s", single);
170 }
171 if (strict)
172 {
173 return;
174 }
175 /* add default porposal to the end if not strict */
176 }
177 if (ike_cfg)
178 {
179 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
180 }
181 else
182 {
183 child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
184 }
185 }
186
187 /**
188 * Build an IKE config from a stroke message
189 */
190 static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg)
191 {
192 stroke_end_t tmp_end;
193 ike_cfg_t *ike_cfg;
194 host_t *host;
195 u_int16_t ikeport;
196
197 host = host_create_from_dns(msg->add_conn.other.address, 0, 0);
198 if (host)
199 {
200 if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
201 host, NULL))
202 {
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;
207 host->destroy(host);
208 }
209 else
210 {
211 host->destroy(host);
212 host = host_create_from_dns(msg->add_conn.me.address, 0, 0);
213 if (host)
214 {
215 if (!hydra->kernel_interface->get_interface(
216 hydra->kernel_interface, host, NULL))
217 {
218 DBG1(DBG_CFG, "left nor right host is our side, "
219 "assuming left=local");
220 }
221 host->destroy(host);
222 }
223 }
224 }
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.other.sendcert != CERT_NEVER_SEND,
229 msg->add_conn.force_encap,
230 msg->add_conn.me.address,
231 msg->add_conn.me.allow_any,
232 ikeport,
233 msg->add_conn.other.address,
234 msg->add_conn.other.allow_any,
235 msg->add_conn.other.ikeport);
236 add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
237 return ike_cfg;
238 }
239
240 /**
241 * Add CRL constraint to config
242 */
243 static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy)
244 {
245 /* CRL/OCSP policy, for remote config only */
246 if (!local)
247 {
248 switch (policy)
249 {
250 case CRL_STRICT_YES:
251 /* if yes, we require a GOOD validation */
252 cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
253 break;
254 case CRL_STRICT_IFURI:
255 /* for ifuri, a SKIPPED validation is sufficient */
256 cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_SKIPPED);
257 break;
258 default:
259 break;
260 }
261 }
262 }
263
264 /**
265 * Parse public key / signature strength constraints
266 */
267 static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg)
268 {
269 enumerator_t *enumerator;
270 bool rsa = FALSE, ecdsa = FALSE, rsa_len = FALSE, ecdsa_len = FALSE;
271 int strength;
272 char *token;
273
274 enumerator = enumerator_create_token(auth, "-", "");
275 while (enumerator->enumerate(enumerator, &token))
276 {
277 bool found = FALSE;
278 int i;
279 struct {
280 char *name;
281 signature_scheme_t scheme;
282 key_type_t key;
283 } schemes[] = {
284 { "md5", SIGN_RSA_EMSA_PKCS1_MD5, KEY_RSA, },
285 { "sha1", SIGN_RSA_EMSA_PKCS1_SHA1, KEY_RSA, },
286 { "sha224", SIGN_RSA_EMSA_PKCS1_SHA224, KEY_RSA, },
287 { "sha256", SIGN_RSA_EMSA_PKCS1_SHA256, KEY_RSA, },
288 { "sha384", SIGN_RSA_EMSA_PKCS1_SHA384, KEY_RSA, },
289 { "sha512", SIGN_RSA_EMSA_PKCS1_SHA512, KEY_RSA, },
290 { "sha1", SIGN_ECDSA_WITH_SHA1_DER, KEY_ECDSA, },
291 { "sha256", SIGN_ECDSA_WITH_SHA256_DER, KEY_ECDSA, },
292 { "sha384", SIGN_ECDSA_WITH_SHA384_DER, KEY_ECDSA, },
293 { "sha512", SIGN_ECDSA_WITH_SHA512_DER, KEY_ECDSA, },
294 { "sha256", SIGN_ECDSA_256, KEY_ECDSA, },
295 { "sha384", SIGN_ECDSA_384, KEY_ECDSA, },
296 { "sha512", SIGN_ECDSA_521, KEY_ECDSA, },
297 };
298
299 if (rsa_len || ecdsa_len)
300 { /* expecting a key strength token */
301 strength = atoi(token);
302 if (strength)
303 {
304 if (rsa_len)
305 {
306 cfg->add(cfg, AUTH_RULE_RSA_STRENGTH, (uintptr_t)strength);
307 }
308 else if (ecdsa_len)
309 {
310 cfg->add(cfg, AUTH_RULE_ECDSA_STRENGTH, (uintptr_t)strength);
311 }
312 }
313 rsa_len = ecdsa_len = FALSE;
314 if (strength)
315 {
316 continue;
317 }
318 }
319 if (streq(token, "rsa"))
320 {
321 rsa = rsa_len = TRUE;
322 continue;
323 }
324 if (streq(token, "ecdsa"))
325 {
326 ecdsa = ecdsa_len = TRUE;
327 continue;
328 }
329 if (streq(token, "pubkey"))
330 {
331 continue;
332 }
333
334 for (i = 0; i < countof(schemes); i++)
335 {
336 if (streq(schemes[i].name, token))
337 {
338 /* for each matching string, allow the scheme, if:
339 * - it is an RSA scheme, and we enforced RSA
340 * - it is an ECDSA scheme, and we enforced ECDSA
341 * - it is not a key type specific scheme
342 */
343 if ((rsa && schemes[i].key == KEY_RSA) ||
344 (ecdsa && schemes[i].key == KEY_ECDSA) ||
345 (!rsa && !ecdsa))
346 {
347 cfg->add(cfg, AUTH_RULE_SIGNATURE_SCHEME,
348 (uintptr_t)schemes[i].scheme);
349 }
350 found = TRUE;
351 }
352 }
353 if (!found)
354 {
355 DBG1(DBG_CFG, "ignoring invalid auth token: '%s'", token);
356 }
357 }
358 enumerator->destroy(enumerator);
359 }
360
361 /**
362 * build authentication config
363 */
364 static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
365 stroke_msg_t *msg, bool local, bool primary)
366 {
367 identification_t *identity;
368 certificate_t *certificate;
369 char *auth, *id, *pubkey, *cert, *ca, *groups;
370 stroke_end_t *end, *other_end;
371 auth_cfg_t *cfg;
372 bool loose = FALSE;
373
374 /* select strings */
375 if (local)
376 {
377 end = &msg->add_conn.me;
378 other_end = &msg->add_conn.other;
379 }
380 else
381 {
382 end = &msg->add_conn.other;
383 other_end = &msg->add_conn.me;
384 }
385 if (primary)
386 {
387 auth = end->auth;
388 id = end->id;
389 if (!id)
390 { /* leftid/rightid fallback to address */
391 id = end->address;
392 }
393 cert = end->cert;
394 ca = end->ca;
395 if (ca && streq(ca, "%same"))
396 {
397 ca = other_end->ca;
398 }
399 }
400 else
401 {
402 auth = end->auth2;
403 id = end->id2;
404 if (local && !id)
405 { /* leftid2 falls back to leftid */
406 id = end->id;
407 }
408 cert = end->cert2;
409 ca = end->ca2;
410 if (ca && streq(ca, "%same"))
411 {
412 ca = other_end->ca2;
413 }
414 }
415 if (id && *id == '%' && !streq(id, "%any"))
416 { /* has only an effect on rightid/2 */
417 loose = !local;
418 id++;
419 }
420
421 if (!auth)
422 {
423 if (primary)
424 {
425 auth = "pubkey";
426 }
427 else
428 { /* no second authentication round, fine. But load certificates
429 * for other purposes (EAP-TLS) */
430 if (cert)
431 {
432 certificate = this->cred->load_peer(this->cred, cert);
433 if (certificate)
434 {
435 certificate->destroy(certificate);
436 }
437 }
438 return NULL;
439 }
440 }
441
442 cfg = auth_cfg_create();
443
444 /* add identity and peer certifcate */
445 identity = identification_create_from_string(id);
446 if (cert)
447 {
448 certificate = this->cred->load_peer(this->cred, cert);
449 if (certificate)
450 {
451 if (local)
452 {
453 this->ca->check_for_hash_and_url(this->ca, certificate);
454 }
455 cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
456 if (identity->get_type(identity) == ID_ANY ||
457 !certificate->has_subject(certificate, identity))
458 {
459 DBG1(DBG_CFG, " id '%Y' not confirmed by certificate, "
460 "defaulting to '%Y'", identity,
461 certificate->get_subject(certificate));
462 identity->destroy(identity);
463 identity = certificate->get_subject(certificate);
464 identity = identity->clone(identity);
465 }
466 }
467 }
468 if (identity->get_type(identity) != ID_ANY)
469 {
470 cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
471 if (loose)
472 {
473 cfg->add(cfg, AUTH_RULE_IDENTITY_LOOSE, TRUE);
474 }
475 }
476 else
477 {
478 identity->destroy(identity);
479 }
480
481 /* add raw RSA public key */
482 pubkey = end->rsakey;
483 if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert"))
484 {
485 certificate = this->cred->load_pubkey(this->cred, KEY_RSA, pubkey,
486 identity);
487 if (certificate)
488 {
489 cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
490 }
491 }
492
493 /* CA constraint */
494 if (ca)
495 {
496 identity = identification_create_from_string(ca);
497 certificate = lib->credmgr->get_cert(lib->credmgr, CERT_X509,
498 KEY_ANY, identity, TRUE);
499 identity->destroy(identity);
500 if (certificate)
501 {
502 cfg->add(cfg, AUTH_RULE_CA_CERT, certificate);
503 }
504 else
505 {
506 DBG1(DBG_CFG, "CA certificate \"%s\" not found, discarding CA "
507 "constraint", ca);
508 }
509 }
510
511 /* groups */
512 groups = primary ? end->groups : end->groups2;
513 if (groups)
514 {
515 enumerator_t *enumerator;
516 char *group;
517
518 enumerator = enumerator_create_token(groups, ",", " ");
519 while (enumerator->enumerate(enumerator, &group))
520 {
521 cfg->add(cfg, AUTH_RULE_GROUP,
522 identification_create_from_string(group));
523 }
524 enumerator->destroy(enumerator);
525 }
526
527 /* certificatePolicies */
528 if (end->cert_policy)
529 {
530 enumerator_t *enumerator;
531 char *policy;
532
533 enumerator = enumerator_create_token(end->cert_policy, ",", " ");
534 while (enumerator->enumerate(enumerator, &policy))
535 {
536 cfg->add(cfg, AUTH_RULE_CERT_POLICY, strdup(policy));
537 }
538 enumerator->destroy(enumerator);
539 }
540
541 /* authentication metod (class, actually) */
542 if (strneq(auth, "pubkey", strlen("pubkey")) ||
543 strneq(auth, "rsa", strlen("rsa")) ||
544 strneq(auth, "ecdsa", strlen("ecdsa")))
545 {
546 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
547 build_crl_policy(cfg, local, msg->add_conn.crl_policy);
548
549 parse_pubkey_constraints(auth, cfg);
550 }
551 else if (streq(auth, "psk") || streq(auth, "secret"))
552 {
553 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
554 }
555 else if (strneq(auth, "xauth", 5))
556 {
557 char *pos;
558
559 pos = strchr(auth, '-');
560 if (pos)
561 {
562 cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
563 }
564 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
565 if (msg->add_conn.xauth_identity)
566 {
567 cfg->add(cfg, AUTH_RULE_XAUTH_IDENTITY,
568 identification_create_from_string(msg->add_conn.xauth_identity));
569 }
570 }
571 else if (strneq(auth, "eap", 3))
572 {
573 eap_vendor_type_t *type;
574
575 cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
576
577 type = eap_vendor_type_from_string(auth);
578 if (type)
579 {
580 cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
581 if (type->vendor)
582 {
583 cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
584 }
585 free(type);
586 }
587
588 if (msg->add_conn.eap_identity)
589 {
590 if (streq(msg->add_conn.eap_identity, "%identity"))
591 {
592 identity = identification_create_from_encoding(ID_ANY,
593 chunk_empty);
594 }
595 else
596 {
597 identity = identification_create_from_string(
598 msg->add_conn.eap_identity);
599 }
600 cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, identity);
601 }
602 if (msg->add_conn.aaa_identity)
603 {
604 cfg->add(cfg, AUTH_RULE_AAA_IDENTITY,
605 identification_create_from_string(msg->add_conn.aaa_identity));
606 }
607 }
608 else
609 {
610 if (!streq(auth, "any"))
611 {
612 DBG1(DBG_CFG, "authentication method %s unknown, fallback to any",
613 auth);
614 }
615 build_crl_policy(cfg, local, msg->add_conn.crl_policy);
616 }
617 return cfg;
618 }
619
620 /**
621 * build a peer_cfg from a stroke msg
622 */
623 static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
624 stroke_msg_t *msg, ike_cfg_t *ike_cfg)
625 {
626 identification_t *peer_id = NULL;
627 peer_cfg_t *mediated_by = NULL;
628 unique_policy_t unique;
629 u_int32_t rekey = 0, reauth = 0, over, jitter;
630 peer_cfg_t *peer_cfg;
631 auth_cfg_t *auth_cfg;
632
633 #ifdef ME
634 if (msg->add_conn.ikeme.mediation && msg->add_conn.ikeme.mediated_by)
635 {
636 DBG1(DBG_CFG, "a mediation connection cannot be a mediated connection "
637 "at the same time, aborting");
638 return NULL;
639 }
640
641 if (msg->add_conn.ikeme.mediation)
642 {
643 /* force unique connections for mediation connections */
644 msg->add_conn.unique = 1;
645 }
646
647 if (msg->add_conn.ikeme.mediated_by)
648 {
649 mediated_by = charon->backends->get_peer_cfg_by_name(charon->backends,
650 msg->add_conn.ikeme.mediated_by);
651 if (!mediated_by)
652 {
653 DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
654 msg->add_conn.ikeme.mediated_by);
655 return NULL;
656 }
657 if (!mediated_by->is_mediation(mediated_by))
658 {
659 DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is "
660 "no mediation connection, aborting",
661 msg->add_conn.ikeme.mediated_by, msg->add_conn.name);
662 mediated_by->destroy(mediated_by);
663 return NULL;
664 }
665 if (msg->add_conn.ikeme.peerid)
666 {
667 peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid);
668 }
669 else if (msg->add_conn.other.id)
670 {
671 peer_id = identification_create_from_string(msg->add_conn.other.id);
672 }
673 }
674 #endif /* ME */
675
676 jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
677 over = msg->add_conn.rekey.margin;
678 if (msg->add_conn.rekey.reauth)
679 {
680 reauth = msg->add_conn.rekey.ike_lifetime - over;
681 }
682 else
683 {
684 rekey = msg->add_conn.rekey.ike_lifetime - over;
685 }
686 switch (msg->add_conn.unique)
687 {
688 case 1: /* yes */
689 case 2: /* replace */
690 unique = UNIQUE_REPLACE;
691 break;
692 case 3: /* keep */
693 unique = UNIQUE_KEEP;
694 break;
695 case 4: /* never */
696 unique = UNIQUE_NEVER;
697 break;
698 default: /* no */
699 unique = UNIQUE_NO;
700 break;
701 }
702 if (msg->add_conn.dpd.action == 0)
703 { /* dpdaction=none disables DPD */
704 msg->add_conn.dpd.delay = 0;
705 }
706
707 /* other.sourceip is managed in stroke_attributes. If it is set, we define
708 * the pool name as the connection name, which the attribute provider
709 * uses to serve pool addresses. */
710 peer_cfg = peer_cfg_create(msg->add_conn.name,
711 msg->add_conn.version, ike_cfg,
712 msg->add_conn.me.sendcert, unique,
713 msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
714 msg->add_conn.mobike, msg->add_conn.aggressive,
715 msg->add_conn.dpd.delay, msg->add_conn.dpd.timeout,
716 msg->add_conn.ikeme.mediation, mediated_by, peer_id);
717
718 if (msg->add_conn.other.sourceip)
719 {
720 enumerator_t *enumerator;
721 char *token;
722
723 enumerator = enumerator_create_token(msg->add_conn.other.sourceip,
724 ",", " ");
725 while (enumerator->enumerate(enumerator, &token))
726 {
727 if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
728 streq(token, "%config") || streq(token, "%cfg") ||
729 streq(token, "%config4") || streq(token, "%config6"))
730 {
731 /* empty pool, uses connection name */
732 this->attributes->add_pool(this->attributes,
733 mem_pool_create(msg->add_conn.name, NULL, 0));
734 peer_cfg->add_pool(peer_cfg, msg->add_conn.name);
735 }
736 else if (*token == '%')
737 {
738 /* external named pool */
739 peer_cfg->add_pool(peer_cfg, token + 1);
740 }
741 else
742 {
743 /* in-memory pool, named using CIDR notation */
744 host_t *base;
745 int bits;
746
747 base = host_create_from_subnet(token, &bits);
748 if (base)
749 {
750 this->attributes->add_pool(this->attributes,
751 mem_pool_create(token, base, bits));
752 peer_cfg->add_pool(peer_cfg, token);
753 base->destroy(base);
754 }
755 else
756 {
757 DBG1(DBG_CFG, "IP pool %s invalid, ignored", token);
758 }
759 }
760 }
761 enumerator->destroy(enumerator);
762 }
763
764 if (msg->add_conn.me.sourceip)
765 {
766 enumerator_t *enumerator;
767 char *token;
768
769 enumerator = enumerator_create_token(msg->add_conn.me.sourceip, ",", " ");
770 while (enumerator->enumerate(enumerator, &token))
771 {
772 host_t *vip = NULL;
773
774 if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
775 streq(token, "%config") || streq(token, "%cfg"))
776 { /* try to deduce an address family */
777 if (msg->add_conn.me.subnets)
778 { /* use the same family as in local subnet, if any */
779 if (strchr(msg->add_conn.me.subnets, '.'))
780 {
781 vip = host_create_any(AF_INET);
782 }
783 else
784 {
785 vip = host_create_any(AF_INET6);
786 }
787 }
788 else if (msg->add_conn.other.subnets)
789 { /* use the same family as in remote subnet, if any */
790 if (strchr(msg->add_conn.other.subnets, '.'))
791 {
792 vip = host_create_any(AF_INET);
793 }
794 else
795 {
796 vip = host_create_any(AF_INET6);
797 }
798 }
799 else
800 {
801 if (strchr(ike_cfg->get_my_addr(ike_cfg, NULL), ':'))
802 {
803 vip = host_create_any(AF_INET6);
804 }
805 else
806 {
807 vip = host_create_any(AF_INET);
808 }
809 }
810 }
811 else if (streq(token, "%config4"))
812 {
813 vip = host_create_any(AF_INET);
814 }
815 else if (streq(token, "%config6"))
816 {
817 vip = host_create_any(AF_INET6);
818 }
819 else
820 {
821 vip = host_create_from_string(token, 0);
822 if (vip)
823 {
824 DBG1(DBG_CFG, "ignored invalid subnet token: %s", token);
825 }
826 }
827
828 if (vip)
829 {
830 peer_cfg->add_virtual_ip(peer_cfg, vip);
831 }
832 }
833 enumerator->destroy(enumerator);
834 }
835
836 /* build leftauth= */
837 auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
838 if (auth_cfg)
839 {
840 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
841 }
842 else
843 { /* we require at least one config on our side */
844 peer_cfg->destroy(peer_cfg);
845 return NULL;
846 }
847 /* build leftauth2= */
848 auth_cfg = build_auth_cfg(this, msg, TRUE, FALSE);
849 if (auth_cfg)
850 {
851 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
852 }
853 /* build rightauth= */
854 auth_cfg = build_auth_cfg(this, msg, FALSE, TRUE);
855 if (auth_cfg)
856 {
857 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
858 }
859 /* build rightauth2= */
860 auth_cfg = build_auth_cfg(this, msg, FALSE, FALSE);
861 if (auth_cfg)
862 {
863 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
864 }
865 return peer_cfg;
866 }
867
868 /**
869 * build a traffic selector from a stroke_end
870 */
871 static void add_ts(private_stroke_config_t *this,
872 stroke_end_t *end, child_cfg_t *child_cfg, bool local)
873 {
874 traffic_selector_t *ts;
875
876 if (end->tohost)
877 {
878 ts = traffic_selector_create_dynamic(end->protocol,
879 end->port ? end->port : 0, end->port ? end->port : 65535);
880 child_cfg->add_traffic_selector(child_cfg, local, ts);
881 }
882 else
883 {
884 host_t *net;
885
886 if (!end->subnets)
887 {
888 net = host_create_from_string(end->address, 0);
889 if (net)
890 {
891 ts = traffic_selector_create_from_subnet(net, 0, end->protocol,
892 end->port);
893 child_cfg->add_traffic_selector(child_cfg, local, ts);
894 }
895 }
896 else
897 {
898 char *del, *start, *bits;
899
900 start = end->subnets;
901 do
902 {
903 int intbits = 0;
904
905 del = strchr(start, ',');
906 if (del)
907 {
908 *del = '\0';
909 }
910 bits = strchr(start, '/');
911 if (bits)
912 {
913 *bits = '\0';
914 intbits = atoi(bits + 1);
915 }
916
917 net = host_create_from_string(start, 0);
918 if (net)
919 {
920 ts = traffic_selector_create_from_subnet(net, intbits,
921 end->protocol, end->port);
922 child_cfg->add_traffic_selector(child_cfg, local, ts);
923 }
924 else
925 {
926 DBG1(DBG_CFG, "invalid subnet: %s, skipped", start);
927 }
928 start = del + 1;
929 }
930 while (del);
931 }
932 }
933 }
934
935 /**
936 * map starter magic values to our action type
937 */
938 static action_t map_action(int starter_action)
939 {
940 switch (starter_action)
941 {
942 case 2: /* =hold */
943 return ACTION_ROUTE;
944 case 3: /* =restart */
945 return ACTION_RESTART;
946 default:
947 return ACTION_NONE;
948 }
949 }
950
951 /**
952 * build a child config from the stroke message
953 */
954 static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
955 stroke_msg_t *msg)
956 {
957 child_cfg_t *child_cfg;
958 lifetime_cfg_t lifetime = {
959 .time = {
960 .life = msg->add_conn.rekey.ipsec_lifetime,
961 .rekey = msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
962 .jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100
963 },
964 .bytes = {
965 .life = msg->add_conn.rekey.life_bytes,
966 .rekey = msg->add_conn.rekey.life_bytes - msg->add_conn.rekey.margin_bytes,
967 .jitter = msg->add_conn.rekey.margin_bytes * msg->add_conn.rekey.fuzz / 100
968 },
969 .packets = {
970 .life = msg->add_conn.rekey.life_packets,
971 .rekey = msg->add_conn.rekey.life_packets - msg->add_conn.rekey.margin_packets,
972 .jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100
973 }
974 };
975 mark_t mark_in = {
976 .value = msg->add_conn.mark_in.value,
977 .mask = msg->add_conn.mark_in.mask
978 };
979 mark_t mark_out = {
980 .value = msg->add_conn.mark_out.value,
981 .mask = msg->add_conn.mark_out.mask
982 };
983
984 child_cfg = child_cfg_create(
985 msg->add_conn.name, &lifetime, msg->add_conn.me.updown,
986 msg->add_conn.me.hostaccess, msg->add_conn.mode, ACTION_NONE,
987 map_action(msg->add_conn.dpd.action),
988 map_action(msg->add_conn.close_action), msg->add_conn.ipcomp,
989 msg->add_conn.inactivity, msg->add_conn.reqid,
990 &mark_in, &mark_out, msg->add_conn.tfc);
991 child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
992 msg->add_conn.install_policy);
993 add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
994 add_ts(this, &msg->add_conn.other, child_cfg, FALSE);
995
996 add_proposals(this, msg->add_conn.algorithms.esp, NULL, child_cfg);
997
998 return child_cfg;
999 }
1000
1001 METHOD(stroke_config_t, add, void,
1002 private_stroke_config_t *this, stroke_msg_t *msg)
1003 {
1004 ike_cfg_t *ike_cfg, *existing_ike;
1005 peer_cfg_t *peer_cfg, *existing;
1006 child_cfg_t *child_cfg;
1007 enumerator_t *enumerator;
1008 bool use_existing = FALSE;
1009
1010 ike_cfg = build_ike_cfg(this, msg);
1011 if (!ike_cfg)
1012 {
1013 return;
1014 }
1015 peer_cfg = build_peer_cfg(this, msg, ike_cfg);
1016 if (!peer_cfg)
1017 {
1018 ike_cfg->destroy(ike_cfg);
1019 return;
1020 }
1021
1022 enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
1023 while (enumerator->enumerate(enumerator, &existing))
1024 {
1025 existing_ike = existing->get_ike_cfg(existing);
1026 if (existing->equals(existing, peer_cfg) &&
1027 existing_ike->equals(existing_ike, peer_cfg->get_ike_cfg(peer_cfg)))
1028 {
1029 use_existing = TRUE;
1030 peer_cfg->destroy(peer_cfg);
1031 peer_cfg = existing;
1032 peer_cfg->get_ref(peer_cfg);
1033 DBG1(DBG_CFG, "added child to existing configuration '%s'",
1034 peer_cfg->get_name(peer_cfg));
1035 break;
1036 }
1037 }
1038 enumerator->destroy(enumerator);
1039
1040 child_cfg = build_child_cfg(this, msg);
1041 if (!child_cfg)
1042 {
1043 peer_cfg->destroy(peer_cfg);
1044 return;
1045 }
1046 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
1047
1048 if (use_existing)
1049 {
1050 peer_cfg->destroy(peer_cfg);
1051 }
1052 else
1053 {
1054 /* add config to backend */
1055 DBG1(DBG_CFG, "added configuration '%s'", msg->add_conn.name);
1056 this->mutex->lock(this->mutex);
1057 this->list->insert_last(this->list, peer_cfg);
1058 this->mutex->unlock(this->mutex);
1059 }
1060 }
1061
1062 METHOD(stroke_config_t, del, void,
1063 private_stroke_config_t *this, stroke_msg_t *msg)
1064 {
1065 enumerator_t *enumerator, *children;
1066 peer_cfg_t *peer;
1067 child_cfg_t *child;
1068 bool deleted = FALSE;
1069
1070 this->mutex->lock(this->mutex);
1071 enumerator = this->list->create_enumerator(this->list);
1072 while (enumerator->enumerate(enumerator, (void**)&peer))
1073 {
1074 bool keep = FALSE;
1075
1076 /* remove any child with such a name */
1077 children = peer->create_child_cfg_enumerator(peer);
1078 while (children->enumerate(children, &child))
1079 {
1080 if (streq(child->get_name(child), msg->del_conn.name))
1081 {
1082 peer->remove_child_cfg(peer, children);
1083 child->destroy(child);
1084 deleted = TRUE;
1085 }
1086 else
1087 {
1088 keep = TRUE;
1089 }
1090 }
1091 children->destroy(children);
1092
1093 /* if peer config matches, or has no children anymore, remove it */
1094 if (!keep || streq(peer->get_name(peer), msg->del_conn.name))
1095 {
1096 this->list->remove_at(this->list, enumerator);
1097 peer->destroy(peer);
1098 deleted = TRUE;
1099 }
1100 }
1101 enumerator->destroy(enumerator);
1102 this->mutex->unlock(this->mutex);
1103
1104 if (deleted)
1105 {
1106 DBG1(DBG_CFG, "deleted connection '%s'", msg->del_conn.name);
1107 }
1108 else
1109 {
1110 DBG1(DBG_CFG, "connection '%s' not found", msg->del_conn.name);
1111 }
1112 }
1113
1114 METHOD(stroke_config_t, set_user_credentials, void,
1115 private_stroke_config_t *this, stroke_msg_t *msg, FILE *prompt)
1116 {
1117 enumerator_t *enumerator, *children, *remote_auth;
1118 peer_cfg_t *peer, *found = NULL;
1119 auth_cfg_t *auth_cfg, *remote_cfg;
1120 auth_class_t auth_class;
1121 child_cfg_t *child;
1122 identification_t *id, *identity, *gw = NULL;
1123 shared_key_type_t type = SHARED_ANY;
1124 chunk_t password = chunk_empty;
1125
1126 this->mutex->lock(this->mutex);
1127 enumerator = this->list->create_enumerator(this->list);
1128 while (enumerator->enumerate(enumerator, (void**)&peer))
1129 { /* find the peer (or child) config with the given name */
1130 if (streq(peer->get_name(peer), msg->user_creds.name))
1131 {
1132 found = peer;
1133 }
1134 else
1135 {
1136 children = peer->create_child_cfg_enumerator(peer);
1137 while (children->enumerate(children, &child))
1138 {
1139 if (streq(child->get_name(child), msg->user_creds.name))
1140 {
1141 found = peer;
1142 break;
1143 }
1144 }
1145 children->destroy(children);
1146 }
1147
1148 if (found)
1149 {
1150 break;
1151 }
1152 }
1153 enumerator->destroy(enumerator);
1154
1155 if (!found)
1156 {
1157 DBG1(DBG_CFG, " no config named '%s'", msg->user_creds.name);
1158 fprintf(prompt, "no config named '%s'\n", msg->user_creds.name);
1159 this->mutex->unlock(this->mutex);
1160 return;
1161 }
1162
1163 id = identification_create_from_string(msg->user_creds.username);
1164 if (strlen(msg->user_creds.username) == 0 ||
1165 !id || id->get_type(id) == ID_ANY)
1166 {
1167 DBG1(DBG_CFG, " invalid username '%s'", msg->user_creds.username);
1168 fprintf(prompt, "invalid username '%s'\n", msg->user_creds.username);
1169 this->mutex->unlock(this->mutex);
1170 DESTROY_IF(id);
1171 return;
1172 }
1173
1174 /* replace/set the username in the first EAP/XAuth auth_cfg, also look for
1175 * a suitable remote ID.
1176 * note that adding the identity here is not fully thread-safe as the
1177 * peer_cfg and in turn the auth_cfg could be in use. for the default use
1178 * case (setting user credentials before upping the connection) this will
1179 * not be a problem, though. */
1180 enumerator = found->create_auth_cfg_enumerator(found, TRUE);
1181 remote_auth = found->create_auth_cfg_enumerator(found, FALSE);
1182 while (enumerator->enumerate(enumerator, (void**)&auth_cfg))
1183 {
1184 if (remote_auth->enumerate(remote_auth, (void**)&remote_cfg))
1185 { /* fall back on rightid, in case aaa_identity is not specified */
1186 identity = remote_cfg->get(remote_cfg, AUTH_RULE_IDENTITY);
1187 if (identity && identity->get_type(identity) != ID_ANY)
1188 {
1189 gw = identity;
1190 }
1191 }
1192
1193 auth_class = (uintptr_t)auth_cfg->get(auth_cfg, AUTH_RULE_AUTH_CLASS);
1194 if (auth_class == AUTH_CLASS_EAP || auth_class == AUTH_CLASS_XAUTH)
1195 {
1196 if (auth_class == AUTH_CLASS_EAP)
1197 {
1198 auth_cfg->add(auth_cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
1199 /* if aaa_identity is specified use that as remote ID */
1200 identity = auth_cfg->get(auth_cfg, AUTH_RULE_AAA_IDENTITY);
1201 if (identity && identity->get_type(identity) != ID_ANY)
1202 {
1203 gw = identity;
1204 }
1205 DBG1(DBG_CFG, " configured EAP-Identity %Y", id);
1206 }
1207 else
1208 {
1209 auth_cfg->add(auth_cfg, AUTH_RULE_XAUTH_IDENTITY,
1210 id->clone(id));
1211 DBG1(DBG_CFG, " configured XAuth username %Y", id);
1212 }
1213 type = SHARED_EAP;
1214 break;
1215 }
1216 }
1217 enumerator->destroy(enumerator);
1218 remote_auth->destroy(remote_auth);
1219 /* clone the gw ID before unlocking the mutex */
1220 if (gw)
1221 {
1222 gw = gw->clone(gw);
1223 }
1224 this->mutex->unlock(this->mutex);
1225
1226 if (type == SHARED_ANY)
1227 {
1228 DBG1(DBG_CFG, " config '%s' unsuitable for user credentials",
1229 msg->user_creds.name);
1230 fprintf(prompt, "config '%s' unsuitable for user credentials\n",
1231 msg->user_creds.name);
1232 id->destroy(id);
1233 DESTROY_IF(gw);
1234 return;
1235 }
1236
1237 if (msg->user_creds.password)
1238 {
1239 char *pass;
1240
1241 pass = msg->user_creds.password;
1242 password = chunk_clone(chunk_create(pass, strlen(pass)));
1243 memwipe(pass, strlen(pass));
1244 }
1245 else
1246 { /* prompt the user for the password */
1247 char buf[256];
1248
1249 fprintf(prompt, "Password:\n");
1250 if (fgets(buf, sizeof(buf), prompt))
1251 {
1252 password = chunk_clone(chunk_create(buf, strlen(buf)));
1253 if (password.len > 0)
1254 { /* trim trailing \n */
1255 password.len--;
1256 }
1257 memwipe(buf, sizeof(buf));
1258 }
1259 }
1260
1261 if (password.len)
1262 {
1263 shared_key_t *shared;
1264 linked_list_t *owners;
1265
1266 shared = shared_key_create(type, password);
1267
1268 owners = linked_list_create();
1269 owners->insert_last(owners, id->clone(id));
1270 if (gw && gw->get_type(gw) != ID_ANY)
1271 {
1272 owners->insert_last(owners, gw->clone(gw));
1273 DBG1(DBG_CFG, " added %N secret for %Y %Y", shared_key_type_names,
1274 type, id, gw);
1275 }
1276 else
1277 {
1278 DBG1(DBG_CFG, " added %N secret for %Y", shared_key_type_names,
1279 type, id);
1280 }
1281 this->cred->add_shared(this->cred, shared, owners);
1282 DBG4(DBG_CFG, " secret: %#B", &password);
1283 }
1284 else
1285 { /* in case a user answers the password prompt by just pressing enter */
1286 chunk_clear(&password);
1287 }
1288 id->destroy(id);
1289 DESTROY_IF(gw);
1290 }
1291
1292 METHOD(stroke_config_t, destroy, void,
1293 private_stroke_config_t *this)
1294 {
1295 this->list->destroy_offset(this->list, offsetof(peer_cfg_t, destroy));
1296 this->mutex->destroy(this->mutex);
1297 free(this);
1298 }
1299
1300 /*
1301 * see header file
1302 */
1303 stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred,
1304 stroke_attribute_t *attributes)
1305 {
1306 private_stroke_config_t *this;
1307
1308 INIT(this,
1309 .public = {
1310 .backend = {
1311 .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
1312 .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
1313 .get_peer_cfg_by_name = _get_peer_cfg_by_name,
1314 },
1315 .add = _add,
1316 .del = _del,
1317 .set_user_credentials = _set_user_credentials,
1318 .destroy = _destroy,
1319 },
1320 .list = linked_list_create(),
1321 .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
1322 .ca = ca,
1323 .cred = cred,
1324 .attributes = attributes,
1325 );
1326
1327 return &this->public;
1328 }
1329