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