ssl_util_ocsp.c revision 12b2973ae4fdb19829e3ccd9d5d3938451c67f41
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file implements an OCSP client including a toy HTTP/1.0
* client. Once httpd depends on a real HTTP client library, most of
* this can be thrown away. */
#include "ssl_private.h"
#ifdef HAVE_OCSP
#include "apr_buckets.h"
#include "apr_uri.h"
/* Serialize an OCSP request which will be sent to the responder at
* given URI to a memory BIO object, which is returned. */
{
int len;
"Host: %s:%d\r\n"
"Content-Length: %d\r\n"
"\r\n",
return NULL;
}
return bio;
}
/* Send the OCSP request serialized into BIO 'request' to the
* responder at given server given by URI. Returns socket object or
* NULL on error. */
conn_rec *c, apr_pool_t *p)
{
char buf[HUGE_STRING_LEN];
int len;
if (rv) {
"could not resolve address of OCSP responder %s",
return NULL;
}
/* establish a connection to the OCSP responder */
/* Cycle through address until a connect() succeeds. */
if (rv == APR_SUCCESS) {
/* Inherit the default I/O timeout. */
if (rv == APR_SUCCESS) {
break;
}
}
}
"could not connect to OCSP responder '%s'",
return NULL;
}
/* send the request and get a response */
"sending request to OCSP responder");
do {
if (rv) {
"failed to send request to OCSP responder '%s'",
return NULL;
}
}
return sd;
}
/* Return a pool-alocated NUL-terminated line, with CRLF stripped,
* read from brigade 'bbin' using 'bbout' as temporary storage. */
conn_rec *c, apr_pool_t *p)
{
char *line;
if (rv) {
"failed reading line from OCSP server");
return NULL;
}
if (rv) {
"failed reading line from OCSP server");
return NULL;
}
"response header line too long from OCSP server");
return NULL;
}
}
return line;
}
/* Maximum values to prevent eating RAM forever. */
#define MAX_HEADERS (256)
/* Read the OCSP response from the socket 'sd', using temporary memory
* BIO 'bio', and return the decoded OCSP response object, or NULL on
* error. */
apr_pool_t *p)
{
char *line;
/* Using brigades for response parsing is much simpler than using
* apr_socket_* directly. */
"bad response from OCSP server: %s",
return NULL;
}
/* Read till end of headers; don't have to even bother parsing the
* Content-Length since the server is obliged to close the
* connection after the response anyway for HTTP/1.0. */
count = 0;
&& ++count < MAX_HEADERS) {
"OCSP response header: %s", line);
}
if (!line) {
"could not read response header from OCSP server");
return NULL;
}
/* Read the response body into the memory BIO. */
count = 0;
while (!APR_BRIGADE_EMPTY(bb)) {
const char *data;
"OCSP response: got EOF");
break;
}
if (rv != APR_SUCCESS) {
"error reading response from OCSP server");
return NULL;
}
if (count > MAX_CONTENT) {
"OCSP response size exceeds %u byte limit",
return NULL;
}
"OCSP response: got %" APR_SIZE_T_FMT
}
/* Finally decode the OCSP response from what's stored in the
* bio. */
"failed to decode OCSP response data");
}
return response;
}
conn_rec *c, apr_pool_t *p)
{
"could not serialize OCSP request");
return NULL;
}
/* Errors already logged. */
return NULL;
}
/* Clear the BIO contents, ready for the response. */
return response;
}
#endif /* HAVE_OCSP */