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