57f6cce27f3cab60fcecf56593ad64db42c6ad2c
[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, "found 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)
781 {
782 switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth))
783 {
784 case VALIDATION_GOOD:
785 DBG1(DBG_CFG, "certificate status is good");
786 return TRUE;
787 case VALIDATION_REVOKED:
788 /* has already been logged */
789 return FALSE;
790 case VALIDATION_SKIPPED:
791 DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
792 break;
793 case VALIDATION_STALE:
794 DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
795 break;
796 case VALIDATION_FAILED:
797 DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
798 break;
799 }
800 }
801 if (crl)
802 {
803 switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth))
804 {
805 case VALIDATION_GOOD:
806 DBG1(DBG_CFG, "certificate status is good");
807 return TRUE;
808 case VALIDATION_REVOKED:
809 /* has already been logged */
810 return FALSE;
811 case VALIDATION_FAILED:
812 case VALIDATION_SKIPPED:
813 DBG1(DBG_CFG, "certificate status is not available");
814 break;
815 case VALIDATION_STALE:
816 DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
817 break;
818 }
819 }
820 }
821 return TRUE;
822 }
823
824 /**
825 * Get a trusted certificate from a credential set
826 */
827 static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
828 key_type_t type, identification_t *id)
829 {
830 certificate_t *subject;
831 public_key_t *public;
832
833 subject = get_cert(this, CERT_ANY, type, id, TRUE);
834 if (!subject)
835 {
836 return NULL;
837 }
838 public = subject->get_public_key(subject);
839 if (!public)
840 {
841 subject->destroy(subject);
842 return NULL;
843 }
844 public->destroy(public);
845 return subject;
846 }
847
848 /**
849 * Get the issuing certificate of a subject certificate
850 */
851 static certificate_t *get_issuer_cert(private_credential_manager_t *this,
852 certificate_t *subject, bool trusted)
853 {
854 enumerator_t *enumerator;
855 certificate_t *issuer = NULL, *candidate;
856
857 enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
858 subject->get_issuer(subject), trusted);
859 while (enumerator->enumerate(enumerator, &candidate))
860 {
861 if (this->cache->issued_by(this->cache, subject, candidate))
862 {
863 issuer = candidate->get_ref(candidate);
864 break;
865 }
866 }
867 enumerator->destroy(enumerator);
868 return issuer;
869 }
870
871 /**
872 * try to verify the trust chain of subject, return TRUE if trusted
873 */
874 static bool verify_trust_chain(private_credential_manager_t *this,
875 certificate_t *subject, auth_info_t *result,
876 bool trusted, bool crl, bool ocsp)
877 {
878 certificate_t *current, *issuer;
879 auth_info_t *auth;
880 u_int level = 0;
881
882 auth = auth_info_create();
883 current = subject->get_ref(subject);
884 while (level++ < MAX_CA_LEVELS)
885 {
886 issuer = get_issuer_cert(this, current, TRUE);
887 if (issuer)
888 {
889 /* accept only self-signed CAs as trust anchor */
890 if (this->cache->issued_by(this->cache, issuer, issuer))
891 {
892 auth->add_item(auth, AUTHZ_CA_CERT, issuer);
893 DBG1(DBG_CFG, " using trusted ca certificate \"%D\"",
894 issuer->get_subject(issuer));
895 trusted = TRUE;
896 }
897 else
898 {
899 auth->add_item(auth, AUTHZ_IM_CERT, issuer);
900 DBG1(DBG_CFG, " using trusted intermediate ca certificate "
901 "\"%D\"", issuer->get_subject(issuer));
902 }
903 }
904 else
905 {
906 issuer = get_issuer_cert(this, current, FALSE);
907 if (issuer)
908 {
909 if (current->equals(current, issuer))
910 {
911 DBG1(DBG_CFG, " self-signed certificate \"%D\" is not trusted",
912 current->get_subject(current));
913 issuer->destroy(issuer);
914 break;
915 }
916 auth->add_item(auth, AUTHZ_IM_CERT, issuer);
917 DBG1(DBG_CFG, " using untrusted intermediate certificate "
918 "\"%D\"", issuer->get_subject(issuer));
919 }
920 else
921 {
922 DBG1(DBG_CFG, "no issuer certificate found for \"%D\"",
923 current->get_subject(current));
924 issuer->destroy(issuer);
925 break;
926 }
927 }
928 if (!check_certificate(this, current, issuer, crl, ocsp,
929 current == subject ? auth : NULL))
930 {
931 trusted = FALSE;
932 issuer->destroy(issuer);
933 break;
934 }
935 current->destroy(current);
936 current = issuer;
937 if (trusted)
938 {
939 break;
940 }
941 }
942 current->destroy(current);
943 if (level > MAX_CA_LEVELS)
944 {
945 DBG1(DBG_CFG, "maximum ca path length of %d levels reached", level);
946 }
947 if (trusted)
948 {
949 result->merge(result, auth);
950 }
951 auth->destroy(auth);
952 return trusted;
953 }
954
955 /**
956 * enumerator for trusted certificates
957 */
958 typedef struct {
959 /** implements enumerator_t interface */
960 enumerator_t public;
961 /** enumerator over candidate peer certificates */
962 enumerator_t *candidates;
963 /** reference to the credential_manager */
964 private_credential_manager_t *this;
965 /** type of the requested key */
966 key_type_t type;
967 /** identity the requested key belongs to */
968 identification_t *id;
969 /** TRUE to do CRL checking */
970 bool crl;
971 /** TRUE to do OCSP checking */
972 bool ocsp;
973 /** currently enumerating certificate */
974 certificate_t *current;
975 /** currently enumerating auth info */
976 auth_info_t *auth;
977 } trusted_enumerator_t;
978
979 /**
980 * Implements trusted_enumerator_t.enumerate
981 */
982 static bool trusted_enumerate(trusted_enumerator_t *this,
983 certificate_t **cert, auth_info_t **auth)
984 {
985 DESTROY_IF(this->current);
986 DESTROY_IF(this->auth);
987 this->auth = auth_info_create();
988
989 if (!this->candidates)
990 {
991 /* first invocation, build enumerator for next one */
992 this->candidates = create_cert_enumerator(this->this, CERT_ANY,
993 this->type, this->id, FALSE);
994 /* check if we have a trusted certificate for that peer */
995 this->current = get_pretrusted_cert(this->this, this->type, this->id);
996 if (this->current)
997 {
998 /* if we find a trusted self signed certificate, we just accept it.
999 * However, in order to fulfill authorization rules, we try to build
1000 * the trust chain if it is not self signed */
1001 if (this->this->cache->issued_by(this->this->cache,
1002 this->current, this->current) ||
1003 verify_trust_chain(this->this, this->current, this->auth,
1004 TRUE, this->crl, this->ocsp))
1005 {
1006 DBG1(DBG_CFG, " using trusted certificate \"%D\"",
1007 this->current->get_subject(this->current));
1008 *cert = this->current;
1009 if (auth)
1010 {
1011 *auth = this->auth;
1012 }
1013 return TRUE;
1014 }
1015 this->current->destroy(this->current);
1016 this->current = NULL;
1017 }
1018 }
1019 /* try to verify the trust chain for each certificate found */
1020 while (this->candidates->enumerate(this->candidates, &this->current))
1021 {
1022 DBG1(DBG_CFG, " using certificate \"%D\"",
1023 this->current->get_subject(this->current));
1024 if (verify_trust_chain(this->this, this->current, this->auth, FALSE,
1025 this->crl, this->ocsp))
1026 {
1027 *cert = this->current->get_ref(this->current);
1028 if (auth)
1029 {
1030 *auth = this->auth;
1031 }
1032 return TRUE;
1033 }
1034 this->current = NULL;
1035 }
1036 return FALSE;
1037 }
1038
1039 /**
1040 * Implements trusted_enumerator_t.destroy
1041 */
1042 static void trusted_destroy(trusted_enumerator_t *this)
1043 {
1044 DESTROY_IF(this->current);
1045 DESTROY_IF(this->auth);
1046 DESTROY_IF(this->candidates);
1047 free(this);
1048 }
1049
1050 /**
1051 * create an enumerator over trusted certificates and their trustchain
1052 */
1053 static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
1054 key_type_t type, identification_t *id, bool crl, bool ocsp)
1055 {
1056 trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t);
1057
1058 enumerator->public.enumerate = (void*)trusted_enumerate;
1059 enumerator->public.destroy = (void*)trusted_destroy;
1060
1061 enumerator->candidates = NULL;
1062 enumerator->this = this;
1063 enumerator->type = type;
1064 enumerator->id = id;
1065 enumerator->crl = crl;
1066 enumerator->ocsp = ocsp;
1067 enumerator->current = NULL;
1068 enumerator->auth = NULL;
1069
1070 return &enumerator->public;
1071 }
1072
1073 /**
1074 * enumerator for public keys
1075 */
1076 typedef struct {
1077 /** implements enumerator_t interface */
1078 enumerator_t public;
1079 /** enumerator over candidate peer certificates */
1080 enumerator_t *inner;
1081 /** reference to the credential_manager */
1082 private_credential_manager_t *this;
1083 /** currently enumerating key */
1084 public_key_t *current;
1085 /** credset wrapper around auth */
1086 auth_info_wrapper_t *wrapper;
1087 } public_enumerator_t;
1088
1089 /**
1090 * Implements public_enumerator_t.enumerate
1091 */
1092 static bool public_enumerate(public_enumerator_t *this,
1093 public_key_t **key, auth_info_t **auth)
1094 {
1095 certificate_t *cert;
1096
1097 while (this->inner->enumerate(this->inner, &cert, auth))
1098 {
1099 DESTROY_IF(this->current);
1100 this->current = cert->get_public_key(cert);
1101 if (this->current)
1102 {
1103 *key = this->current;
1104 return TRUE;
1105 }
1106 }
1107 return FALSE;
1108 }
1109
1110 /**
1111 * Implements public_enumerator_t.destroy
1112 */
1113 static void public_destroy(public_enumerator_t *this)
1114 {
1115 DESTROY_IF(this->current);
1116 this->inner->destroy(this->inner);
1117 if (this->wrapper)
1118 {
1119 this->this->sets->remove(this->this->sets, this->wrapper, NULL);
1120 this->wrapper->destroy(this->wrapper);
1121 }
1122 this->this->mutex->unlock(this->this->mutex);
1123 free(this);
1124 }
1125
1126 /**
1127 * Implementation of credential_manager_t.create_public_enumerator.
1128 */
1129 static enumerator_t* create_public_enumerator(private_credential_manager_t *this,
1130 key_type_t type, identification_t *id, auth_info_t *auth)
1131 {
1132 public_enumerator_t *enumerator = malloc_thing(public_enumerator_t);
1133
1134 enumerator->public.enumerate = (void*)public_enumerate;
1135 enumerator->public.destroy = (void*)public_destroy;
1136 enumerator->inner = create_trusted_enumerator(this, type, id, TRUE, TRUE);
1137 enumerator->this = this;
1138 enumerator->current = NULL;
1139 enumerator->wrapper = NULL;
1140 this->mutex->lock(this->mutex);
1141 if (auth)
1142 {
1143 enumerator->wrapper = auth_info_wrapper_create(auth);
1144 this->sets->insert_last(this->sets, enumerator->wrapper);
1145 }
1146 return &enumerator->public;
1147 }
1148
1149 /**
1150 * Check if a certificate's keyid is contained in the auth helper
1151 */
1152 static bool auth_contains_cacert(auth_info_t *auth, certificate_t *cert)
1153 {
1154 enumerator_t *enumerator;
1155 identification_t *value;
1156 auth_item_t type;
1157 bool found = FALSE;
1158
1159 enumerator = auth->create_item_enumerator(auth);
1160 while (enumerator->enumerate(enumerator, &type, &value))
1161 {
1162 if (type == AUTHN_CA_CERT && cert->equals(cert, (certificate_t*)value))
1163 {
1164 found = TRUE;
1165 break;
1166 }
1167 if (type == AUTHN_CA_CERT_KEYID)
1168 {
1169 public_key_t *public;
1170 identification_t *certid, *keyid;
1171
1172 public = cert->get_public_key(cert);
1173 if (public)
1174 {
1175 keyid = (identification_t*)value;
1176 certid = public->get_id(public, keyid->get_type(keyid));
1177 if (certid && certid->equals(certid, keyid))
1178 {
1179 public->destroy(public);
1180 found = TRUE;
1181 break;
1182 }
1183 public->destroy(public);
1184 }
1185 }
1186 }
1187 enumerator->destroy(enumerator);
1188 return found;
1189 }
1190
1191 /**
1192 * build a trustchain from subject up to a trust anchor in trusted
1193 */
1194 static auth_info_t *build_trustchain(private_credential_manager_t *this,
1195 certificate_t *subject, auth_info_t *auth)
1196 {
1197 certificate_t *issuer, *current;
1198 auth_info_t *trustchain;
1199 u_int level = 0;
1200
1201 trustchain = auth_info_create();
1202
1203 if (!auth->get_item(auth, AUTHN_CA_CERT, (void**)&current))
1204 {
1205 /* no trust anchor specified, return this cert only */
1206 trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, subject);
1207 return trustchain;
1208 }
1209 current = subject->get_ref(subject);
1210 while (TRUE)
1211 {
1212 if (auth_contains_cacert(auth, current))
1213 {
1214 trustchain->add_item(trustchain, AUTHZ_CA_CERT, current);
1215 current->destroy(current);
1216 return trustchain;
1217 }
1218 if (subject == current)
1219 {
1220 trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, current);
1221 }
1222 else
1223 {
1224 trustchain->add_item(trustchain, AUTHZ_IM_CERT, current);
1225 }
1226 issuer = get_issuer_cert(this, current, FALSE);
1227 if (!issuer || issuer->equals(issuer, current) || level > MAX_CA_LEVELS)
1228 {
1229 DESTROY_IF(issuer);
1230 current->destroy(current);
1231 break;
1232 }
1233 current->destroy(current);
1234 current = issuer;
1235 level++;
1236 }
1237 trustchain->destroy(trustchain);
1238 return NULL;
1239 }
1240
1241 /**
1242 * find a private key of a give certificate
1243 */
1244 static private_key_t *get_private_by_cert(private_credential_manager_t *this,
1245 certificate_t *cert, key_type_t type)
1246 {
1247 private_key_t *private = NULL;
1248 identification_t* keyid;
1249 public_key_t *public;
1250
1251 public = cert->get_public_key(cert);
1252 if (public)
1253 {
1254 keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
1255 if (keyid)
1256 {
1257 private = get_private_by_keyid(this, type, keyid);
1258 }
1259 public->destroy(public);
1260 }
1261 return private;
1262 }
1263
1264 /**
1265 * Implementation of credential_manager_t.get_private.
1266 */
1267 static private_key_t *get_private(private_credential_manager_t *this,
1268 key_type_t type, identification_t *id,
1269 auth_info_t *auth)
1270 {
1271 enumerator_t *enumerator;
1272 certificate_t *cert;
1273 private_key_t *private = NULL;
1274 auth_info_t *trustchain;
1275
1276 /* check if this is a lookup by key ID, and do it if so */
1277 if (id)
1278 {
1279 switch (id->get_type(id))
1280 {
1281 case ID_PUBKEY_SHA1:
1282 case ID_PUBKEY_INFO_SHA1:
1283 return get_private_by_keyid(this, type, id);
1284 default:
1285 break;
1286 }
1287 }
1288
1289 this->mutex->lock(this->mutex);
1290 /* try to build a trustchain for each certificate found */
1291 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1292 while (enumerator->enumerate(enumerator, &cert))
1293 {
1294 private = get_private_by_cert(this, cert, type);
1295 if (private)
1296 {
1297 trustchain = build_trustchain(this, cert, auth);
1298 if (trustchain)
1299 {
1300 auth->merge(auth, trustchain);
1301 trustchain->destroy(trustchain);
1302 break;
1303 }
1304 private->destroy(private);
1305 private = NULL;
1306 }
1307 }
1308 enumerator->destroy(enumerator);
1309 /* if no valid trustchain was found, fall back to the first usable cert */
1310 if (!private)
1311 {
1312 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1313 while (enumerator->enumerate(enumerator, &cert))
1314 {
1315 private = get_private_by_cert(this, cert, type);
1316 if (private)
1317 {
1318 auth->add_item(auth, AUTHZ_SUBJECT_CERT, cert);
1319 break;
1320 }
1321 }
1322 enumerator->destroy(enumerator);
1323 }
1324 this->mutex->unlock(this->mutex);
1325 return private;
1326 }
1327
1328 /**
1329 * Implementation of credential_manager_t.flush_cache.
1330 */
1331 static void flush_cache(private_credential_manager_t *this,
1332 certificate_type_t type)
1333 {
1334 this->mutex->lock(this->mutex);
1335 this->cache->flush(this->cache, type);
1336 this->mutex->unlock(this->mutex);
1337 }
1338
1339 /**
1340 * Implementation of credential_manager_t.add_set.
1341 */
1342 static void add_set(private_credential_manager_t *this,
1343 credential_set_t *set)
1344 {
1345 this->mutex->lock(this->mutex);
1346 this->sets->insert_last(this->sets, set);
1347 this->mutex->unlock(this->mutex);
1348 }
1349 /**
1350 * Implementation of credential_manager_t.remove_set.
1351 */
1352 static void remove_set(private_credential_manager_t *this, credential_set_t *set)
1353 {
1354 this->mutex->lock(this->mutex);
1355 this->sets->remove(this->sets, set, NULL);
1356 this->mutex->unlock(this->mutex);
1357 }
1358
1359 /**
1360 * Implementation of credential_manager_t.destroy
1361 */
1362 static void destroy(private_credential_manager_t *this)
1363 {
1364 this->sets->remove(this->sets, this->cache, NULL);
1365 this->sets->destroy(this->sets);
1366 this->cache->destroy(this->cache);
1367 this->mutex->destroy(this->mutex);
1368 free(this);
1369 }
1370
1371 /*
1372 * see header file
1373 */
1374 credential_manager_t *credential_manager_create()
1375 {
1376 private_credential_manager_t *this = malloc_thing(private_credential_manager_t);
1377
1378 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;
1379 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;
1380 this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, credential_type_t type, identification_t *id))create_cdp_enumerator;
1381 this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert;
1382 this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared;
1383 this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_info_t*))get_private;
1384 this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_info_t *aut))create_public_enumerator;
1385 this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache;
1386 this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set;
1387 this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set;
1388 this->public.destroy = (void(*)(credential_manager_t*))destroy;
1389
1390 this->sets = linked_list_create();
1391 this->cache = cert_cache_create();
1392 this->sets->insert_first(this->sets, this->cache);
1393 this->mutex = mutex_create(MUTEX_RECURSIVE);
1394
1395 return &this->public;
1396 }
1397