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