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