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