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