add support for smartcards in charon by using the ENGINE API provided by OpenSSL...
[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[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 this->lock->write_lock(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 (line.len > 2 && strneq(": ", line.ptr, 2))
725 {
726 /* no ids, skip the ':' */
727 ids = chunk_empty;
728 line.ptr++;
729 line.len--;
730 }
731 else if (extract_token_str(&ids, " : ", &line))
732 {
733 /* NULL terminate the extracted id string */
734 *(ids.ptr + ids.len) = '\0';
735 }
736 else
737 {
738 DBG1(DBG_CFG, "line %d: missing ' : ' separator", line_nr);
739 goto error;
740 }
741
742 if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
743 {
744 DBG1(DBG_CFG, "line %d: missing token", line_nr);
745 goto error;
746 }
747 if (match("RSA", &token) || match("ECDSA", &token))
748 {
749 char path[PATH_MAX];
750 chunk_t filename;
751 chunk_t secret = chunk_empty;
752 private_key_t *key;
753 bool pgp = FALSE;
754 chunk_t chunk = chunk_empty;
755 key_type_t key_type = match("RSA", &token) ? KEY_RSA : KEY_ECDSA;
756
757 err_t ugh = extract_value(&filename, &line);
758
759 if (ugh != NULL)
760 {
761 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
762 goto error;
763 }
764 if (filename.len == 0)
765 {
766 DBG1(DBG_CFG, "line %d: empty filename", line_nr);
767 goto error;
768 }
769 if (*filename.ptr == '/')
770 {
771 /* absolute path name */
772 snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
773 }
774 else
775 {
776 /* relative path name */
777 snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
778 filename.len, filename.ptr);
779 }
780
781 /* check for optional passphrase */
782 if (eat_whitespace(&line))
783 {
784 ugh = extract_secret(&secret, &line);
785 if (ugh != NULL)
786 {
787 DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
788 goto error;
789 }
790 }
791
792 if (pem_asn1_load_file(path, &secret, &chunk, &pgp))
793 {
794 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
795 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
796 free(chunk.ptr);
797 if (key)
798 {
799 DBG1(DBG_CFG, " loaded private key file '%s'", path);
800 this->private->insert_last(this->private, key);
801 }
802 }
803 chunk_clear(&secret);
804 }
805 else if (match("PIN", &token))
806 {
807 chunk_t sc = chunk_empty;
808 char smartcard[32], keyid[22], pin[32];
809 private_key_t *key;
810 u_int slot;
811
812 err_t ugh = extract_value(&sc, &line);
813
814 if (ugh != NULL)
815 {
816 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
817 goto error;
818 }
819 if (sc.len == 0)
820 {
821 DBG1(DBG_CFG, "line %d: expected %%smartcard specifier", line_nr);
822 goto error;
823 }
824 snprintf(smartcard, sizeof(smartcard), "%.*s", sc.len, sc.ptr);
825 smartcard[sizeof(smartcard) - 1] = '\0';
826
827 /* parse slot and key id. only two formats are supported.
828 * first try %smartcard<slot>:<keyid> */
829 if (sscanf(smartcard, "%%smartcard%u:%s", &slot, keyid) == 2)
830 {
831 snprintf(smartcard, sizeof(smartcard), "%u:%s", slot, keyid);
832 }
833 /* then try %smartcard:<keyid> */
834 else if (sscanf(smartcard, "%%smartcard:%s", keyid) == 1)
835 {
836 snprintf(smartcard, sizeof(smartcard), "%s", keyid);
837 }
838 else
839 {
840 DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not"
841 " supported or invalid", line_nr);
842 goto error;
843 }
844
845 if (!eat_whitespace(&line))
846 {
847 DBG1(DBG_CFG, "line %d: expected PIN", line_nr);
848 goto error;
849 }
850 ugh = extract_secret(&chunk, &line);
851 if (ugh != NULL)
852 {
853 DBG1(DBG_CFG, "line %d: malformed PIN: %s", line_nr, ugh);
854 goto error;
855 }
856 snprintf(pin, sizeof(pin), "%.*s", chunk.len, chunk.ptr);
857 pin[sizeof(pin) - 1] = '\0';
858
859 /* we assume an RSA key */
860 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
861 BUILD_SMARTCARD_KEYID, smartcard,
862 BUILD_SMARTCARD_PIN, pin, BUILD_END);
863
864 if (key)
865 {
866 DBG1(DBG_CFG, " loaded private key from %.*s", sc.len, sc.ptr);
867 this->private->insert_last(this->private, key);
868 }
869 memset(pin, 0, sizeof(pin));
870 }
871 else if ((match("PSK", &token) && (type = SHARED_IKE)) ||
872 (match("EAP", &token) && (type = SHARED_EAP)) ||
873 (match("XAUTH", &token) && (type = SHARED_EAP)))
874 {
875 stroke_shared_key_t *shared_key;
876 chunk_t secret = chunk_empty;
877 bool any = TRUE;
878
879 err_t ugh = extract_secret(&secret, &line);
880 if (ugh != NULL)
881 {
882 DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
883 goto error;
884 }
885 shared_key = stroke_shared_key_create(type, secret);
886 DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type,
887 ids.len > 0 ? (char*)ids.ptr : "%any");
888 DBG4(DBG_CFG, " secret: %#B", &secret);
889
890 this->shared->insert_last(this->shared, shared_key);
891 while (ids.len > 0)
892 {
893 chunk_t id;
894 identification_t *peer_id;
895
896 ugh = extract_value(&id, &ids);
897 if (ugh != NULL)
898 {
899 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
900 goto error;
901 }
902 if (id.len == 0)
903 {
904 continue;
905 }
906
907 if (type == SHARED_EAP)
908 {
909 /* we use a special EAP identity type for EAP secrets */
910 peer_id = identification_create_from_encoding(ID_EAP, id);
911 }
912 else
913 {
914 /* NULL terminate the ID string */
915 *(id.ptr + id.len) = '\0';
916 peer_id = identification_create_from_string(id.ptr);
917 if (peer_id == NULL)
918 {
919 DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
920 goto error;
921 }
922 if (peer_id->get_type(peer_id) == ID_ANY)
923 {
924 peer_id->destroy(peer_id);
925 continue;
926 }
927 }
928
929 shared_key->add_owner(shared_key, peer_id);
930 any = FALSE;
931 }
932 if (any)
933 {
934 shared_key->add_owner(shared_key,
935 identification_create_from_encoding(ID_ANY, chunk_empty));
936 }
937 }
938 else
939 {
940 DBG1(DBG_CFG, "line %d: token must be either "
941 "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr);
942 goto error;
943 }
944 }
945 error:
946 this->lock->unlock(this->lock);
947 chunk_clear(&chunk);
948 }
949
950 /**
951 * load all certificates from ipsec.d
952 */
953 static void load_certs(private_stroke_cred_t *this)
954 {
955 DBG1(DBG_CFG, "loading ca certificates from '%s'",
956 CA_CERTIFICATE_DIR);
957 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
958
959 DBG1(DBG_CFG, "loading aa certificates from '%s'",
960 AA_CERTIFICATE_DIR);
961 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
962
963 DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'",
964 OCSP_CERTIFICATE_DIR);
965 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER);
966
967 DBG1(DBG_CFG, "loading attribute certificates from '%s'",
968 ATTR_CERTIFICATE_DIR);
969 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
970
971 DBG1(DBG_CFG, "loading crls from '%s'",
972 CRL_DIR);
973 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
974 }
975
976 /**
977 * Implementation of stroke_cred_t.reread.
978 */
979 static void reread(private_stroke_cred_t *this, stroke_msg_t *msg)
980 {
981 if (msg->reread.flags & REREAD_SECRETS)
982 {
983 DBG1(DBG_CFG, "rereading secrets");
984 load_secrets(this);
985 }
986 if (msg->reread.flags & REREAD_CACERTS)
987 {
988 DBG1(DBG_CFG, "rereading ca certificates from '%s'",
989 CA_CERTIFICATE_DIR);
990 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
991 }
992 if (msg->reread.flags & REREAD_OCSPCERTS)
993 {
994 DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'",
995 OCSP_CERTIFICATE_DIR);
996 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509,
997 X509_OCSP_SIGNER);
998 }
999 if (msg->reread.flags & REREAD_AACERTS)
1000 {
1001 DBG1(DBG_CFG, "rereading aa certificates from '%s'",
1002 AA_CERTIFICATE_DIR);
1003 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
1004 }
1005 if (msg->reread.flags & REREAD_ACERTS)
1006 {
1007 DBG1(DBG_CFG, "rereading attribute certificates from '%s'",
1008 ATTR_CERTIFICATE_DIR);
1009 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
1010 }
1011 if (msg->reread.flags & REREAD_CRLS)
1012 {
1013 DBG1(DBG_CFG, "rereading crls from '%s'",
1014 CRL_DIR);
1015 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
1016 }
1017 }
1018
1019 /**
1020 * Implementation of stroke_cred_t.destroy
1021 */
1022 static void destroy(private_stroke_cred_t *this)
1023 {
1024 this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
1025 this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy));
1026 this->private->destroy_offset(this->private, offsetof(private_key_t, destroy));
1027 this->lock->destroy(this->lock);
1028 free(this);
1029 }
1030
1031 /*
1032 * see header file
1033 */
1034 stroke_cred_t *stroke_cred_create()
1035 {
1036 private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t);
1037
1038 this->public.set.create_private_enumerator = (void*)create_private_enumerator;
1039 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
1040 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
1041 this->public.set.create_cdp_enumerator = (void*)return_null;
1042 this->public.set.cache_cert = (void*)cache_cert;
1043 this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg))reread;
1044 this->public.load_ca = (certificate_t*(*)(stroke_cred_t*, char *filename))load_ca;
1045 this->public.load_peer = (certificate_t*(*)(stroke_cred_t*, char *filename))load_peer;
1046 this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl;
1047 this->public.destroy = (void(*)(stroke_cred_t*))destroy;
1048
1049 this->certs = linked_list_create();
1050 this->shared = linked_list_create();
1051 this->private = linked_list_create();
1052 this->lock = rwlock_create(RWLOCK_DEFAULT);
1053
1054 load_certs(this);
1055 load_secrets(this);
1056
1057 this->cachecrl = FALSE;
1058
1059 return &this->public;
1060 }
1061