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