From 18e503f30facd53d5be24a7d84f1a9456652e399 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 30 Sep 2009 21:40:55 +0000 Subject: [PATCH] PR: 2064, 728 Submitted by: steve@openssl.org Add support for custom headers in OCSP requests. --- CHANGES | 4 ++++ apps/apps.h | 1 + apps/ocsp.c | 42 +++++++++++++++++++++++++------- apps/s_server.c | 2 +- crypto/ocsp/ocsp.h | 3 +++ crypto/ocsp/ocsp_ht.c | 56 +++++++++++++++++++++++++++++++------------ 6 files changed, 84 insertions(+), 24 deletions(-) diff --git a/CHANGES b/CHANGES index a8397f861c..a9284d67e3 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,10 @@ Changes between 0.9.8k and 1.0 [xx XXX xxxx] + *) Update OCSP request code to permit adding custom headers to the request: + some responders need this. + [Steve Henson] + *) Extensive audit of libcrypto with DEBUG_UNUSED. Fix many cases where return value is ignored. NB. The functions RAND_add(), RAND_seed(), BIO_set_cipher() and some obscure PEM functions were changed so they diff --git a/apps/apps.h b/apps/apps.h index 361ca9eea4..35a0266414 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -259,6 +259,7 @@ ENGINE *setup_engine(BIO *err, const char *engine, int debug); #ifndef OPENSSL_NO_OCSP OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req, char *host, char *path, char *port, int use_ssl, + STACK_OF(CONF_VALUE) *headers, int req_timeout); #endif diff --git a/apps/ocsp.c b/apps/ocsp.c index 173a67b4c4..01847dfad7 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -75,6 +75,7 @@ #include #include #include +#include #if defined(NETWARE_CLIB) # ifdef NETWARE_BSDSOCK @@ -113,6 +114,7 @@ static BIO *init_responder(char *port); static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port); static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp); static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path, + STACK_OF(CONF_VALUE) *headers, OCSP_REQUEST *req, int req_timeout); #undef PROG @@ -131,6 +133,7 @@ int MAIN(int argc, char **argv) char *rsignfile = NULL, *rkeyfile = NULL; char *outfile = NULL; int add_nonce = 1, noverify = 0, use_ssl = -1; + STACK_OF(CONF_VALUE) *headers = NULL; OCSP_REQUEST *req = NULL; OCSP_RESPONSE *resp = NULL; OCSP_BASICRESP *bs = NULL; @@ -230,6 +233,16 @@ int MAIN(int argc, char **argv) } else badarg = 1; } + else if (!strcmp(*args, "-header")) + { + if (args[1] && args[2]) + { + if (!X509V3_add_value(args[1], args[2], &headers)) + goto end; + args += 2; + } + else badarg = 1; + } else if (!strcmp(*args, "-ignore_err")) ignore_err = 1; else if (!strcmp(*args, "-noverify")) @@ -756,7 +769,7 @@ int MAIN(int argc, char **argv) { #ifndef OPENSSL_NO_SOCK resp = process_responder(bio_err, req, host, path, - port, use_ssl, req_timeout); + port, use_ssl, headers, req_timeout); if (!resp) goto end; #else @@ -905,6 +918,7 @@ end: sk_OCSP_CERTID_free(ids); sk_X509_pop_free(sign_other, X509_free); sk_X509_pop_free(verify_other, X509_free); + sk_CONF_VALUE_pop_free(headers, X509V3_conf_free); if (use_ssl != -1) { @@ -1260,10 +1274,12 @@ static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) } static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path, + STACK_OF(CONF_VALUE) *headers, OCSP_REQUEST *req, int req_timeout) { int fd; int rv; + int i; OCSP_REQ_CTX *ctx = NULL; OCSP_RESPONSE *rsp = NULL; fd_set confds; @@ -1280,16 +1296,13 @@ static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path, return NULL; } - if (req_timeout == -1) - return OCSP_sendreq_bio(cbio, path, req); - if (BIO_get_fd(cbio, &fd) <= 0) { BIO_puts(err, "Can't get connection fd\n"); goto err; } - if (rv <= 0) + if (req_timeout != -1 && rv <= 0) { FD_ZERO(&confds); openssl_fdset(fd, &confds); @@ -1304,15 +1317,27 @@ static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path, } - ctx = OCSP_sendreq_new(cbio, path, req, -1); + ctx = OCSP_sendreq_new(cbio, path, NULL, -1); if (!ctx) return NULL; + + for (i = 0; i < sk_CONF_VALUE_num(headers); i++) + { + CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i); + if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value)) + goto err; + } + + if (!OCSP_REQ_CTX_set1_req(ctx, req)) + goto err; for (;;) { rv = OCSP_sendreq_nbio(&rsp, ctx); if (rv != -1) break; + if (req_timeout == -1) + continue; FD_ZERO(&confds); openssl_fdset(fd, &confds); tv.tv_usec = 0; @@ -1336,7 +1361,7 @@ static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path, BIO_puts(err, "Select error\n"); break; } - + } err: if (ctx) @@ -1347,6 +1372,7 @@ static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path, OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req, char *host, char *path, char *port, int use_ssl, + STACK_OF(CONF_VALUE) *headers, int req_timeout) { BIO *cbio = NULL; @@ -1381,7 +1407,7 @@ OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req, sbio = BIO_new_ssl(ctx, 1); cbio = BIO_push(sbio, cbio); } - resp = query_responder(err, cbio, path, req, req_timeout); + resp = query_responder(err, cbio, path, headers, req, req_timeout); if (!resp) BIO_printf(bio_err, "Error querying OCSP responsder\n"); end: diff --git a/apps/s_server.c b/apps/s_server.c index 6277c797fc..eeebabe4e6 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -787,7 +787,7 @@ BIO_printf(err, "cert_status: received %d ids\n", sk_OCSP_RESPID_num(ids)); if (!OCSP_REQUEST_add_ext(req, ext, -1)) goto err; } - resp = process_responder(err, req, host, path, port, use_ssl, + resp = process_responder(err, req, host, path, port, use_ssl, NULL, srctx->timeout); if (!resp) { diff --git a/crypto/ocsp/ocsp.h b/crypto/ocsp/ocsp.h index 1741e419c0..31e45744ba 100644 --- a/crypto/ocsp/ocsp.h +++ b/crypto/ocsp/ocsp.h @@ -406,6 +406,9 @@ OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, int maxline); int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx); void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx); +int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req); +int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, + const char *name, const char *value); OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer); diff --git a/crypto/ocsp/ocsp_ht.c b/crypto/ocsp/ocsp_ht.c index 38602fae4a..12bbfcffd1 100644 --- a/crypto/ocsp/ocsp_ht.c +++ b/crypto/ocsp/ocsp_ht.c @@ -118,39 +118,65 @@ void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx) OPENSSL_free(rctx); } -OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, - int maxline) +int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req) { - static const char post_hdr[] = "POST %s HTTP/1.0\r\n" + static const char req_hdr[] = "Content-Type: application/ocsp-request\r\n" "Content-Length: %d\r\n\r\n"; + if (BIO_printf(rctx->mem, req_hdr, i2d_OCSP_REQUEST(req, NULL)) <= 0) + return 0; + if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0) + return 0; + rctx->state = OHS_ASN1_WRITE; + rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL); + return 1; + } + +int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, + const char *name, const char *value) + { + if (!name) + return 0; + if (BIO_puts(rctx->mem, name) <= 0) + return 0; + if (value) + { + if (BIO_write(rctx->mem, ": ", 2) != 2) + return 0; + if (BIO_puts(rctx->mem, value) <= 0) + return 0; + } + if (BIO_write(rctx->mem, "\r\n", 2) != 2) + return 0; + return 1; + } + +OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, + int maxline) + { + static const char post_hdr[] = "POST %s HTTP/1.0\r\n"; OCSP_REQ_CTX *rctx; rctx = OPENSSL_malloc(sizeof(OCSP_REQ_CTX)); - rctx->state = OHS_FIRSTLINE; + rctx->state = OHS_ERROR; rctx->mem = BIO_new(BIO_s_mem()); rctx->io = io; + rctx->asn1_len = 0; if (maxline > 0) rctx->iobuflen = maxline; else rctx->iobuflen = OCSP_MAX_LINE_LEN; rctx->iobuf = OPENSSL_malloc(rctx->iobuflen); + if (!rctx->iobuf) + return 0; if (!path) path = "/"; - if (BIO_printf(rctx->mem, post_hdr, path, - i2d_OCSP_REQUEST(req, NULL)) <= 0) - { - rctx->state = OHS_ERROR; + if (BIO_printf(rctx->mem, post_hdr, path) <= 0) return 0; - } - if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0) - { - rctx->state = OHS_ERROR; + + if (req && !OCSP_REQ_CTX_set1_req(rctx, req)) return 0; - } - rctx->state = OHS_ASN1_WRITE; - rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL); return rctx; } -- 2.25.1