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