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