6ae232055d4d8a97267517c5e50074c2c819941and/* Licensed to the Apache Software Foundation (ASF) under one or more
6ae232055d4d8a97267517c5e50074c2c819941and * contributor license agreements. See the NOTICE file distributed with
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * this work for additional information regarding copyright ownership.
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * The ASF licenses this file to You under the Apache License, Version 2.0
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * (the "License"); you may not use this file except in compliance with
6ae232055d4d8a97267517c5e50074c2c819941and * the License. You may obtain a copy of the License at
6ae232055d4d8a97267517c5e50074c2c819941and *
6ae232055d4d8a97267517c5e50074c2c819941and * http://www.apache.org/licenses/LICENSE-2.0
6ae232055d4d8a97267517c5e50074c2c819941and *
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * Unless required by applicable law or agreed to in writing, software
6ae232055d4d8a97267517c5e50074c2c819941and * distributed under the License is distributed on an "AS IS" BASIS,
6ae232055d4d8a97267517c5e50074c2c819941and * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * See the License for the specific language governing permissions and
2e545ce2450a9953665f701bb05350f0d3f26275nd * limitations under the License.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen
6ae232055d4d8a97267517c5e50074c2c819941and/* This file implements an OCSP client including a toy HTTP/1.0
6ae232055d4d8a97267517c5e50074c2c819941and * client. Once httpd depends on a real HTTP client library, most of
6ae232055d4d8a97267517c5e50074c2c819941and * this can be thrown away. */
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen
3f08db06526d6901aa08c110b5bc7dde6bc39905nd#include "ssl_private.h"
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and#ifndef OPENSSL_NO_OCSP
6ae232055d4d8a97267517c5e50074c2c819941and
b43f840409794ed298e8634f6284741f193b6c4ftakashi#include "apr_buckets.h"
6ae232055d4d8a97267517c5e50074c2c819941and#include "apr_uri.h"
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and/* Serialize an OCSP request which will be sent to the responder at
b43f840409794ed298e8634f6284741f193b6c4ftakashi * given URI to a memory BIO object, which is returned. */
bc9d4698fce0238d2f6f2682e99423ebb1149976rbowenstatic BIO *serialize_request(OCSP_REQUEST *req, const apr_uri_t *uri)
6ae232055d4d8a97267517c5e50074c2c819941and{
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung BIO *bio;
6ae232055d4d8a97267517c5e50074c2c819941and int len;
b43f840409794ed298e8634f6284741f193b6c4ftakashi
b43f840409794ed298e8634f6284741f193b6c4ftakashi len = i2d_OCSP_REQUEST(req, NULL);
b43f840409794ed298e8634f6284741f193b6c4ftakashi
b43f840409794ed298e8634f6284741f193b6c4ftakashi bio = BIO_new(BIO_s_mem());
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and BIO_printf(bio, "POST %s%s%s HTTP/1.0\r\n"
6ae232055d4d8a97267517c5e50074c2c819941and "Host: %s:%d\r\n"
6ae232055d4d8a97267517c5e50074c2c819941and "Content-Type: application/ocsp-request\r\n"
6ae232055d4d8a97267517c5e50074c2c819941and "Content-Length: %d\r\n"
6ae232055d4d8a97267517c5e50074c2c819941and "\r\n",
6ae232055d4d8a97267517c5e50074c2c819941and uri->path ? uri->path : "/",
6ae232055d4d8a97267517c5e50074c2c819941and uri->query ? "?" : "", uri->query ? uri->query : "",
6ae232055d4d8a97267517c5e50074c2c819941and uri->hostname, uri->port, len);
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and if (i2d_OCSP_REQUEST_bio(bio, req) != 1) {
6ae232055d4d8a97267517c5e50074c2c819941and BIO_free(bio);
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and return bio;
6ae232055d4d8a97267517c5e50074c2c819941and}
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar
6ae232055d4d8a97267517c5e50074c2c819941and/* Send the OCSP request serialized into BIO 'request' to the
6ae232055d4d8a97267517c5e50074c2c819941and * responder at given server given by URI. Returns socket object or
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar * NULL on error. */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coarstatic apr_socket_t *send_request(BIO *request, const apr_uri_t *uri,
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar apr_interval_time_t timeout,
6ae232055d4d8a97267517c5e50074c2c819941and conn_rec *c, apr_pool_t *p)
6ae232055d4d8a97267517c5e50074c2c819941and{
6ae232055d4d8a97267517c5e50074c2c819941and apr_status_t rv;
6ae232055d4d8a97267517c5e50074c2c819941and apr_sockaddr_t *sa;
6ae232055d4d8a97267517c5e50074c2c819941and apr_socket_t *sd;
6ae232055d4d8a97267517c5e50074c2c819941and char buf[HUGE_STRING_LEN];
6ae232055d4d8a97267517c5e50074c2c819941and int len;
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and rv = apr_sockaddr_info_get(&sa, uri->hostname, APR_UNSPEC, uri->port, 0, p);
6ae232055d4d8a97267517c5e50074c2c819941and if (rv) {
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01972)
6ae232055d4d8a97267517c5e50074c2c819941and "could not resolve address of OCSP responder %s",
6ae232055d4d8a97267517c5e50074c2c819941and uri->hostinfo);
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and /* establish a connection to the OCSP responder */
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01973)
6ae232055d4d8a97267517c5e50074c2c819941and "connecting to OCSP responder '%s'", uri->hostinfo);
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and /* Cycle through address until a connect() succeeds. */
6ae232055d4d8a97267517c5e50074c2c819941and for (; sa; sa = sa->next) {
6ae232055d4d8a97267517c5e50074c2c819941and rv = apr_socket_create(&sd, sa->family, SOCK_STREAM, APR_PROTO_TCP, p);
6ae232055d4d8a97267517c5e50074c2c819941and if (rv == APR_SUCCESS) {
6ae232055d4d8a97267517c5e50074c2c819941and apr_socket_timeout_set(sd, timeout);
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and rv = apr_socket_connect(sd, sa);
6ae232055d4d8a97267517c5e50074c2c819941and if (rv == APR_SUCCESS) {
6ae232055d4d8a97267517c5e50074c2c819941and break;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and apr_socket_close(sd);
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and if (sa == NULL) {
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01974)
6ae232055d4d8a97267517c5e50074c2c819941and "could not connect to OCSP responder '%s'",
6ae232055d4d8a97267517c5e50074c2c819941and uri->hostinfo);
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and /* send the request and get a response */
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01975)
6ae232055d4d8a97267517c5e50074c2c819941and "sending request to OCSP responder");
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and while ((len = BIO_read(request, buf, sizeof buf)) > 0) {
6ae232055d4d8a97267517c5e50074c2c819941and char *wbuf = buf;
6ae232055d4d8a97267517c5e50074c2c819941and apr_size_t remain = len;
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and do {
6ae232055d4d8a97267517c5e50074c2c819941and apr_size_t wlen = remain;
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and rv = apr_socket_send(sd, wbuf, &wlen);
6ae232055d4d8a97267517c5e50074c2c819941and wbuf += remain;
6ae232055d4d8a97267517c5e50074c2c819941and remain -= wlen;
6ae232055d4d8a97267517c5e50074c2c819941and } while (rv == APR_SUCCESS && remain > 0);
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and if (rv) {
6ae232055d4d8a97267517c5e50074c2c819941and apr_socket_close(sd);
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01976)
6ae232055d4d8a97267517c5e50074c2c819941and "failed to send request to OCSP responder '%s'",
6ae232055d4d8a97267517c5e50074c2c819941and uri->hostinfo);
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and return sd;
6ae232055d4d8a97267517c5e50074c2c819941and}
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and/* Return a pool-allocated NUL-terminated line, with CRLF stripped,
6ae232055d4d8a97267517c5e50074c2c819941and * read from brigade 'bbin' using 'bbout' as temporary storage. */
6ae232055d4d8a97267517c5e50074c2c819941andstatic char *get_line(apr_bucket_brigade *bbout, apr_bucket_brigade *bbin,
6ae232055d4d8a97267517c5e50074c2c819941and conn_rec *c, apr_pool_t *p)
6ae232055d4d8a97267517c5e50074c2c819941and{
6ae232055d4d8a97267517c5e50074c2c819941and apr_status_t rv;
6ae232055d4d8a97267517c5e50074c2c819941and apr_size_t len;
6ae232055d4d8a97267517c5e50074c2c819941and char *line;
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and apr_brigade_cleanup(bbout);
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and rv = apr_brigade_split_line(bbout, bbin, APR_BLOCK_READ, 8192);
6ae232055d4d8a97267517c5e50074c2c819941and if (rv) {
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01977)
6ae232055d4d8a97267517c5e50074c2c819941and "failed reading line from OCSP server");
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and rv = apr_brigade_pflatten(bbout, &line, &len, p);
6ae232055d4d8a97267517c5e50074c2c819941and if (rv) {
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01978)
6ae232055d4d8a97267517c5e50074c2c819941and "failed reading line from OCSP server");
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and if (len == 0) {
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(02321)
6ae232055d4d8a97267517c5e50074c2c819941and "empty response from OCSP server");
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and if (line[len-1] != APR_ASCII_LF) {
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01979)
6ae232055d4d8a97267517c5e50074c2c819941and "response header line too long from OCSP server");
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and line[len-1] = '\0';
6ae232055d4d8a97267517c5e50074c2c819941and if (len > 1 && line[len-2] == APR_ASCII_CR) {
6ae232055d4d8a97267517c5e50074c2c819941and line[len-2] = '\0';
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and return line;
6ae232055d4d8a97267517c5e50074c2c819941and}
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and/* Maximum values to prevent eating RAM forever. */
6ae232055d4d8a97267517c5e50074c2c819941and#define MAX_HEADERS (256)
6ae232055d4d8a97267517c5e50074c2c819941and#define MAX_CONTENT (2048 * 1024)
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and/* Read the OCSP response from the socket 'sd', using temporary memory
6ae232055d4d8a97267517c5e50074c2c819941and * BIO 'bio', and return the decoded OCSP response object, or NULL on
6ae232055d4d8a97267517c5e50074c2c819941and * error. */
6ae232055d4d8a97267517c5e50074c2c819941andstatic OCSP_RESPONSE *read_response(apr_socket_t *sd, BIO *bio, conn_rec *c,
6ae232055d4d8a97267517c5e50074c2c819941and apr_pool_t *p)
6ae232055d4d8a97267517c5e50074c2c819941and{
6ae232055d4d8a97267517c5e50074c2c819941and apr_bucket_brigade *bb, *tmpbb;
6ae232055d4d8a97267517c5e50074c2c819941and OCSP_RESPONSE *response;
6ae232055d4d8a97267517c5e50074c2c819941and char *line;
6ae232055d4d8a97267517c5e50074c2c819941and apr_size_t count;
6ae232055d4d8a97267517c5e50074c2c819941and apr_int64_t code;
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and /* Using brigades for response parsing is much simpler than using
6ae232055d4d8a97267517c5e50074c2c819941and * apr_socket_* directly. */
6ae232055d4d8a97267517c5e50074c2c819941and bb = apr_brigade_create(p, c->bucket_alloc);
6ae232055d4d8a97267517c5e50074c2c819941and tmpbb = apr_brigade_create(p, c->bucket_alloc);
6ae232055d4d8a97267517c5e50074c2c819941and APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_socket_create(sd, c->bucket_alloc));
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and line = get_line(tmpbb, bb, c, p);
6ae232055d4d8a97267517c5e50074c2c819941and if (!line || strncmp(line, "HTTP/", 5)
6ae232055d4d8a97267517c5e50074c2c819941and || (line = ap_strchr(line, ' ')) == NULL
6ae232055d4d8a97267517c5e50074c2c819941and || (code = apr_atoi64(++line)) < 200 || code > 299) {
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01980)
6ae232055d4d8a97267517c5e50074c2c819941and "bad response from OCSP server: %s",
6ae232055d4d8a97267517c5e50074c2c819941and line ? line : "(none)");
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and /* Read till end of headers; don't have to even bother parsing the
6ae232055d4d8a97267517c5e50074c2c819941and * Content-Length since the server is obliged to close the
6ae232055d4d8a97267517c5e50074c2c819941and * connection after the response anyway for HTTP/1.0. */
6ae232055d4d8a97267517c5e50074c2c819941and count = 0;
6ae232055d4d8a97267517c5e50074c2c819941and while ((line = get_line(tmpbb, bb, c, p)) != NULL && line[0]
6ae232055d4d8a97267517c5e50074c2c819941and && ++count < MAX_HEADERS) {
6ae232055d4d8a97267517c5e50074c2c819941and ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01981)
6ae232055d4d8a97267517c5e50074c2c819941and "OCSP response header: %s", line);
6ae232055d4d8a97267517c5e50074c2c819941and }
6ae232055d4d8a97267517c5e50074c2c819941and
6ae232055d4d8a97267517c5e50074c2c819941and if (count == MAX_HEADERS) {
b43f840409794ed298e8634f6284741f193b6c4ftakashi ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01982)
bc9d4698fce0238d2f6f2682e99423ebb1149976rbowen "could not read response headers from OCSP server, "
6ae232055d4d8a97267517c5e50074c2c819941and "exceeded maximum count (%u)", MAX_HEADERS);
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung return NULL;
727872d18412fc021f03969b8641810d8896820bhumbedooh }
0d0ba3a410038e179b695446bb149cce6264e0abnd else if (!line) {
727872d18412fc021f03969b8641810d8896820bhumbedooh ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01983)
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh "could not read response header from OCSP server");
0d0ba3a410038e179b695446bb149cce6264e0abnd return NULL;
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh }
727872d18412fc021f03969b8641810d8896820bhumbedooh
0d0ba3a410038e179b695446bb149cce6264e0abnd /* Read the response body into the memory BIO. */
0d0ba3a410038e179b695446bb149cce6264e0abnd count = 0;
0d0ba3a410038e179b695446bb149cce6264e0abnd while (!APR_BRIGADE_EMPTY(bb)) {
ac082aefa89416cbdc9a1836eaf3bed9698201c8humbedooh const char *data;
0d0ba3a410038e179b695446bb149cce6264e0abnd apr_size_t len;
0d0ba3a410038e179b695446bb149cce6264e0abnd apr_status_t rv;
0d0ba3a410038e179b695446bb149cce6264e0abnd apr_bucket *e = APR_BRIGADE_FIRST(bb);
727872d18412fc021f03969b8641810d8896820bhumbedooh
0d0ba3a410038e179b695446bb149cce6264e0abnd rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
0d0ba3a410038e179b695446bb149cce6264e0abnd if (rv == APR_EOF) {
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01984)
205f749042ed530040a4f0080dbcb47ceae8a374rjung "OCSP response: got EOF");
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen break;
0d0ba3a410038e179b695446bb149cce6264e0abnd }
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd if (rv != APR_SUCCESS) {
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01985)
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd "error reading response from OCSP server");
6ae232055d4d8a97267517c5e50074c2c819941and return NULL;
}
if (len == 0) {
/* Ignore zero-length buckets (possible side-effect of
* line splitting). */
apr_bucket_delete(e);
continue;
}
count += len;
if (count > MAX_CONTENT) {
ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01986)
"OCSP response size exceeds %u byte limit",
MAX_CONTENT);
return NULL;
}
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01987)
"OCSP response: got %" APR_SIZE_T_FMT
" bytes, %" APR_SIZE_T_FMT " total", len, count);
BIO_write(bio, data, (int)len);
apr_bucket_delete(e);
}
apr_brigade_destroy(bb);
apr_brigade_destroy(tmpbb);
/* Finally decode the OCSP response from what's stored in the
* bio. */
response = d2i_OCSP_RESPONSE_bio(bio, NULL);
if (response == NULL) {
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01988)
"failed to decode OCSP response data");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, mySrvFromConn(c));
}
return response;
}
OCSP_RESPONSE *modssl_dispatch_ocsp_request(const apr_uri_t *uri,
apr_interval_time_t timeout,
OCSP_REQUEST *request,
conn_rec *c, apr_pool_t *p)
{
OCSP_RESPONSE *response = NULL;
apr_socket_t *sd;
BIO *bio;
bio = serialize_request(request, uri);
if (bio == NULL) {
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01989)
"could not serialize OCSP request");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, mySrvFromConn(c));
return NULL;
}
sd = send_request(bio, uri, timeout, c, p);
if (sd == NULL) {
/* Errors already logged. */
BIO_free(bio);
return NULL;
}
/* Clear the BIO contents, ready for the response. */
(void)BIO_reset(bio);
response = read_response(sd, bio, c, p);
apr_socket_close(sd);
BIO_free(bio);
return response;
}
#endif /* HAVE_OCSP */