migrated write_chunk() to chunk_write()
[strongswan.git] / src / charon / plugins / stroke / stroke_cred.c
1 /*
2 * Copyright (C) 2008 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 * $Id$
17 */
18
19 #include <sys/stat.h>
20 #include <limits.h>
21
22 #include "stroke_cred.h"
23 #include "stroke_shared_key.h"
24
25 #include <credentials/certificates/x509.h>
26 #include <credentials/certificates/crl.h>
27 #include <credentials/certificates/ac.h>
28 #include <utils/linked_list.h>
29 #include <utils/lexparser.h>
30 #include <utils/mutex.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 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 data->this->lock->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 this->lock->read_lock(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 this->lock->read_lock(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 this->lock->read_lock(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 data->this->lock->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 this->lock->read_lock(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 this->lock->read_lock(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 this->lock->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 this->lock->write_lock(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 this->lock->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 this->lock->write_lock(this->lock);
463 this->certs->insert_last(this->certs, cert);
464 this->lock->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[BUF_LEN];
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 chunk_write(chunk, buf, "crl", 022, TRUE);
589 free(chunk.ptr);
590 }
591 }
592 }
593
594 /**
595 * Implementation of stroke_cred_t.cachecrl.
596 */
597 static void cachecrl(private_stroke_cred_t *this, bool enabled)
598 {
599 DBG1(DBG_CFG, "crl caching to %s %s",
600 CRL_DIR, enabled ? "enabled" : "disabled");
601 this->cachecrl = enabled;
602 }
603
604
605 /**
606 * Convert a string of characters into a binary secret
607 * A string between single or double quotes is treated as ASCII characters
608 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
609 */
610 static err_t extract_secret(chunk_t *secret, chunk_t *line)
611 {
612 chunk_t raw_secret;
613 char delimiter = ' ';
614 bool quotes = FALSE;
615
616 if (!eat_whitespace(line))
617 {
618 return "missing secret";
619 }
620
621 if (*line->ptr == '\'' || *line->ptr == '"')
622 {
623 quotes = TRUE;
624 delimiter = *line->ptr;
625 line->ptr++; line->len--;
626 }
627
628 if (!extract_token(&raw_secret, delimiter, line))
629 {
630 if (delimiter == ' ')
631 {
632 raw_secret = *line;
633 }
634 else
635 {
636 return "missing second delimiter";
637 }
638 }
639
640 if (quotes)
641 {
642 /* treat as an ASCII string */
643 *secret = chunk_clone(raw_secret);
644 return NULL;
645 }
646 /* treat 0x as hex, 0s as base64 */
647 if (raw_secret.len > 2)
648 {
649 if (strncasecmp("0x", raw_secret.ptr, 2) == 0)
650 {
651 *secret = chunk_from_hex(chunk_skip(raw_secret, 2), NULL);
652 return NULL;
653 }
654 if (strncasecmp("0s", raw_secret.ptr, 2) == 0)
655 {
656 *secret = chunk_from_base64(chunk_skip(raw_secret, 2), NULL);
657 return NULL;
658 }
659 }
660 *secret = chunk_clone(raw_secret);
661 return NULL;
662 }
663
664 /**
665 * reload ipsec.secrets
666 */
667 static void load_secrets(private_stroke_cred_t *this)
668 {
669 size_t bytes;
670 int line_nr = 0;
671 chunk_t chunk, src, line;
672 FILE *fd;
673 private_key_t *private;
674 shared_key_t *shared;
675
676 DBG1(DBG_CFG, "loading secrets from '%s'", SECRETS_FILE);
677
678 fd = fopen(SECRETS_FILE, "r");
679 if (fd == NULL)
680 {
681 DBG1(DBG_CFG, "opening secrets file '%s' failed");
682 return;
683 }
684
685 /* TODO: do error checks */
686 fseek(fd, 0, SEEK_END);
687 chunk.len = ftell(fd);
688 rewind(fd);
689 chunk.ptr = malloc(chunk.len);
690 bytes = fread(chunk.ptr, 1, chunk.len, fd);
691 fclose(fd);
692 src = chunk;
693
694 this->lock->write_lock(this->lock);
695 while (this->shared->remove_last(this->shared,
696 (void**)&shared) == SUCCESS)
697 {
698 shared->destroy(shared);
699 }
700 while (this->private->remove_last(this->private,
701 (void**)&private) == SUCCESS)
702 {
703 private->destroy(private);
704 }
705
706 while (fetchline(&src, &line))
707 {
708 chunk_t ids, token;
709 shared_key_type_t type;
710
711 line_nr++;
712
713 if (!eat_whitespace(&line))
714 {
715 continue;
716 }
717 if (line.len > 2 && strneq(": ", line.ptr, 2))
718 {
719 /* no ids, skip the ':' */
720 ids = chunk_empty;
721 line.ptr++;
722 line.len--;
723 }
724 else if (extract_token_str(&ids, " : ", &line))
725 {
726 /* NULL terminate the extracted id string */
727 *(ids.ptr + ids.len) = '\0';
728 }
729 else
730 {
731 DBG1(DBG_CFG, "line %d: missing ' : ' separator", line_nr);
732 goto error;
733 }
734
735 if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
736 {
737 DBG1(DBG_CFG, "line %d: missing token", line_nr);
738 goto error;
739 }
740 if (match("RSA", &token) || match("ECDSA", &token))
741 {
742 char path[PATH_MAX];
743 chunk_t filename;
744 chunk_t secret = chunk_empty;
745 private_key_t *key;
746 bool pgp = FALSE;
747 chunk_t chunk = chunk_empty;
748 key_type_t key_type = match("RSA", &token) ? KEY_RSA : KEY_ECDSA;
749
750 err_t ugh = extract_value(&filename, &line);
751
752 if (ugh != NULL)
753 {
754 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
755 goto error;
756 }
757 if (filename.len == 0)
758 {
759 DBG1(DBG_CFG, "line %d: empty filename", line_nr);
760 goto error;
761 }
762 if (*filename.ptr == '/')
763 {
764 /* absolute path name */
765 snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
766 }
767 else
768 {
769 /* relative path name */
770 snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
771 filename.len, filename.ptr);
772 }
773
774 /* check for optional passphrase */
775 if (eat_whitespace(&line))
776 {
777 ugh = extract_secret(&secret, &line);
778 if (ugh != NULL)
779 {
780 DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
781 goto error;
782 }
783 }
784
785 if (pem_asn1_load_file(path, &secret, &chunk, &pgp))
786 {
787 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
788 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
789 free(chunk.ptr);
790 if (key)
791 {
792 DBG1(DBG_CFG, " loaded private key file '%s'", path);
793 this->private->insert_last(this->private, key);
794 }
795 }
796 chunk_clear(&secret);
797 }
798 else if (match("PIN", &token))
799 {
800 chunk_t sc = chunk_empty, secret = chunk_empty;
801 char smartcard[32], keyid[22], pin[32];
802 private_key_t *key;
803 u_int slot;
804
805 err_t ugh = extract_value(&sc, &line);
806
807 if (ugh != NULL)
808 {
809 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
810 goto error;
811 }
812 if (sc.len == 0)
813 {
814 DBG1(DBG_CFG, "line %d: expected %%smartcard specifier", line_nr);
815 goto error;
816 }
817 snprintf(smartcard, sizeof(smartcard), "%.*s", sc.len, sc.ptr);
818 smartcard[sizeof(smartcard) - 1] = '\0';
819
820 /* parse slot and key id. only two formats are supported.
821 * first try %smartcard<slot>:<keyid> */
822 if (sscanf(smartcard, "%%smartcard%u:%s", &slot, keyid) == 2)
823 {
824 snprintf(smartcard, sizeof(smartcard), "%u:%s", slot, keyid);
825 }
826 /* then try %smartcard:<keyid> */
827 else if (sscanf(smartcard, "%%smartcard:%s", keyid) == 1)
828 {
829 snprintf(smartcard, sizeof(smartcard), "%s", keyid);
830 }
831 else
832 {
833 DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not"
834 " supported or invalid", line_nr);
835 goto error;
836 }
837
838 if (!eat_whitespace(&line))
839 {
840 DBG1(DBG_CFG, "line %d: expected PIN", line_nr);
841 goto error;
842 }
843 ugh = extract_secret(&secret, &line);
844 if (ugh != NULL)
845 {
846 DBG1(DBG_CFG, "line %d: malformed PIN: %s", line_nr, ugh);
847 goto error;
848 }
849 snprintf(pin, sizeof(pin), "%.*s", secret.len, secret.ptr);
850 pin[sizeof(pin) - 1] = '\0';
851
852 /* we assume an RSA key */
853 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
854 BUILD_SMARTCARD_KEYID, smartcard,
855 BUILD_SMARTCARD_PIN, pin, BUILD_END);
856
857 if (key)
858 {
859 DBG1(DBG_CFG, " loaded private key from %.*s", sc.len, sc.ptr);
860 this->private->insert_last(this->private, key);
861 }
862 memset(pin, 0, sizeof(pin));
863 chunk_clear(&secret);
864 }
865 else if ((match("PSK", &token) && (type = SHARED_IKE)) ||
866 (match("EAP", &token) && (type = SHARED_EAP)) ||
867 (match("XAUTH", &token) && (type = SHARED_EAP)))
868 {
869 stroke_shared_key_t *shared_key;
870 chunk_t secret = chunk_empty;
871 bool any = TRUE;
872
873 err_t ugh = extract_secret(&secret, &line);
874 if (ugh != NULL)
875 {
876 DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
877 goto error;
878 }
879 shared_key = stroke_shared_key_create(type, secret);
880 DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type,
881 ids.len > 0 ? (char*)ids.ptr : "%any");
882 DBG4(DBG_CFG, " secret: %#B", &secret);
883
884 this->shared->insert_last(this->shared, shared_key);
885 while (ids.len > 0)
886 {
887 chunk_t id;
888 identification_t *peer_id;
889
890 ugh = extract_value(&id, &ids);
891 if (ugh != NULL)
892 {
893 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
894 goto error;
895 }
896 if (id.len == 0)
897 {
898 continue;
899 }
900
901 /* NULL terminate the ID string */
902 *(id.ptr + id.len) = '\0';
903 peer_id = identification_create_from_string(id.ptr);
904 if (peer_id->get_type(peer_id) == ID_ANY)
905 {
906 peer_id->destroy(peer_id);
907 continue;
908 }
909
910 shared_key->add_owner(shared_key, peer_id);
911 any = FALSE;
912 }
913 if (any)
914 {
915 shared_key->add_owner(shared_key,
916 identification_create_from_encoding(ID_ANY, chunk_empty));
917 }
918 }
919 else
920 {
921 DBG1(DBG_CFG, "line %d: token must be either "
922 "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr);
923 goto error;
924 }
925 }
926 error:
927 this->lock->unlock(this->lock);
928 chunk_clear(&chunk);
929 }
930
931 /**
932 * load all certificates from ipsec.d
933 */
934 static void load_certs(private_stroke_cred_t *this)
935 {
936 DBG1(DBG_CFG, "loading ca certificates from '%s'",
937 CA_CERTIFICATE_DIR);
938 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
939
940 DBG1(DBG_CFG, "loading aa certificates from '%s'",
941 AA_CERTIFICATE_DIR);
942 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
943
944 DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'",
945 OCSP_CERTIFICATE_DIR);
946 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER);
947
948 DBG1(DBG_CFG, "loading attribute certificates from '%s'",
949 ATTR_CERTIFICATE_DIR);
950 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
951
952 DBG1(DBG_CFG, "loading crls from '%s'",
953 CRL_DIR);
954 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
955 }
956
957 /**
958 * Implementation of stroke_cred_t.reread.
959 */
960 static void reread(private_stroke_cred_t *this, stroke_msg_t *msg)
961 {
962 if (msg->reread.flags & REREAD_SECRETS)
963 {
964 DBG1(DBG_CFG, "rereading secrets");
965 load_secrets(this);
966 }
967 if (msg->reread.flags & REREAD_CACERTS)
968 {
969 DBG1(DBG_CFG, "rereading ca certificates from '%s'",
970 CA_CERTIFICATE_DIR);
971 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
972 }
973 if (msg->reread.flags & REREAD_OCSPCERTS)
974 {
975 DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'",
976 OCSP_CERTIFICATE_DIR);
977 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509,
978 X509_OCSP_SIGNER);
979 }
980 if (msg->reread.flags & REREAD_AACERTS)
981 {
982 DBG1(DBG_CFG, "rereading aa certificates from '%s'",
983 AA_CERTIFICATE_DIR);
984 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
985 }
986 if (msg->reread.flags & REREAD_ACERTS)
987 {
988 DBG1(DBG_CFG, "rereading attribute certificates from '%s'",
989 ATTR_CERTIFICATE_DIR);
990 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
991 }
992 if (msg->reread.flags & REREAD_CRLS)
993 {
994 DBG1(DBG_CFG, "rereading crls from '%s'",
995 CRL_DIR);
996 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
997 }
998 }
999
1000 /**
1001 * Implementation of stroke_cred_t.destroy
1002 */
1003 static void destroy(private_stroke_cred_t *this)
1004 {
1005 this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
1006 this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy));
1007 this->private->destroy_offset(this->private, offsetof(private_key_t, destroy));
1008 this->lock->destroy(this->lock);
1009 free(this);
1010 }
1011
1012 /*
1013 * see header file
1014 */
1015 stroke_cred_t *stroke_cred_create()
1016 {
1017 private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t);
1018
1019 this->public.set.create_private_enumerator = (void*)create_private_enumerator;
1020 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
1021 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
1022 this->public.set.create_cdp_enumerator = (void*)return_null;
1023 this->public.set.cache_cert = (void*)cache_cert;
1024 this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg))reread;
1025 this->public.load_ca = (certificate_t*(*)(stroke_cred_t*, char *filename))load_ca;
1026 this->public.load_peer = (certificate_t*(*)(stroke_cred_t*, char *filename))load_peer;
1027 this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl;
1028 this->public.destroy = (void(*)(stroke_cred_t*))destroy;
1029
1030 this->certs = linked_list_create();
1031 this->shared = linked_list_create();
1032 this->private = linked_list_create();
1033 this->lock = rwlock_create(RWLOCK_DEFAULT);
1034
1035 load_certs(this);
1036 load_secrets(this);
1037
1038 this->cachecrl = FALSE;
1039
1040 return &this->public;
1041 }
1042