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