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