PR: 2064, 728
authorDr. Stephen Henson <steve@openssl.org>
Wed, 30 Sep 2009 21:40:55 +0000 (21:40 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 30 Sep 2009 21:40:55 +0000 (21:40 +0000)
Submitted by: steve@openssl.org

Add support for custom headers in OCSP requests.

CHANGES
apps/apps.h
apps/ocsp.c
apps/s_server.c
crypto/ocsp/ocsp.h
crypto/ocsp/ocsp_ht.c

diff --git a/CHANGES b/CHANGES
index a8397f8..a9284d6 100644 (file)
--- 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
index 361ca9e..35a0266 100644 (file)
@@ -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
 
index 173a67b..01847df 100644 (file)
@@ -75,6 +75,7 @@
 #include <openssl/ssl.h>
 #include <openssl/evp.h>
 #include <openssl/bn.h>
+#include <openssl/x509v3.h>
 
 #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:
index 6277c79..eeebabe 100644 (file)
@@ -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)
                {
index 1741e41..31e4574 100644 (file)
@@ -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);
 
index 38602fa..12bbfcf 100644 (file)
@@ -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;
        }