refactored trustchain verification, this should fix #33
[strongswan.git] / src / charon / credentials / credential_manager.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "credential_manager.h"
19
20 #include <daemon.h>
21 #include <utils/linked_list.h>
22 #include <utils/mutex.h>
23 #include <credentials/sets/auth_info_wrapper.h>
24 #include <credentials/sets/ocsp_response_wrapper.h>
25 #include <credentials/certificates/x509.h>
26 #include <credentials/certificates/crl.h>
27 #include <credentials/certificates/ocsp_request.h>
28 #include <credentials/certificates/ocsp_response.h>
29
30 #define MAX_CA_LEVELS 6
31
32 typedef struct private_credential_manager_t private_credential_manager_t;
33
34 /**
35 * private data of credential_manager
36 */
37 struct private_credential_manager_t {
38
39 /**
40 * public functions
41 */
42 credential_manager_t public;
43
44 /**
45 * list of credential sets
46 */
47 linked_list_t *sets;
48
49 /**
50 * mutex to gain exclusive access
51 */
52 mutex_t *mutex;
53 };
54
55 /** data to pass to create_private_enumerator */
56 typedef struct {
57 private_credential_manager_t *this;
58 key_type_t type;
59 identification_t* keyid;
60 } private_data_t;
61
62 /** data to pass to create_cert_enumerator */
63 typedef struct {
64 private_credential_manager_t *this;
65 certificate_type_t cert;
66 key_type_t key;
67 identification_t *id;
68 bool trusted;
69 } cert_data_t;
70
71 /** data to pass to create_cdp_enumerator */
72 typedef struct {
73 private_credential_manager_t *this;
74 certificate_type_t type;
75 identification_t *id;
76 } cdp_data_t;
77
78 /** data to pass to create_shared_enumerator */
79 typedef struct {
80 private_credential_manager_t *this;
81 shared_key_type_t type;
82 identification_t *me;
83 identification_t *other;
84 } shared_data_t;
85
86 /**
87 * cleanup function for cert data
88 */
89 static void destroy_cert_data(cert_data_t *data)
90 {
91 data->this->mutex->unlock(data->this->mutex);
92 free(data);
93 }
94
95 /**
96 * enumerator constructor for certificates
97 */
98 static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data)
99 {
100 return set->create_cert_enumerator(set, data->cert, data->key,
101 data->id, data->trusted);
102 }
103
104 /**
105 * Implementation of credential_manager_t.create_cert_enumerator.
106 */
107 static enumerator_t *create_cert_enumerator(private_credential_manager_t *this,
108 certificate_type_t certificate, key_type_t key,
109 identification_t *id, bool trusted)
110 {
111 cert_data_t *data = malloc_thing(cert_data_t);
112 data->this = this;
113 data->cert = certificate;
114 data->key = key;
115 data->id = id;
116 data->trusted = trusted;
117
118 this->mutex->lock(this->mutex);
119 return enumerator_create_nested(this->sets->create_enumerator(this->sets),
120 (void*)create_cert, data,
121 (void*)destroy_cert_data);
122 }
123
124 /**
125 * Implementation of credential_manager_t.get_cert.
126 */
127 static certificate_t *get_cert(private_credential_manager_t *this,
128 certificate_type_t cert, key_type_t key,
129 identification_t *id, bool trusted)
130 {
131 certificate_t *current, *found = NULL;
132 enumerator_t *enumerator;
133
134 this->mutex->lock(this->mutex);
135 enumerator = create_cert_enumerator(this, cert, key, id, trusted);
136 if (enumerator->enumerate(enumerator, &current))
137 {
138 /* TODO: best match? order by keyid, subject, sualtname */
139 found = current->get_ref(current);
140 }
141 enumerator->destroy(enumerator);
142 this->mutex->unlock(this->mutex);
143 return found;
144 }
145
146
147 /**
148 * cleanup function for cdp data
149 */
150 static void destroy_cdp_data(cdp_data_t *data)
151 {
152 data->this->mutex->unlock(data->this->mutex);
153 free(data);
154 }
155
156 /**
157 * enumerator constructor for CDPs
158 */
159 static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data)
160 {
161 return set->create_cdp_enumerator(set, data->type, data->id);
162 }
163 /**
164 * Implementation of credential_manager_t.create_cdp_enumerator.
165 */
166 static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this,
167 credential_type_t type, identification_t *id)
168 {
169 cdp_data_t *data = malloc_thing(cdp_data_t);
170 data->this = this;
171 data->type = type;
172 data->id = id;
173
174 this->mutex->lock(this->mutex);
175 return enumerator_create_nested(this->sets->create_enumerator(this->sets),
176 (void*)create_cdp, data,
177 (void*)destroy_cdp_data);
178 }
179
180 /**
181 * cleanup function for private data
182 */
183 static void destroy_private_data(private_data_t *data)
184 {
185 data->this->mutex->unlock(data->this->mutex);
186 free(data);
187 }
188
189 /**
190 * enumerator constructor for private keys
191 */
192 static enumerator_t *create_private(credential_set_t *set, private_data_t *data)
193 {
194 return set->create_private_enumerator(set, data->type, data->keyid);
195 }
196
197 /**
198 * Implementation of credential_manager_t.get_private_by_keyid.
199 */
200 static enumerator_t* create_private_enumerator(
201 private_credential_manager_t *this,
202 key_type_t key, identification_t *keyid)
203 {
204 private_data_t *data;
205
206 data = malloc_thing(private_data_t);
207 data->this = this;
208 data->type = key;
209 data->keyid = keyid;
210 this->mutex->lock(this->mutex);
211 return enumerator_create_nested(this->sets->create_enumerator(this->sets),
212 (void*)create_private, data, (void*)destroy_private_data);
213 }
214
215 /**
216 * Implementation of credential_manager_t.get_private_by_keyid.
217 */
218 static private_key_t *get_private_by_keyid(private_credential_manager_t *this,
219 key_type_t key, identification_t *keyid)
220 {
221 private_key_t *found = NULL;
222 enumerator_t *enumerator;
223
224 enumerator = create_private_enumerator(this, key, keyid);
225 if (enumerator->enumerate(enumerator, &found))
226 {
227 found->get_ref(found);
228 }
229 enumerator->destroy(enumerator);
230 return found;
231 }
232
233 /**
234 * cleanup function for shared data
235 */
236 static void destroy_shared_data(shared_data_t *data)
237 {
238 data->this->mutex->unlock(data->this->mutex);
239 free(data);
240 }
241
242 /**
243 * enumerator constructor for shared keys
244 */
245 static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data)
246 {
247 return set->create_shared_enumerator(set, data->type, data->me, data->other);
248 }
249
250 /**
251 * Implementation of credential_manager_t.create_shared_enumerator.
252 */
253 static enumerator_t *create_shared_enumerator(private_credential_manager_t *this,
254 shared_key_type_t type,
255 identification_t *me, identification_t *other)
256 {
257 shared_data_t *data = malloc_thing(shared_data_t);
258 data->this = this;
259 data->type = type;
260 data->me = me;
261 data->other = other;
262
263 this->mutex->lock(this->mutex);
264 return enumerator_create_nested(this->sets->create_enumerator(this->sets),
265 (void*)create_shared, data,
266 (void*)destroy_shared_data);
267 }
268
269 /**
270 * Implementation of credential_manager_t.get_shared.
271 */
272 static shared_key_t *get_shared(private_credential_manager_t *this,
273 shared_key_type_t type, identification_t *me,
274 identification_t *other)
275 {
276 shared_key_t *current, *found = NULL;
277 id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE;
278 id_match_t *match_me, *match_other;
279 enumerator_t *enumerator;
280
281 enumerator = create_shared_enumerator(this, type, me, other);
282 while (enumerator->enumerate(enumerator, &current, &match_me, &match_other))
283 {
284 if (match_other > best_other ||
285 (match_other == best_other && match_me > best_me))
286 {
287 DESTROY_IF(found);
288 found = current->get_ref(current);
289 best_me = match_me;
290 best_other = match_other;
291 }
292 }
293 enumerator->destroy(enumerator);
294 return found;
295 }
296
297 /**
298 * forward declaration
299 */
300 static certificate_t *get_trusted_cert(private_credential_manager_t *this,
301 key_type_t type, identification_t *id,
302 auth_info_t *auth, bool crl, bool ocsp);
303
304 /**
305 * Do an OCSP request
306 */
307 static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
308 certificate_t *subject, certificate_t *issuer)
309 {
310 certificate_t *request, *response;
311 chunk_t send, receive;
312
313 /* TODO: requestor name, signature */
314 request = lib->creds->create(lib->creds,
315 CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
316 BUILD_CA_CERT, issuer->get_ref(issuer),
317 BUILD_CERT, subject->get_ref(subject), BUILD_END);
318 if (!request)
319 {
320 DBG1(DBG_CFG, "generating ocsp request failed");
321 return NULL;
322 }
323
324 send = request->get_encoding(request);
325 request->destroy(request);
326
327 DBG1(DBG_CFG, "requesting ocsp response from '%s' ...", url);
328 if (lib->fetcher->fetch(lib->fetcher, url, &receive,
329 FETCH_REQUEST_DATA, send,
330 FETCH_REQUEST_TYPE, "application/ocsp-request",
331 FETCH_END) != SUCCESS)
332 {
333 DBG1(DBG_CFG, "ocsp request to %s failed", url);
334 chunk_free(&send);
335 return NULL;
336 }
337 chunk_free(&send);
338
339 response = lib->creds->create(lib->creds,
340 CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
341 BUILD_BLOB_ASN1_DER, receive, BUILD_END);
342 if (!response)
343 {
344 DBG1(DBG_CFG, "parsing ocsp response failed");
345 return NULL;
346 }
347
348
349 /* verify the signature of the ocsp response */
350 {
351 certificate_t *issuer_cert;
352 identification_t *responder;
353 auth_info_t *auth;
354 ocsp_response_wrapper_t *wrapper;
355
356 auth = auth_info_create();
357 wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
358 this->sets->insert_first(this->sets, wrapper);
359 responder = response->get_issuer(response);
360 DBG1(DBG_CFG, "ocsp signer is \"%D\"", responder);
361 issuer_cert = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE);
362 this->sets->remove(this->sets, wrapper, NULL);
363 wrapper->destroy(wrapper);
364 auth->destroy(auth);
365
366 if (!issuer_cert)
367 {
368 DBG1(DBG_CFG, "ocsp response untrusted: no signer certificate found");
369 response->destroy(response);
370 return NULL;
371 }
372 if (response->issued_by(response, issuer_cert, TRUE))
373 {
374 DBG1(DBG_CFG, "ocsp response correctly signed by \"%D\"",
375 issuer_cert->get_subject(issuer_cert));
376 issuer_cert->destroy(issuer_cert);
377 }
378 else
379 {
380 DBG1(DBG_CFG, "ocsp response not issued by \"%D\"",
381 issuer_cert->get_subject(issuer_cert));
382 issuer_cert->destroy(issuer_cert);
383 response->destroy(response);
384 return NULL;
385 }
386 }
387 /* TODO: cache response? */
388 return response;
389 }
390
391 /**
392 * validate a x509 certificate using OCSP
393 */
394 static cert_validation_t check_ocsp(private_credential_manager_t *this,
395 x509_t *subject, x509_t *issuer,
396 auth_info_t *auth)
397 {
398 certificate_t *sub = (certificate_t*)subject;
399 certificate_t *best_cert = NULL;
400 certificate_t *cert;
401 public_key_t *public;
402 cert_validation_t valid = VALIDATION_SKIPPED;
403 identification_t *keyid = NULL;
404 bool stale = TRUE;
405
406 /* derive the authorityKeyIdentifier from the issuer's public key */
407 cert = &issuer->interface;
408 public = cert->get_public_key(cert);
409 if (public)
410 {
411 keyid = public->get_id(public, ID_PUBKEY_SHA1);
412 }
413
414 /* find a cached ocsp response by authorityKeyIdentifier */
415 if (keyid)
416 {
417 enumerator_t *enumerator = create_cert_enumerator(this,
418 CERT_X509_OCSP_RESPONSE,
419 KEY_ANY, keyid, TRUE);
420 certificate_t *cert;
421
422 while (enumerator->enumerate(enumerator, &cert))
423 {
424 if (cert->has_subject(cert, sub->get_subject(sub)))
425 {
426 /* select most recent ocsp response */
427 if (best_cert == NULL || cert->is_newer(cert, best_cert))
428 {
429 DESTROY_IF(best_cert);
430 best_cert = cert->get_ref(cert);
431 }
432 }
433 }
434 enumerator->destroy(enumerator);
435 }
436
437 /* check the validity of the cached ocsp response if one was found */
438 if (best_cert)
439 {
440 time_t nextUpdate;
441
442 stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
443 DBG1(DBG_CFG, "cached ocsp response is %s %#T",
444 stale? "stale: since":"valid: until",
445 &nextUpdate, FALSE );
446 }
447
448 /* fallback to URL fetching from CDPs */
449 if (stale && keyid)
450 {
451 enumerator_t *enumerator = create_cdp_enumerator(this,
452 CERT_X509_OCSP_RESPONSE, keyid);
453 char *uri;
454
455 while (enumerator->enumerate(enumerator, &uri))
456 {
457 certificate_t* cert = fetch_ocsp(this, uri, &subject->interface,
458 &issuer->interface);
459
460 /* redefine default since we have at least one uri */
461 valid = VALIDATION_FAILED;
462
463 if (cert)
464 {
465 /* select most recent ocsp response until valid one is found */
466 if (best_cert == NULL || cert->is_newer(cert, best_cert))
467 {
468 time_t nextUpdate;
469
470 DESTROY_IF(best_cert);
471 best_cert = cert;
472 stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
473 DBG1(DBG_CFG, "ocsp response is %s %#T",
474 stale? "stale: since":"valid: until",
475 &nextUpdate, FALSE );
476 if (!stale)
477 {
478 break;
479 }
480 }
481 else
482 {
483 cert->destroy(cert);
484 }
485 }
486 }
487 enumerator->destroy(enumerator);
488 }
489
490 /* fallback to URL fetching from subject certificate's URIs */
491 if (stale)
492 {
493 enumerator_t *enumerator = subject->create_ocsp_uri_enumerator(subject);
494 char *uri;
495
496 while (enumerator->enumerate(enumerator, &uri))
497 {
498 certificate_t* cert = fetch_ocsp(this, uri, &subject->interface,
499 &issuer->interface);
500
501 /* redefine default since we have at least one uri */
502 valid = VALIDATION_FAILED;
503
504 if (cert)
505 {
506 /* select most recent ocsp response until valid one is found */
507 if (best_cert == NULL || cert->is_newer(cert, best_cert))
508 {
509 time_t nextUpdate;
510
511 DESTROY_IF(best_cert);
512 best_cert = cert;
513 stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
514 DBG1(DBG_CFG, "ocsp response is %s %#T",
515 stale? "stale: since":"valid: until",
516 &nextUpdate, FALSE );
517 if (!stale)
518 {
519 break;
520 }
521 }
522 else
523 {
524 cert->destroy(cert);
525 }
526 }
527 }
528 enumerator->destroy(enumerator);
529 }
530 DESTROY_IF(public);
531
532 /* if we have an ocsp response, check the revocation status */
533 if (best_cert)
534 {
535 time_t revocation, this_update, next_update;
536 crl_reason_t reason;
537 ocsp_response_t *response = (ocsp_response_t*)best_cert;
538
539 valid = response->get_status(response, subject, issuer, &revocation,
540 &reason, &this_update, &next_update);
541 switch (valid)
542 {
543 case VALIDATION_FAILED:
544 DBG1(DBG_CFG, "subject not found in ocsp response");
545 break;
546 case VALIDATION_REVOKED:
547 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
548 &revocation, crl_reason_names, reason);
549 break;
550 case VALIDATION_GOOD:
551 case VALIDATION_UNKNOWN:
552 default:
553 break;
554 }
555 best_cert->destroy(best_cert);
556 }
557
558 if (auth)
559 {
560 auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid);
561 }
562 return valid;
563 }
564
565 /**
566 * fetch a CRL from an URL
567 */
568 static certificate_t* fetch_crl(private_credential_manager_t *this, char *url)
569 {
570 certificate_t *crl_cert;
571 chunk_t chunk;
572
573 /* TODO: unlock the manager while fetching? */
574 DBG1(DBG_CFG, "fetching crl from '%s' ...", url);
575 if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
576 {
577 DBG1(DBG_CFG, "crl fetching failed");
578 return NULL;
579 }
580 crl_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
581 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
582 if (!crl_cert)
583 {
584 DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
585 return NULL;
586 }
587
588 /* verify the signature of the fetched crl */
589 {
590 identification_t *issuer = crl_cert->get_issuer(crl_cert);
591 auth_info_t *auth = auth_info_create();
592 certificate_t *issuer_cert = get_trusted_cert(this, KEY_ANY, issuer,
593 auth, FALSE, FALSE);
594 auth->destroy(auth);
595
596 if (!issuer_cert)
597 {
598 DBG1(DBG_CFG, "crl is untrusted: issuer certificate not found");
599 crl_cert->destroy(crl_cert);
600 return NULL;
601 }
602
603 if (crl_cert->issued_by(crl_cert, issuer_cert, TRUE))
604 {
605 DBG1(DBG_CFG, "crl correctly signed by \"%D\"",
606 issuer_cert->get_subject(issuer_cert));
607 issuer_cert->destroy(issuer_cert);
608 }
609 else
610 {
611 DBG1(DBG_CFG, "crl not issued by \"%D\"",
612 issuer_cert->get_subject(issuer_cert));
613 issuer_cert->destroy(issuer_cert);
614 crl_cert->destroy(crl_cert);
615 return NULL;
616 }
617 }
618 return crl_cert;
619 }
620
621 /**
622 * validate a x509 certificate using CRL
623 */
624 static cert_validation_t check_crl(private_credential_manager_t *this,
625 x509_t *subject, x509_t *issuer,
626 auth_info_t *auth)
627 {
628 identification_t *keyid = NULL;
629 certificate_t *best_cert = NULL;
630 certificate_t *cert;
631 public_key_t *public;
632 cert_validation_t valid = VALIDATION_SKIPPED;
633 bool stale = TRUE;
634
635 /* derive the authorityKeyIdentifier from the issuer's public key */
636 cert = &issuer->interface;
637 public = cert->get_public_key(cert);
638 if (public)
639 {
640 keyid = public->get_id(public, ID_PUBKEY_SHA1);
641 }
642
643 /* find a cached crl by authorityKeyIdentifier */
644 if (keyid)
645 {
646 enumerator_t *enumerator = create_cert_enumerator(this, CERT_X509_CRL,
647 KEY_ANY, keyid, TRUE);
648 certificate_t *cert;
649
650 while (enumerator->enumerate(enumerator, &cert))
651 {
652 /* select most recent crl */
653 if (best_cert == NULL || cert->is_newer(cert, best_cert))
654 {
655 DESTROY_IF(best_cert);
656 best_cert = cert->get_ref(cert);
657 }
658 }
659 enumerator->destroy(enumerator);
660 }
661
662 /* check the validity of the cached crl if one was found */
663 if (best_cert)
664 {
665 time_t nextUpdate;
666
667 stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
668 DBG1(DBG_CFG, "cached crl is %s %#T",
669 stale? "stale: since":"valid: until",
670 &nextUpdate, FALSE );
671 }
672
673 /* fallback to fetching crls from cdps defined in ca info sections */
674 if (stale && keyid)
675 {
676 enumerator_t *enumerator = create_cdp_enumerator(this, CERT_X509_CRL,
677 keyid);
678 char *uri;
679
680 while (enumerator->enumerate(enumerator, &uri))
681 {
682 certificate_t *cert = fetch_crl(this, uri);
683
684 /* redefine default since we have at least one uri */
685 valid = VALIDATION_FAILED;
686
687 if (cert)
688 {
689 /* select most recent crl until valid one is found */
690 if (best_cert == NULL || cert->is_newer(cert, best_cert))
691 {
692 time_t nextUpdate;
693
694 DESTROY_IF(best_cert);
695 best_cert = cert;
696 stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
697 DBG1(DBG_CFG, "fetched crl is %s %#T",
698 stale? "stale: since":"valid: until",
699 &nextUpdate, FALSE );
700 if (!stale)
701 {
702 break;
703 }
704 }
705 else
706 {
707 cert->destroy(cert);
708 }
709 }
710 }
711 enumerator->destroy(enumerator);
712 }
713
714 /* fallback to fetching crls from cdps defined in the subject's certificate */
715 if (stale)
716 {
717 enumerator_t *enumerator = subject->create_crl_uri_enumerator(subject);
718 char *uri;
719
720 while (enumerator->enumerate(enumerator, &uri))
721 {
722 certificate_t *cert = fetch_crl(this, uri);
723
724 /* redefine default since we have at least one uri */
725 valid = VALIDATION_FAILED;
726
727 if (cert)
728 {
729 /* select most recent crl until valid one is found */
730 if (best_cert == NULL || cert->is_newer(cert, best_cert))
731 {
732 time_t nextUpdate;
733
734 DESTROY_IF(best_cert);
735 best_cert = cert;
736 stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
737 DBG1(DBG_CFG, "fetched crl is %s %#T",
738 stale? "stale: since":"valid: until",
739 &nextUpdate, FALSE );
740 if (!stale)
741 {
742 break;
743 }
744 }
745 else
746 {
747 cert->destroy(cert);
748 }
749 }
750 }
751 enumerator->destroy(enumerator);
752 }
753 DESTROY_IF(public);
754
755 /* if we have a crl, check the revocation status */
756 if (best_cert)
757 {
758 chunk_t subject_serial = subject->get_serial(subject);
759 chunk_t serial;
760 time_t revocation;
761 crl_reason_t reason;
762 crl_t *crl = (crl_t*)best_cert;
763 enumerator_t *enumerator = crl->create_enumerator(crl);
764
765 /* redefine default */
766 valid = stale ? VALIDATION_UNKNOWN : VALIDATION_GOOD;
767
768 while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
769 {
770 if (chunk_equals(serial, subject_serial))
771 {
772 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
773 &revocation, crl_reason_names, reason);
774 valid = VALIDATION_REVOKED;
775 break;
776 }
777 }
778 enumerator->destroy(enumerator);
779 best_cert->destroy(best_cert);
780 }
781
782 if (auth)
783 {
784 auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
785 }
786 return valid;
787 }
788
789 /**
790 * check a certificate for its lifetime
791 */
792 static bool check_certificate(private_credential_manager_t *this,
793 certificate_t *subject, certificate_t *issuer,
794 bool crl, bool ocsp, auth_info_t *auth)
795 {
796 time_t not_before, not_after;
797
798 if (!subject->get_validity(subject, NULL, &not_before, &not_after))
799 {
800 DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
801 &not_before, &not_after);
802 return FALSE;
803 }
804 if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
805 {
806 DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
807 &not_before, &not_after);
808 return FALSE;
809 }
810 if (issuer->get_type(issuer) == CERT_X509 &&
811 subject->get_type(subject) == CERT_X509)
812 {
813 if (ocsp)
814 {
815 switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth))
816 {
817 case VALIDATION_GOOD:
818 DBG1(DBG_CFG, "certificate status is good");
819 return TRUE;
820 case VALIDATION_REVOKED:
821 /* has already been logged */
822 return FALSE;
823 case VALIDATION_SKIPPED:
824 DBG2(DBG_CFG, "OCSP check skipped, no OCSP URI found");
825 break;
826 case VALIDATION_FAILED:
827 case VALIDATION_UNKNOWN:
828 DBG1(DBG_CFG, "OCSP check failed, fallback to CRL");
829 break;
830 }
831 }
832 if (crl)
833 {
834 switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth))
835 {
836 case VALIDATION_GOOD:
837 DBG1(DBG_CFG, "certificate status is good");
838 return TRUE;
839 case VALIDATION_REVOKED:
840 /* has already been logged */
841 return FALSE;
842 case VALIDATION_UNKNOWN:
843 DBG1(DBG_CFG, "certificate status is unknown");
844 break;
845 case VALIDATION_FAILED:
846 case VALIDATION_SKIPPED:
847 DBG1(DBG_CFG, "certificate status is not available");
848 break;
849 default:
850 break;
851 }
852 }
853 }
854 return TRUE;
855 }
856
857 /**
858 * Get a trusted certificate from a credential set
859 */
860 static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
861 key_type_t type, identification_t *id)
862 {
863 certificate_t *subject;
864 public_key_t *public;
865
866 subject = get_cert(this, CERT_ANY, type, id, TRUE);
867 if (!subject)
868 {
869 return NULL;
870 }
871 public = subject->get_public_key(subject);
872 if (!public)
873 {
874 subject->destroy(subject);
875 return NULL;
876 }
877 public->destroy(public);
878 return subject;
879 }
880
881 /**
882 * try to build the next link in the trustchain, either to a root CA (trusted)
883 * or to an intermediate CA.
884 */
885 static auth_info_t *verify_trustchain(private_credential_manager_t *this,
886 certificate_t **issuerp, bool crl,
887 bool ocsp, bool peer, bool trusted)
888 {
889 enumerator_t *enumerator;
890 certificate_t *candidate, *issuer;
891 auth_info_t *auth = NULL;
892
893 issuer = *issuerp;
894 enumerator = create_cert_enumerator(this, issuer->get_type(issuer), KEY_ANY,
895 issuer->get_issuer(issuer), trusted);
896 while (enumerator->enumerate(enumerator, &candidate))
897 {
898 if (!issuer->issued_by(issuer, candidate, TRUE))
899 {
900 continue;
901 }
902 auth = auth_info_create();
903 if (check_certificate(this, issuer, candidate, crl, ocsp,
904 peer ? auth : NULL))
905 {
906 issuer->destroy(issuer);
907 *issuerp = candidate->get_ref(candidate);
908 break;
909 }
910 auth->destroy(auth);
911 auth = NULL;
912 break;
913 }
914 enumerator->destroy(enumerator);
915 return auth;
916 }
917
918 /**
919 * Get a trusted certificate by verifying the trustchain
920 */
921 static certificate_t *get_trusted_cert(private_credential_manager_t *this,
922 key_type_t type, identification_t *id,
923 auth_info_t *auth, bool crl, bool ocsp)
924 {
925 certificate_t *subject, *issuer;
926 bool peer = TRUE, trusted = FALSE;
927 auth_info_t *auth1, *auth2;
928 u_int level = 0;
929
930 /* check if we have a trusted certificate for that peer */
931 subject = get_pretrusted_cert(this, type, id);
932 if (subject)
933 { /* if we find a trusted certificate, we accept it. However, to
934 * fullfill authorization rules, we try build the trustchain anyway. */
935 trusted = TRUE;
936 }
937 else
938 { /* check for an untrusted peer certificate */
939 subject = get_cert(this, CERT_ANY, type, id, FALSE);
940 }
941 if (!subject)
942 {
943 DBG1(DBG_CFG, "no certificate found for '%D'", id);
944 return NULL;
945 }
946 DBG1(DBG_CFG, " using end entity certificate \"%D\"",
947 subject->get_subject(subject));
948 auth1 = auth_info_create();
949 auth->add_item(auth, AUTHZ_SUBJECT_CERT, subject);
950 issuer = subject->get_ref(subject);
951 while (level++ < MAX_CA_LEVELS)
952 {
953 /* look for a trusted CA certificate */
954 auth2 = verify_trustchain(this, &issuer, crl, ocsp, peer, TRUE);
955 if (auth2)
956 {
957 DBG1(DBG_CFG, " using trusted root CA certificate \"%D\"",
958 issuer->get_subject(issuer));
959 auth1->merge(auth1, auth2);
960 auth2->destroy(auth2);
961 auth1->add_item(auth1, AUTHZ_CA_CERT, issuer);
962 trusted = TRUE;
963 break;
964 }
965 /* check for a untrusted intermediate CA */
966 auth2 = verify_trustchain(this, &issuer, crl, ocsp, peer, FALSE);
967 if (auth2)
968 {
969 DBG1(DBG_CFG, " using intermediate CA certificate \"%D\"",
970 issuer->get_subject(issuer));
971 auth1->merge(auth1, auth2);
972 auth2->destroy(auth2);
973 auth1->add_item(auth1, AUTHZ_IM_CERT, issuer);
974 peer = FALSE;
975 continue;
976 }
977 break;
978 }
979 issuer->destroy(issuer);
980 if (trusted)
981 {
982 auth->add_item(auth, AUTHZ_SUBJECT_CERT, subject);
983 auth->merge(auth, auth1);
984 }
985 else
986 {
987 subject->destroy(subject);
988 subject = NULL;
989 }
990 auth1->destroy(auth1);
991 return subject;
992 }
993
994 /**
995 * Implementation of credential_manager_t.get_public.
996 */
997 static public_key_t *get_public(private_credential_manager_t *this,
998 key_type_t type, identification_t *id,
999 auth_info_t *auth)
1000 {
1001 public_key_t *public = NULL;
1002 certificate_t *cert;
1003 auth_info_wrapper_t *wrapper;
1004
1005 wrapper = auth_info_wrapper_create(auth);
1006 this->mutex->lock(this->mutex);
1007 this->sets->insert_first(this->sets, wrapper);
1008
1009 cert = get_trusted_cert(this, type, id, auth, TRUE, TRUE);
1010 if (cert)
1011 {
1012 public = cert->get_public_key(cert);
1013 cert->destroy(cert);
1014 }
1015
1016 this->sets->remove(this->sets, wrapper, NULL);
1017 wrapper->destroy(wrapper);
1018 this->mutex->unlock(this->mutex);
1019 return public;
1020 }
1021
1022 /**
1023 * Get the issuing certificate of a subject certificate
1024 */
1025 static certificate_t *get_issuer_cert(private_credential_manager_t *this,
1026 certificate_t *subject)
1027 {
1028 enumerator_t *enumerator;
1029 certificate_t *issuer = NULL, *candidate;
1030
1031 enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
1032 subject->get_issuer(subject), FALSE);
1033 while (enumerator->enumerate(enumerator, &candidate))
1034 {
1035 if (subject->issued_by(subject, candidate, FALSE))
1036 {
1037 issuer = candidate->get_ref(candidate);
1038 break;
1039 }
1040 }
1041 enumerator->destroy(enumerator);
1042 return issuer;
1043 }
1044
1045 /**
1046 * Check if a certificate's keyid is contained in the auth helper
1047 */
1048 static bool auth_contains_cacert(auth_info_t *auth, certificate_t *cert)
1049 {
1050 enumerator_t *enumerator;
1051 identification_t *value;
1052 auth_item_t type;
1053 bool found = FALSE;
1054
1055 enumerator = auth->create_item_enumerator(auth);
1056 while (enumerator->enumerate(enumerator, &type, &value))
1057 {
1058 if (type == AUTHN_CA_CERT && cert->equals(cert, (certificate_t*)value))
1059 {
1060 found = TRUE;
1061 break;
1062 }
1063 }
1064 enumerator->destroy(enumerator);
1065 return found;
1066 }
1067
1068 /**
1069 * build a trustchain from subject up to a trust anchor in trusted
1070 */
1071 static auth_info_t *build_trustchain(private_credential_manager_t *this,
1072 certificate_t *subject, auth_info_t *auth)
1073 {
1074 certificate_t *issuer, *current;
1075 auth_info_t *trustchain;
1076 u_int level = 0;
1077
1078 trustchain = auth_info_create();
1079
1080 if (!auth->get_item(auth, AUTHN_CA_CERT, (void**)&current))
1081 {
1082 /* no trust anchor specified, return this cert only */
1083 trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, subject);
1084 return trustchain;
1085 }
1086
1087 current = subject->get_ref(subject);
1088 while (TRUE)
1089 {
1090 if (auth_contains_cacert(auth, current))
1091 {
1092 trustchain->add_item(trustchain, AUTHZ_CA_CERT, current);
1093 current->destroy(current);
1094 return trustchain;
1095 }
1096 if (subject == current)
1097 {
1098 trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, current);
1099 }
1100 else
1101 {
1102 trustchain->add_item(trustchain, AUTHZ_IM_CERT, current);
1103 }
1104 issuer = get_issuer_cert(this, current);
1105 if (!issuer || issuer->equals(issuer, current) || level > MAX_CA_LEVELS)
1106 {
1107 DESTROY_IF(issuer);
1108 current->destroy(current);
1109 break;
1110 }
1111 current->destroy(current);
1112 current = issuer;
1113 level++;
1114 }
1115 trustchain->destroy(trustchain);
1116 return NULL;
1117 }
1118
1119 /**
1120 * find a private key of a give certificate
1121 */
1122 static private_key_t *get_private_by_cert(private_credential_manager_t *this,
1123 certificate_t *cert, key_type_t type)
1124 {
1125 private_key_t *private = NULL;
1126 identification_t* keyid;
1127 public_key_t *public;
1128
1129 public = cert->get_public_key(cert);
1130 if (public)
1131 {
1132 keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
1133 if (keyid)
1134 {
1135 private = get_private_by_keyid(this, type, keyid);
1136 }
1137 public->destroy(public);
1138 }
1139 return private;
1140 }
1141
1142 /**
1143 * Implementation of credential_manager_t.get_private.
1144 */
1145 static private_key_t *get_private(private_credential_manager_t *this,
1146 key_type_t type, identification_t *id,
1147 auth_info_t *auth)
1148 {
1149 enumerator_t *enumerator;
1150 certificate_t *cert;
1151 private_key_t *private = NULL;
1152 auth_info_t *trustchain;
1153
1154 /* check if this is a lookup by key ID, and do it if so */
1155 if (id)
1156 {
1157 switch (id->get_type(id))
1158 {
1159 case ID_PUBKEY_SHA1:
1160 case ID_PUBKEY_INFO_SHA1:
1161 return get_private_by_keyid(this, type, id);
1162 default:
1163 break;
1164 }
1165 }
1166
1167 this->mutex->lock(this->mutex);
1168 /* get all available end entity certificates for ourself */
1169 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1170 while (enumerator->enumerate(enumerator, &cert))
1171 {
1172 private = get_private_by_cert(this, cert, type);
1173 if (private)
1174 {
1175 trustchain = build_trustchain(this, cert, auth);
1176 if (trustchain)
1177 {
1178 auth->merge(auth, trustchain);
1179 trustchain->destroy(trustchain);
1180 break;
1181 }
1182 private->destroy(private);
1183 }
1184 }
1185 enumerator->destroy(enumerator);
1186 this->mutex->unlock(this->mutex);
1187 return private;
1188 }
1189
1190 /**
1191 * Implementation of credential_manager_t.add_set.
1192 */
1193 static void add_set(private_credential_manager_t *this,
1194 credential_set_t *set)
1195 {
1196 this->mutex->lock(this->mutex);
1197 this->sets->insert_last(this->sets, set);
1198 this->mutex->unlock(this->mutex);
1199 }
1200 /**
1201 * Implementation of credential_manager_t.remove_set.
1202 */
1203 static void remove_set(private_credential_manager_t *this, credential_set_t *set)
1204 {
1205 this->mutex->lock(this->mutex);
1206 this->sets->remove(this->sets, set, NULL);
1207 this->mutex->unlock(this->mutex);
1208 }
1209
1210 /**
1211 * Implementation of credential_manager_t.destroy
1212 */
1213 static void destroy(private_credential_manager_t *this)
1214 {
1215 this->sets->destroy(this->sets);
1216 this->mutex->destroy(this->mutex);
1217 free(this);
1218 }
1219
1220 /*
1221 * see header file
1222 */
1223 credential_manager_t *credential_manager_create()
1224 {
1225 private_credential_manager_t *this = malloc_thing(private_credential_manager_t);
1226
1227 this->public.create_cert_enumerator = (enumerator_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *id,bool))create_cert_enumerator;
1228 this->public.create_shared_enumerator = (enumerator_t *(*)(credential_manager_t *this, shared_key_type_t type,identification_t *me, identification_t *other))create_shared_enumerator;
1229 this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, credential_type_t type, identification_t *id))create_cdp_enumerator;
1230 this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert;
1231 this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared;
1232 this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_info_t*))get_private;
1233 this->public.get_public = (public_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_info_t*))get_public;
1234 this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set;
1235 this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set;
1236 this->public.destroy = (void(*)(credential_manager_t*))destroy;
1237
1238 this->sets = linked_list_create();
1239 this->mutex = mutex_create(MUTEX_RECURSIVE);
1240
1241 return &this->public;
1242 }
1243