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