implementation of strictcrlpolicy=ifuri
[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/ac.h>
36 #include <crypto/crl.h>
37 #include <asn1/ttodata.h>
38
39 #include "local_credential_store.h"
40
41 #define PATH_BUF 256
42 #define MAX_CA_PATH_LEN 7
43
44 typedef struct shared_key_t shared_key_t;
45
46 /**
47 * Private date of a shared_key_t object
48 */
49 struct shared_key_t {
50
51 /**
52 * shared secret
53 */
54 chunk_t secret;
55
56 /**
57 * list of peer IDs
58 */
59 linked_list_t *peers;
60 };
61
62
63 /**
64 * Implementation of shared_key_t.destroy.
65 */
66 static void shared_key_destroy(shared_key_t *this)
67 {
68 this->peers->destroy_offset(this->peers, offsetof(identification_t, destroy));
69 chunk_free(&this->secret);
70 free(this);
71 }
72
73 /**
74 * @brief Creates a shared_key_t object.
75 *
76 * @param shared_key shared key value
77 * @return shared_key_t object
78 *
79 * @ingroup config
80 */
81 static shared_key_t *shared_key_create(chunk_t secret)
82 {
83 shared_key_t *this = malloc_thing(shared_key_t);
84
85 /* private data */
86 this->secret = chunk_clone(secret);
87 this->peers = linked_list_create();
88
89 return (this);
90 }
91
92 /* ------------------------------------------------------------------------ *
93 * the ca_info_t object as a central control element
94
95 +--------------------------------------------------------+
96 | local_credential_store_t |
97 +--------------------------------------------------------+
98 | |
99 +---------------------------+ +-------------------------+
100 | linked_list_t *auth_certs | | linked_list_t *ca_infos |
101 +---------------------------+ +-------------------------+
102 | |
103 | +------------------------- +
104 | | ca_info_t |
105 | +--------------------------+
106 +---------------+ | char *name |
107 | x509_t |<--| x509_t *cacert |
108 +---------------+ | linked_list_t *attrcerts | +----------------------+
109 | chunk_t keyid | | linked_list_t *certinfos |-->| certinfo_t |
110 +---------------+ | linked_list_t *ocspuris | +----------------------+
111 | | crl_t *crl | | chunk_t serialNumber |
112 | | linked_list_t *crluris | | cert_status_t status |
113 +---------------+ | pthread_mutex_t mutex | | time_t thisUpdate |
114 | x509_t | +--------------------------+ | time_t nextUpdate |
115 +---------------+ | | bool once |
116 | chunk_t keyid | | +----------------------+
117 +---------------+ +------------------------- + |
118 | | ca_info_t | +----------------------+
119 | +--------------------------+ | certinfo_t |
120 +---------------+ | char *name | +----------------------+
121 | x509_t |<--| x509_t *cacert | | chunk_t serialNumber |
122 +---------------+ | linked_list_t *attrcerts | | cert_status_t status |
123 | chunk_t keyid | | linked_list_t *certinfos | | time_t thisUpdate |
124 +---------------+ | linked_list_t *ocspuris | | time_t nextUpdate |
125 | | crl_t *crl | | bool once |
126 | | linked_list_t *crluris | +----------------------+
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 EAP keys
152 */
153 linked_list_t *eap_keys;
154
155 /**
156 * list of key_entry_t's with private keys
157 */
158 linked_list_t *private_keys;
159
160 /**
161 * list of X.509 certificates with public keys
162 */
163 linked_list_t *certs;
164
165 /**
166 * list of X.509 authority certificates with public keys
167 */
168 linked_list_t *auth_certs;
169
170 /**
171 * list of X.509 CA information records
172 */
173 linked_list_t *ca_infos;
174 };
175
176
177 /**
178 * Get a key from a list with shared_key_t's
179 */
180 static status_t get_key(linked_list_t *keys,
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 = keys->create_iterator(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 /**
247 * Implementation of local_credential_store_t.get_shared_key.
248 */
249 static status_t get_shared_key(private_local_credential_store_t *this,
250 identification_t *my_id,
251 identification_t *other_id, chunk_t *secret)
252 {
253 return get_key(this->shared_keys, my_id, other_id, secret);
254 }
255
256 /**
257 * Implementation of local_credential_store_t.get_eap_key.
258 */
259 static status_t get_eap_key(private_local_credential_store_t *this,
260 identification_t *my_id,
261 identification_t *other_id, chunk_t *secret)
262 {
263 return get_key(this->eap_keys, my_id, other_id, secret);
264 }
265
266 /**
267 * Implementation of credential_store_t.get_certificate.
268 */
269 static x509_t* get_certificate(private_local_credential_store_t *this,
270 identification_t *id)
271 {
272 x509_t *found = NULL;
273 x509_t *current_cert;
274
275 iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE);
276
277 while (iterator->iterate(iterator, (void**)&current_cert))
278 {
279 if (id->equals(id, current_cert->get_subject(current_cert)) ||
280 current_cert->equals_subjectAltName(current_cert, id))
281 {
282 found = current_cert;
283 break;
284 }
285 }
286 iterator->destroy(iterator);
287 return found;
288 }
289
290 /**
291 * Implementation of local_credential_store_t.get_rsa_public_key.
292 */
293 static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *this,
294 identification_t *id)
295 {
296 x509_t *cert = get_certificate(this, id);
297
298 return (cert == NULL)? NULL:cert->get_public_key(cert);
299 }
300
301 /**
302 * Implementation of credential_store_t.get_issuer.
303 */
304 static ca_info_t* get_issuer(private_local_credential_store_t *this, const x509_t *cert)
305 {
306 ca_info_t *found = NULL;
307 ca_info_t *ca_info;
308
309 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
310
311 while (iterator->iterate(iterator, (void**)&ca_info))
312 {
313 if (ca_info->is_cert_issuer(ca_info, cert))
314 {
315 found = ca_info;
316 break;
317 }
318 }
319 iterator->destroy(iterator);
320
321 return found;
322 }
323
324 /**
325 * Implementation of local_credential_store_t.get_trusted_public_key.
326 */
327 static rsa_public_key_t *get_trusted_public_key(private_local_credential_store_t *this,
328 identification_t *id)
329 {
330 cert_status_t status;
331 err_t ugh;
332
333 x509_t *cert = get_certificate(this, id);
334
335 if (cert == NULL)
336 return NULL;
337
338 ugh = cert->is_valid(cert, NULL);
339 if (ugh != NULL)
340 {
341 DBG1(DBG_CFG, "certificate %s", ugh);
342 return NULL;
343 }
344
345 if (!cert->is_self_signed(cert))
346 {
347 ca_info_t *issuer = get_issuer(this, cert);
348
349 if (issuer == NULL)
350 {
351 DBG1(DBG_CFG, "issuer of public key not found");
352 return NULL;
353 }
354 status = cert->get_status(cert);
355
356 if (status == CERT_REVOKED
357 || status == CERT_UNTRUSTED
358 || (issuer->is_strict(issuer) && status != CERT_GOOD))
359 {
360 DBG1(DBG_CFG, "certificate status: %N", cert_status_names, status);
361 return NULL;
362 }
363 if (status == CERT_GOOD && cert->get_until(cert) < time(NULL))
364 {
365 DBG1(DBG_CFG, "certificate is good but crl is stale");
366 return NULL;
367 }
368 }
369 return cert->get_public_key(cert);
370 }
371
372 /**
373 * Implementation of local_credential_store_t.get_rsa_private_key.
374 */
375 static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this,
376 rsa_public_key_t *pubkey)
377 {
378 rsa_private_key_t *found = NULL, *current;
379
380 iterator_t *iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
381
382 while (iterator->iterate(iterator, (void**)&current))
383 {
384 if (current->belongs_to(current, pubkey))
385 {
386 found = current->clone(current);
387 break;
388 }
389 }
390 iterator->destroy(iterator);
391 return found;
392 }
393
394 /**
395 * Implementation of local_credential_store_t.has_rsa_private_key.
396 */
397 static bool has_rsa_private_key(private_local_credential_store_t *this, rsa_public_key_t *pubkey)
398 {
399 bool found = FALSE;
400 rsa_private_key_t *current;
401
402 iterator_t *iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
403
404 while (iterator->iterate(iterator, (void**)&current))
405 {
406 if (current->belongs_to(current, pubkey))
407 {
408 found = TRUE;
409 break;
410 }
411 }
412 iterator->destroy(iterator);
413 return found;
414 }
415
416 /**
417 * Implementation of credential_store_t.get_auth_certificate.
418 */
419 static x509_t* get_auth_certificate(private_local_credential_store_t *this,
420 u_int auth_flags,
421 identification_t *id)
422 {
423 x509_t *found = NULL;
424 x509_t *current_cert;
425
426 iterator_t *iterator = this->auth_certs->create_iterator(this->auth_certs, TRUE);
427
428 while (iterator->iterate(iterator, (void**)&current_cert))
429 {
430 if (current_cert->has_authority_flag(current_cert, auth_flags)
431 && id->equals(id, current_cert->get_subject(current_cert)))
432 {
433 found = current_cert;
434 break;
435 }
436 }
437 iterator->destroy(iterator);
438
439 return found;
440 }
441
442 /**
443 * Implementation of credential_store_t.get_ca_certificate_by_keyid.
444 */
445 static x509_t* get_ca_certificate_by_keyid(private_local_credential_store_t *this,
446 chunk_t keyid)
447 {
448 x509_t *found = NULL;
449 x509_t *current_cert;
450
451 iterator_t *iterator = this->auth_certs->create_iterator(this->auth_certs, TRUE);
452
453 while (iterator->iterate(iterator, (void**)&current_cert))
454 {
455 rsa_public_key_t *pubkey = current_cert->get_public_key(current_cert);
456
457 if (current_cert->has_authority_flag(current_cert, AUTH_CA)
458 && chunk_equals(keyid, pubkey->get_keyid(pubkey)))
459 {
460 found = current_cert;
461 break;
462 }
463 }
464 iterator->destroy(iterator);
465
466 return found;
467 }
468
469 /**
470 * Find an exact copy of a certificate in a linked list
471 */
472 static x509_t* find_certificate(linked_list_t *certs, x509_t *cert)
473 {
474 x509_t *found_cert = NULL, *current_cert;
475
476 iterator_t *iterator = certs->create_iterator(certs, TRUE);
477
478 while (iterator->iterate(iterator, (void**)&current_cert))
479 {
480 if (cert->equals(cert, current_cert))
481 {
482 found_cert = current_cert;
483 break;
484 }
485 }
486 iterator->destroy(iterator);
487
488 return found_cert;
489 }
490
491 /**
492 * Adds crl and ocsp uris to the corresponding issuer info record
493 */
494 static void add_uris(ca_info_t *issuer, x509_t *cert)
495 {
496 iterator_t *iterator;
497 identification_t *uri;
498
499 /* add any crl distribution points to the issuer ca info record */
500 iterator = cert->create_crluri_iterator(cert);
501
502 while (iterator->iterate(iterator, (void**)&uri))
503 {
504 issuer->add_crluri(issuer, uri->get_encoding(uri));
505 }
506 iterator->destroy(iterator);
507
508 /* add any ocsp access points to the issuer ca info record */
509 iterator = cert->create_ocspuri_iterator(cert);
510
511 while (iterator->iterate(iterator, (void**)&uri))
512 {
513 issuer->add_ocspuri(issuer, uri->get_encoding(uri));
514 }
515 iterator->destroy(iterator);
516 }
517
518 /**
519 * Implementation of credential_store_t.is_trusted
520 */
521 static bool is_trusted(private_local_credential_store_t *this, x509_t *cert)
522 {
523 int pathlen;
524 time_t until = UNDEFINED_TIME;
525 x509_t *cert_to_be_trusted = cert;
526
527 DBG2(DBG_CFG, "establishing trust in certificate:");
528
529 for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
530 {
531 err_t ugh = NULL;
532 ca_info_t *issuer;
533 x509_t *issuer_cert;
534 rsa_public_key_t *issuer_public_key;
535 bool valid_signature;
536
537 DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert));
538 DBG2(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert));
539
540 ugh = cert->is_valid(cert, &until);
541 if (ugh != NULL)
542 {
543 DBG1(DBG_CFG, "certificate %s", ugh);
544 return FALSE;
545 }
546 DBG2(DBG_CFG, "certificate is valid");
547
548 issuer = get_issuer(this, cert);
549 if (issuer == NULL)
550 {
551 DBG1(DBG_CFG, "issuer not found");
552 return FALSE;
553 }
554 DBG2(DBG_CFG, "issuer found");
555
556 issuer_cert = issuer->get_certificate(issuer);
557 issuer_public_key = issuer_cert->get_public_key(issuer_cert);
558 valid_signature = cert->verify(cert, issuer_public_key);
559
560 if (!valid_signature)
561 {
562 DBG1(DBG_CFG, "certificate signature is invalid");
563 return FALSE;
564 }
565 DBG2(DBG_CFG, "certificate signature is valid");
566
567 /* check if cert is a self-signed root ca */
568 if (pathlen > 0 && cert->is_self_signed(cert))
569 {
570 DBG2(DBG_CFG, "reached self-signed root ca");
571 cert_to_be_trusted->set_until(cert_to_be_trusted, until);
572 cert_to_be_trusted->set_status(cert_to_be_trusted, CERT_GOOD);
573 return TRUE;
574 }
575 else
576 {
577 /* go up one step in the trust chain */
578 cert = issuer_cert;
579 }
580 }
581 DBG1(DBG_CFG, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
582 return FALSE;
583 }
584
585 /**
586 * Implementation of credential_store_t.verify.
587 */
588 static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *found)
589 {
590 int pathlen;
591 time_t until = UNDEFINED_TIME;
592
593 x509_t *end_cert = cert;
594 x509_t *cert_copy = find_certificate(this->certs, end_cert);
595
596 DBG2(DBG_CFG, "verifying end entity certificate:");
597
598 *found = (cert_copy != NULL);
599 if (*found)
600 {
601 DBG2(DBG_CFG,
602 "end entitity certificate is already in credential store");
603 }
604
605 for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
606 {
607 err_t ugh = NULL;
608 ca_info_t *issuer;
609 x509_t *issuer_cert;
610 rsa_public_key_t *issuer_public_key;
611 bool valid_signature;
612
613 DBG1(DBG_CFG, "subject: '%D'", cert->get_subject(cert));
614 DBG1(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert));
615
616 ugh = cert->is_valid(cert, &until);
617 if (ugh != NULL)
618 {
619 DBG1(DBG_CFG, "certificate %s", ugh);
620 return FALSE;
621 }
622 DBG2(DBG_CFG, "certificate is valid");
623
624 issuer = get_issuer(this, cert);
625 if (issuer == NULL)
626 {
627 DBG1(DBG_CFG, "issuer not found");
628 return FALSE;
629 }
630 DBG2(DBG_CFG, "issuer found");
631
632 issuer_cert = issuer->get_certificate(issuer);
633 issuer_public_key = issuer_cert->get_public_key(issuer_cert);
634 valid_signature = cert->verify(cert, issuer_public_key);
635
636 if (!valid_signature)
637 {
638 DBG1(DBG_CFG, "certificate signature is invalid");
639 return FALSE;
640 }
641 DBG2(DBG_CFG, "certificate signature is valid");
642
643 /* check if cert is a self-signed root ca */
644 if (pathlen > 0 && cert->is_self_signed(cert))
645 {
646 DBG1(DBG_CFG, "reached self-signed root ca");
647
648 /* set the definite status and trust interval of the end entity certificate */
649 end_cert->set_until(end_cert, until);
650 if (cert_copy)
651 {
652 cert_copy->set_status(cert_copy, end_cert->get_status(end_cert));
653 cert_copy->set_until(cert_copy, until);
654 }
655 return TRUE;
656 }
657 else
658 {
659 bool strict;
660 time_t nextUpdate;
661 cert_status_t status;
662 certinfo_t *certinfo = certinfo_create(cert->get_serialNumber(cert));
663
664 certinfo->set_nextUpdate(certinfo, until);
665
666 if (pathlen == 0)
667 {
668 /* add any crl and ocsp uris contained in the certificate under test */
669 add_uris(issuer, cert);
670 }
671
672 strict = issuer->is_strict(issuer);
673 DBG1(DBG_CFG, "issuer %s a strict crl policy",
674 strict ? "enforces":"does not enforce");
675
676 /* first check certificate revocation using ocsp */
677 status = issuer->verify_by_ocsp(issuer, certinfo, &this->public.credential_store);
678
679 /* if ocsp service is not available then fall back to crl */
680 if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && strict))
681 {
682 status = issuer->verify_by_crl(issuer, certinfo, CRL_DIR);
683 }
684
685 nextUpdate = certinfo->get_nextUpdate(certinfo);
686 cert->set_status(cert, status);
687
688 switch (status)
689 {
690 case CERT_GOOD:
691 /* set nextUpdate */
692 cert->set_until(cert, nextUpdate);
693
694 /* if status information is stale */
695 if (strict && nextUpdate < time(NULL))
696 {
697 DBG2(DBG_CFG, "certificate is good but status is stale");
698 certinfo->destroy(certinfo);
699 return FALSE;
700 }
701 DBG1(DBG_CFG, "certificate is good");
702
703 /* with strict crl policy the public key must have the same
704 * lifetime as the validity of the ocsp status or crl lifetime
705 */
706 if (strict && nextUpdate < until)
707 until = nextUpdate;
708 break;
709 case CERT_REVOKED:
710 {
711 time_t revocationTime = certinfo->get_revocationTime(certinfo);
712 DBG1(DBG_CFG,
713 "certificate was revoked on %T, reason: %N",
714 &revocationTime, crl_reason_names,
715 certinfo->get_revocationReason(certinfo));
716
717 /* set revocationTime */
718 cert->set_until(cert, revocationTime);
719
720 /* update status of end certificate in the credential store */
721 if (cert_copy)
722 {
723 if (pathlen > 0)
724 {
725 cert_copy->set_status(cert_copy, CERT_UNTRUSTED);
726 }
727 else
728 {
729 cert_copy->set_status(cert_copy, CERT_REVOKED);
730 cert_copy->set_until(cert_copy,
731 certinfo->get_revocationTime(certinfo));
732 }
733 }
734 certinfo->destroy(certinfo);
735 return FALSE;
736 }
737 case CERT_UNKNOWN:
738 case CERT_UNDEFINED:
739 default:
740 DBG1(DBG_CFG, "certificate status unknown");
741 if (strict)
742 {
743 /* update status of end certificate in the credential store */
744 if (cert_copy)
745 {
746 cert_copy->set_status(cert_copy, CERT_UNTRUSTED);
747 }
748 certinfo->destroy(certinfo);
749 return FALSE;
750 }
751 break;
752 }
753 certinfo->destroy(certinfo);
754 }
755 /* go up one step in the trust chain */
756 cert = issuer_cert;
757 }
758 DBG1(DBG_CFG, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
759 return FALSE;
760 }
761
762 /**
763 * Add a unique certificate to a linked list
764 */
765 static x509_t* add_certificate(linked_list_t *certs, x509_t *cert)
766 {
767 x509_t *found_cert = find_certificate(certs, cert);
768
769 if (found_cert)
770 {
771 /* add the authority flags */
772 found_cert->add_authority_flags(found_cert, cert->get_authority_flags(cert));
773
774 cert->destroy(cert);
775 return found_cert;
776 }
777 else
778 {
779 certs->insert_last(certs, (void*)cert);
780 return cert;
781 }
782 }
783
784 /**
785 * Add a unique ca info record to a linked list
786 */
787 static void add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_info)
788 {
789 ca_info_t *current_ca_info;
790 ca_info_t *found_ca_info = NULL;
791
792 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
793
794 while (iterator->iterate(iterator, (void**)&current_ca_info))
795 {
796 if (current_ca_info->equals(current_ca_info, ca_info))
797 {
798 found_ca_info = current_ca_info;
799 break;
800 }
801 }
802 iterator->destroy(iterator);
803
804 if (found_ca_info)
805 {
806 current_ca_info->add_info(current_ca_info, ca_info);
807 ca_info->destroy(ca_info);
808 }
809 else
810 {
811 this->ca_infos->insert_last(this->ca_infos, (void*)ca_info);
812 }
813 }
814
815 /**
816 * Release ca info record of a given name
817 */
818 static status_t release_ca_info(private_local_credential_store_t *this, const char *name)
819 {
820 status_t status = NOT_FOUND;
821 ca_info_t *ca_info;
822
823 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
824
825 while (iterator->iterate(iterator, (void**)&ca_info))
826 {
827 if (ca_info->equals_name_release_info(ca_info, name))
828 {
829 status = SUCCESS;
830 break;
831 }
832 }
833 iterator->destroy(iterator);
834
835 return status;
836 }
837
838 /**
839 * Implements local_credential_store_t.add_end_certificate
840 */
841 static x509_t* add_end_certificate(private_local_credential_store_t *this, x509_t *cert)
842 {
843 x509_t *ret_cert = add_certificate(this->certs, cert);
844
845 /* add crl and ocsp uris the first time the certificate is added */
846 if (ret_cert == cert)
847 {
848 ca_info_t *issuer = get_issuer(this, cert);
849
850 if (issuer)
851 {
852 add_uris(issuer, cert);
853 }
854 }
855 return ret_cert;
856 }
857
858 /**
859 * Implements local_credential_store_t.add_auth_certificate
860 */
861 static x509_t* add_auth_certificate(private_local_credential_store_t *this, x509_t *cert, u_int auth_flags)
862 {
863 cert->add_authority_flags(cert, auth_flags);
864 return add_certificate(this->auth_certs, cert);
865 }
866
867 /**
868 * Implements local_credential_store_t.create_cert_iterator
869 */
870 static iterator_t* create_cert_iterator(private_local_credential_store_t *this)
871 {
872 return this->certs->create_iterator(this->certs, TRUE);
873 }
874
875 /**
876 * Implements local_credential_store_t.create_cacert_iterator
877 */
878 static iterator_t* create_auth_cert_iterator(private_local_credential_store_t *this)
879 {
880 return this->auth_certs->create_iterator(this->auth_certs, TRUE);
881 }
882
883 /**
884 * Implements local_credential_store_t.create_cainfo_iterator
885 */
886 static iterator_t* create_cainfo_iterator(private_local_credential_store_t *this)
887 {
888 return this->ca_infos->create_iterator(this->ca_infos, TRUE);
889 }
890
891 /**
892 * Implements local_credential_store_t.load_auth_certificates
893 */
894 static void load_auth_certificates(private_local_credential_store_t *this,
895 u_int auth_flag,
896 const char* label,
897 const char* path)
898 {
899 struct dirent* entry;
900 struct stat stb;
901 DIR* dir;
902
903 DBG1(DBG_CFG, "loading %s certificates from '%s'", label, path);
904
905 dir = opendir(path);
906 if (dir == NULL)
907 {
908 DBG1(DBG_CFG, "error opening %s certs directory '%s'", label, path);
909 return;
910 }
911
912 while ((entry = readdir(dir)) != NULL)
913 {
914 char file[PATH_BUF];
915
916 snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
917
918 if (stat(file, &stb) == -1)
919 {
920 continue;
921 }
922 /* try to parse all regular files */
923 if (stb.st_mode & S_IFREG)
924 {
925 x509_t *cert = x509_create_from_file(file, label);
926
927 if (cert)
928 {
929 err_t ugh = cert->is_valid(cert, NULL);
930
931 if (ugh != NULL)
932 {
933 DBG1(DBG_CFG, "warning: %s certificate %s", label, ugh);
934 }
935
936 if (auth_flag == AUTH_CA && !cert->is_ca(cert))
937 {
938 DBG1(DBG_CFG, " CA basic constraints flag not set, cert discarded");
939 cert->destroy(cert);
940 }
941 else
942 {
943 x509_t *ret_cert;
944
945 cert->add_authority_flags(cert, auth_flag);
946
947 ret_cert = add_certificate(this->auth_certs, cert);
948
949 if (auth_flag == AUTH_CA && ret_cert == cert)
950 {
951 ca_info_t *ca_info = ca_info_create(NULL, cert);
952
953 add_ca_info(this, ca_info);
954 }
955 }
956 }
957 }
958 }
959 closedir(dir);
960 }
961
962 /**
963 * Implements local_credential_store_t.load_ca_certificates
964 */
965 static void load_ca_certificates(private_local_credential_store_t *this)
966 {
967 load_auth_certificates(this, AUTH_CA, "ca", CA_CERTIFICATE_DIR);
968
969 /* add any crl and ocsp uris found in the ca certificates to the
970 * corresponding issuer info record. We can do this only after all
971 * ca certificates have been loaded and the ca hierarchy is known.
972 */
973 {
974 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
975 ca_info_t *ca_info;
976
977 while (iterator->iterate(iterator, (void **)&ca_info))
978 {
979 x509_t *cacert = ca_info->get_certificate(ca_info);
980 ca_info_t *issuer = get_issuer(this, cacert);
981
982 if (issuer)
983 {
984 add_uris(issuer, cacert);
985 }
986 }
987 iterator->destroy(iterator);
988 }
989 }
990
991 /**
992 * Implements local_credential_store_t.load_aa_certificates
993 */
994 static void load_aa_certificates(private_local_credential_store_t *this)
995 {
996 load_auth_certificates(this, AUTH_AA, "aa", AA_CERTIFICATE_DIR);
997 }
998
999 /**
1000 * Add a unique attribute certificate to a linked list
1001 */
1002 static void add_attr_certificate(private_local_credential_store_t *this, x509ac_t *cert)
1003 {
1004 /* TODO add a new attribute certificate to the linked list */
1005 }
1006
1007 /**
1008 * Implements local_credential_store_t.load_attr_certificates
1009 */
1010 static void load_attr_certificates(private_local_credential_store_t *this)
1011 {
1012 struct dirent* entry;
1013 struct stat stb;
1014 DIR* dir;
1015
1016 const char *path = ATTR_CERTIFICATE_DIR;
1017
1018 DBG1(DBG_CFG, "loading attribute certificates from '%s'", path);
1019
1020 dir = opendir(ATTR_CERTIFICATE_DIR);
1021 if (dir == NULL)
1022 {
1023 DBG1(DBG_CFG, "error opening attribute certs directory '%s'", path);
1024 return;
1025 }
1026
1027 while ((entry = readdir(dir)) != NULL)
1028 {
1029 char file[PATH_BUF];
1030
1031 snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
1032
1033 if (stat(file, &stb) == -1)
1034 {
1035 continue;
1036 }
1037 /* try to parse all regular files */
1038 if (stb.st_mode & S_IFREG)
1039 {
1040 x509ac_t *cert = x509ac_create_from_file(file);
1041
1042 if (cert)
1043 {
1044 err_t ugh = cert->is_valid(cert, NULL);
1045
1046 if (ugh != NULL)
1047 {
1048 DBG1(DBG_CFG, "warning: attribute certificate %s", ugh);
1049 }
1050 add_attr_certificate(this, cert);
1051 }
1052 }
1053 }
1054 closedir(dir);
1055
1056
1057 }
1058
1059 /**
1060 * Implements local_credential_store_t.load_ocsp_certificates
1061 */
1062 static void load_ocsp_certificates(private_local_credential_store_t *this)
1063 {
1064 load_auth_certificates(this, AUTH_OCSP, "ocsp", OCSP_CERTIFICATE_DIR);
1065 }
1066
1067 /**
1068 * Add the latest crl to the issuing ca
1069 */
1070 static void add_crl(private_local_credential_store_t *this, crl_t *crl, const char *path)
1071 {
1072 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
1073 ca_info_t *ca_info;
1074 bool found = FALSE;
1075
1076 while (iterator->iterate(iterator, (void**)&ca_info))
1077 {
1078 if (ca_info->is_crl_issuer(ca_info, crl))
1079 {
1080 char buffer[BUF_LEN];
1081 chunk_t uri = { buffer, 7 + strlen(path) };
1082
1083 ca_info->add_crl(ca_info, crl);
1084 if (uri.len < BUF_LEN)
1085 {
1086 snprintf(buffer, BUF_LEN, "file://%s", path);
1087 ca_info->add_crluri(ca_info, uri);
1088 }
1089 found = TRUE;
1090 break;
1091 }
1092 }
1093 iterator->destroy(iterator);
1094
1095 if (!found)
1096 {
1097 crl->destroy(crl);
1098 DBG2(DBG_CFG, " no issuing ca found for this crl - discarded");
1099 }
1100 }
1101
1102 /**
1103 * Implements local_credential_store_t.load_crls
1104 */
1105 static void load_crls(private_local_credential_store_t *this)
1106 {
1107 struct dirent* entry;
1108 struct stat stb;
1109 DIR* dir;
1110 crl_t *crl;
1111
1112 DBG1(DBG_CFG, "loading crls from '%s'", CRL_DIR);
1113
1114 dir = opendir(CRL_DIR);
1115 if (dir == NULL)
1116 {
1117 DBG1(DBG_CFG, "error opening crl directory '%s'", CRL_DIR);
1118 return;
1119 }
1120
1121 while ((entry = readdir(dir)) != NULL)
1122 {
1123 char file[PATH_BUF];
1124
1125 snprintf(file, sizeof(file), "%s/%s", CRL_DIR, entry->d_name);
1126
1127 if (stat(file, &stb) == -1)
1128 {
1129 continue;
1130 }
1131 /* try to parse all regular files */
1132 if (stb.st_mode & S_IFREG)
1133 {
1134 crl = crl_create_from_file(file);
1135 if (crl)
1136 {
1137 DBG1(DBG_CFG, " crl is %s", crl->is_valid(crl)? "valid":"stale");
1138 add_crl(this, crl, file);
1139 }
1140 }
1141 }
1142 closedir(dir);
1143 }
1144
1145 /**
1146 * Convert a string of characters into a binary secret
1147 * A string between single or double quotes is treated as ASCII characters
1148 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
1149 */
1150 static err_t extract_secret(chunk_t *secret, chunk_t *line)
1151 {
1152 chunk_t raw_secret;
1153 char delimiter = ' ';
1154 bool quotes = FALSE;
1155
1156 if (!eat_whitespace(line))
1157 {
1158 return "missing secret";
1159 }
1160
1161 if (*line->ptr == '\'' || *line->ptr == '"')
1162 {
1163 quotes = TRUE;
1164 delimiter = *line->ptr;
1165 line->ptr++; line->len--;
1166 }
1167
1168 if (!extract_token(&raw_secret, delimiter, line))
1169 {
1170 if (delimiter == ' ')
1171 {
1172 raw_secret = *line;
1173 }
1174 else
1175 {
1176 return "missing second delimiter";
1177 }
1178 }
1179
1180 if (quotes)
1181 { /* treat as an ASCII string */
1182 if (raw_secret.len > secret->len)
1183 return "secret larger than buffer";
1184 memcpy(secret->ptr, raw_secret.ptr, raw_secret.len);
1185 secret->len = raw_secret.len;
1186 }
1187 else
1188 { /* convert from HEX or Base64 to binary */
1189 size_t len;
1190 err_t ugh = ttodata(raw_secret.ptr, raw_secret.len, 0, secret->ptr, secret->len, &len);
1191
1192 if (ugh != NULL)
1193 return ugh;
1194 if (len > secret->len)
1195 return "secret larger than buffer";
1196 secret->len = len;
1197 }
1198 return NULL;
1199 }
1200
1201 /**
1202 * Implements local_credential_store_t.load_secrets
1203 */
1204 static void load_secrets(private_local_credential_store_t *this)
1205 {
1206 FILE *fd = fopen(SECRETS_FILE, "r");
1207
1208 if (fd)
1209 {
1210 int bytes;
1211 int line_nr = 0;
1212 chunk_t chunk, src, line;
1213
1214 DBG1(DBG_CFG, "loading secrets from \"%s\"", SECRETS_FILE);
1215
1216 fseek(fd, 0, SEEK_END);
1217 chunk.len = ftell(fd);
1218 rewind(fd);
1219 chunk.ptr = malloc(chunk.len);
1220 bytes = fread(chunk.ptr, 1, chunk.len, fd);
1221 fclose(fd);
1222
1223 src = chunk;
1224
1225 while (fetchline(&src, &line))
1226 {
1227 chunk_t ids, token;
1228 bool is_eap = FALSE;
1229
1230 line_nr++;
1231
1232 if (!eat_whitespace(&line))
1233 {
1234 continue;
1235 }
1236 if (!extract_token(&ids, ':', &line))
1237 {
1238 DBG1(DBG_CFG, "line %d: missing ':' separator", line_nr);
1239 goto error;
1240 }
1241 /* NULL terminate the ids string by replacing the : separator */
1242 *(ids.ptr + ids.len) = '\0';
1243
1244 if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
1245 {
1246 DBG1(DBG_CFG, "line %d: missing token", line_nr);
1247 goto error;
1248 }
1249 if (match("RSA", &token))
1250 {
1251 char path[PATH_BUF];
1252 chunk_t filename;
1253
1254 char buf[BUF_LEN];
1255 chunk_t secret = { buf, BUF_LEN };
1256 chunk_t *passphrase = NULL;
1257
1258 rsa_private_key_t *key;
1259
1260 err_t ugh = extract_value(&filename, &line);
1261
1262 if (ugh != NULL)
1263 {
1264 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
1265 goto error;
1266 }
1267 if (filename.len == 0)
1268 {
1269 DBG1(DBG_CFG, "line %d: empty filename", line_nr);
1270 goto error;
1271 }
1272 if (*filename.ptr == '/')
1273 {
1274 /* absolute path name */
1275 snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
1276 }
1277 else
1278 {
1279 /* relative path name */
1280 snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
1281 filename.len, filename.ptr);
1282 }
1283
1284 /* check for optional passphrase */
1285 if (eat_whitespace(&line))
1286 {
1287 ugh = extract_secret(&secret, &line);
1288 if (ugh != NULL)
1289 {
1290 DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
1291 goto error;
1292 }
1293 if (secret.len > 0)
1294 passphrase = &secret;
1295 }
1296 key = rsa_private_key_create_from_file(path, passphrase);
1297 if (key)
1298 {
1299 this->private_keys->insert_last(this->private_keys, (void*)key);
1300 }
1301 }
1302 else if ( match("PSK", &token) ||
1303 ((match("EAP", &token) || match("XAUTH", &token)) && (is_eap = TRUE)))
1304 {
1305 shared_key_t *shared_key;
1306
1307 char buf[BUF_LEN];
1308 chunk_t secret = { buf, BUF_LEN };
1309
1310 err_t ugh = extract_secret(&secret, &line);
1311 if (ugh != NULL)
1312 {
1313 DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
1314 goto error;
1315 }
1316
1317 DBG1(DBG_CFG, " loading %s key for %s",
1318 is_eap ? "EAP" : "shared",
1319 ids.len > 0 ? (char*)ids.ptr : "%any");
1320
1321 DBG4(DBG_CFG, " secret:", secret);
1322
1323 shared_key = shared_key_create(secret);
1324 if (shared_key)
1325 {
1326 if (is_eap)
1327 {
1328 this->eap_keys->insert_last(this->eap_keys, (void*)shared_key);
1329 }
1330 else
1331 {
1332 this->shared_keys->insert_last(this->shared_keys, (void*)shared_key);
1333 }
1334 }
1335 while (ids.len > 0)
1336 {
1337 chunk_t id;
1338 identification_t *peer_id;
1339
1340 ugh = extract_value(&id, &ids);
1341 if (ugh != NULL)
1342 {
1343 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
1344 goto error;
1345 }
1346 if (id.len == 0)
1347 {
1348 continue;
1349 }
1350
1351 /* NULL terminate the ID string */
1352 *(id.ptr + id.len) = '\0';
1353
1354 peer_id = identification_create_from_string(id.ptr);
1355 if (peer_id == NULL)
1356 {
1357 DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
1358 goto error;
1359 }
1360
1361 if (peer_id->get_type(peer_id) == ID_ANY)
1362 {
1363 peer_id->destroy(peer_id);
1364 continue;
1365 }
1366 shared_key->peers->insert_last(shared_key->peers, (void*)peer_id);
1367 }
1368 }
1369 else if (match("PIN", &token))
1370 {
1371
1372 }
1373 else
1374 {
1375 DBG1(DBG_CFG, "line %d: token must be either "
1376 "RSA, PSK, EAP, or PIN", line_nr, token.len);
1377 goto error;
1378 }
1379 }
1380 error:
1381 free(chunk.ptr);
1382 }
1383 else
1384 {
1385 DBG1(DBG_CFG, "could not open file '%s'", SECRETS_FILE);
1386 }
1387 }
1388
1389 /**
1390 * Implementation of local_credential_store_t.destroy.
1391 */
1392 static void destroy(private_local_credential_store_t *this)
1393 {
1394 this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy));
1395 this->auth_certs->destroy_offset(this->auth_certs, offsetof(x509_t, destroy));
1396 this->ca_infos->destroy_offset(this->ca_infos, offsetof(ca_info_t, destroy));
1397 this->private_keys->destroy_offset(this->private_keys, offsetof(rsa_private_key_t, destroy));
1398 this->shared_keys->destroy_function(this->shared_keys, (void*)shared_key_destroy);
1399 this->eap_keys->destroy_function(this->eap_keys, (void*)shared_key_destroy);
1400 free(this);
1401 }
1402
1403 /**
1404 * Described in header.
1405 */
1406 local_credential_store_t * local_credential_store_create(void)
1407 {
1408 private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t);
1409
1410 this->public.credential_store.get_shared_key = (status_t (*) (credential_store_t*,identification_t*,identification_t*,chunk_t*))get_shared_key;
1411 this->public.credential_store.get_eap_key = (status_t (*) (credential_store_t*,identification_t*,identification_t*,chunk_t*))get_eap_key;
1412 this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key;
1413 this->public.credential_store.get_rsa_private_key = (rsa_private_key_t* (*) (credential_store_t*,rsa_public_key_t*))get_rsa_private_key;
1414 this->public.credential_store.has_rsa_private_key = (bool (*) (credential_store_t*,rsa_public_key_t*))has_rsa_private_key;
1415 this->public.credential_store.get_trusted_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_trusted_public_key;
1416 this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate;
1417 this->public.credential_store.get_auth_certificate = (x509_t* (*) (credential_store_t*,u_int,identification_t*))get_auth_certificate;
1418 this->public.credential_store.get_ca_certificate_by_keyid = (x509_t* (*) (credential_store_t*,chunk_t))get_ca_certificate_by_keyid;
1419 this->public.credential_store.get_issuer = (ca_info_t* (*) (credential_store_t*,const x509_t*))get_issuer;
1420 this->public.credential_store.is_trusted = (bool (*) (credential_store_t*,x509_t*))is_trusted;
1421 this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify;
1422 this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate;
1423 this->public.credential_store.add_auth_certificate = (x509_t* (*) (credential_store_t*,x509_t*,u_int))add_auth_certificate;
1424 this->public.credential_store.add_ca_info = (void (*) (credential_store_t*,ca_info_t*))add_ca_info;
1425 this->public.credential_store.release_ca_info = (status_t (*) (credential_store_t*,const char*))release_ca_info;
1426 this->public.credential_store.create_cert_iterator = (iterator_t* (*) (credential_store_t*))create_cert_iterator;
1427 this->public.credential_store.create_auth_cert_iterator = (iterator_t* (*) (credential_store_t*))create_auth_cert_iterator;
1428 this->public.credential_store.create_cainfo_iterator = (iterator_t* (*) (credential_store_t*))create_cainfo_iterator;
1429 this->public.credential_store.load_ca_certificates = (void (*) (credential_store_t*))load_ca_certificates;
1430 this->public.credential_store.load_aa_certificates = (void (*) (credential_store_t*))load_aa_certificates;
1431 this->public.credential_store.load_attr_certificates = (void (*) (credential_store_t*))load_attr_certificates;
1432 this->public.credential_store.load_ocsp_certificates = (void (*) (credential_store_t*))load_ocsp_certificates;
1433 this->public.credential_store.load_crls = (void (*) (credential_store_t*))load_crls;
1434 this->public.credential_store.load_secrets = (void (*) (credential_store_t*))load_secrets;
1435 this->public.credential_store.destroy = (void (*) (credential_store_t*))destroy;
1436
1437 /* private variables */
1438 this->shared_keys = linked_list_create();
1439 this->eap_keys = linked_list_create();
1440 this->private_keys = linked_list_create();
1441 this->certs = linked_list_create();
1442 this->auth_certs = linked_list_create();
1443 this->ca_infos = linked_list_create();
1444
1445 return (&this->public);
1446 }