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