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