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