Annotation of src/usr.bin/openssl/ocsp.c, Revision 1.1
1.1 ! jsing 1: /* $OpenBSD: ocsp.c,v 1.31 2014/08/24 16:07:29 bcook Exp $ */
! 2: /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
! 3: * project 2000.
! 4: */
! 5: /* ====================================================================
! 6: * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: *
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: *
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in
! 17: * the documentation and/or other materials provided with the
! 18: * distribution.
! 19: *
! 20: * 3. All advertising materials mentioning features or use of this
! 21: * software must display the following acknowledgment:
! 22: * "This product includes software developed by the OpenSSL Project
! 23: * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
! 24: *
! 25: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
! 26: * endorse or promote products derived from this software without
! 27: * prior written permission. For written permission, please contact
! 28: * licensing@OpenSSL.org.
! 29: *
! 30: * 5. Products derived from this software may not be called "OpenSSL"
! 31: * nor may "OpenSSL" appear in their names without prior written
! 32: * permission of the OpenSSL Project.
! 33: *
! 34: * 6. Redistributions of any form whatsoever must retain the following
! 35: * acknowledgment:
! 36: * "This product includes software developed by the OpenSSL Project
! 37: * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
! 38: *
! 39: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
! 40: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 41: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 42: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
! 43: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! 44: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 45: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
! 46: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 47: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 48: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 49: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
! 50: * OF THE POSSIBILITY OF SUCH DAMAGE.
! 51: * ====================================================================
! 52: *
! 53: * This product includes cryptographic software written by Eric Young
! 54: * (eay@cryptsoft.com). This product includes software written by Tim
! 55: * Hudson (tjh@cryptsoft.com).
! 56: *
! 57: */
! 58: #ifndef OPENSSL_NO_OCSP
! 59:
! 60: #include <sys/select.h>
! 61:
! 62: #include <stdio.h>
! 63: #include <stdlib.h>
! 64: #include <limits.h>
! 65: #include <string.h>
! 66: #include <time.h>
! 67:
! 68: /* Needs to be included before the openssl headers! */
! 69: #include "apps.h"
! 70:
! 71: #include <openssl/bn.h>
! 72: #include <openssl/crypto.h>
! 73: #include <openssl/err.h>
! 74: #include <openssl/evp.h>
! 75: #include <openssl/ssl.h>
! 76: #include <openssl/x509v3.h>
! 77:
! 78: /* Maximum leeway in validity period: default 5 minutes */
! 79: #define MAX_VALIDITY_PERIOD (5 * 60)
! 80:
! 81: static int
! 82: add_ocsp_cert(OCSP_REQUEST ** req, X509 * cert, const EVP_MD * cert_id_md, X509 * issuer,
! 83: STACK_OF(OCSP_CERTID) * ids);
! 84: static int add_ocsp_serial(OCSP_REQUEST ** req, char *serial, const EVP_MD * cert_id_md, X509 * issuer,
! 85: STACK_OF(OCSP_CERTID) * ids);
! 86: static int print_ocsp_summary(BIO * out, OCSP_BASICRESP * bs, OCSP_REQUEST * req,
! 87: STACK_OF(OPENSSL_STRING) * names,
! 88: STACK_OF(OCSP_CERTID) * ids, long nsec,
! 89: long maxage);
! 90:
! 91: static int make_ocsp_response(OCSP_RESPONSE ** resp, OCSP_REQUEST * req, CA_DB * db,
! 92: X509 * ca, X509 * rcert, EVP_PKEY * rkey,
! 93: STACK_OF(X509) * rother, unsigned long flags,
! 94: int nmin, int ndays);
! 95:
! 96: static char **lookup_serial(CA_DB * db, ASN1_INTEGER * ser);
! 97: static BIO *init_responder(char *port);
! 98: static int do_responder(OCSP_REQUEST ** preq, BIO ** pcbio, BIO * acbio, char *port);
! 99: static int send_ocsp_response(BIO * cbio, OCSP_RESPONSE * resp);
! 100: static OCSP_RESPONSE *query_responder(BIO * err, BIO * cbio, char *path,
! 101: STACK_OF(CONF_VALUE) * headers,
! 102: OCSP_REQUEST * req, int req_timeout);
! 103:
! 104:
! 105: int ocsp_main(int, char **);
! 106:
! 107: int
! 108: ocsp_main(int argc, char **argv)
! 109: {
! 110: ENGINE *e = NULL;
! 111: char **args;
! 112: char *host = NULL, *port = NULL, *path = "/";
! 113: char *reqin = NULL, *respin = NULL;
! 114: char *reqout = NULL, *respout = NULL;
! 115: char *signfile = NULL, *keyfile = NULL;
! 116: char *rsignfile = NULL, *rkeyfile = NULL;
! 117: char *outfile = NULL;
! 118: int add_nonce = 1, noverify = 0, use_ssl = -1;
! 119: STACK_OF(CONF_VALUE) * headers = NULL;
! 120: OCSP_REQUEST *req = NULL;
! 121: OCSP_RESPONSE *resp = NULL;
! 122: OCSP_BASICRESP *bs = NULL;
! 123: X509 *issuer = NULL, *cert = NULL;
! 124: X509 *signer = NULL, *rsigner = NULL;
! 125: EVP_PKEY *key = NULL, *rkey = NULL;
! 126: BIO *acbio = NULL, *cbio = NULL;
! 127: BIO *derbio = NULL;
! 128: BIO *out = NULL;
! 129: int req_timeout = -1;
! 130: int req_text = 0, resp_text = 0;
! 131: long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
! 132: char *CAfile = NULL, *CApath = NULL;
! 133: X509_STORE *store = NULL;
! 134: STACK_OF(X509) * sign_other = NULL, *verify_other = NULL, *rother = NULL;
! 135: char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
! 136: unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
! 137: int ret = 1;
! 138: int accept_count = -1;
! 139: int badarg = 0;
! 140: int i;
! 141: int ignore_err = 0;
! 142: STACK_OF(OPENSSL_STRING) * reqnames = NULL;
! 143: STACK_OF(OCSP_CERTID) * ids = NULL;
! 144: X509 *rca_cert = NULL;
! 145: char *ridx_filename = NULL;
! 146: char *rca_filename = NULL;
! 147: CA_DB *rdb = NULL;
! 148: int nmin = 0, ndays = -1;
! 149: const EVP_MD *cert_id_md = NULL;
! 150: const char *errstr = NULL;
! 151:
! 152: args = argv + 1;
! 153: reqnames = sk_OPENSSL_STRING_new_null();
! 154: ids = sk_OCSP_CERTID_new_null();
! 155: while (!badarg && *args && *args[0] == '-') {
! 156: if (!strcmp(*args, "-out")) {
! 157: if (args[1]) {
! 158: args++;
! 159: outfile = *args;
! 160: } else
! 161: badarg = 1;
! 162: } else if (!strcmp(*args, "-timeout")) {
! 163: if (args[1]) {
! 164: args++;
! 165: req_timeout = strtonum(*args, 0,
! 166: INT_MAX, &errstr);
! 167: if (errstr) {
! 168: BIO_printf(bio_err,
! 169: "Illegal timeout value %s: %s\n",
! 170: *args, errstr);
! 171: badarg = 1;
! 172: }
! 173: } else
! 174: badarg = 1;
! 175: } else if (!strcmp(*args, "-url")) {
! 176: if (args[1]) {
! 177: args++;
! 178: if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl)) {
! 179: BIO_printf(bio_err, "Error parsing URL\n");
! 180: badarg = 1;
! 181: }
! 182: } else
! 183: badarg = 1;
! 184: } else if (!strcmp(*args, "-host")) {
! 185: if (args[1]) {
! 186: args++;
! 187: host = *args;
! 188: } else
! 189: badarg = 1;
! 190: } else if (!strcmp(*args, "-port")) {
! 191: if (args[1]) {
! 192: args++;
! 193: port = *args;
! 194: } else
! 195: badarg = 1;
! 196: } else if (!strcmp(*args, "-header")) {
! 197: if (args[1] && args[2]) {
! 198: if (!X509V3_add_value(args[1], args[2], &headers))
! 199: goto end;
! 200: args += 2;
! 201: } else
! 202: badarg = 1;
! 203: } else if (!strcmp(*args, "-ignore_err"))
! 204: ignore_err = 1;
! 205: else if (!strcmp(*args, "-noverify"))
! 206: noverify = 1;
! 207: else if (!strcmp(*args, "-nonce"))
! 208: add_nonce = 2;
! 209: else if (!strcmp(*args, "-no_nonce"))
! 210: add_nonce = 0;
! 211: else if (!strcmp(*args, "-resp_no_certs"))
! 212: rflags |= OCSP_NOCERTS;
! 213: else if (!strcmp(*args, "-resp_key_id"))
! 214: rflags |= OCSP_RESPID_KEY;
! 215: else if (!strcmp(*args, "-no_certs"))
! 216: sign_flags |= OCSP_NOCERTS;
! 217: else if (!strcmp(*args, "-no_signature_verify"))
! 218: verify_flags |= OCSP_NOSIGS;
! 219: else if (!strcmp(*args, "-no_cert_verify"))
! 220: verify_flags |= OCSP_NOVERIFY;
! 221: else if (!strcmp(*args, "-no_chain"))
! 222: verify_flags |= OCSP_NOCHAIN;
! 223: else if (!strcmp(*args, "-no_cert_checks"))
! 224: verify_flags |= OCSP_NOCHECKS;
! 225: else if (!strcmp(*args, "-no_explicit"))
! 226: verify_flags |= OCSP_NOEXPLICIT;
! 227: else if (!strcmp(*args, "-trust_other"))
! 228: verify_flags |= OCSP_TRUSTOTHER;
! 229: else if (!strcmp(*args, "-no_intern"))
! 230: verify_flags |= OCSP_NOINTERN;
! 231: else if (!strcmp(*args, "-text")) {
! 232: req_text = 1;
! 233: resp_text = 1;
! 234: } else if (!strcmp(*args, "-req_text"))
! 235: req_text = 1;
! 236: else if (!strcmp(*args, "-resp_text"))
! 237: resp_text = 1;
! 238: else if (!strcmp(*args, "-reqin")) {
! 239: if (args[1]) {
! 240: args++;
! 241: reqin = *args;
! 242: } else
! 243: badarg = 1;
! 244: } else if (!strcmp(*args, "-respin")) {
! 245: if (args[1]) {
! 246: args++;
! 247: respin = *args;
! 248: } else
! 249: badarg = 1;
! 250: } else if (!strcmp(*args, "-signer")) {
! 251: if (args[1]) {
! 252: args++;
! 253: signfile = *args;
! 254: } else
! 255: badarg = 1;
! 256: } else if (!strcmp(*args, "-VAfile")) {
! 257: if (args[1]) {
! 258: args++;
! 259: verify_certfile = *args;
! 260: verify_flags |= OCSP_TRUSTOTHER;
! 261: } else
! 262: badarg = 1;
! 263: } else if (!strcmp(*args, "-sign_other")) {
! 264: if (args[1]) {
! 265: args++;
! 266: sign_certfile = *args;
! 267: } else
! 268: badarg = 1;
! 269: } else if (!strcmp(*args, "-verify_other")) {
! 270: if (args[1]) {
! 271: args++;
! 272: verify_certfile = *args;
! 273: } else
! 274: badarg = 1;
! 275: } else if (!strcmp(*args, "-CAfile")) {
! 276: if (args[1]) {
! 277: args++;
! 278: CAfile = *args;
! 279: } else
! 280: badarg = 1;
! 281: } else if (!strcmp(*args, "-CApath")) {
! 282: if (args[1]) {
! 283: args++;
! 284: CApath = *args;
! 285: } else
! 286: badarg = 1;
! 287: } else if (!strcmp(*args, "-validity_period")) {
! 288: if (args[1]) {
! 289: args++;
! 290: nsec = strtonum(*args, 0, LONG_MAX, &errstr);
! 291: if (errstr) {
! 292: BIO_printf(bio_err,
! 293: "Illegal validity period %s: %s\n",
! 294: *args, errstr);
! 295: badarg = 1;
! 296: }
! 297: } else
! 298: badarg = 1;
! 299: } else if (!strcmp(*args, "-status_age")) {
! 300: if (args[1]) {
! 301: args++;
! 302: maxage = strtonum(*args, 0, LONG_MAX, &errstr);
! 303: if (errstr) {
! 304: BIO_printf(bio_err,
! 305: "Illegal validity age %s: %s\n",
! 306: *args, errstr);
! 307: badarg = 1;
! 308: }
! 309: } else
! 310: badarg = 1;
! 311: } else if (!strcmp(*args, "-signkey")) {
! 312: if (args[1]) {
! 313: args++;
! 314: keyfile = *args;
! 315: } else
! 316: badarg = 1;
! 317: } else if (!strcmp(*args, "-reqout")) {
! 318: if (args[1]) {
! 319: args++;
! 320: reqout = *args;
! 321: } else
! 322: badarg = 1;
! 323: } else if (!strcmp(*args, "-respout")) {
! 324: if (args[1]) {
! 325: args++;
! 326: respout = *args;
! 327: } else
! 328: badarg = 1;
! 329: } else if (!strcmp(*args, "-path")) {
! 330: if (args[1]) {
! 331: args++;
! 332: path = *args;
! 333: } else
! 334: badarg = 1;
! 335: } else if (!strcmp(*args, "-issuer")) {
! 336: if (args[1]) {
! 337: args++;
! 338: X509_free(issuer);
! 339: issuer = load_cert(bio_err, *args, FORMAT_PEM,
! 340: NULL, e, "issuer certificate");
! 341: if (!issuer)
! 342: goto end;
! 343: } else
! 344: badarg = 1;
! 345: } else if (!strcmp(*args, "-cert")) {
! 346: if (args[1]) {
! 347: args++;
! 348: X509_free(cert);
! 349: cert = load_cert(bio_err, *args, FORMAT_PEM,
! 350: NULL, e, "certificate");
! 351: if (!cert)
! 352: goto end;
! 353: if (!cert_id_md)
! 354: cert_id_md = EVP_sha1();
! 355: if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
! 356: goto end;
! 357: if (!sk_OPENSSL_STRING_push(reqnames, *args))
! 358: goto end;
! 359: } else
! 360: badarg = 1;
! 361: } else if (!strcmp(*args, "-serial")) {
! 362: if (args[1]) {
! 363: args++;
! 364: if (!cert_id_md)
! 365: cert_id_md = EVP_sha1();
! 366: if (!add_ocsp_serial(&req, *args, cert_id_md, issuer, ids))
! 367: goto end;
! 368: if (!sk_OPENSSL_STRING_push(reqnames, *args))
! 369: goto end;
! 370: } else
! 371: badarg = 1;
! 372: } else if (!strcmp(*args, "-index")) {
! 373: if (args[1]) {
! 374: args++;
! 375: ridx_filename = *args;
! 376: } else
! 377: badarg = 1;
! 378: } else if (!strcmp(*args, "-CA")) {
! 379: if (args[1]) {
! 380: args++;
! 381: rca_filename = *args;
! 382: } else
! 383: badarg = 1;
! 384: } else if (!strcmp(*args, "-nmin")) {
! 385: if (args[1]) {
! 386: args++;
! 387: nmin = strtonum(*args, 0, INT_MAX, &errstr);
! 388: if (errstr) {
! 389: BIO_printf(bio_err,
! 390: "Illegal update period %s: %s\n",
! 391: *args, errstr);
! 392: badarg = 1;
! 393: }
! 394: }
! 395: if (ndays == -1)
! 396: ndays = 0;
! 397: else
! 398: badarg = 1;
! 399: } else if (!strcmp(*args, "-nrequest")) {
! 400: if (args[1]) {
! 401: args++;
! 402: accept_count = strtonum(*args, 0, INT_MAX, &errstr);
! 403: if (errstr) {
! 404: BIO_printf(bio_err,
! 405: "Illegal accept count %s: %s\n",
! 406: *args, errstr);
! 407: badarg = 1;
! 408: }
! 409: } else
! 410: badarg = 1;
! 411: } else if (!strcmp(*args, "-ndays")) {
! 412: if (args[1]) {
! 413: args++;
! 414: ndays = strtonum(*args, 0, INT_MAX, &errstr);
! 415: if (errstr) {
! 416: BIO_printf(bio_err,
! 417: "Illegal update period %s: %s\n",
! 418: *args, errstr);
! 419: badarg = 1;
! 420: }
! 421: } else
! 422: badarg = 1;
! 423: } else if (!strcmp(*args, "-rsigner")) {
! 424: if (args[1]) {
! 425: args++;
! 426: rsignfile = *args;
! 427: } else
! 428: badarg = 1;
! 429: } else if (!strcmp(*args, "-rkey")) {
! 430: if (args[1]) {
! 431: args++;
! 432: rkeyfile = *args;
! 433: } else
! 434: badarg = 1;
! 435: } else if (!strcmp(*args, "-rother")) {
! 436: if (args[1]) {
! 437: args++;
! 438: rcertfile = *args;
! 439: } else
! 440: badarg = 1;
! 441: } else if ((cert_id_md = EVP_get_digestbyname((*args) + 1)) == NULL) {
! 442: badarg = 1;
! 443: }
! 444: args++;
! 445: }
! 446:
! 447: /* Have we anything to do? */
! 448: if (!req && !reqin && !respin && !(port && ridx_filename))
! 449: badarg = 1;
! 450:
! 451: if (badarg) {
! 452: BIO_printf(bio_err, "OCSP utility\n");
! 453: BIO_printf(bio_err, "Usage ocsp [options]\n");
! 454: BIO_printf(bio_err, "where options are\n");
! 455: BIO_printf(bio_err, "-out file output filename\n");
! 456: BIO_printf(bio_err, "-issuer file issuer certificate\n");
! 457: BIO_printf(bio_err, "-cert file certificate to check\n");
! 458: BIO_printf(bio_err, "-serial n serial number to check\n");
! 459: BIO_printf(bio_err, "-signer file certificate to sign OCSP request with\n");
! 460: BIO_printf(bio_err, "-signkey file private key to sign OCSP request with\n");
! 461: BIO_printf(bio_err, "-sign_other file additional certificates to include in signed request\n");
! 462: BIO_printf(bio_err, "-no_certs don't include any certificates in signed request\n");
! 463: BIO_printf(bio_err, "-req_text print text form of request\n");
! 464: BIO_printf(bio_err, "-resp_text print text form of response\n");
! 465: BIO_printf(bio_err, "-text print text form of request and response\n");
! 466: BIO_printf(bio_err, "-reqout file write DER encoded OCSP request to \"file\"\n");
! 467: BIO_printf(bio_err, "-respout file write DER encoded OCSP reponse to \"file\"\n");
! 468: BIO_printf(bio_err, "-reqin file read DER encoded OCSP request from \"file\"\n");
! 469: BIO_printf(bio_err, "-respin file read DER encoded OCSP reponse from \"file\"\n");
! 470: BIO_printf(bio_err, "-nonce add OCSP nonce to request\n");
! 471: BIO_printf(bio_err, "-no_nonce don't add OCSP nonce to request\n");
! 472: BIO_printf(bio_err, "-url URL OCSP responder URL\n");
! 473: BIO_printf(bio_err, "-host host:n send OCSP request to host on port n\n");
! 474: BIO_printf(bio_err, "-path path to use in OCSP request\n");
! 475: BIO_printf(bio_err, "-CApath dir trusted certificates directory\n");
! 476: BIO_printf(bio_err, "-CAfile file trusted certificates file\n");
! 477: BIO_printf(bio_err, "-VAfile file validator certificates file\n");
! 478: BIO_printf(bio_err, "-validity_period n maximum validity discrepancy in seconds\n");
! 479: BIO_printf(bio_err, "-status_age n maximum status age in seconds\n");
! 480: BIO_printf(bio_err, "-noverify don't verify response at all\n");
! 481: BIO_printf(bio_err, "-verify_other file additional certificates to search for signer\n");
! 482: BIO_printf(bio_err, "-trust_other don't verify additional certificates\n");
! 483: BIO_printf(bio_err, "-no_intern don't search certificates contained in response for signer\n");
! 484: BIO_printf(bio_err, "-no_signature_verify don't check signature on response\n");
! 485: BIO_printf(bio_err, "-no_cert_verify don't check signing certificate\n");
! 486: BIO_printf(bio_err, "-no_chain don't chain verify response\n");
! 487: BIO_printf(bio_err, "-no_cert_checks don't do additional checks on signing certificate\n");
! 488: BIO_printf(bio_err, "-port num port to run responder on\n");
! 489: BIO_printf(bio_err, "-index file certificate status index file\n");
! 490: BIO_printf(bio_err, "-CA file CA certificate\n");
! 491: BIO_printf(bio_err, "-rsigner file responder certificate to sign responses with\n");
! 492: BIO_printf(bio_err, "-rkey file responder key to sign responses with\n");
! 493: BIO_printf(bio_err, "-rother file other certificates to include in response\n");
! 494: BIO_printf(bio_err, "-resp_no_certs don't include any certificates in response\n");
! 495: BIO_printf(bio_err, "-nmin n number of minutes before next update\n");
! 496: BIO_printf(bio_err, "-ndays n number of days before next update\n");
! 497: BIO_printf(bio_err, "-resp_key_id identify reponse by signing certificate key ID\n");
! 498: BIO_printf(bio_err, "-nrequest n number of requests to accept (default unlimited)\n");
! 499: BIO_printf(bio_err, "-<dgst alg> use specified digest in the request\n");
! 500: goto end;
! 501: }
! 502: if (outfile)
! 503: out = BIO_new_file(outfile, "w");
! 504: else
! 505: out = BIO_new_fp(stdout, BIO_NOCLOSE);
! 506:
! 507: if (!out) {
! 508: BIO_printf(bio_err, "Error opening output file\n");
! 509: goto end;
! 510: }
! 511: if (!req && (add_nonce != 2))
! 512: add_nonce = 0;
! 513:
! 514: if (!req && reqin) {
! 515: derbio = BIO_new_file(reqin, "rb");
! 516: if (!derbio) {
! 517: BIO_printf(bio_err, "Error Opening OCSP request file\n");
! 518: goto end;
! 519: }
! 520: req = d2i_OCSP_REQUEST_bio(derbio, NULL);
! 521: BIO_free(derbio);
! 522: if (!req) {
! 523: BIO_printf(bio_err, "Error reading OCSP request\n");
! 524: goto end;
! 525: }
! 526: }
! 527: if (!req && port) {
! 528: acbio = init_responder(port);
! 529: if (!acbio)
! 530: goto end;
! 531: }
! 532: if (rsignfile && !rdb) {
! 533: if (!rkeyfile)
! 534: rkeyfile = rsignfile;
! 535: rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
! 536: NULL, e, "responder certificate");
! 537: if (!rsigner) {
! 538: BIO_printf(bio_err, "Error loading responder certificate\n");
! 539: goto end;
! 540: }
! 541: rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM,
! 542: NULL, e, "CA certificate");
! 543: if (rcertfile) {
! 544: rother = load_certs(bio_err, rcertfile, FORMAT_PEM,
! 545: NULL, e, "responder other certificates");
! 546: if (!rother)
! 547: goto end;
! 548: }
! 549: rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL,
! 550: "responder private key");
! 551: if (!rkey)
! 552: goto end;
! 553: }
! 554: if (acbio)
! 555: BIO_printf(bio_err, "Waiting for OCSP client connections...\n");
! 556:
! 557: redo_accept:
! 558:
! 559: if (acbio) {
! 560: if (!do_responder(&req, &cbio, acbio, port))
! 561: goto end;
! 562: if (!req) {
! 563: resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
! 564: send_ocsp_response(cbio, resp);
! 565: goto done_resp;
! 566: }
! 567: }
! 568: if (!req && (signfile || reqout || host || add_nonce || ridx_filename)) {
! 569: BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
! 570: goto end;
! 571: }
! 572: if (req && add_nonce)
! 573: OCSP_request_add1_nonce(req, NULL, -1);
! 574:
! 575: if (signfile) {
! 576: if (!keyfile)
! 577: keyfile = signfile;
! 578: signer = load_cert(bio_err, signfile, FORMAT_PEM,
! 579: NULL, e, "signer certificate");
! 580: if (!signer) {
! 581: BIO_printf(bio_err, "Error loading signer certificate\n");
! 582: goto end;
! 583: }
! 584: if (sign_certfile) {
! 585: sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM,
! 586: NULL, e, "signer certificates");
! 587: if (!sign_other)
! 588: goto end;
! 589: }
! 590: key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL,
! 591: "signer private key");
! 592: if (!key)
! 593: goto end;
! 594:
! 595: if (!OCSP_request_sign(req, signer, key, NULL, sign_other, sign_flags)) {
! 596: BIO_printf(bio_err, "Error signing OCSP request\n");
! 597: goto end;
! 598: }
! 599: }
! 600: if (req_text && req)
! 601: OCSP_REQUEST_print(out, req, 0);
! 602:
! 603: if (reqout) {
! 604: derbio = BIO_new_file(reqout, "wb");
! 605: if (!derbio) {
! 606: BIO_printf(bio_err, "Error opening file %s\n", reqout);
! 607: goto end;
! 608: }
! 609: i2d_OCSP_REQUEST_bio(derbio, req);
! 610: BIO_free(derbio);
! 611: }
! 612: if (ridx_filename && (!rkey || !rsigner || !rca_cert)) {
! 613: BIO_printf(bio_err, "Need a responder certificate, key and CA for this operation!\n");
! 614: goto end;
! 615: }
! 616: if (ridx_filename && !rdb) {
! 617: rdb = load_index(ridx_filename, NULL);
! 618: if (!rdb)
! 619: goto end;
! 620: if (!index_index(rdb))
! 621: goto end;
! 622: }
! 623: if (rdb) {
! 624: i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey, rother, rflags, nmin, ndays);
! 625: if (cbio)
! 626: send_ocsp_response(cbio, resp);
! 627: } else if (host) {
! 628: resp = process_responder(bio_err, req, host, path,
! 629: port, use_ssl, headers, req_timeout);
! 630: if (!resp)
! 631: goto end;
! 632: } else if (respin) {
! 633: derbio = BIO_new_file(respin, "rb");
! 634: if (!derbio) {
! 635: BIO_printf(bio_err, "Error Opening OCSP response file\n");
! 636: goto end;
! 637: }
! 638: resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
! 639: BIO_free(derbio);
! 640: if (!resp) {
! 641: BIO_printf(bio_err, "Error reading OCSP response\n");
! 642: goto end;
! 643: }
! 644: } else {
! 645: ret = 0;
! 646: goto end;
! 647: }
! 648:
! 649: done_resp:
! 650:
! 651: if (respout) {
! 652: derbio = BIO_new_file(respout, "wb");
! 653: if (!derbio) {
! 654: BIO_printf(bio_err, "Error opening file %s\n", respout);
! 655: goto end;
! 656: }
! 657: i2d_OCSP_RESPONSE_bio(derbio, resp);
! 658: BIO_free(derbio);
! 659: }
! 660: i = OCSP_response_status(resp);
! 661:
! 662: if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
! 663: BIO_printf(out, "Responder Error: %s (%d)\n",
! 664: OCSP_response_status_str(i), i);
! 665: if (ignore_err)
! 666: goto redo_accept;
! 667: ret = 0;
! 668: goto end;
! 669: }
! 670: if (resp_text)
! 671: OCSP_RESPONSE_print(out, resp, 0);
! 672:
! 673: /* If running as responder don't verify our own response */
! 674: if (cbio) {
! 675: if (accept_count > 0)
! 676: accept_count--;
! 677: /* Redo if more connections needed */
! 678: if (accept_count) {
! 679: BIO_free_all(cbio);
! 680: cbio = NULL;
! 681: OCSP_REQUEST_free(req);
! 682: req = NULL;
! 683: OCSP_RESPONSE_free(resp);
! 684: resp = NULL;
! 685: goto redo_accept;
! 686: }
! 687: goto end;
! 688: }
! 689: if (!store)
! 690: store = setup_verify(bio_err, CAfile, CApath);
! 691: if (!store)
! 692: goto end;
! 693: if (verify_certfile) {
! 694: verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM,
! 695: NULL, e, "validator certificate");
! 696: if (!verify_other)
! 697: goto end;
! 698: }
! 699: bs = OCSP_response_get1_basic(resp);
! 700:
! 701: if (!bs) {
! 702: BIO_printf(bio_err, "Error parsing response\n");
! 703: goto end;
! 704: }
! 705: if (!noverify) {
! 706: if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
! 707: if (i == -1)
! 708: BIO_printf(bio_err, "WARNING: no nonce in response\n");
! 709: else {
! 710: BIO_printf(bio_err, "Nonce Verify error\n");
! 711: goto end;
! 712: }
! 713: }
! 714: i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
! 715: if (i < 0)
! 716: i = OCSP_basic_verify(bs, NULL, store, 0);
! 717:
! 718: if (i <= 0) {
! 719: BIO_printf(bio_err, "Response Verify Failure\n");
! 720: ERR_print_errors(bio_err);
! 721: } else
! 722: BIO_printf(bio_err, "Response verify OK\n");
! 723:
! 724: }
! 725: if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
! 726: goto end;
! 727:
! 728: ret = 0;
! 729:
! 730: end:
! 731: ERR_print_errors(bio_err);
! 732: X509_free(signer);
! 733: X509_STORE_free(store);
! 734: EVP_PKEY_free(key);
! 735: EVP_PKEY_free(rkey);
! 736: X509_free(issuer);
! 737: X509_free(cert);
! 738: X509_free(rsigner);
! 739: X509_free(rca_cert);
! 740: free_index(rdb);
! 741: BIO_free_all(cbio);
! 742: BIO_free_all(acbio);
! 743: BIO_free(out);
! 744: OCSP_REQUEST_free(req);
! 745: OCSP_RESPONSE_free(resp);
! 746: OCSP_BASICRESP_free(bs);
! 747: sk_OPENSSL_STRING_free(reqnames);
! 748: sk_OCSP_CERTID_free(ids);
! 749: sk_X509_pop_free(sign_other, X509_free);
! 750: sk_X509_pop_free(verify_other, X509_free);
! 751: sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
! 752:
! 753: if (use_ssl != -1) {
! 754: free(host);
! 755: free(port);
! 756: free(path);
! 757: }
! 758: return (ret);
! 759: }
! 760:
! 761: static int
! 762: add_ocsp_cert(OCSP_REQUEST ** req, X509 * cert, const EVP_MD * cert_id_md, X509 * issuer,
! 763: STACK_OF(OCSP_CERTID) * ids)
! 764: {
! 765: OCSP_CERTID *id;
! 766: if (!issuer) {
! 767: BIO_printf(bio_err, "No issuer certificate specified\n");
! 768: return 0;
! 769: }
! 770: if (!*req)
! 771: *req = OCSP_REQUEST_new();
! 772: if (!*req)
! 773: goto err;
! 774: id = OCSP_cert_to_id(cert_id_md, cert, issuer);
! 775: if (!id || !sk_OCSP_CERTID_push(ids, id))
! 776: goto err;
! 777: if (!OCSP_request_add0_id(*req, id))
! 778: goto err;
! 779: return 1;
! 780:
! 781: err:
! 782: BIO_printf(bio_err, "Error Creating OCSP request\n");
! 783: return 0;
! 784: }
! 785:
! 786: static int
! 787: add_ocsp_serial(OCSP_REQUEST ** req, char *serial, const EVP_MD * cert_id_md, X509 * issuer,
! 788: STACK_OF(OCSP_CERTID) * ids)
! 789: {
! 790: OCSP_CERTID *id;
! 791: X509_NAME *iname;
! 792: ASN1_BIT_STRING *ikey;
! 793: ASN1_INTEGER *sno;
! 794: if (!issuer) {
! 795: BIO_printf(bio_err, "No issuer certificate specified\n");
! 796: return 0;
! 797: }
! 798: if (!*req)
! 799: *req = OCSP_REQUEST_new();
! 800: if (!*req)
! 801: goto err;
! 802: iname = X509_get_subject_name(issuer);
! 803: ikey = X509_get0_pubkey_bitstr(issuer);
! 804: sno = s2i_ASN1_INTEGER(NULL, serial);
! 805: if (!sno) {
! 806: BIO_printf(bio_err, "Error converting serial number %s\n", serial);
! 807: return 0;
! 808: }
! 809: id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno);
! 810: ASN1_INTEGER_free(sno);
! 811: if (!id || !sk_OCSP_CERTID_push(ids, id))
! 812: goto err;
! 813: if (!OCSP_request_add0_id(*req, id))
! 814: goto err;
! 815: return 1;
! 816:
! 817: err:
! 818: BIO_printf(bio_err, "Error Creating OCSP request\n");
! 819: return 0;
! 820: }
! 821:
! 822: static int
! 823: print_ocsp_summary(BIO * out, OCSP_BASICRESP * bs, OCSP_REQUEST * req,
! 824: STACK_OF(OPENSSL_STRING) * names,
! 825: STACK_OF(OCSP_CERTID) * ids, long nsec,
! 826: long maxage)
! 827: {
! 828: OCSP_CERTID *id;
! 829: char *name;
! 830: int i;
! 831:
! 832: int status, reason;
! 833:
! 834: ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
! 835:
! 836: if (!bs || !req || !sk_OPENSSL_STRING_num(names) || !sk_OCSP_CERTID_num(ids))
! 837: return 1;
! 838:
! 839: for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) {
! 840: id = sk_OCSP_CERTID_value(ids, i);
! 841: name = sk_OPENSSL_STRING_value(names, i);
! 842: BIO_printf(out, "%s: ", name);
! 843:
! 844: if (!OCSP_resp_find_status(bs, id, &status, &reason,
! 845: &rev, &thisupd, &nextupd)) {
! 846: BIO_puts(out, "ERROR: No Status found.\n");
! 847: continue;
! 848: }
! 849: /*
! 850: * Check validity: if invalid write to output BIO so we know
! 851: * which response this refers to.
! 852: */
! 853: if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
! 854: BIO_puts(out, "WARNING: Status times invalid.\n");
! 855: ERR_print_errors(out);
! 856: }
! 857: BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
! 858:
! 859: BIO_puts(out, "\tThis Update: ");
! 860: ASN1_GENERALIZEDTIME_print(out, thisupd);
! 861: BIO_puts(out, "\n");
! 862:
! 863: if (nextupd) {
! 864: BIO_puts(out, "\tNext Update: ");
! 865: ASN1_GENERALIZEDTIME_print(out, nextupd);
! 866: BIO_puts(out, "\n");
! 867: }
! 868: if (status != V_OCSP_CERTSTATUS_REVOKED)
! 869: continue;
! 870:
! 871: if (reason != -1)
! 872: BIO_printf(out, "\tReason: %s\n",
! 873: OCSP_crl_reason_str(reason));
! 874:
! 875: BIO_puts(out, "\tRevocation Time: ");
! 876: ASN1_GENERALIZEDTIME_print(out, rev);
! 877: BIO_puts(out, "\n");
! 878: }
! 879:
! 880: return 1;
! 881: }
! 882:
! 883:
! 884: static int
! 885: make_ocsp_response(OCSP_RESPONSE ** resp, OCSP_REQUEST * req, CA_DB * db,
! 886: X509 * ca, X509 * rcert, EVP_PKEY * rkey,
! 887: STACK_OF(X509) * rother, unsigned long flags,
! 888: int nmin, int ndays)
! 889: {
! 890: ASN1_TIME *thisupd = NULL, *nextupd = NULL;
! 891: OCSP_CERTID *cid, *ca_id = NULL;
! 892: OCSP_BASICRESP *bs = NULL;
! 893: int i, id_count, ret = 1;
! 894:
! 895: id_count = OCSP_request_onereq_count(req);
! 896:
! 897: if (id_count <= 0) {
! 898: *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
! 899: goto end;
! 900: }
! 901: bs = OCSP_BASICRESP_new();
! 902: thisupd = X509_gmtime_adj(NULL, 0);
! 903: if (ndays != -1)
! 904: nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24);
! 905:
! 906: /* Examine each certificate id in the request */
! 907: for (i = 0; i < id_count; i++) {
! 908: OCSP_ONEREQ *one;
! 909: ASN1_INTEGER *serial;
! 910: char **inf;
! 911: ASN1_OBJECT *cert_id_md_oid;
! 912: const EVP_MD *cert_id_md;
! 913: one = OCSP_request_onereq_get0(req, i);
! 914: cid = OCSP_onereq_get0_id(one);
! 915:
! 916: OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, cid);
! 917:
! 918: cert_id_md = EVP_get_digestbyobj(cert_id_md_oid);
! 919: if (!cert_id_md) {
! 920: *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
! 921: NULL);
! 922: goto end;
! 923: }
! 924: if (ca_id)
! 925: OCSP_CERTID_free(ca_id);
! 926: ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca);
! 927:
! 928: /* Is this request about our CA? */
! 929: if (OCSP_id_issuer_cmp(ca_id, cid)) {
! 930: OCSP_basic_add1_status(bs, cid,
! 931: V_OCSP_CERTSTATUS_UNKNOWN,
! 932: 0, NULL,
! 933: thisupd, nextupd);
! 934: continue;
! 935: }
! 936: OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
! 937: inf = lookup_serial(db, serial);
! 938: if (!inf)
! 939: OCSP_basic_add1_status(bs, cid,
! 940: V_OCSP_CERTSTATUS_UNKNOWN,
! 941: 0, NULL,
! 942: thisupd, nextupd);
! 943: else if (inf[DB_type][0] == DB_TYPE_VAL)
! 944: OCSP_basic_add1_status(bs, cid,
! 945: V_OCSP_CERTSTATUS_GOOD,
! 946: 0, NULL,
! 947: thisupd, nextupd);
! 948: else if (inf[DB_type][0] == DB_TYPE_REV) {
! 949: ASN1_OBJECT *inst = NULL;
! 950: ASN1_TIME *revtm = NULL;
! 951: ASN1_GENERALIZEDTIME *invtm = NULL;
! 952: OCSP_SINGLERESP *single;
! 953: int reason = -1;
! 954: unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
! 955: single = OCSP_basic_add1_status(bs, cid,
! 956: V_OCSP_CERTSTATUS_REVOKED,
! 957: reason, revtm,
! 958: thisupd, nextupd);
! 959: if (invtm)
! 960: OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0);
! 961: else if (inst)
! 962: OCSP_SINGLERESP_add1_ext_i2d(single, NID_hold_instruction_code, inst, 0, 0);
! 963: ASN1_OBJECT_free(inst);
! 964: ASN1_TIME_free(revtm);
! 965: ASN1_GENERALIZEDTIME_free(invtm);
! 966: }
! 967: }
! 968:
! 969: OCSP_copy_nonce(bs, req);
! 970:
! 971: OCSP_basic_sign(bs, rcert, rkey, NULL, rother, flags);
! 972:
! 973: *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
! 974:
! 975: end:
! 976: ASN1_TIME_free(thisupd);
! 977: ASN1_TIME_free(nextupd);
! 978: OCSP_CERTID_free(ca_id);
! 979: OCSP_BASICRESP_free(bs);
! 980: return ret;
! 981:
! 982: }
! 983:
! 984: static char **
! 985: lookup_serial(CA_DB * db, ASN1_INTEGER * ser)
! 986: {
! 987: int i;
! 988: BIGNUM *bn = NULL;
! 989: char *itmp, *row[DB_NUMBER], **rrow;
! 990: for (i = 0; i < DB_NUMBER; i++)
! 991: row[i] = NULL;
! 992: bn = ASN1_INTEGER_to_BN(ser, NULL);
! 993: OPENSSL_assert(bn); /* FIXME: should report an error at this
! 994: * point and abort */
! 995: if (BN_is_zero(bn))
! 996: itmp = strdup("00");
! 997: else
! 998: itmp = BN_bn2hex(bn);
! 999: row[DB_serial] = itmp;
! 1000: BN_free(bn);
! 1001: rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
! 1002: free(itmp);
! 1003: return rrow;
! 1004: }
! 1005:
! 1006: /* Quick and dirty OCSP server: read in and parse input request */
! 1007:
! 1008: static BIO *
! 1009: init_responder(char *port)
! 1010: {
! 1011: BIO *acbio = NULL, *bufbio = NULL;
! 1012: bufbio = BIO_new(BIO_f_buffer());
! 1013: if (!bufbio)
! 1014: goto err;
! 1015: acbio = BIO_new_accept(port);
! 1016: if (!acbio)
! 1017: goto err;
! 1018: BIO_set_accept_bios(acbio, bufbio);
! 1019: bufbio = NULL;
! 1020:
! 1021: if (BIO_do_accept(acbio) <= 0) {
! 1022: BIO_printf(bio_err, "Error setting up accept BIO\n");
! 1023: ERR_print_errors(bio_err);
! 1024: goto err;
! 1025: }
! 1026: return acbio;
! 1027:
! 1028: err:
! 1029: BIO_free_all(acbio);
! 1030: BIO_free(bufbio);
! 1031: return NULL;
! 1032: }
! 1033:
! 1034: static int
! 1035: do_responder(OCSP_REQUEST ** preq, BIO ** pcbio, BIO * acbio, char *port)
! 1036: {
! 1037: int have_post = 0, len;
! 1038: OCSP_REQUEST *req = NULL;
! 1039: char inbuf[1024];
! 1040: BIO *cbio = NULL;
! 1041:
! 1042: if (BIO_do_accept(acbio) <= 0) {
! 1043: BIO_printf(bio_err, "Error accepting connection\n");
! 1044: ERR_print_errors(bio_err);
! 1045: return 0;
! 1046: }
! 1047: cbio = BIO_pop(acbio);
! 1048: *pcbio = cbio;
! 1049:
! 1050: for (;;) {
! 1051: len = BIO_gets(cbio, inbuf, sizeof inbuf);
! 1052: if (len <= 0)
! 1053: return 1;
! 1054: /* Look for "POST" signalling start of query */
! 1055: if (!have_post) {
! 1056: if (strncmp(inbuf, "POST", 4)) {
! 1057: BIO_printf(bio_err, "Invalid request\n");
! 1058: return 1;
! 1059: }
! 1060: have_post = 1;
! 1061: }
! 1062: /* Look for end of headers */
! 1063: if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
! 1064: break;
! 1065: }
! 1066:
! 1067: /* Try to read OCSP request */
! 1068:
! 1069: req = d2i_OCSP_REQUEST_bio(cbio, NULL);
! 1070:
! 1071: if (!req) {
! 1072: BIO_printf(bio_err, "Error parsing OCSP request\n");
! 1073: ERR_print_errors(bio_err);
! 1074: }
! 1075: *preq = req;
! 1076:
! 1077: return 1;
! 1078:
! 1079: }
! 1080:
! 1081: static int
! 1082: send_ocsp_response(BIO * cbio, OCSP_RESPONSE * resp)
! 1083: {
! 1084: static const char http_resp[] =
! 1085: "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
! 1086: "Content-Length: %d\r\n\r\n";
! 1087: if (!cbio)
! 1088: return 0;
! 1089: BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
! 1090: i2d_OCSP_RESPONSE_bio(cbio, resp);
! 1091: (void) BIO_flush(cbio);
! 1092: return 1;
! 1093: }
! 1094:
! 1095: static OCSP_RESPONSE *
! 1096: query_responder(BIO * err, BIO * cbio, char *path,
! 1097: STACK_OF(CONF_VALUE) * headers,
! 1098: OCSP_REQUEST * req, int req_timeout)
! 1099: {
! 1100: int fd;
! 1101: int rv;
! 1102: int i;
! 1103: OCSP_REQ_CTX *ctx = NULL;
! 1104: OCSP_RESPONSE *rsp = NULL;
! 1105: fd_set confds;
! 1106: struct timeval tv;
! 1107:
! 1108: if (req_timeout != -1)
! 1109: BIO_set_nbio(cbio, 1);
! 1110:
! 1111: rv = BIO_do_connect(cbio);
! 1112:
! 1113: if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
! 1114: BIO_puts(err, "Error connecting BIO\n");
! 1115: return NULL;
! 1116: }
! 1117: if (BIO_get_fd(cbio, &fd) <= 0) {
! 1118: BIO_puts(err, "Can't get connection fd\n");
! 1119: goto err;
! 1120: }
! 1121: if (req_timeout != -1 && rv <= 0) {
! 1122: FD_ZERO(&confds);
! 1123: FD_SET(fd, &confds);
! 1124: tv.tv_usec = 0;
! 1125: tv.tv_sec = req_timeout;
! 1126: rv = select(fd + 1, NULL, &confds, NULL, &tv);
! 1127: if (rv == 0) {
! 1128: BIO_puts(err, "Timeout on connect\n");
! 1129: return NULL;
! 1130: }
! 1131: }
! 1132: ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
! 1133: if (!ctx)
! 1134: return NULL;
! 1135:
! 1136: for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
! 1137: CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
! 1138: if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
! 1139: goto err;
! 1140: }
! 1141:
! 1142: if (!OCSP_REQ_CTX_set1_req(ctx, req))
! 1143: goto err;
! 1144:
! 1145: for (;;) {
! 1146: rv = OCSP_sendreq_nbio(&rsp, ctx);
! 1147: if (rv != -1)
! 1148: break;
! 1149: if (req_timeout == -1)
! 1150: continue;
! 1151: FD_ZERO(&confds);
! 1152: FD_SET(fd, &confds);
! 1153: tv.tv_usec = 0;
! 1154: tv.tv_sec = req_timeout;
! 1155: if (BIO_should_read(cbio))
! 1156: rv = select(fd + 1, &confds, NULL, NULL, &tv);
! 1157: else if (BIO_should_write(cbio))
! 1158: rv = select(fd + 1, NULL, &confds, NULL, &tv);
! 1159: else {
! 1160: BIO_puts(err, "Unexpected retry condition\n");
! 1161: goto err;
! 1162: }
! 1163: if (rv == 0) {
! 1164: BIO_puts(err, "Timeout on request\n");
! 1165: break;
! 1166: }
! 1167: if (rv == -1) {
! 1168: BIO_puts(err, "Select error\n");
! 1169: break;
! 1170: }
! 1171: }
! 1172: err:
! 1173: if (ctx)
! 1174: OCSP_REQ_CTX_free(ctx);
! 1175:
! 1176: return rsp;
! 1177: }
! 1178:
! 1179: OCSP_RESPONSE *
! 1180: process_responder(BIO * err, OCSP_REQUEST * req,
! 1181: char *host, char *path, char *port, int use_ssl,
! 1182: STACK_OF(CONF_VALUE) * headers,
! 1183: int req_timeout)
! 1184: {
! 1185: BIO *cbio = NULL;
! 1186: SSL_CTX *ctx = NULL;
! 1187: OCSP_RESPONSE *resp = NULL;
! 1188: cbio = BIO_new_connect(host);
! 1189: if (!cbio) {
! 1190: BIO_printf(err, "Error creating connect BIO\n");
! 1191: goto end;
! 1192: }
! 1193: if (port)
! 1194: BIO_set_conn_port(cbio, port);
! 1195: if (use_ssl == 1) {
! 1196: BIO *sbio;
! 1197: ctx = SSL_CTX_new(SSLv23_client_method());
! 1198: if (ctx == NULL) {
! 1199: BIO_printf(err, "Error creating SSL context.\n");
! 1200: goto end;
! 1201: }
! 1202: SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
! 1203: sbio = BIO_new_ssl(ctx, 1);
! 1204: cbio = BIO_push(sbio, cbio);
! 1205: }
! 1206: resp = query_responder(err, cbio, path, headers, req, req_timeout);
! 1207: if (!resp)
! 1208: BIO_printf(bio_err, "Error querying OCSP responder\n");
! 1209: end:
! 1210: if (cbio)
! 1211: BIO_free_all(cbio);
! 1212: if (ctx)
! 1213: SSL_CTX_free(ctx);
! 1214: return resp;
! 1215: }
! 1216:
! 1217: #endif