removed deprecated iterator methods (has_next & current)
[strongswan.git] / src / charon / config / credentials / local_credential_store.c
1 /**
2 * @file local_credential_store.c
3 *
4 * @brief Implementation of local_credential_store_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <sys/stat.h>
24 #include <dirent.h>
25 #include <string.h>
26 #include <pthread.h>
27
28 #include <types.h>
29 #include <utils/lexparser.h>
30 #include <utils/linked_list.h>
31 #include <crypto/certinfo.h>
32 #include <crypto/rsa/rsa_public_key.h>
33 #include <crypto/x509.h>
34 #include <crypto/crl.h>
35 #include <asn1/ttodata.h>
36
37 #include "local_credential_store.h"
38
39 #define PATH_BUF 256
40 #define MAX_CA_PATH_LEN 7
41
42 typedef struct shared_key_t shared_key_t;
43
44 /**
45 * Private date of a shared_key_t object
46 */
47 struct shared_key_t {
48
49 /**
50 * shared secret
51 */
52 chunk_t secret;
53
54 /**
55 * list of peer IDs
56 */
57 linked_list_t *peers;
58 };
59
60
61 /**
62 * Implementation of shared_key_t.destroy.
63 */
64 static void shared_key_destroy(shared_key_t *this)
65 {
66 this->peers->destroy_offset(this->peers, offsetof(identification_t, destroy));
67 chunk_free(&this->secret);
68 free(this);
69 }
70
71 /**
72 * @brief Creates a shared_key_t object.
73 *
74 * @param shared_key shared key value
75 * @return shared_key_t object
76 *
77 * @ingroup config
78 */
79 static shared_key_t *shared_key_create(chunk_t secret)
80 {
81 shared_key_t *this = malloc_thing(shared_key_t);
82
83 /* private data */
84 this->secret = chunk_clone(secret);
85 this->peers = linked_list_create();
86
87 return (this);
88 }
89
90
91 typedef struct private_local_credential_store_t private_local_credential_store_t;
92
93 /**
94 * Private data of an local_credential_store_t object
95 */
96 struct private_local_credential_store_t {
97
98 /**
99 * Public part
100 */
101 local_credential_store_t public;
102
103 /**
104 * list of shared keys
105 */
106 linked_list_t *shared_keys;
107
108 /**
109 * list of key_entry_t's with private keys
110 */
111 linked_list_t *private_keys;
112
113 /**
114 * list of X.509 certificates with public keys
115 */
116 linked_list_t *certs;
117
118 /**
119 * list of X.509 CA certificates with public keys
120 */
121 linked_list_t *ca_certs;
122
123 /**
124 * list of X.509 CRLs
125 */
126 linked_list_t *crls;
127
128 /**
129 * mutex controlling the access to the crls linked list
130 */
131 pthread_mutex_t crls_mutex;
132
133 /**
134 * enforce strict crl policy
135 */
136 bool strict;
137 };
138
139
140 /**
141 * Implementation of local_credential_store_t.get_shared_key.
142 */
143 static status_t get_shared_key(private_local_credential_store_t *this,
144 identification_t *my_id,
145 identification_t *other_id, chunk_t *secret)
146 {
147 typedef enum {
148 PRIO_UNDEFINED= 0x00,
149 PRIO_ANY_MATCH= 0x01,
150 PRIO_MY_MATCH= 0x02,
151 PRIO_OTHER_MATCH= 0x04,
152 } prio_t;
153
154 prio_t best_prio = PRIO_UNDEFINED;
155 chunk_t found = CHUNK_INITIALIZER;
156 shared_key_t *shared_key;
157
158 iterator_t *iterator = this->shared_keys->create_iterator(this->shared_keys, TRUE);
159
160 while (iterator->iterate(iterator, (void**)&shared_key))
161 {
162 iterator_t *peer_iterator;
163 identification_t *peer_id;
164 prio_t prio = PRIO_UNDEFINED;
165
166 peer_iterator = shared_key->peers->create_iterator(shared_key->peers, TRUE);
167
168 if (peer_iterator->get_count(peer_iterator) == 0)
169 {
170 /* this is a wildcard shared key */
171 prio = PRIO_ANY_MATCH;
172 }
173 else
174 {
175 while (peer_iterator->iterate(peer_iterator, (void**)&peer_id))
176 {
177 if (my_id->equals(my_id, peer_id))
178 {
179 prio |= PRIO_MY_MATCH;
180 }
181 if (other_id->equals(other_id, peer_id))
182 {
183 prio |= PRIO_OTHER_MATCH;
184 }
185 }
186 }
187 peer_iterator->destroy(peer_iterator);
188
189 if (prio > best_prio)
190 {
191 best_prio = prio;
192 found = shared_key->secret;
193 }
194 }
195 iterator->destroy(iterator);
196
197 if (best_prio == PRIO_UNDEFINED)
198 {
199 return NOT_FOUND;
200 }
201 else
202 {
203 *secret = chunk_clone(found);
204 return SUCCESS;
205 }
206 }
207
208 /**
209 * Implementation of credential_store_t.get_certificate.
210 */
211 static x509_t* get_certificate(private_local_credential_store_t *this,
212 identification_t * id)
213 {
214 x509_t *found = NULL, *cert;
215
216 iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE);
217
218 while (iterator->iterate(iterator, (void**)&cert))
219 {
220 if (id->equals(id, cert->get_subject(cert)) ||
221 cert->equals_subjectAltName(cert, id))
222 {
223 found = cert;
224 break;
225 }
226 }
227 iterator->destroy(iterator);
228 return found;
229 }
230
231 /**
232 * Implementation of local_credential_store_t.get_rsa_public_key.
233 */
234 static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *this,
235 identification_t *id)
236 {
237 x509_t *cert = get_certificate(this, id);
238
239 return (cert == NULL)? NULL:cert->get_public_key(cert);
240 }
241
242 /**
243 * Implementation of local_credential_store_t.get_trusted_public_key.
244 */
245 static rsa_public_key_t *get_trusted_public_key(private_local_credential_store_t *this,
246 identification_t *id)
247 {
248 cert_status_t status;
249 err_t ugh;
250
251 x509_t *cert = get_certificate(this, id);
252
253 if (cert == NULL)
254 return NULL;
255
256 ugh = cert->is_valid(cert, NULL);
257 if (ugh != NULL)
258 {
259 DBG1(SIG_DBG_CFG, "certificate %s", ugh);
260 return NULL;
261 }
262
263 status = cert->get_status(cert);
264 if (status == CERT_REVOKED || status == CERT_UNTRUSTED || (this->strict && status != CERT_GOOD))
265 {
266 DBG1(SIG_DBG_CFG, "certificate status: %N", cert_status_names, status);
267 return NULL;
268 }
269 if (status == CERT_GOOD && cert->get_until(cert) < time(NULL))
270 {
271 DBG1(SIG_DBG_CFG, "certificate is good but crl is stale");
272 return NULL;
273 }
274
275 return cert->get_public_key(cert);
276 }
277
278 /**
279 * Implementation of local_credential_store_t.get_rsa_private_key.
280 */
281 static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this,
282 rsa_public_key_t *pubkey)
283 {
284 rsa_private_key_t *found = NULL, *current;
285
286 iterator_t *iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
287
288 while (iterator->iterate(iterator, (void**)&current))
289 {
290 if (current->belongs_to(current, pubkey))
291 {
292 found = current->clone(current);
293 break;
294 }
295 }
296 iterator->destroy(iterator);
297 return found;
298 }
299
300 /**
301 * Implementation of local_credential_store_t.has_rsa_private_key.
302 */
303 static bool has_rsa_private_key(private_local_credential_store_t *this, rsa_public_key_t *pubkey)
304 {
305 bool found = FALSE;
306 rsa_private_key_t *current;
307
308 iterator_t *iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
309
310 while (iterator->iterate(iterator, (void**)&current))
311 {
312 if (current->belongs_to(current, pubkey))
313 {
314 found = TRUE;
315 break;
316 }
317 }
318 iterator->destroy(iterator);
319 return found;
320 }
321
322 /**
323 * Implementation of credential_store_t.get_issuer_certificate.
324 */
325 static x509_t* get_issuer_certificate(private_local_credential_store_t *this,
326 const x509_t *cert)
327 {
328 x509_t *issuer_cert = NULL, *current_cert;;
329
330 iterator_t *iterator = this->ca_certs->create_iterator(this->ca_certs, TRUE);
331 while (iterator->iterate(iterator, (void**)&current_cert))
332 {
333 if (cert->is_issuer(cert, current_cert))
334 {
335 issuer_cert = current_cert;
336 break;
337 }
338 }
339 iterator->destroy(iterator);
340
341 return issuer_cert;
342 }
343
344 /**
345 * Implementation of credential_store_t.get_crl.
346 */
347 static crl_t* get_crl(private_local_credential_store_t *this, const x509_t *issuer)
348 {
349 crl_t *crl = NULL, *current_crl;
350
351 iterator_t *iterator = this->crls->create_iterator(this->crls, TRUE);
352
353 while (iterator->iterate(iterator, (void**)&current_crl))
354 {
355 if (current_crl->is_issuer(current_crl, issuer))
356 {
357 crl = current_crl;
358 break;
359 }
360 }
361 iterator->destroy(iterator);
362
363 return crl;
364 }
365
366 /**
367 * Verify the certificate status using CRLs
368 */
369 static cert_status_t verify_by_crl(private_local_credential_store_t* this, const x509_t *cert,
370 const x509_t *issuer_cert, certinfo_t *certinfo)
371 {
372 crl_t *crl;
373 bool valid_signature;
374 rsa_public_key_t *issuer_public_key;
375
376
377 pthread_mutex_lock(&(this->crls_mutex));
378
379 crl = get_crl(this, issuer_cert);
380 if (crl == NULL)
381 {
382 DBG1(SIG_DBG_CFG, "crl not found");
383 goto err;
384 }
385 DBG2(SIG_DBG_CFG, "crl found");
386
387 issuer_public_key = issuer_cert->get_public_key(issuer_cert);
388 valid_signature = crl->verify(crl, issuer_public_key);
389
390 if (!valid_signature)
391 {
392 DBG1(SIG_DBG_CFG, "crl signature is invalid");
393 goto err;
394 }
395 DBG2(SIG_DBG_CFG, "crl signature is valid");
396
397 crl->get_status(crl, certinfo);
398
399 err:
400 pthread_mutex_unlock(&(this->crls_mutex));
401 return certinfo->get_status(certinfo);
402 }
403
404 /**
405 * Verify the certificate status using OCSP
406 */
407 static cert_status_t verify_by_ocsp(private_local_credential_store_t* this,
408 const x509_t *cert, certinfo_t *certinfo)
409 {
410 /* TODO implement function */
411 return CERT_UNDEFINED;
412 }
413
414 /**
415 * Find an exact copy of a certificate in a linked list
416 */
417 static x509_t* find_certificate_copy(linked_list_t *certs, x509_t *cert)
418 {
419 x509_t *found_cert = NULL, *current_cert;
420
421 iterator_t *iterator = certs->create_iterator(certs, TRUE);
422
423 while (iterator->iterate(iterator, (void**)&current_cert))
424 {
425 if (cert->equals(cert, current_cert))
426 {
427 found_cert = current_cert;
428 break;
429 }
430 }
431 iterator->destroy(iterator);
432
433 return found_cert;
434 }
435
436 /**
437 * Implementation of credential_store_t.verify.
438 */
439 static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *found)
440 {
441 int pathlen;
442 time_t until = UNDEFINED_TIME;
443
444 x509_t *end_cert = cert;
445 x509_t *cert_copy = find_certificate_copy(this->certs, end_cert);
446
447 *found = (cert_copy != NULL);
448 if (*found)
449 {
450 DBG2(SIG_DBG_CFG,
451 "end entitity certificate is already in credential store");
452 }
453
454 for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
455 {
456 err_t ugh = NULL;
457 x509_t *issuer_cert;
458 rsa_public_key_t *issuer_public_key;
459 bool valid_signature;
460
461 identification_t *subject = cert->get_subject(cert);
462 identification_t *issuer = cert->get_issuer(cert);
463
464 DBG2(SIG_DBG_CFG, "subject: '%D'", subject);
465 DBG2(SIG_DBG_CFG, "issuer: '%D'", issuer);
466
467 ugh = cert->is_valid(cert, &until);
468 if (ugh != NULL)
469 {
470 DBG1(SIG_DBG_CFG, "certificate %s", ugh);
471 return FALSE;
472 }
473 DBG2(SIG_DBG_CFG, "certificate is valid");
474
475 issuer_cert = get_issuer_certificate(this, cert);
476 if (issuer_cert == NULL)
477 {
478 DBG1(SIG_DBG_CFG, "issuer certificate not found");
479 return FALSE;
480 }
481 DBG2(SIG_DBG_CFG, "issuer certificate found");
482
483 issuer_public_key = issuer_cert->get_public_key(issuer_cert);
484 valid_signature = cert->verify(cert, issuer_public_key);
485
486 if (!valid_signature)
487 {
488 DBG1(SIG_DBG_CFG, "certificate signature is invalid");
489 return FALSE;
490 }
491 DBG2(SIG_DBG_CFG, "certificate signature is valid");
492
493 /* check if cert is a self-signed root ca */
494 if (pathlen > 0 && cert->is_self_signed(cert))
495 {
496 DBG2(SIG_DBG_CFG, "reached self-signed root ca");
497
498 /* set the definite status and trust interval of the end entity certificate */
499 end_cert->set_until(end_cert, until);
500 if (cert_copy)
501 {
502 cert_copy->set_status(cert_copy, end_cert->get_status(end_cert));
503 cert_copy->set_until(cert_copy, until);
504 }
505 return TRUE;
506 }
507 else
508 {
509 time_t nextUpdate;
510 cert_status_t status;
511 certinfo_t *certinfo = certinfo_create(cert->get_serialNumber(cert));
512
513 certinfo->set_nextUpdate(certinfo, until);
514
515 /* first check certificate revocation using ocsp */
516 status = verify_by_ocsp(this, cert, certinfo);
517
518 /* if ocsp service is not available then fall back to crl */
519 if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict))
520 {
521 status = verify_by_crl(this, cert, issuer_cert, certinfo);
522 }
523
524 nextUpdate = certinfo->get_nextUpdate(certinfo);
525 cert->set_status(cert, status);
526
527 switch (status)
528 {
529 case CERT_GOOD:
530 /* set nextUpdate */
531 cert->set_until(cert, nextUpdate);
532
533 /* if status information is stale */
534 if (this->strict && nextUpdate < time(NULL))
535 {
536 DBG2(SIG_DBG_CFG, "certificate is good but status is stale");
537 return FALSE;
538 }
539 DBG2(SIG_DBG_CFG, "certificate is good");
540
541 /* with strict crl policy the public key must have the same
542 * lifetime as the validity of the ocsp status or crl lifetime
543 */
544 if (this->strict && nextUpdate < until)
545 until = nextUpdate;
546 break;
547 case CERT_REVOKED:
548 {
549 time_t revocationTime = certinfo->get_revocationTime(certinfo);
550 DBG1(SIG_DBG_CFG,
551 "certificate was revoked on %T, reason: %N",
552 revocationTime, crl_reason_names,
553 certinfo->get_revocationReason(certinfo));
554
555 /* set revocationTime */
556 cert->set_until(cert, revocationTime);
557
558 /* update status of end certificate in the credential store */
559 if (cert_copy)
560 {
561 if (pathlen > 0)
562 {
563 cert_copy->set_status(cert_copy, CERT_UNTRUSTED);
564 }
565 else
566 {
567 cert_copy->set_status(cert_copy, CERT_REVOKED);
568 cert_copy->set_until(cert_copy,
569 certinfo->get_revocationTime(certinfo));
570 }
571 }
572 return FALSE;
573 }
574 case CERT_UNKNOWN:
575 case CERT_UNDEFINED:
576 default:
577 DBG2(SIG_DBG_CFG, "certificate status unknown");
578 if (this->strict)
579 {
580 /* update status of end certificate in the credential store */
581 if (cert_copy)
582 {
583 cert_copy->set_status(cert_copy, CERT_UNTRUSTED);
584 }
585 return FALSE;
586 }
587 break;
588 }
589 certinfo->destroy(certinfo);
590 }
591 /* go up one step in the trust chain */
592 cert = issuer_cert;
593 }
594 DBG1(SIG_DBG_CFG, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
595 return FALSE;
596 }
597
598 /**
599 * Add a unique certificate to a linked list
600 */
601 static x509_t* add_certificate(linked_list_t *certs, x509_t *cert)
602 {
603 x509_t *found_cert = find_certificate_copy(certs, cert);
604
605 if (found_cert)
606 {
607 cert->destroy(cert);
608 return found_cert;
609 }
610 else
611 {
612 certs->insert_last(certs, (void*)cert);
613 return cert;
614 }
615 }
616
617 /**
618 * Implements local_credential_store_t.add_end_certificate
619 */
620 static x509_t* add_end_certificate(private_local_credential_store_t *this, x509_t *cert)
621 {
622 return add_certificate(this->certs, cert);
623 }
624
625 /**
626 * Implements local_credential_store_t.add_ca_certificate
627 */
628 static x509_t* add_ca_certificate(private_local_credential_store_t *this, x509_t *cert)
629 {
630 return add_certificate(this->ca_certs, cert);
631 }
632
633 /**
634 * Implements local_credential_store_t.create_cert_iterator
635 */
636 static iterator_t* create_cert_iterator(private_local_credential_store_t *this)
637 {
638 return this->certs->create_iterator(this->certs, TRUE);
639 }
640
641 /**
642 * Implements local_credential_store_t.create_cacert_iterator
643 */
644 static iterator_t* create_cacert_iterator(private_local_credential_store_t *this)
645 {
646 return this->ca_certs->create_iterator(this->ca_certs, TRUE);
647 }
648
649 /**
650 * Implements local_credential_store_t.create_crl_iterator
651 */
652 static iterator_t* create_crl_iterator(private_local_credential_store_t *this)
653 {
654 return this->crls->create_iterator_locked(this->crls, &(this->crls_mutex));
655 }
656
657 /**
658 * Implements local_credential_store_t.load_ca_certificates
659 */
660 static void load_ca_certificates(private_local_credential_store_t *this)
661 {
662 struct dirent* entry;
663 struct stat stb;
664 DIR* dir;
665 x509_t *cert;
666
667 DBG1(SIG_DBG_CFG, "loading ca certificates from '%s/'", CA_CERTIFICATE_DIR);
668
669 dir = opendir(CA_CERTIFICATE_DIR);
670 if (dir == NULL)
671 {
672 DBG1(SIG_DBG_CFG, "error opening ca certs directory %s'", CA_CERTIFICATE_DIR);
673 return;
674 }
675
676 while ((entry = readdir(dir)) != NULL)
677 {
678 char file[PATH_BUF];
679
680 snprintf(file, sizeof(file), "%s/%s", CA_CERTIFICATE_DIR, entry->d_name);
681
682 if (stat(file, &stb) == -1)
683 {
684 continue;
685 }
686 /* try to parse all regular files */
687 if (stb.st_mode & S_IFREG)
688 {
689 cert = x509_create_from_file(file, "ca certificate");
690 if (cert)
691 {
692 err_t ugh = cert->is_valid(cert, NULL);
693
694 if (ugh != NULL)
695 {
696 DBG1(SIG_DBG_CFG, "warning: ca certificate %s", ugh);
697 }
698 if (cert->is_ca(cert))
699 {
700 cert = add_certificate(this->ca_certs, cert);
701 }
702 else
703 {
704 DBG1(SIG_DBG_CFG, " CA basic constraints flag not set, cert discarded");
705 cert->destroy(cert);
706 }
707 }
708 }
709 }
710 closedir(dir);
711 }
712
713 /**
714 * Add the latest crl to a linked list
715 */
716 static crl_t* add_crl(linked_list_t *crls, crl_t *crl)
717 {
718 bool found = FALSE;
719 crl_t *current_crl;
720
721 iterator_t *iterator = crls->create_iterator(crls, TRUE);
722
723 while (iterator->iterate(iterator, (void**)&current_crl))
724 {
725 if (crl->equals_issuer(crl, current_crl))
726 {
727 found = TRUE;
728 if (crl->is_newer(crl, current_crl))
729 {
730 crl_t *old_crl = NULL;
731
732 iterator->replace(iterator, (void**)&old_crl, (void*)crl);
733 if (old_crl != NULL)
734 {
735 old_crl->destroy(old_crl);
736 }
737 DBG2(SIG_DBG_CFG, " thisUpdate is newer - existing crl replaced");
738 }
739 else
740 {
741 crl->destroy(crl);
742 crl = current_crl;
743 DBG2(SIG_DBG_CFG, " thisUpdate is not newer - existing crl retained");
744 }
745 break;
746 }
747 }
748 iterator->destroy(iterator);
749
750 if (!found)
751 {
752 crls->insert_last(crls, (void*)crl);
753 DBG2(SIG_DBG_CFG, " crl added");
754 }
755 return crl;
756 }
757
758 /**
759 * Implements local_credential_store_t.load_crls
760 */
761 static void load_crls(private_local_credential_store_t *this)
762 {
763 struct dirent* entry;
764 struct stat stb;
765 DIR* dir;
766 crl_t *crl;
767
768 DBG1(SIG_DBG_CFG, "loading crls from '%s/'", CRL_DIR);
769
770 dir = opendir(CRL_DIR);
771 if (dir == NULL)
772 {
773 DBG1(SIG_DBG_CFG, "error opening crl directory %s'", CRL_DIR);
774 return;
775 }
776
777 while ((entry = readdir(dir)) != NULL)
778 {
779 char file[PATH_BUF];
780
781 snprintf(file, sizeof(file), "%s/%s", CRL_DIR, entry->d_name);
782
783 if (stat(file, &stb) == -1)
784 {
785 continue;
786 }
787 /* try to parse all regular files */
788 if (stb.st_mode & S_IFREG)
789 {
790 crl = crl_create_from_file(file);
791 if (crl)
792 {
793 err_t ugh = crl->is_valid(crl, NULL, this->strict);
794
795 if (ugh != NULL)
796 {
797 DBG1(SIG_DBG_CFG, "warning: crl %s", ugh);
798 }
799 pthread_mutex_lock(&(this->crls_mutex));
800 crl = add_crl(this->crls, crl);
801 pthread_mutex_unlock(&(this->crls_mutex));
802 }
803 }
804 }
805 closedir(dir);
806 }
807
808 /**
809 * Convert a string of characters into a binary secret
810 * A string between single or double quotes is treated as ASCII characters
811 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
812 */
813 static err_t extract_secret(chunk_t *secret, chunk_t *line)
814 {
815 chunk_t raw_secret;
816 char delimiter = ' ';
817 bool quotes = FALSE;
818
819 if (!eat_whitespace(line))
820 {
821 return "missing secret";
822 }
823
824 if (*line->ptr == '\'' || *line->ptr == '"')
825 {
826 quotes = TRUE;
827 delimiter = *line->ptr;
828 line->ptr++; line->len--;
829 }
830
831 if (!extract_token(&raw_secret, delimiter, line))
832 {
833 if (delimiter == ' ')
834 {
835 raw_secret = *line;
836 }
837 else
838 {
839 return "missing second delimiter";
840 }
841 }
842
843 if (quotes)
844 { /* treat as an ASCII string */
845 if (raw_secret.len > secret->len)
846 return "secret larger than buffer";
847 memcpy(secret->ptr, raw_secret.ptr, raw_secret.len);
848 secret->len = raw_secret.len;
849 }
850 else
851 { /* convert from HEX or Base64 to binary */
852 size_t len;
853 err_t ugh = ttodata(raw_secret.ptr, raw_secret.len, 0, secret->ptr, secret->len, &len);
854
855 if (ugh != NULL)
856 return ugh;
857 if (len > secret->len)
858 return "secret larger than buffer";
859 secret->len = len;
860 }
861 return NULL;
862 }
863
864 /**
865 * Implements local_credential_store_t.load_secrets
866 */
867 static void load_secrets(private_local_credential_store_t *this)
868 {
869 FILE *fd = fopen(SECRETS_FILE, "r");
870
871 if (fd)
872 {
873 int bytes;
874 int line_nr = 0;
875 chunk_t chunk, src, line;
876
877 DBG1(SIG_DBG_CFG, "loading secrets from \"%s\"", SECRETS_FILE);
878
879 fseek(fd, 0, SEEK_END);
880 chunk.len = ftell(fd);
881 rewind(fd);
882 chunk.ptr = malloc(chunk.len);
883 bytes = fread(chunk.ptr, 1, chunk.len, fd);
884 fclose(fd);
885
886 src = chunk;
887
888 while (fetchline(&src, &line))
889 {
890 chunk_t ids, token;
891
892 line_nr++;
893
894 if (!eat_whitespace(&line))
895 {
896 continue;
897 }
898 if (!extract_token(&ids, ':', &line))
899 {
900 DBG1(SIG_DBG_CFG, "line %d: missing ':' separator", line_nr);
901 goto error;
902 }
903 /* NULL terminate the ids string by replacing the : separator */
904 *(ids.ptr + ids.len) = '\0';
905
906 if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
907 {
908 DBG1(SIG_DBG_CFG, "line %d: missing token", line_nr);
909 goto error;
910 }
911 if (match("RSA", &token))
912 {
913 char path[PATH_BUF];
914 chunk_t filename;
915
916 char buf[BUF_LEN];
917 chunk_t secret = { buf, BUF_LEN };
918 chunk_t *passphrase = NULL;
919
920 rsa_private_key_t *key;
921
922 err_t ugh = extract_value(&filename, &line);
923
924 if (ugh != NULL)
925 {
926 DBG1(SIG_DBG_CFG, "line %d: %s", line_nr, ugh);
927 goto error;
928 }
929 if (filename.len == 0)
930 {
931 DBG1(SIG_DBG_CFG, "line %d: empty filename", line_nr);
932 goto error;
933 }
934 if (*filename.ptr == '/')
935 {
936 /* absolute path name */
937 snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
938 }
939 else
940 {
941 /* relative path name */
942 snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
943 filename.len, filename.ptr);
944 }
945
946 /* check for optional passphrase */
947 if (eat_whitespace(&line))
948 {
949 ugh = extract_secret(&secret, &line);
950 if (ugh != NULL)
951 {
952 DBG1(SIG_DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
953 goto error;
954 }
955 if (secret.len > 0)
956 passphrase = &secret;
957 }
958 key = rsa_private_key_create_from_file(path, passphrase);
959 if (key)
960 {
961 this->private_keys->insert_last(this->private_keys, (void*)key);
962 }
963 }
964 else if (match("PSK", &token))
965 {
966 shared_key_t *shared_key;
967
968 char buf[BUF_LEN];
969 chunk_t secret = { buf, BUF_LEN };
970
971 err_t ugh = extract_secret(&secret, &line);
972 if (ugh != NULL)
973 {
974 DBG1(SIG_DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
975 goto error;
976 }
977
978 if (ids.len > 0)
979 {
980 DBG1(SIG_DBG_CFG, " loading shared key for %s", ids.ptr);
981 }
982 else
983 {
984 DBG1(SIG_DBG_CFG, " loading shared key for %%any");
985 }
986
987 DBG4(SIG_DBG_CFG, " secret:", secret);
988
989 shared_key = shared_key_create(secret);
990 if (shared_key)
991 {
992 this->shared_keys->insert_last(this->shared_keys, (void*)shared_key);
993 }
994 while (ids.len > 0)
995 {
996 chunk_t id;
997 identification_t *peer_id;
998
999 ugh = extract_value(&id, &ids);
1000 if (ugh != NULL)
1001 {
1002 DBG1(SIG_DBG_CFG, "line %d: %s", line_nr, ugh);
1003 goto error;
1004 }
1005 if (id.len == 0)
1006 {
1007 continue;
1008 }
1009
1010 /* NULL terminate the ID string */
1011 *(id.ptr + id.len) = '\0';
1012
1013 peer_id = identification_create_from_string(id.ptr);
1014 if (peer_id == NULL)
1015 {
1016 DBG1(SIG_DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
1017 goto error;
1018 }
1019
1020 if (peer_id->get_type(peer_id) == ID_ANY)
1021 {
1022 peer_id->destroy(peer_id);
1023 continue;
1024 }
1025 shared_key->peers->insert_last(shared_key->peers, (void*)peer_id);
1026 }
1027 }
1028 else if (match("PIN", &token))
1029 {
1030
1031 }
1032 else
1033 {
1034 DBG1(SIG_DBG_CFG, "line %d: token must be either "
1035 "RSA, PSK, or PIN", line_nr, token.len);
1036 goto error;
1037 }
1038 }
1039 error:
1040 free(chunk.ptr);
1041 }
1042 else
1043 {
1044 DBG1(SIG_DBG_CFG, "could not open file '%s'", SECRETS_FILE);
1045 }
1046 }
1047
1048 /**
1049 * Implementation of local_credential_store_t.destroy.
1050 */
1051 static void destroy(private_local_credential_store_t *this)
1052 {
1053 this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy));
1054 this->ca_certs->destroy_offset(this->ca_certs, offsetof(x509_t, destroy));
1055 this->crls->destroy_offset(this->crls, offsetof(crl_t, destroy));
1056 this->private_keys->destroy_offset(this->private_keys, offsetof(rsa_private_key_t, destroy));
1057 this->shared_keys->destroy_function(this->shared_keys, (void*)shared_key_destroy);
1058 free(this);
1059 }
1060
1061 /**
1062 * Described in header.
1063 */
1064 local_credential_store_t * local_credential_store_create(bool strict)
1065 {
1066 private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t);
1067
1068 this->public.credential_store.get_shared_key = (status_t (*) (credential_store_t*,identification_t*,identification_t*,chunk_t*))get_shared_key;
1069 this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key;
1070 this->public.credential_store.get_rsa_private_key = (rsa_private_key_t* (*) (credential_store_t*,rsa_public_key_t*))get_rsa_private_key;
1071 this->public.credential_store.has_rsa_private_key = (bool (*) (credential_store_t*,rsa_public_key_t*))has_rsa_private_key;
1072 this->public.credential_store.get_trusted_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_trusted_public_key;
1073 this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate;
1074 this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify;
1075 this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate;
1076 this->public.credential_store.add_ca_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_ca_certificate;
1077 this->public.credential_store.create_cert_iterator = (iterator_t* (*) (credential_store_t*))create_cert_iterator;
1078 this->public.credential_store.create_cacert_iterator = (iterator_t* (*) (credential_store_t*))create_cacert_iterator;
1079 this->public.credential_store.create_crl_iterator = (iterator_t* (*) (credential_store_t*))create_crl_iterator;
1080 this->public.credential_store.load_ca_certificates = (void (*) (credential_store_t*))load_ca_certificates;
1081 this->public.credential_store.load_crls = (void (*) (credential_store_t*))load_crls;
1082 this->public.credential_store.load_secrets = (void (*) (credential_store_t*))load_secrets;
1083 this->public.credential_store.destroy = (void (*) (credential_store_t*))destroy;
1084
1085 /* initialize mutexes */
1086 pthread_mutex_init(&(this->crls_mutex), NULL);
1087
1088 /* private variables */
1089 this->shared_keys = linked_list_create();
1090 this->private_keys = linked_list_create();
1091 this->certs = linked_list_create();
1092 this->ca_certs = linked_list_create();
1093 this->crls = linked_list_create();
1094 this->strict = strict;
1095
1096 return (&this->public);
1097 }