using shared read locks in credential set enumerators to avoid deadlocks
[strongswan.git] / src / charon / plugins / stroke / stroke_cred.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #define _GNU_SOURCE
19 #include <pthread.h>
20 #include <sys/stat.h>
21 #include <limits.h>
22
23 #include "stroke_cred.h"
24 #include "stroke_shared_key.h"
25
26 #include <credentials/certificates/x509.h>
27 #include <credentials/certificates/crl.h>
28 #include <credentials/certificates/ac.h>
29 #include <utils/linked_list.h>
30 #include <utils/lexparser.h>
31 #include <asn1/pem.h>
32 #include <daemon.h>
33
34 /* configuration directories and files */
35 #define CONFIG_DIR IPSEC_CONFDIR
36 #define IPSEC_D_DIR CONFIG_DIR "/ipsec.d"
37 #define PRIVATE_KEY_DIR IPSEC_D_DIR "/private"
38 #define CERTIFICATE_DIR IPSEC_D_DIR "/certs"
39 #define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts"
40 #define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts"
41 #define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts"
42 #define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts"
43 #define CRL_DIR IPSEC_D_DIR "/crls"
44 #define SECRETS_FILE CONFIG_DIR "/ipsec.secrets"
45
46 typedef struct private_stroke_cred_t private_stroke_cred_t;
47
48 /**
49 * private data of stroke_cred
50 */
51 struct private_stroke_cred_t {
52
53 /**
54 * public functions
55 */
56 stroke_cred_t public;
57
58 /**
59 * list of trusted peer/signer/CA certificates (certificate_t)
60 */
61 linked_list_t *certs;
62
63 /**
64 * list of shared secrets (private_shared_key_t)
65 */
66 linked_list_t *shared;
67
68 /**
69 * list of private keys (private_key_t)
70 */
71 linked_list_t *private;
72
73 /**
74 * read-write lock to lists
75 */
76 pthread_rwlock_t lock;
77
78 /**
79 * cache CRLs to disk?
80 */
81 bool cachecrl;
82 };
83
84 /**
85 * data to pass to various filters
86 */
87 typedef struct {
88 private_stroke_cred_t *this;
89 identification_t *id;
90 } id_data_t;
91
92 /**
93 * destroy id enumerator data and unlock list
94 */
95 static void id_data_destroy(id_data_t *data)
96 {
97 pthread_rwlock_unlock(&data->this->lock);
98 free(data);
99 }
100
101 /**
102 * filter function for private key enumerator
103 */
104 static bool private_filter(id_data_t *data,
105 private_key_t **in, private_key_t **out)
106 {
107 identification_t *candidate;
108 id_type_t type;
109
110 if (data->id == NULL)
111 {
112 *out = *in;
113 return TRUE;
114 }
115 type = data->id->get_type(data->id);
116 if (type == ID_KEY_ID)
117 { /* handle ID_KEY_ID as a ID_PUBKEY_SHA1 */
118 type = ID_PUBKEY_SHA1;
119 }
120 candidate = (*in)->get_id(*in, type);
121 if (candidate &&
122 chunk_equals(candidate->get_encoding(candidate),
123 data->id->get_encoding(data->id)))
124 {
125 *out = *in;
126 return TRUE;
127 }
128 return FALSE;
129 }
130
131 /**
132 * Implements credential_set_t.create_private_enumerator
133 */
134 static enumerator_t* create_private_enumerator(private_stroke_cred_t *this,
135 key_type_t type, identification_t *id)
136 {
137 id_data_t *data;
138
139 data = malloc_thing(id_data_t);
140 data->this = this;
141 data->id = id;
142
143 pthread_rwlock_rdlock(&this->lock);
144 return enumerator_create_filter(this->private->create_enumerator(this->private),
145 (void*)private_filter, data,
146 (void*)id_data_destroy);
147 }
148
149 /**
150 * filter function for certs enumerator
151 */
152 static bool certs_filter(id_data_t *data, certificate_t **in, certificate_t **out)
153 {
154 public_key_t *public;
155 identification_t *candidate;
156 certificate_t *cert = *in;
157 certificate_type_t type = cert->get_type(cert);
158
159 if (type == CERT_X509_CRL || type == CERT_X509_AC)
160 {
161 return FALSE;
162 }
163
164 if (data->id == NULL || cert->has_subject(cert, data->id))
165 {
166 *out = *in;
167 return TRUE;
168 }
169
170 public = (cert)->get_public_key(cert);
171 if (public)
172 {
173 candidate = public->get_id(public, data->id->get_type(data->id));
174 if (candidate && data->id->equals(data->id, candidate))
175 {
176 public->destroy(public);
177 *out = *in;
178 return TRUE;
179 }
180 public->destroy(public);
181 }
182 return FALSE;
183 }
184
185 /**
186 * filter function for crl enumerator
187 */
188 static bool crl_filter(id_data_t *data, certificate_t **in, certificate_t **out)
189 {
190 certificate_t *cert = *in;
191
192 if (cert->get_type(cert) != CERT_X509_CRL)
193 {
194 return FALSE;
195 }
196
197 if (data->id == NULL || cert->has_issuer(cert, data->id))
198 {
199 *out = *in;
200 return TRUE;
201 }
202 return FALSE;
203 }
204
205 /**
206 * filter function for attribute certificate enumerator
207 */
208 static bool ac_filter(id_data_t *data, certificate_t **in, certificate_t **out)
209 {
210 certificate_t *cert = *in;
211
212 if (cert->get_type(cert) != CERT_X509_AC)
213 {
214 return FALSE;
215 }
216
217 if (data->id == NULL || cert->has_subject(cert, data->id))
218 {
219 *out = *in;
220 return TRUE;
221 }
222 return FALSE;
223 }
224
225 /**
226 * Implements credential_set_t.create_cert_enumerator
227 */
228 static enumerator_t* create_cert_enumerator(private_stroke_cred_t *this,
229 certificate_type_t cert, key_type_t key,
230 identification_t *id, bool trusted)
231 {
232 id_data_t *data;
233
234 if (cert == CERT_X509_CRL || cert == CERT_X509_AC)
235 {
236 if (trusted)
237 {
238 return NULL;
239 }
240 data = malloc_thing(id_data_t);
241 data->this = this;
242 data->id = id;
243
244 pthread_rwlock_rdlock(&this->lock);
245 return enumerator_create_filter(this->certs->create_enumerator(this->certs),
246 (cert == CERT_X509_CRL)? (void*)crl_filter : (void*)ac_filter,
247 data, (void*)id_data_destroy);
248 }
249 if (cert != CERT_X509 && cert != CERT_ANY)
250 { /* we only have X509 certificates. TODO: ACs? */
251 return NULL;
252 }
253 data = malloc_thing(id_data_t);
254 data->this = this;
255 data->id = id;
256
257 pthread_rwlock_rdlock(&this->lock);
258 return enumerator_create_filter(this->certs->create_enumerator(this->certs),
259 (void*)certs_filter, data,
260 (void*)id_data_destroy);
261 }
262
263 typedef struct {
264 private_stroke_cred_t *this;
265 identification_t *me;
266 identification_t *other;
267 shared_key_type_t type;
268 } shared_data_t;
269
270 /**
271 * free shared key enumerator data and unlock list
272 */
273 static void shared_data_destroy(shared_data_t *data)
274 {
275 pthread_rwlock_unlock(&data->this->lock);
276 free(data);
277 }
278
279 /**
280 * filter function for certs enumerator
281 */
282 static bool shared_filter(shared_data_t *data,
283 stroke_shared_key_t **in, shared_key_t **out,
284 void **unused1, id_match_t *me,
285 void **unused2, id_match_t *other)
286 {
287 id_match_t my_match, other_match;
288 stroke_shared_key_t *stroke = *in;
289 shared_key_t *shared = &stroke->shared;
290
291 if (data->type != SHARED_ANY && shared->get_type(shared) != data->type)
292 {
293 return FALSE;
294 }
295
296 my_match = stroke->has_owner(stroke, data->me);
297 other_match = stroke->has_owner(stroke, data->other);
298 if (!my_match && !other_match)
299 {
300 return FALSE;
301 }
302 *out = shared;
303 if (me)
304 {
305 *me = my_match;
306 }
307 if (other)
308 {
309 *other = other_match;
310 }
311 return TRUE;
312 }
313
314 /**
315 * Implements credential_set_t.create_shared_enumerator
316 */
317 static enumerator_t* create_shared_enumerator(private_stroke_cred_t *this,
318 shared_key_type_t type, identification_t *me,
319 identification_t *other)
320 {
321 shared_data_t *data = malloc_thing(shared_data_t);
322
323 data->this = this;
324 data->me = me;
325 data->other = other;
326 data->type = type;
327 pthread_rwlock_rdlock(&this->lock);
328 return enumerator_create_filter(this->shared->create_enumerator(this->shared),
329 (void*)shared_filter, data,
330 (void*)shared_data_destroy);
331 }
332
333 /**
334 * Add a certificate to chain
335 */
336 static certificate_t* add_cert(private_stroke_cred_t *this, certificate_t *cert)
337 {
338 certificate_t *current;
339 enumerator_t *enumerator;
340 bool new = TRUE;
341
342 pthread_rwlock_rdlock(&this->lock);
343 enumerator = this->certs->create_enumerator(this->certs);
344 while (enumerator->enumerate(enumerator, (void**)&current))
345 {
346 if (current->equals(current, cert))
347 {
348 /* cert already in queue */
349 cert->destroy(cert);
350 cert = current;
351 new = FALSE;
352 break;
353 }
354 }
355 enumerator->destroy(enumerator);
356
357 if (new)
358 {
359 this->certs->insert_last(this->certs, cert);
360 }
361 pthread_rwlock_unlock(&this->lock);
362 return cert;
363 }
364
365 /**
366 * Implementation of stroke_cred_t.load_ca.
367 */
368 static certificate_t* load_ca(private_stroke_cred_t *this, char *filename)
369 {
370 certificate_t *cert;
371 char path[PATH_MAX];
372
373 if (*filename == '/')
374 {
375 snprintf(path, sizeof(path), "%s", filename);
376 }
377 else
378 {
379 snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename);
380 }
381
382 cert = lib->creds->create(lib->creds,
383 CRED_CERTIFICATE, CERT_X509,
384 BUILD_FROM_FILE, path,
385 BUILD_X509_FLAG, X509_CA,
386 BUILD_END);
387 if (cert)
388 {
389 return (certificate_t*)add_cert(this, cert);
390 }
391 return NULL;
392 }
393
394 /**
395 * Add X.509 CRL to chain
396 */
397 static bool add_crl(private_stroke_cred_t *this, crl_t* crl)
398 {
399 certificate_t *current, *cert = &crl->certificate;
400 enumerator_t *enumerator;
401 bool new = TRUE, found = FALSE;
402
403 pthread_rwlock_wrlock(&this->lock);
404 enumerator = this->certs->create_enumerator(this->certs);
405 while (enumerator->enumerate(enumerator, (void**)&current))
406 {
407 if (current->get_type(current) == CERT_X509_CRL)
408 {
409 crl_t *crl_c = (crl_t*)current;
410 identification_t *authkey = crl->get_authKeyIdentifier(crl);
411 identification_t *authkey_c = crl_c->get_authKeyIdentifier(crl_c);
412
413 /* if compare authorityKeyIdentifiers if available */
414 if (authkey != NULL && authkey_c != NULL &&
415 authkey->equals(authkey, authkey_c))
416 {
417 found = TRUE;
418 }
419 else
420 {
421 identification_t *issuer = cert->get_issuer(cert);
422 identification_t *issuer_c = current->get_issuer(current);
423
424 /* otherwise compare issuer distinguished names */
425 if (issuer->equals(issuer, issuer_c))
426 {
427 found = TRUE;
428 }
429 }
430 if (found)
431 {
432 new = cert->is_newer(cert, current);
433 if (new)
434 {
435 this->certs->remove_at(this->certs, enumerator);
436 }
437 else
438 {
439 cert->destroy(cert);
440 }
441 break;
442 }
443 }
444 }
445 enumerator->destroy(enumerator);
446
447 if (new)
448 {
449 this->certs->insert_last(this->certs, cert);
450 }
451 pthread_rwlock_unlock(&this->lock);
452 return new;
453 }
454
455 /**
456 * Add X.509 attribute certificate to chain
457 */
458 static bool add_ac(private_stroke_cred_t *this, ac_t* ac)
459 {
460 certificate_t *cert = &ac->certificate;
461
462 pthread_rwlock_wrlock(&this->lock);
463 this->certs->insert_last(this->certs, cert);
464 pthread_rwlock_unlock(&this->lock);
465 return TRUE;
466 }
467
468 /**
469 * Implementation of stroke_cred_t.load_peer.
470 */
471 static certificate_t* load_peer(private_stroke_cred_t *this, char *filename)
472 {
473 certificate_t *cert;
474 char path[PATH_MAX];
475
476 if (*filename == '/')
477 {
478 snprintf(path, sizeof(path), "%s", filename);
479 }
480 else
481 {
482 snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
483 }
484
485 cert = lib->creds->create(lib->creds,
486 CRED_CERTIFICATE, CERT_X509,
487 BUILD_FROM_FILE, path,
488 BUILD_X509_FLAG, 0,
489 BUILD_END);
490 if (cert)
491 {
492 cert = add_cert(this, cert);
493 return cert->get_ref(cert);
494 }
495 return NULL;
496 }
497
498 /**
499 * load trusted certificates from a directory
500 */
501 static void load_certdir(private_stroke_cred_t *this, char *path,
502 certificate_type_t type, x509_flag_t flag)
503 {
504 struct stat st;
505 char *file;
506
507 enumerator_t *enumerator = enumerator_create_directory(path);
508
509 if (!enumerator)
510 {
511 DBG1(DBG_CFG, " reading directory failed");
512 return;
513 }
514
515 while (enumerator->enumerate(enumerator, NULL, &file, &st))
516 {
517 certificate_t *cert;
518
519 if (!S_ISREG(st.st_mode))
520 {
521 /* skip special file */
522 continue;
523 }
524 switch (type)
525 {
526 case CERT_X509:
527 cert = lib->creds->create(lib->creds,
528 CRED_CERTIFICATE, CERT_X509,
529 BUILD_FROM_FILE, file,
530 BUILD_X509_FLAG, flag,
531 BUILD_END);
532 if (cert)
533 {
534 add_cert(this, cert);
535 }
536 break;
537 case CERT_X509_CRL:
538 cert = lib->creds->create(lib->creds,
539 CRED_CERTIFICATE, CERT_X509_CRL,
540 BUILD_FROM_FILE, file,
541 BUILD_END);
542 if (cert)
543 {
544 add_crl(this, (crl_t*)cert);
545 }
546 break;
547 case CERT_X509_AC:
548 cert = lib->creds->create(lib->creds,
549 CRED_CERTIFICATE, CERT_X509_AC,
550 BUILD_FROM_FILE, file,
551 BUILD_END);
552 if (cert)
553 {
554 add_ac(this, (ac_t*)cert);
555 }
556 break;
557 default:
558 break;
559 }
560 }
561 enumerator->destroy(enumerator);
562 }
563
564 /**
565 * Implementation of credential_set_t.cache_cert.
566 */
567 static void cache_cert(private_stroke_cred_t *this, certificate_t *cert)
568 {
569 if (cert->get_type(cert) == CERT_X509_CRL && this->cachecrl)
570 {
571 /* CRLs get written to /etc/ipsec.d/crls/authkeyId.crl */
572 crl_t *crl = (crl_t*)cert;
573
574 cert->get_ref(cert);
575 if (add_crl(this, crl))
576 {
577 char buf[256];
578 chunk_t chunk, hex;
579 identification_t *id;
580
581 id = crl->get_authKeyIdentifier(crl);
582 chunk = id->get_encoding(id);
583 hex = chunk_to_hex(chunk, NULL, FALSE);
584 snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_DIR, hex);
585 free(hex.ptr);
586
587 chunk = cert->get_encoding(cert);
588 if (chunk_write(chunk, buf, 022, TRUE))
589 {
590 DBG1(DBG_CFG, " written crl to '%s'", buf);
591 }
592 else
593 {
594 DBG1(DBG_CFG, " writing crl to '%s' failed", buf);
595 }
596 free(chunk.ptr);
597 }
598 }
599 }
600
601 /**
602 * Implementation of stroke_cred_t.cachecrl.
603 */
604 static void cachecrl(private_stroke_cred_t *this, bool enabled)
605 {
606 DBG1(DBG_CFG, "crl caching to %s %s",
607 CRL_DIR, enabled ? "enabled" : "disabled");
608 this->cachecrl = enabled;
609 }
610
611
612 /**
613 * Convert a string of characters into a binary secret
614 * A string between single or double quotes is treated as ASCII characters
615 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
616 */
617 static err_t extract_secret(chunk_t *secret, chunk_t *line)
618 {
619 chunk_t raw_secret;
620 char delimiter = ' ';
621 bool quotes = FALSE;
622
623 if (!eat_whitespace(line))
624 {
625 return "missing secret";
626 }
627
628 if (*line->ptr == '\'' || *line->ptr == '"')
629 {
630 quotes = TRUE;
631 delimiter = *line->ptr;
632 line->ptr++; line->len--;
633 }
634
635 if (!extract_token(&raw_secret, delimiter, line))
636 {
637 if (delimiter == ' ')
638 {
639 raw_secret = *line;
640 }
641 else
642 {
643 return "missing second delimiter";
644 }
645 }
646
647 if (quotes)
648 {
649 /* treat as an ASCII string */
650 *secret = chunk_clone(raw_secret);
651 return NULL;
652 }
653 /* treat 0x as hex, 0s as base64 */
654 if (raw_secret.len > 2)
655 {
656 if (strncasecmp("0x", raw_secret.ptr, 2) == 0)
657 {
658 *secret = chunk_from_hex(chunk_skip(raw_secret, 2), NULL);
659 return NULL;
660 }
661 if (strncasecmp("0s", raw_secret.ptr, 2) == 0)
662 {
663 *secret = chunk_from_base64(chunk_skip(raw_secret, 2), NULL);
664 return NULL;
665 }
666 }
667 *secret = chunk_clone(raw_secret);
668 return NULL;
669 }
670
671 /**
672 * reload ipsec.secrets
673 */
674 static void load_secrets(private_stroke_cred_t *this)
675 {
676 size_t bytes;
677 int line_nr = 0;
678 chunk_t chunk, src, line;
679 FILE *fd;
680 private_key_t *private;
681 shared_key_t *shared;
682
683 DBG1(DBG_CFG, "loading secrets from '%s'", SECRETS_FILE);
684
685 fd = fopen(SECRETS_FILE, "r");
686 if (fd == NULL)
687 {
688 DBG1(DBG_CFG, "opening secrets file '%s' failed");
689 return;
690 }
691
692 /* TODO: do error checks */
693 fseek(fd, 0, SEEK_END);
694 chunk.len = ftell(fd);
695 rewind(fd);
696 chunk.ptr = malloc(chunk.len);
697 bytes = fread(chunk.ptr, 1, chunk.len, fd);
698 fclose(fd);
699 src = chunk;
700
701 pthread_rwlock_wrlock(&this->lock);
702 while (this->shared->remove_last(this->shared,
703 (void**)&shared) == SUCCESS)
704 {
705 shared->destroy(shared);
706 }
707 while (this->private->remove_last(this->private,
708 (void**)&private) == SUCCESS)
709 {
710 private->destroy(private);
711 }
712
713 while (fetchline(&src, &line))
714 {
715 chunk_t ids, token;
716 shared_key_type_t type;
717
718 line_nr++;
719
720 if (!eat_whitespace(&line))
721 {
722 continue;
723 }
724 if (!extract_last_token(&ids, ':', &line))
725 {
726 DBG1(DBG_CFG, "line %d: missing ':' separator", line_nr);
727 goto error;
728 }
729 /* NULL terminate the ids string by replacing the : separator */
730 *(ids.ptr + ids.len) = '\0';
731
732 if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
733 {
734 DBG1(DBG_CFG, "line %d: missing token", line_nr);
735 goto error;
736 }
737 if (match("RSA", &token) || match("ECDSA", &token))
738 {
739 char path[PATH_MAX];
740 chunk_t filename;
741 chunk_t secret = chunk_empty;
742 private_key_t *key;
743 bool pgp = FALSE;
744 chunk_t chunk = chunk_empty;
745 key_type_t key_type = match("RSA", &token) ? KEY_RSA : KEY_ECDSA;
746
747 err_t ugh = extract_value(&filename, &line);
748
749 if (ugh != NULL)
750 {
751 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
752 goto error;
753 }
754 if (filename.len == 0)
755 {
756 DBG1(DBG_CFG, "line %d: empty filename", line_nr);
757 goto error;
758 }
759 if (*filename.ptr == '/')
760 {
761 /* absolute path name */
762 snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
763 }
764 else
765 {
766 /* relative path name */
767 snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
768 filename.len, filename.ptr);
769 }
770
771 /* check for optional passphrase */
772 if (eat_whitespace(&line))
773 {
774 ugh = extract_secret(&secret, &line);
775 if (ugh != NULL)
776 {
777 DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
778 goto error;
779 }
780 }
781
782 if (pem_asn1_load_file(path, &secret, &chunk, &pgp))
783 {
784 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
785 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
786 if (key)
787 {
788 DBG1(DBG_CFG, " loaded private key file '%s'", path);
789 this->private->insert_last(this->private, key);
790 }
791 }
792 chunk_clear(&secret);
793 }
794 else if ((match("PSK", &token) && (type = SHARED_IKE)) ||
795 (match("EAP", &token) && (type = SHARED_EAP)) ||
796 (match("XAUTH", &token) && (type = SHARED_EAP)) ||
797 (match("PIN", &token) && (type = SHARED_PIN)))
798 {
799 stroke_shared_key_t *shared_key;
800 chunk_t secret = chunk_empty;
801 bool any = TRUE;
802
803 err_t ugh = extract_secret(&secret, &line);
804 if (ugh != NULL)
805 {
806 DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
807 goto error;
808 }
809 shared_key = stroke_shared_key_create(type, secret);
810 DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type,
811 ids.len > 0 ? (char*)ids.ptr : "%any");
812 DBG4(DBG_CFG, " secret: %#B", &secret);
813
814 this->shared->insert_last(this->shared, shared_key);
815 while (ids.len > 0)
816 {
817 chunk_t id;
818 identification_t *peer_id;
819
820 ugh = extract_value(&id, &ids);
821 if (ugh != NULL)
822 {
823 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
824 goto error;
825 }
826 if (id.len == 0)
827 {
828 continue;
829 }
830
831 /* NULL terminate the ID string */
832 *(id.ptr + id.len) = '\0';
833
834 peer_id = identification_create_from_string(id.ptr);
835 if (peer_id == NULL)
836 {
837 DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
838 goto error;
839 }
840 if (peer_id->get_type(peer_id) == ID_ANY)
841 {
842 peer_id->destroy(peer_id);
843 continue;
844 }
845
846 shared_key->add_owner(shared_key, peer_id);
847 any = FALSE;
848 }
849 if (any)
850 {
851 shared_key->add_owner(shared_key,
852 identification_create_from_encoding(ID_ANY, chunk_empty));
853 }
854 }
855 else
856 {
857 DBG1(DBG_CFG, "line %d: token must be either "
858 "RSA, EC, PSK, EAP, or PIN", line_nr);
859 goto error;
860 }
861 }
862 error:
863 pthread_rwlock_unlock(&this->lock);
864 chunk_clear(&chunk);
865 }
866
867 /**
868 * load all certificates from ipsec.d
869 */
870 static void load_certs(private_stroke_cred_t *this)
871 {
872 DBG1(DBG_CFG, "loading ca certificates from '%s'",
873 CA_CERTIFICATE_DIR);
874 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
875
876 DBG1(DBG_CFG, "loading aa certificates from '%s'",
877 AA_CERTIFICATE_DIR);
878 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
879
880 DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'",
881 OCSP_CERTIFICATE_DIR);
882 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER);
883
884 DBG1(DBG_CFG, "loading attribute certificates from '%s'",
885 ATTR_CERTIFICATE_DIR);
886 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
887
888 DBG1(DBG_CFG, "loading crls from '%s'",
889 CRL_DIR);
890 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
891 }
892
893 /**
894 * Implementation of stroke_cred_t.reread.
895 */
896 static void reread(private_stroke_cred_t *this, stroke_msg_t *msg)
897 {
898 if (msg->reread.flags & REREAD_SECRETS)
899 {
900 DBG1(DBG_CFG, "rereading secrets");
901 load_secrets(this);
902 }
903 if (msg->reread.flags & REREAD_CACERTS)
904 {
905 DBG1(DBG_CFG, "rereading ca certificates from '%s'",
906 CA_CERTIFICATE_DIR);
907 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
908 }
909 if (msg->reread.flags & REREAD_OCSPCERTS)
910 {
911 DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'",
912 OCSP_CERTIFICATE_DIR);
913 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509,
914 X509_OCSP_SIGNER);
915 }
916 if (msg->reread.flags & REREAD_AACERTS)
917 {
918 DBG1(DBG_CFG, "rereading aa certificates from '%s'",
919 AA_CERTIFICATE_DIR);
920 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
921 }
922 if (msg->reread.flags & REREAD_ACERTS)
923 {
924 DBG1(DBG_CFG, "rereading attribute certificates from '%s'",
925 ATTR_CERTIFICATE_DIR);
926 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
927 }
928 if (msg->reread.flags & REREAD_CRLS)
929 {
930 DBG1(DBG_CFG, "rereading crls from '%s'",
931 CRL_DIR);
932 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
933 }
934 }
935
936 /**
937 * Implementation of stroke_cred_t.destroy
938 */
939 static void destroy(private_stroke_cred_t *this)
940 {
941 this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
942 this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy));
943 this->private->destroy_offset(this->private, offsetof(private_key_t, destroy));
944 pthread_rwlock_destroy(&this->lock);
945 free(this);
946 }
947
948 /*
949 * see header file
950 */
951 stroke_cred_t *stroke_cred_create()
952 {
953 private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t);
954
955 this->public.set.create_private_enumerator = (void*)create_private_enumerator;
956 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
957 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
958 this->public.set.create_cdp_enumerator = (void*)return_null;
959 this->public.set.cache_cert = (void*)cache_cert;
960 this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg))reread;
961 this->public.load_ca = (certificate_t*(*)(stroke_cred_t*, char *filename))load_ca;
962 this->public.load_peer = (certificate_t*(*)(stroke_cred_t*, char *filename))load_peer;
963 this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl;
964 this->public.destroy = (void(*)(stroke_cred_t*))destroy;
965
966 this->certs = linked_list_create();
967 this->shared = linked_list_create();
968 this->private = linked_list_create();
969 pthread_rwlock_init(&this->lock, NULL);
970
971 load_certs(this);
972 load_secrets(this);
973
974 this->cachecrl = FALSE;
975
976 return &this->public;
977 }
978