revocation: Restrict OCSP signing to specific certificates
[strongswan.git] / src / libstrongswan / plugins / revocation / revocation_validator.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2009 Andreas Steffen
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "revocation_validator.h"
19
20 #include <utils/debug.h>
21 #include <credentials/certificates/x509.h>
22 #include <credentials/certificates/crl.h>
23 #include <credentials/certificates/ocsp_request.h>
24 #include <credentials/certificates/ocsp_response.h>
25 #include <credentials/sets/ocsp_response_wrapper.h>
26 #include <selectors/traffic_selector.h>
27
28 typedef struct private_revocation_validator_t private_revocation_validator_t;
29
30 /**
31 * Private data of an revocation_validator_t object.
32 */
33 struct private_revocation_validator_t {
34
35 /**
36 * Public revocation_validator_t interface.
37 */
38 revocation_validator_t public;
39 };
40
41 /**
42 * Do an OCSP request
43 */
44 static certificate_t *fetch_ocsp(char *url, certificate_t *subject,
45 certificate_t *issuer)
46 {
47 certificate_t *request, *response;
48 chunk_t send, receive;
49
50 /* TODO: requestor name, signature */
51 request = lib->creds->create(lib->creds,
52 CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
53 BUILD_CA_CERT, issuer,
54 BUILD_CERT, subject, BUILD_END);
55 if (!request)
56 {
57 DBG1(DBG_CFG, "generating ocsp request failed");
58 return NULL;
59 }
60
61 if (!request->get_encoding(request, CERT_ASN1_DER, &send))
62 {
63 DBG1(DBG_CFG, "encoding ocsp request failed");
64 request->destroy(request);
65 return NULL;
66 }
67 request->destroy(request);
68
69 DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url);
70 if (lib->fetcher->fetch(lib->fetcher, url, &receive,
71 FETCH_REQUEST_DATA, send,
72 FETCH_REQUEST_TYPE, "application/ocsp-request",
73 FETCH_END) != SUCCESS)
74 {
75 DBG1(DBG_CFG, "ocsp request to %s failed", url);
76 chunk_free(&send);
77 return NULL;
78 }
79 chunk_free(&send);
80
81 response = lib->creds->create(lib->creds,
82 CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
83 BUILD_BLOB_ASN1_DER, receive, BUILD_END);
84 chunk_free(&receive);
85 if (!response)
86 {
87 DBG1(DBG_CFG, "parsing ocsp response failed");
88 return NULL;
89 }
90 return response;
91 }
92
93 /**
94 * check the signature of an OCSP response
95 */
96 static bool verify_ocsp(ocsp_response_t *response, certificate_t *ca)
97 {
98 certificate_t *issuer, *subject;
99 identification_t *responder;
100 ocsp_response_wrapper_t *wrapper;
101 enumerator_t *enumerator;
102 x509_t *x509;
103 bool verified = FALSE, found = FALSE;
104
105 wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
106 lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE);
107
108 subject = &response->certificate;
109 responder = subject->get_issuer(subject);
110
111 /* check OCSP response using CA or directly delegated OCSP signer */
112 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, CERT_X509,
113 KEY_ANY, responder, FALSE);
114 while (enumerator->enumerate(enumerator, &issuer))
115 {
116 x509 = (x509_t*)issuer;
117 if (!issuer->get_validity(issuer, NULL, NULL, NULL))
118 { /* OCSP signer currently invalid */
119 continue;
120 }
121 found = TRUE;
122 if (!ca->equals(ca, issuer))
123 { /* delegated OCSP signer? */
124 if (!lib->credmgr->issued_by(lib->credmgr, issuer, ca, NULL))
125 { /* OCSP response not signed by CA, nor delegated OCSP signer */
126 continue;
127 }
128 if (!(x509->get_flags(x509) & X509_OCSP_SIGNER))
129 { /* delegated OCSP signer does not have OCSP signer flag */
130 continue;
131 }
132 }
133 if (lib->credmgr->issued_by(lib->credmgr, subject, issuer, NULL))
134 {
135 DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
136 issuer->get_subject(issuer));
137 verified = TRUE;
138 break;
139 }
140 DBG1(DBG_CFG, "ocsp response verification failed, "
141 "invalid signature");
142 }
143 enumerator->destroy(enumerator);
144
145 if (!verified)
146 {
147 /* as fallback, use any locally installed OCSP signer certificate */
148 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
149 CERT_X509, KEY_ANY, responder, TRUE);
150 while (enumerator->enumerate(enumerator, &issuer))
151 {
152 x509 = (x509_t*)issuer;
153 /* while issued_by() accepts both OCSP signer or CA basic
154 * constraint flags to verify OCSP responses, unrelated but trusted
155 * OCSP signers must explicitly have the OCSP signer flag set. */
156 if ((x509->get_flags(x509) & X509_OCSP_SIGNER) &&
157 issuer->get_validity(issuer, NULL, NULL, NULL))
158 {
159 found = TRUE;
160 if (lib->credmgr->issued_by(lib->credmgr, subject, issuer, NULL))
161 {
162 DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
163 issuer->get_subject(issuer));
164 verified = TRUE;
165 break;
166 }
167 DBG1(DBG_CFG, "ocsp response verification failed, "
168 "invalid signature");
169 }
170 }
171 enumerator->destroy(enumerator);
172 }
173
174 lib->credmgr->remove_local_set(lib->credmgr, &wrapper->set);
175 wrapper->destroy(wrapper);
176
177 if (!found)
178 {
179 DBG1(DBG_CFG, "ocsp response verification failed, "
180 "no signer certificate '%Y' found", responder);
181 }
182 return verified;
183 }
184
185 /**
186 * Get the better of two OCSP responses, and check for usable OCSP info
187 */
188 static certificate_t *get_better_ocsp(certificate_t *cand, certificate_t *best,
189 x509_t *subject, x509_t *issuer,
190 cert_validation_t *valid, bool cache)
191 {
192 ocsp_response_t *response;
193 time_t revocation, this_update, next_update, valid_until;
194 crl_reason_t reason;
195 bool revoked = FALSE;
196
197 response = (ocsp_response_t*)cand;
198
199 /* check ocsp signature */
200 if (!verify_ocsp(response, &issuer->interface))
201 {
202 cand->destroy(cand);
203 return best;
204 }
205 /* check if response contains our certificate */
206 switch (response->get_status(response, subject, issuer, &revocation, &reason,
207 &this_update, &next_update))
208 {
209 case VALIDATION_REVOKED:
210 /* subject has been revoked by a valid OCSP response */
211 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
212 &revocation, TRUE, crl_reason_names, reason);
213 revoked = TRUE;
214 break;
215 case VALIDATION_GOOD:
216 /* results in either good or stale */
217 break;
218 default:
219 case VALIDATION_FAILED:
220 /* candidate unusable, does not contain our cert */
221 DBG1(DBG_CFG, " ocsp response contains no status on our certificate");
222 cand->destroy(cand);
223 return best;
224 }
225
226 /* select the better of the two responses */
227 if (best == NULL || certificate_is_newer(cand, best))
228 {
229 DESTROY_IF(best);
230 best = cand;
231 if (best->get_validity(best, NULL, NULL, &valid_until))
232 {
233 DBG1(DBG_CFG, " ocsp response is valid: until %T",
234 &valid_until, FALSE);
235 *valid = VALIDATION_GOOD;
236 if (cache)
237 { /* cache non-stale only, stale certs get refetched */
238 lib->credmgr->cache_cert(lib->credmgr, best);
239 }
240 }
241 else
242 {
243 DBG1(DBG_CFG, " ocsp response is stale: since %T",
244 &valid_until, FALSE);
245 *valid = VALIDATION_STALE;
246 }
247 }
248 else
249 {
250 *valid = VALIDATION_STALE;
251 cand->destroy(cand);
252 }
253 if (revoked)
254 { /* revoked always counts, even if stale */
255 *valid = VALIDATION_REVOKED;
256 }
257 return best;
258 }
259
260 /**
261 * validate a x509 certificate using OCSP
262 */
263 static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer,
264 auth_cfg_t *auth)
265 {
266 enumerator_t *enumerator;
267 cert_validation_t valid = VALIDATION_SKIPPED;
268 certificate_t *best = NULL, *current;
269 identification_t *keyid = NULL;
270 public_key_t *public;
271 chunk_t chunk;
272 char *uri = NULL;
273
274 /** lookup cache for valid OCSP responses */
275 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
276 CERT_X509_OCSP_RESPONSE, KEY_ANY, NULL, FALSE);
277 while (enumerator->enumerate(enumerator, &current))
278 {
279 current->get_ref(current);
280 best = get_better_ocsp(current, best, subject, issuer, &valid, FALSE);
281 if (best && valid != VALIDATION_STALE)
282 {
283 DBG1(DBG_CFG, " using cached ocsp response");
284 break;
285 }
286 }
287 enumerator->destroy(enumerator);
288
289 /* derive the authorityKeyIdentifier from the issuer's public key */
290 current = &issuer->interface;
291 public = current->get_public_key(current);
292 if (public && public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
293 {
294 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
295 }
296 /** fetch from configured OCSP responder URLs */
297 if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
298 {
299 enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
300 CERT_X509_OCSP_RESPONSE, keyid);
301 while (enumerator->enumerate(enumerator, &uri))
302 {
303 current = fetch_ocsp(uri, &subject->interface, &issuer->interface);
304 if (current)
305 {
306 best = get_better_ocsp(current, best, subject, issuer,
307 &valid, TRUE);
308 if (best && valid != VALIDATION_STALE)
309 {
310 break;
311 }
312 }
313 }
314 enumerator->destroy(enumerator);
315 }
316 DESTROY_IF(public);
317 DESTROY_IF(keyid);
318
319 /* fallback to URL fetching from subject certificate's URIs */
320 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
321 {
322 enumerator = subject->create_ocsp_uri_enumerator(subject);
323 while (enumerator->enumerate(enumerator, &uri))
324 {
325 current = fetch_ocsp(uri, &subject->interface, &issuer->interface);
326 if (current)
327 {
328 best = get_better_ocsp(current, best, subject, issuer,
329 &valid, TRUE);
330 if (best && valid != VALIDATION_STALE)
331 {
332 break;
333 }
334 }
335 }
336 enumerator->destroy(enumerator);
337 }
338 /* an uri was found, but no result. switch validation state to failed */
339 if (valid == VALIDATION_SKIPPED && uri)
340 {
341 valid = VALIDATION_FAILED;
342 }
343 if (auth)
344 {
345 auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid);
346 if (valid == VALIDATION_GOOD)
347 { /* successful OCSP check fulfills also CRL constraint */
348 auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
349 }
350 }
351 DESTROY_IF(best);
352 return valid;
353 }
354
355 /**
356 * fetch a CRL from an URL
357 */
358 static certificate_t* fetch_crl(char *url)
359 {
360 certificate_t *crl;
361 chunk_t chunk;
362
363 DBG1(DBG_CFG, " fetching crl from '%s' ...", url);
364 if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
365 {
366 DBG1(DBG_CFG, "crl fetching failed");
367 return NULL;
368 }
369 crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
370 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
371 chunk_free(&chunk);
372 if (!crl)
373 {
374 DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
375 return NULL;
376 }
377 return crl;
378 }
379
380 /**
381 * check the signature of an CRL
382 */
383 static bool verify_crl(certificate_t *crl)
384 {
385 certificate_t *issuer;
386 enumerator_t *enumerator;
387 bool verified = FALSE;
388
389 enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
390 KEY_ANY, crl->get_issuer(crl), FALSE);
391 while (enumerator->enumerate(enumerator, &issuer, NULL))
392 {
393 if (lib->credmgr->issued_by(lib->credmgr, crl, issuer, NULL))
394 {
395 DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
396 issuer->get_subject(issuer));
397 verified = TRUE;
398 break;
399 }
400 }
401 enumerator->destroy(enumerator);
402
403 return verified;
404 }
405
406 /**
407 * Get the better of two CRLs, and check for usable CRL info
408 */
409 static certificate_t *get_better_crl(certificate_t *cand, certificate_t *best,
410 x509_t *subject, cert_validation_t *valid,
411 bool cache, crl_t *base)
412 {
413 enumerator_t *enumerator;
414 time_t revocation, valid_until;
415 crl_reason_t reason;
416 chunk_t serial;
417 crl_t *crl = (crl_t*)cand;
418
419 if (base)
420 {
421 if (!crl->is_delta_crl(crl, &serial) ||
422 !chunk_equals(serial, base->get_serial(base)))
423 {
424 cand->destroy(cand);
425 return best;
426 }
427 }
428 else
429 {
430 if (crl->is_delta_crl(crl, NULL))
431 {
432 cand->destroy(cand);
433 return best;
434 }
435 }
436
437 /* check CRL signature */
438 if (!verify_crl(cand))
439 {
440 DBG1(DBG_CFG, "crl response verification failed");
441 cand->destroy(cand);
442 return best;
443 }
444
445 enumerator = crl->create_enumerator(crl);
446 while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
447 {
448 if (chunk_equals(serial, subject->get_serial(subject)))
449 {
450 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
451 &revocation, TRUE, crl_reason_names, reason);
452 if (reason != CRL_REASON_CERTIFICATE_HOLD)
453 {
454 *valid = VALIDATION_REVOKED;
455 }
456 else
457 {
458 /* if the cert is on hold, a newer CRL might not contain it */
459 *valid = VALIDATION_ON_HOLD;
460 }
461 enumerator->destroy(enumerator);
462 DESTROY_IF(best);
463 return cand;
464 }
465 }
466 enumerator->destroy(enumerator);
467
468 /* select the better of the two CRLs */
469 if (best == NULL || crl_is_newer(crl, (crl_t*)best))
470 {
471 DESTROY_IF(best);
472 best = cand;
473 if (best->get_validity(best, NULL, NULL, &valid_until))
474 {
475 DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE);
476 *valid = VALIDATION_GOOD;
477 if (cache)
478 { /* we cache non-stale crls only, as a stale crls are refetched */
479 lib->credmgr->cache_cert(lib->credmgr, best);
480 }
481 }
482 else
483 {
484 DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE);
485 *valid = VALIDATION_STALE;
486 }
487 }
488 else
489 {
490 *valid = VALIDATION_STALE;
491 cand->destroy(cand);
492 }
493 return best;
494 }
495
496 /**
497 * Find or fetch a certificate for a given crlIssuer
498 */
499 static cert_validation_t find_crl(x509_t *subject, identification_t *issuer,
500 crl_t *base, certificate_t **best,
501 bool *uri_found)
502 {
503 cert_validation_t valid = VALIDATION_SKIPPED;
504 enumerator_t *enumerator;
505 certificate_t *current;
506 char *uri;
507
508 /* find a cached (delta) crl */
509 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
510 CERT_X509_CRL, KEY_ANY, issuer, FALSE);
511 while (enumerator->enumerate(enumerator, &current))
512 {
513 current->get_ref(current);
514 *best = get_better_crl(current, *best, subject, &valid, FALSE, base);
515 if (*best && valid != VALIDATION_STALE)
516 {
517 DBG1(DBG_CFG, " using cached crl");
518 break;
519 }
520 }
521 enumerator->destroy(enumerator);
522
523 /* fallback to fetching crls from credential sets cdps */
524 if (!base && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
525 {
526 enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
527 CERT_X509_CRL, issuer);
528 while (enumerator->enumerate(enumerator, &uri))
529 {
530 *uri_found = TRUE;
531 current = fetch_crl(uri);
532 if (current)
533 {
534 if (!current->has_issuer(current, issuer))
535 {
536 DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match CRL "
537 "issuer '%Y'", current->get_issuer(current), issuer);
538 current->destroy(current);
539 continue;
540 }
541 *best = get_better_crl(current, *best, subject,
542 &valid, TRUE, base);
543 if (*best && valid != VALIDATION_STALE)
544 {
545 break;
546 }
547 }
548 }
549 enumerator->destroy(enumerator);
550 }
551 return valid;
552 }
553
554 /**
555 * Look for a delta CRL for a given base CRL
556 */
557 static cert_validation_t check_delta_crl(x509_t *subject, x509_t *issuer,
558 crl_t *base, cert_validation_t base_valid)
559 {
560 cert_validation_t valid = VALIDATION_SKIPPED;
561 certificate_t *best = NULL, *current;
562 enumerator_t *enumerator;
563 identification_t *id;
564 x509_cdp_t *cdp;
565 chunk_t chunk;
566 bool uri;
567
568 /* find cached delta CRL via subjectKeyIdentifier */
569 chunk = issuer->get_subjectKeyIdentifier(issuer);
570 if (chunk.len)
571 {
572 id = identification_create_from_encoding(ID_KEY_ID, chunk);
573 valid = find_crl(subject, id, base, &best, &uri);
574 id->destroy(id);
575 }
576
577 /* find delta CRL by CRLIssuer */
578 enumerator = subject->create_crl_uri_enumerator(subject);
579 while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
580 enumerator->enumerate(enumerator, &cdp))
581 {
582 if (cdp->issuer)
583 {
584 valid = find_crl(subject, cdp->issuer, base, &best, &uri);
585 }
586 }
587 enumerator->destroy(enumerator);
588
589 /* fetch from URIs found in Freshest CRL extension */
590 enumerator = base->create_delta_crl_uri_enumerator(base);
591 while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
592 enumerator->enumerate(enumerator, &cdp))
593 {
594 current = fetch_crl(cdp->uri);
595 if (current)
596 {
597 if (cdp->issuer && !current->has_issuer(current, cdp->issuer))
598 {
599 DBG1(DBG_CFG, "issuer of fetched delta CRL '%Y' does not match "
600 "certificates CRL issuer '%Y'",
601 current->get_issuer(current), cdp->issuer);
602 current->destroy(current);
603 continue;
604 }
605 best = get_better_crl(current, best, subject, &valid, TRUE, base);
606 if (best && valid != VALIDATION_STALE)
607 {
608 break;
609 }
610 }
611 }
612 enumerator->destroy(enumerator);
613
614 if (best)
615 {
616 best->destroy(best);
617 return valid;
618 }
619 return base_valid;
620 }
621
622 /**
623 * validate a x509 certificate using CRL
624 */
625 static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
626 auth_cfg_t *auth)
627 {
628 cert_validation_t valid = VALIDATION_SKIPPED;
629 certificate_t *best = NULL;
630 identification_t *id;
631 x509_cdp_t *cdp;
632 bool uri_found = FALSE;
633 certificate_t *current;
634 enumerator_t *enumerator;
635 chunk_t chunk;
636
637 /* use issuers subjectKeyIdentifier to find a cached CRL / fetch from CDP */
638 chunk = issuer->get_subjectKeyIdentifier(issuer);
639 if (chunk.len)
640 {
641 id = identification_create_from_encoding(ID_KEY_ID, chunk);
642 valid = find_crl(subject, id, NULL, &best, &uri_found);
643 id->destroy(id);
644 }
645
646 /* find a cached CRL or fetch via configured CDP via CRLIssuer */
647 enumerator = subject->create_crl_uri_enumerator(subject);
648 while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
649 enumerator->enumerate(enumerator, &cdp))
650 {
651 if (cdp->issuer)
652 {
653 valid = find_crl(subject, cdp->issuer, NULL, &best, &uri_found);
654 }
655 }
656 enumerator->destroy(enumerator);
657
658 /* fallback to fetching CRLs from CDPs found in subjects certificate */
659 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
660 {
661 enumerator = subject->create_crl_uri_enumerator(subject);
662 while (enumerator->enumerate(enumerator, &cdp))
663 {
664 uri_found = TRUE;
665 current = fetch_crl(cdp->uri);
666 if (current)
667 {
668 if (cdp->issuer && !current->has_issuer(current, cdp->issuer))
669 {
670 DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match "
671 "certificates CRL issuer '%Y'",
672 current->get_issuer(current), cdp->issuer);
673 current->destroy(current);
674 continue;
675 }
676 best = get_better_crl(current, best, subject, &valid,
677 TRUE, NULL);
678 if (best && valid != VALIDATION_STALE)
679 {
680 break;
681 }
682 }
683 }
684 enumerator->destroy(enumerator);
685 }
686
687 /* look for delta CRLs */
688 if (best && (valid == VALIDATION_GOOD || valid == VALIDATION_STALE))
689 {
690 valid = check_delta_crl(subject, issuer, (crl_t*)best, valid);
691 }
692
693 /* an uri was found, but no result. switch validation state to failed */
694 if (valid == VALIDATION_SKIPPED && uri_found)
695 {
696 valid = VALIDATION_FAILED;
697 }
698 if (auth)
699 {
700 if (valid == VALIDATION_SKIPPED)
701 { /* if we skipped CRL validation, we use the result of OCSP for
702 * constraint checking */
703 auth->add(auth, AUTH_RULE_CRL_VALIDATION,
704 auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
705 }
706 else
707 {
708 auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid);
709 }
710 }
711 DESTROY_IF(best);
712 return valid;
713 }
714
715 METHOD(cert_validator_t, validate, bool,
716 private_revocation_validator_t *this, certificate_t *subject,
717 certificate_t *issuer, bool online, u_int pathlen, bool anchor,
718 auth_cfg_t *auth)
719 {
720 if (subject->get_type(subject) == CERT_X509 &&
721 issuer->get_type(issuer) == CERT_X509 &&
722 online)
723 {
724 DBG1(DBG_CFG, "checking certificate status of \"%Y\"",
725 subject->get_subject(subject));
726 switch (check_ocsp((x509_t*)subject, (x509_t*)issuer,
727 pathlen ? NULL : auth))
728 {
729 case VALIDATION_GOOD:
730 DBG1(DBG_CFG, "certificate status is good");
731 return TRUE;
732 case VALIDATION_REVOKED:
733 case VALIDATION_ON_HOLD:
734 /* has already been logged */
735 lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_REVOKED,
736 subject);
737 return FALSE;
738 case VALIDATION_SKIPPED:
739 DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
740 break;
741 case VALIDATION_STALE:
742 DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
743 break;
744 case VALIDATION_FAILED:
745 DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
746 break;
747 }
748 switch (check_crl((x509_t*)subject, (x509_t*)issuer,
749 pathlen ? NULL : auth))
750 {
751 case VALIDATION_GOOD:
752 DBG1(DBG_CFG, "certificate status is good");
753 return TRUE;
754 case VALIDATION_REVOKED:
755 case VALIDATION_ON_HOLD:
756 /* has already been logged */
757 lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_REVOKED,
758 subject);
759 return FALSE;
760 case VALIDATION_FAILED:
761 case VALIDATION_SKIPPED:
762 DBG1(DBG_CFG, "certificate status is not available");
763 break;
764 case VALIDATION_STALE:
765 DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
766 break;
767 }
768 lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_VALIDATION_FAILED,
769 subject);
770 }
771 return TRUE;
772 }
773
774 METHOD(revocation_validator_t, destroy, void,
775 private_revocation_validator_t *this)
776 {
777 free(this);
778 }
779
780 /**
781 * See header
782 */
783 revocation_validator_t *revocation_validator_create()
784 {
785 private_revocation_validator_t *this;
786
787 INIT(this,
788 .public = {
789 .validator.validate = _validate,
790 .destroy = _destroy,
791 },
792 );
793
794 return &this->public;
795 }