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