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