ac97f73a499d0b23bd8dd6d404f364f123e635c7
[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->remove(this->sets, this->cache, NULL);
370 this->sets->insert_first(this->sets, wrapper);
371 this->sets->insert_first(this->sets, this->cache);
372
373 subject = &response->certificate;
374 responder = subject->get_issuer(subject);
375 enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE, FALSE);
376 while (enumerator->enumerate(enumerator, &issuer, NULL))
377 {
378 if (this->cache->issued_by(this->cache, subject, issuer))
379 {
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", &valid_until);
441 *valid = VALIDATION_GOOD;
442 }
443 else
444 {
445 DBG1(DBG_CFG, " ocsp response is stale: since %#T", &valid_until);
446 *valid = VALIDATION_STALE;
447 }
448 }
449 else
450 {
451 *valid = VALIDATION_STALE;
452 cand->destroy(cand);
453 }
454 return best;
455 }
456
457 /**
458 * validate a x509 certificate using OCSP
459 */
460 static cert_validation_t check_ocsp(private_credential_manager_t *this,
461 x509_t *subject, x509_t *issuer,
462 auth_info_t *auth)
463 {
464 enumerator_t *enumerator;
465 cert_validation_t valid = VALIDATION_SKIPPED;
466 certificate_t *best = NULL, *current;
467 identification_t *keyid = NULL;
468 public_key_t *public;
469 char *uri = NULL;
470
471 /** lookup cache for valid OCSP responses */
472 enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE,
473 KEY_ANY, NULL, FALSE);
474 while (enumerator->enumerate(enumerator, &current))
475 {
476 current->get_ref(current);
477 best = get_better_ocsp(this, current, best, subject, issuer, &valid);
478 if (best && valid != VALIDATION_STALE)
479 {
480 DBG1(DBG_CFG, "found cached ocsp response");
481 break;
482 }
483 }
484 enumerator->destroy(enumerator);
485
486 /* derive the authorityKeyIdentifier from the issuer's public key */
487 current = &issuer->interface;
488 public = current->get_public_key(current);
489 if (public)
490 {
491 keyid = public->get_id(public, ID_PUBKEY_SHA1);
492 }
493 /** fetch from configured OCSP responder URLs */
494 if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
495 {
496 enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid);
497 while (enumerator->enumerate(enumerator, &uri))
498 {
499 current = fetch_ocsp(this, uri, &subject->interface,
500 &issuer->interface);
501 if (current)
502 {
503 best = get_better_ocsp(this, current, best, subject, issuer, &valid);
504 if (best && valid != VALIDATION_STALE)
505 {
506 break;
507 }
508 }
509 }
510 enumerator->destroy(enumerator);
511 }
512 DESTROY_IF(public);
513
514 /* fallback to URL fetching from subject certificate's URIs */
515 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
516 {
517 enumerator = subject->create_ocsp_uri_enumerator(subject);
518 while (enumerator->enumerate(enumerator, &uri))
519 {
520 current = fetch_ocsp(this, uri, &subject->interface,
521 &issuer->interface);
522 if (current)
523 {
524 best = get_better_ocsp(this, current, best, subject, issuer, &valid);
525 if (best && valid != VALIDATION_STALE)
526 {
527 break;
528 }
529 }
530 }
531 enumerator->destroy(enumerator);
532 }
533 /* an uri was found, but no result. switch validation state to failed */
534 if (valid == VALIDATION_SKIPPED && uri)
535 {
536 valid = VALIDATION_FAILED;
537 }
538 if (auth)
539 {
540 auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid);
541 }
542 DESTROY_IF(best);
543 return valid;
544 }
545
546 /**
547 * fetch a CRL from an URL
548 */
549 static certificate_t* fetch_crl(private_credential_manager_t *this, char *url)
550 {
551 certificate_t *crl;
552 chunk_t chunk;
553
554 /* TODO: unlock the manager while fetching? */
555 DBG1(DBG_CFG, "fetching crl from '%s' ...", url);
556 if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
557 {
558 DBG1(DBG_CFG, "crl fetching failed");
559 return NULL;
560 }
561 crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
562 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
563 if (!crl)
564 {
565 DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
566 return NULL;
567 }
568 return crl;
569 }
570
571 /**
572 * check the signature of an CRL
573 */
574 static bool verify_crl(private_credential_manager_t *this, certificate_t *crl)
575 {
576 certificate_t *issuer;
577 enumerator_t *enumerator;
578 bool verified = FALSE;
579
580 enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl),
581 FALSE, FALSE);
582 while (enumerator->enumerate(enumerator, &issuer, NULL))
583 {
584 if (this->cache->issued_by(this->cache, crl, issuer))
585 {
586 DBG1(DBG_CFG, " crl correctly signed by \"%D\"",
587 issuer->get_subject(issuer));
588 verified = TRUE;
589 break;
590 }
591 }
592 enumerator->destroy(enumerator);
593
594 return verified;
595 }
596
597 /**
598 * Get the better of two CRLs, and check for usable CRL info
599 */
600 static certificate_t *get_better_crl(private_credential_manager_t *this,
601 certificate_t *cand, certificate_t *best,
602 x509_t *subject, x509_t *issuer,
603 cert_validation_t *valid)
604 {
605 enumerator_t *enumerator;
606 time_t revocation, valid_until;
607 crl_reason_t reason;
608 chunk_t serial;
609 crl_t *crl;
610
611 /* check CRL signature */
612 if (!verify_crl(this, cand))
613 {
614 DBG1(DBG_CFG, "crl response verification failed");
615 cand->destroy(cand);
616 return best;
617 }
618
619 crl = (crl_t*)cand;
620 enumerator = crl->create_enumerator(crl);
621 while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
622 {
623 if (chunk_equals(serial, subject->get_serial(subject)))
624 {
625 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
626 &revocation, crl_reason_names, reason);
627 *valid = VALIDATION_REVOKED;
628 enumerator->destroy(enumerator);
629 DESTROY_IF(best);
630 return cand;
631 }
632 }
633 enumerator->destroy(enumerator);
634
635 /* select the better of the two CRLs */
636 if (best == NULL || cand->is_newer(cand, best))
637 {
638 DESTROY_IF(best);
639 best = cand;
640 if (best->get_validity(best, NULL, NULL, &valid_until))
641 {
642 DBG1(DBG_CFG, " crl is valid: until %#T", &valid_until);
643 *valid = VALIDATION_GOOD;
644 }
645 else
646 {
647 DBG1(DBG_CFG, " crl is stale: since %#T", &valid_until);
648 *valid = VALIDATION_STALE;
649 }
650 }
651 else
652 {
653 *valid = VALIDATION_STALE;
654 cand->destroy(cand);
655 }
656 return best;
657 }
658
659 /**
660 * validate a x509 certificate using CRL
661 */
662 static cert_validation_t check_crl(private_credential_manager_t *this,
663 x509_t *subject, x509_t *issuer,
664 auth_info_t *auth)
665 {
666 cert_validation_t valid = VALIDATION_SKIPPED;
667 identification_t *keyid = NULL;
668 certificate_t *best = NULL;
669 certificate_t *current;
670 public_key_t *public;
671 enumerator_t *enumerator;
672 char *uri;
673
674 /* derive the authorityKeyIdentifier from the issuer's public key */
675 current = &issuer->interface;
676 public = current->get_public_key(current);
677 if (public)
678 {
679 keyid = public->get_id(public, ID_PUBKEY_SHA1);
680 }
681
682 /* find a cached crl by authorityKeyIdentifier */
683 if (keyid)
684 {
685 enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY,
686 keyid, FALSE);
687 while (enumerator->enumerate(enumerator, &current))
688 {
689 current->get_ref(current);
690 best = get_better_crl(this, current, best, subject, issuer, &valid);
691 if (best && valid != VALIDATION_STALE)
692 {
693 DBG1(DBG_CFG, "found cached crl");
694 break;
695 }
696 }
697 enumerator->destroy(enumerator);
698 }
699
700 /* fallback to fetching crls from credential sets cdps */
701 if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
702 {
703 enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid);
704
705 while (enumerator->enumerate(enumerator, &uri))
706 {
707 current = fetch_crl(this, uri);
708 if (current)
709 {
710 best = get_better_crl(this, current, best, subject, issuer, &valid);
711 if (best && valid != VALIDATION_STALE)
712 {
713 break;
714 }
715 }
716 }
717 enumerator->destroy(enumerator);
718 }
719 DESTROY_IF(public);
720
721 /* fallback to fetching crls from cdps from subject's certificate */
722 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
723 {
724 enumerator = subject->create_crl_uri_enumerator(subject);
725
726 while (enumerator->enumerate(enumerator, &uri))
727 {
728 current = fetch_crl(this, uri);
729 if (current)
730 {
731 best = get_better_crl(this, current, best, subject, issuer, &valid);
732 if (best && valid != VALIDATION_STALE)
733 {
734 break;
735 }
736 }
737 }
738 enumerator->destroy(enumerator);
739 }
740
741 /* an uri was found, but no result. switch validation state to failed */
742 if (valid == VALIDATION_SKIPPED && uri)
743 {
744 valid = VALIDATION_FAILED;
745 }
746 if (auth)
747 {
748 auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
749 }
750 DESTROY_IF(best);
751 return valid;
752 }
753
754 /**
755 * check a certificate for its lifetime
756 */
757 static bool check_certificate(private_credential_manager_t *this,
758 certificate_t *subject, certificate_t *issuer,
759 bool crl, bool ocsp, auth_info_t *auth)
760 {
761 time_t not_before, not_after;
762
763 if (!subject->get_validity(subject, NULL, &not_before, &not_after))
764 {
765 DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
766 &not_before, &not_after);
767 return FALSE;
768 }
769 if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
770 {
771 DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
772 &not_before, &not_after);
773 return FALSE;
774 }
775 if (issuer->get_type(issuer) == CERT_X509 &&
776 subject->get_type(subject) == CERT_X509)
777 {
778 if (ocsp)
779 {
780 switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth))
781 {
782 case VALIDATION_GOOD:
783 DBG1(DBG_CFG, "certificate status is good");
784 return TRUE;
785 case VALIDATION_REVOKED:
786 /* has already been logged */
787 return FALSE;
788 case VALIDATION_SKIPPED:
789 DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
790 break;
791 case VALIDATION_STALE:
792 DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
793 break;
794 case VALIDATION_FAILED:
795 DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
796 break;
797 }
798 }
799 if (crl)
800 {
801 switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth))
802 {
803 case VALIDATION_GOOD:
804 DBG1(DBG_CFG, "certificate status is good");
805 return TRUE;
806 case VALIDATION_REVOKED:
807 /* has already been logged */
808 return FALSE;
809 case VALIDATION_FAILED:
810 case VALIDATION_SKIPPED:
811 DBG1(DBG_CFG, "certificate status is not available");
812 break;
813 case VALIDATION_STALE:
814 DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
815 break;
816 }
817 }
818 }
819 return TRUE;
820 }
821
822 /**
823 * Get a trusted certificate from a credential set
824 */
825 static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
826 key_type_t type, identification_t *id)
827 {
828 certificate_t *subject;
829 public_key_t *public;
830
831 subject = get_cert(this, CERT_ANY, type, id, TRUE);
832 if (!subject)
833 {
834 return NULL;
835 }
836 public = subject->get_public_key(subject);
837 if (!public)
838 {
839 subject->destroy(subject);
840 return NULL;
841 }
842 public->destroy(public);
843 return subject;
844 }
845
846 /**
847 * Get the issuing certificate of a subject certificate
848 */
849 static certificate_t *get_issuer_cert(private_credential_manager_t *this,
850 certificate_t *subject, bool trusted)
851 {
852 enumerator_t *enumerator;
853 certificate_t *issuer = NULL, *candidate;
854
855 enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
856 subject->get_issuer(subject), trusted);
857 while (enumerator->enumerate(enumerator, &candidate))
858 {
859 if (this->cache->issued_by(this->cache, subject, candidate))
860 {
861 issuer = candidate->get_ref(candidate);
862 break;
863 }
864 }
865 enumerator->destroy(enumerator);
866 return issuer;
867 }
868
869 /**
870 * try to verify the trust chain of subject, return TRUE if trusted
871 */
872 static bool verify_trust_chain(private_credential_manager_t *this,
873 certificate_t *subject, auth_info_t *result,
874 bool trusted, bool crl, bool ocsp)
875 {
876 certificate_t *current, *issuer;
877 auth_info_t *auth;
878 u_int level = 0;
879
880 auth = auth_info_create();
881 current = subject->get_ref(subject);
882 while (level++ < MAX_CA_LEVELS)
883 {
884 issuer = get_issuer_cert(this, current, TRUE);
885 if (issuer)
886 {
887 /* accept only self-signed CAs as trust anchor */
888 if (this->cache->issued_by(this->cache, issuer, issuer))
889 {
890 auth->add_item(auth, AUTHZ_CA_CERT, issuer);
891 DBG1(DBG_CFG, " using trusted ca certificate \"%D\"",
892 issuer->get_subject(issuer));
893 trusted = TRUE;
894 }
895 else
896 {
897 auth->add_item(auth, AUTHZ_IM_CERT, issuer);
898 DBG1(DBG_CFG, " using trusted intermediate ca certificate "
899 "\"%D\"", issuer->get_subject(issuer));
900 }
901 }
902 else
903 {
904 issuer = get_issuer_cert(this, current, FALSE);
905 if (issuer)
906 {
907 if (current->equals(current, issuer))
908 {
909 DBG1(DBG_CFG, " self-signed certificate \"%D\" is not trusted",
910 current->get_subject(current));
911 issuer->destroy(issuer);
912 break;
913 }
914 auth->add_item(auth, AUTHZ_IM_CERT, issuer);
915 DBG1(DBG_CFG, " using untrusted intermediate certificate "
916 "\"%D\"", issuer->get_subject(issuer));
917 }
918 else
919 {
920 DBG1(DBG_CFG, "no issuer certificate found for \"%D\"",
921 issuer->get_subject(issuer));
922 current->destroy(current);
923 break;
924 }
925 }
926 if (!check_certificate(this, current, issuer, crl, ocsp,
927 current == subject ? auth : NULL))
928 {
929 trusted = FALSE;
930 issuer->destroy(issuer);
931 break;
932 }
933 current->destroy(current);
934 current = issuer;
935 if (trusted)
936 {
937 break;
938 }
939 }
940 current->destroy(current);
941 if (trusted)
942 {
943 result->merge(result, auth);
944 }
945 auth->destroy(auth);
946 return trusted;
947 }
948
949 /**
950 * enumerator for trusted certificates
951 */
952 typedef struct {
953 /** implements enumerator_t interface */
954 enumerator_t public;
955 /** enumerator over candidate peer certificates */
956 enumerator_t *candidates;
957 /** reference to the credential_manager */
958 private_credential_manager_t *this;
959 /** type of the requested key */
960 key_type_t type;
961 /** identity the requested key belongs to */
962 identification_t *id;
963 /** TRUE to do CRL checking */
964 bool crl;
965 /** TRUE to do OCSP checking */
966 bool ocsp;
967 /** currently enumerating certificate */
968 certificate_t *current;
969 /** currently enumerating auth info */
970 auth_info_t *auth;
971 } trusted_enumerator_t;
972
973 /**
974 * Implements trusted_enumerator_t.enumerate
975 */
976 static bool trusted_enumerate(trusted_enumerator_t *this,
977 certificate_t **cert, auth_info_t **auth)
978 {
979 DESTROY_IF(this->current);
980 DESTROY_IF(this->auth);
981 this->auth = auth_info_create();
982
983 if (!this->candidates)
984 {
985 /* first invocation, build enumerator for next one */
986 this->candidates = create_cert_enumerator(this->this, CERT_ANY,
987 this->type, this->id, FALSE);
988 /* check if we have a trusted certificate for that peer */
989 this->current = get_pretrusted_cert(this->this, this->type, this->id);
990 if (this->current)
991 {
992 /* if we find a trusted self signed certificate, we just accept it.
993 * However, in order to fulfill authorization rules, we try to build
994 * the trust chain if it is not self signed */
995 if (this->this->cache->issued_by(this->this->cache,
996 this->current, this->current) ||
997 verify_trust_chain(this->this, this->current, this->auth,
998 TRUE, this->crl, this->ocsp))
999 {
1000 DBG1(DBG_CFG, " using trusted certificate \"%D\"",
1001 this->current->get_subject(this->current));
1002 *cert = this->current;
1003 if (auth)
1004 {
1005 *auth = this->auth;
1006 }
1007 return TRUE;
1008 }
1009 return FALSE;
1010 }
1011 }
1012 /* try to verify the trust chain for each certificate found */
1013 while (this->candidates->enumerate(this->candidates, &this->current))
1014 {
1015 DBG1(DBG_CFG, " using certificate \"%D\"",
1016 this->current->get_subject(this->current));
1017 if (verify_trust_chain(this->this, this->current, this->auth, FALSE,
1018 this->crl, this->ocsp))
1019 {
1020 *cert = this->current->get_ref(this->current);
1021 if (auth)
1022 {
1023 *auth = this->auth;
1024 }
1025 return TRUE;
1026 }
1027 }
1028 return FALSE;
1029 }
1030
1031 /**
1032 * Implements trusted_enumerator_t.destroy
1033 */
1034 static void trusted_destroy(trusted_enumerator_t *this)
1035 {
1036 DESTROY_IF(this->current);
1037 DESTROY_IF(this->auth);
1038 DESTROY_IF(this->candidates);
1039 free(this);
1040 }
1041
1042 /**
1043 * create an enumerator over trusted certificates and their trustchain
1044 */
1045 static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
1046 key_type_t type, identification_t *id, bool crl, bool ocsp)
1047 {
1048 trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t);
1049
1050 enumerator->public.enumerate = (void*)trusted_enumerate;
1051 enumerator->public.destroy = (void*)trusted_destroy;
1052
1053 enumerator->candidates = NULL;
1054 enumerator->this = this;
1055 enumerator->type = type;
1056 enumerator->id = id;
1057 enumerator->crl = crl;
1058 enumerator->ocsp = ocsp;
1059 enumerator->current = NULL;
1060 enumerator->auth = NULL;
1061
1062 return &enumerator->public;
1063 }
1064
1065 /**
1066 * enumerator for public keys
1067 */
1068 typedef struct {
1069 /** implements enumerator_t interface */
1070 enumerator_t public;
1071 /** enumerator over candidate peer certificates */
1072 enumerator_t *inner;
1073 /** reference to the credential_manager */
1074 private_credential_manager_t *this;
1075 /** currently enumerating key */
1076 public_key_t *current;
1077 /** credset wrapper around auth */
1078 auth_info_wrapper_t *wrapper;
1079 } public_enumerator_t;
1080
1081 /**
1082 * Implements public_enumerator_t.enumerate
1083 */
1084 static bool public_enumerate(public_enumerator_t *this,
1085 public_key_t **key, auth_info_t **auth)
1086 {
1087 certificate_t *cert;
1088
1089 while (this->inner->enumerate(this->inner, &cert, auth))
1090 {
1091 DESTROY_IF(this->current);
1092 this->current = cert->get_public_key(cert);
1093 if (this->current)
1094 {
1095 *key = this->current;
1096 return TRUE;
1097 }
1098 }
1099 return FALSE;
1100 }
1101
1102 /**
1103 * Implements public_enumerator_t.destroy
1104 */
1105 static void public_destroy(public_enumerator_t *this)
1106 {
1107 if (this->wrapper)
1108 {
1109 this->this->sets->remove(this->this->sets, this->wrapper, NULL);
1110 this->this->mutex->unlock(this->this->mutex);
1111 this->wrapper->destroy(this->wrapper);
1112 }
1113 DESTROY_IF(this->current);
1114 this->inner->destroy(this->inner);
1115 free(this);
1116 }
1117
1118 /**
1119 * Implementation of credential_manager_t.create_public_enumerator.
1120 */
1121 static enumerator_t* create_public_enumerator(private_credential_manager_t *this,
1122 key_type_t type, identification_t *id, auth_info_t *auth)
1123 {
1124 public_enumerator_t *enumerator = malloc_thing(public_enumerator_t);
1125
1126 enumerator->public.enumerate = (void*)public_enumerate;
1127 enumerator->public.destroy = (void*)public_destroy;
1128 enumerator->inner = create_trusted_enumerator(this, type, id, TRUE, TRUE);
1129 enumerator->this = this;
1130 enumerator->current = NULL;
1131 enumerator->wrapper = NULL;
1132 this->mutex->lock(this->mutex);
1133 if (auth)
1134 {
1135 enumerator->wrapper = auth_info_wrapper_create(auth);
1136 this->sets->remove(this->sets, this->cache, NULL);
1137 this->sets->insert_first(this->sets, enumerator->wrapper);
1138 this->sets->insert_first(this->sets, this->cache);
1139 }
1140 return &enumerator->public;
1141 }
1142
1143 /**
1144 * Check if a certificate's keyid is contained in the auth helper
1145 */
1146 static bool auth_contains_cacert(auth_info_t *auth, certificate_t *cert)
1147 {
1148 enumerator_t *enumerator;
1149 identification_t *value;
1150 auth_item_t type;
1151 bool found = FALSE;
1152
1153 enumerator = auth->create_item_enumerator(auth);
1154 while (enumerator->enumerate(enumerator, &type, &value))
1155 {
1156 if (type == AUTHN_CA_CERT && cert->equals(cert, (certificate_t*)value))
1157 {
1158 found = TRUE;
1159 break;
1160 }
1161 if (type == AUTHN_CA_CERT_KEYID)
1162 {
1163 public_key_t *public;
1164 identification_t *certid, *keyid;
1165
1166 public = cert->get_public_key(cert);
1167 if (public)
1168 {
1169 keyid = (identification_t*)value;
1170 certid = public->get_id(public, keyid->get_type(keyid));
1171 if (certid && certid->equals(certid, keyid))
1172 {
1173 public->destroy(public);
1174 found = TRUE;
1175 break;
1176 }
1177 public->destroy(public);
1178 }
1179 }
1180 }
1181 enumerator->destroy(enumerator);
1182 return found;
1183 }
1184
1185 /**
1186 * build a trustchain from subject up to a trust anchor in trusted
1187 */
1188 static auth_info_t *build_trustchain(private_credential_manager_t *this,
1189 certificate_t *subject, auth_info_t *auth)
1190 {
1191 certificate_t *issuer, *current;
1192 auth_info_t *trustchain;
1193 u_int level = 0;
1194
1195 trustchain = auth_info_create();
1196
1197 if (!auth->get_item(auth, AUTHN_CA_CERT, (void**)&current))
1198 {
1199 /* no trust anchor specified, return this cert only */
1200 trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, subject);
1201 return trustchain;
1202 }
1203 current = subject->get_ref(subject);
1204 while (TRUE)
1205 {
1206 if (auth_contains_cacert(auth, current))
1207 {
1208 trustchain->add_item(trustchain, AUTHZ_CA_CERT, current);
1209 current->destroy(current);
1210 return trustchain;
1211 }
1212 if (subject == current)
1213 {
1214 trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, current);
1215 }
1216 else
1217 {
1218 trustchain->add_item(trustchain, AUTHZ_IM_CERT, current);
1219 }
1220 issuer = get_issuer_cert(this, current, FALSE);
1221 if (!issuer || issuer->equals(issuer, current) || level > MAX_CA_LEVELS)
1222 {
1223 DESTROY_IF(issuer);
1224 current->destroy(current);
1225 break;
1226 }
1227 current->destroy(current);
1228 current = issuer;
1229 level++;
1230 }
1231 trustchain->destroy(trustchain);
1232 return NULL;
1233 }
1234
1235 /**
1236 * find a private key of a give certificate
1237 */
1238 static private_key_t *get_private_by_cert(private_credential_manager_t *this,
1239 certificate_t *cert, key_type_t type)
1240 {
1241 private_key_t *private = NULL;
1242 identification_t* keyid;
1243 public_key_t *public;
1244
1245 public = cert->get_public_key(cert);
1246 if (public)
1247 {
1248 keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
1249 if (keyid)
1250 {
1251 private = get_private_by_keyid(this, type, keyid);
1252 }
1253 public->destroy(public);
1254 }
1255 return private;
1256 }
1257
1258 /**
1259 * Implementation of credential_manager_t.get_private.
1260 */
1261 static private_key_t *get_private(private_credential_manager_t *this,
1262 key_type_t type, identification_t *id,
1263 auth_info_t *auth)
1264 {
1265 enumerator_t *enumerator;
1266 certificate_t *cert;
1267 private_key_t *private = NULL;
1268 auth_info_t *trustchain;
1269
1270 /* check if this is a lookup by key ID, and do it if so */
1271 if (id)
1272 {
1273 switch (id->get_type(id))
1274 {
1275 case ID_PUBKEY_SHA1:
1276 case ID_PUBKEY_INFO_SHA1:
1277 return get_private_by_keyid(this, type, id);
1278 default:
1279 break;
1280 }
1281 }
1282
1283 this->mutex->lock(this->mutex);
1284 /* try to build a trustchain for each certificate found */
1285 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1286 while (enumerator->enumerate(enumerator, &cert))
1287 {
1288 private = get_private_by_cert(this, cert, type);
1289 if (private)
1290 {
1291 trustchain = build_trustchain(this, cert, auth);
1292 if (trustchain)
1293 {
1294 auth->merge(auth, trustchain);
1295 trustchain->destroy(trustchain);
1296 break;
1297 }
1298 private->destroy(private);
1299 private = NULL;
1300 }
1301 }
1302 enumerator->destroy(enumerator);
1303 /* if no valid trustchain was found, fall back to the first usable cert */
1304 if (!private)
1305 {
1306 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1307 while (enumerator->enumerate(enumerator, &cert))
1308 {
1309 private = get_private_by_cert(this, cert, type);
1310 if (private)
1311 {
1312 auth->add_item(auth, AUTHZ_SUBJECT_CERT, cert);
1313 break;
1314 }
1315 }
1316 enumerator->destroy(enumerator);
1317 }
1318 this->mutex->unlock(this->mutex);
1319 return private;
1320 }
1321
1322 /**
1323 * Implementation of credential_manager_t.flush_cache.
1324 */
1325 static void flush_cache(private_credential_manager_t *this,
1326 certificate_type_t type)
1327 {
1328 this->mutex->lock(this->mutex);
1329 this->cache->flush(this->cache, type);
1330 this->mutex->unlock(this->mutex);
1331 }
1332
1333 /**
1334 * Implementation of credential_manager_t.add_set.
1335 */
1336 static void add_set(private_credential_manager_t *this,
1337 credential_set_t *set)
1338 {
1339 this->mutex->lock(this->mutex);
1340 this->sets->insert_last(this->sets, set);
1341 this->mutex->unlock(this->mutex);
1342 }
1343 /**
1344 * Implementation of credential_manager_t.remove_set.
1345 */
1346 static void remove_set(private_credential_manager_t *this, credential_set_t *set)
1347 {
1348 this->mutex->lock(this->mutex);
1349 this->sets->remove(this->sets, set, NULL);
1350 this->mutex->unlock(this->mutex);
1351 }
1352
1353 /**
1354 * Implementation of credential_manager_t.destroy
1355 */
1356 static void destroy(private_credential_manager_t *this)
1357 {
1358 this->sets->remove(this->sets, this->cache, NULL);
1359 this->sets->destroy(this->sets);
1360 this->cache->destroy(this->cache);
1361 this->mutex->destroy(this->mutex);
1362 free(this);
1363 }
1364
1365 /*
1366 * see header file
1367 */
1368 credential_manager_t *credential_manager_create()
1369 {
1370 private_credential_manager_t *this = malloc_thing(private_credential_manager_t);
1371
1372 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;
1373 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;
1374 this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, credential_type_t type, identification_t *id))create_cdp_enumerator;
1375 this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert;
1376 this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared;
1377 this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_info_t*))get_private;
1378 this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_info_t *aut))create_public_enumerator;
1379 this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache;
1380 this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set;
1381 this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set;
1382 this->public.destroy = (void(*)(credential_manager_t*))destroy;
1383
1384 this->sets = linked_list_create();
1385 this->cache = cert_cache_create();
1386 this->sets->insert_first(this->sets, this->cache);
1387 this->mutex = mutex_create(MUTEX_RECURSIVE);
1388
1389 return &this->public;
1390 }
1391