summaryrefslogtreecommitdiff
path: root/modules/ssl/ssl_engine_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ssl/ssl_engine_io.c')
-rw-r--r--modules/ssl/ssl_engine_io.c728
1 files changed, 0 insertions, 728 deletions
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
deleted file mode 100644
index 4ba1574ca8..0000000000
--- a/modules/ssl/ssl_engine_io.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_io.c
-** I/O Functions
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``MY HACK: This universe.
- Just one little problem:
- core keeps dumping.''
- -- Unknown */
-#include "mod_ssl.h"
-
-/* _________________________________________________________________
-**
-** I/O Request Body Sucking and Re-Injection
-** _________________________________________________________________
-*/
-
-#ifndef SSL_CONSERVATIVE
-
-/*
- * Background:
- *
- * 1. When the client sends a HTTP/HTTPS request, Apache's core code
- * reads only the request line ("METHOD /path HTTP/x.y") and the
- * attached MIME headers ("Foo: bar") up to the terminating line ("CR
- * LF"). An attached request body (for instance the data of a POST
- * method) is _NOT_ read. Instead it is read by mod_cgi's content
- * handler and directly passed to the CGI script.
- *
- * 2. mod_ssl supports per-directory re-configuration of SSL parameters.
- * This is implemented by performing an SSL renegotiation of the
- * re-configured parameters after the request is read, but before the
- * response is sent. In more detail: the renegotiation happens after the
- * request line and MIME headers were read, but _before_ the attached
- * request body is read. The reason simply is that in the HTTP protocol
- * usually there is no acknowledgment step between the headers and the
- * body (there is the 100-continue feature and the chunking facility
- * only), so Apache has no API hook for this step.
- *
- * 3. the problem now occurs when the client sends a POST request for
- * URL /foo via HTTPS the server and the server has SSL parameters
- * re-configured on a per-URL basis for /foo. Then mod_ssl has to
- * perform an SSL renegotiation after the request was read and before
- * the response is sent. But the problem is the pending POST body data
- * in the receive buffer of SSL (which Apache still has not read - it's
- * pending until mod_cgi sucks it in). When mod_ssl now tries to perform
- * the renegotiation the pending data leads to an I/O error.
- *
- * Solution Idea:
- *
- * There are only two solutions: Either to simply state that POST
- * requests to URLs with SSL re-configurations are not allowed, or to
- * renegotiate really after the _complete_ request (i.e. including
- * the POST body) was read. Obviously the latter would be preferred,
- * but it cannot be done easily inside Apache, because as already
- * mentioned, there is no API step between the body reading and the body
- * processing. And even when we mod_ssl would hook directly into the
- * loop of mod_cgi, we wouldn't solve the problem for other handlers, of
- * course. So the only general solution is to suck in the pending data
- * of the request body from the OpenSSL BIO into the Apache BUFF. Then
- * the renegotiation can be done and after this step Apache can proceed
- * processing the request as before.
- *
- * Solution Implementation:
- *
- * We cannot simply suck in the data via an SSL_read-based loop because of
- * HTTP chunking. Instead we _have_ to use the Apache API for this step which
- * is aware of HTTP chunking. So the trick is to suck in the pending request
- * data via the Apache API (which uses Apache's BUFF code and in the
- * background mod_ssl's I/O glue code) and re-inject it later into the Apache
- * BUFF code again. This way the data flows twice through the Apache BUFF, of
- * course. But this way the solution doesn't depend on any Apache specifics
- * and is fully transparent to Apache modules.
- */
-
-struct ssl_io_suck_st {
- BOOL active;
- char *bufptr;
- int buflen;
- char *pendptr;
- int pendlen;
-};
-
-/* prepare request_rec structure for input sucking */
-static void ssl_io_suck_start(request_rec *r)
-{
- struct ssl_io_suck_st *ss;
-
- ss = ap_ctx_get(r->ctx, "ssl::io::suck");
- if (ss == NULL) {
- ss = ap_palloc(r->pool, sizeof(struct ssl_io_suck_st));
- ap_ctx_set(r->ctx, "ssl::io::suck", ss);
- ss->buflen = 8192;
- ss->bufptr = ap_palloc(r->pool, ss->buflen);
- }
- ss->pendptr = ss->bufptr;
- ss->pendlen = 0;
- ss->active = FALSE;
- return;
-}
-
-/* record a sucked input chunk */
-static void ssl_io_suck_record(request_rec *r, char *buf, int len)
-{
- struct ssl_io_suck_st *ss;
-
- if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
- return;
- if (((ss->bufptr + ss->buflen) - (ss->pendptr + ss->pendlen)) < len) {
- /* "expand" buffer: actually we cannot really expand the buffer
- here, because Apache's pool system doesn't support expanding chunks
- of memory. Instead we have to either reuse processed data or
- allocate a new chunk of memory in advance if we really need more
- memory. */
- int newlen;
- char *newptr;
-
- if (( (ss->pendptr - ss->bufptr)
- + ((ss->bufptr + ss->buflen) - (ss->pendptr + ss->pendlen)) ) >= len) {
- /* make memory available by reusing already processed data */
- memmove(ss->bufptr, ss->pendptr, ss->pendlen);
- ss->pendptr = ss->bufptr;
- }
- else {
- /* too bad, we have to allocate a new larger buffer */
- newlen = (ss->buflen * 2) + len;
- newptr = ap_palloc(r->pool, newlen);
- ss->bufptr = newptr;
- ss->buflen = newlen;
- memcpy(ss->bufptr, ss->pendptr, ss->pendlen);
- ss->pendptr = ss->bufptr;
- }
- }
- memcpy(ss->pendptr+ss->pendlen, buf, len);
- ss->pendlen += len;
- return;
-}
-
-/* finish request_rec after input sucking */
-static void ssl_io_suck_end(request_rec *r)
-{
- struct ssl_io_suck_st *ss;
-
- if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
- return;
- ss->active = TRUE;
- r->read_body = REQUEST_NO_BODY;
- r->read_length = 0;
- r->read_chunked = 0;
- r->remaining = 0;
- ap_bsetflag(r->connection->client, B_CHUNK, 0);
- return;
-}
-
-void ssl_io_suck(request_rec *r, SSL *ssl)
-{
- int rc;
- int len;
- char *buf;
- int buflen;
- char c;
- int sucked;
-
- if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) == OK) {
- if (ap_should_client_block(r)) {
-
- /* read client request block through Apache API */
- buflen = HUGE_STRING_LEN;
- buf = ap_palloc(r->pool, buflen);
- ap_hard_timeout("SSL I/O request body pre-sucking", r);
- sucked = 0;
- ssl_io_suck_start(r);
- while ((len = ap_get_client_block(r, buf, buflen)) > 0) {
- ssl_io_suck_record(r, buf, len);
- sucked += len;
- }
- ssl_io_suck_end(r);
- ap_kill_timeout(r);
-
- /* suck trailing data (usually CR LF) which
- is still in the Apache BUFF layer */
- while (ap_bpeekc(r->connection->client) != EOF) {
- c = ap_bgetc(r->connection->client);
- ssl_io_suck_record(r, &c, 1);
- sucked++;
- }
-
- ssl_log(r->server, SSL_LOG_TRACE,
- "I/O: sucked %d bytes of input data from SSL/TLS I/O layer "
- "for delayed injection into Apache I/O layer", sucked);
- }
- }
- return;
-}
-
-/* the SSL_read replacement routine which knows about the suck buffer */
-static int ssl_io_suck_read(SSL *ssl, char *buf, int len)
-{
- ap_ctx *actx;
- struct ssl_io_suck_st *ss;
- request_rec *r = NULL;
- int rv;
-
- actx = (ap_ctx *)SSL_get_app_data2(ssl);
- if (actx != NULL)
- r = (request_rec *)ap_ctx_get(actx, "ssl::request_rec");
-
- rv = -1;
- if (r != NULL) {
- ss = ap_ctx_get(r->ctx, "ssl::io::suck");
- if (ss != NULL) {
- if (ss->active && ss->pendlen > 0) {
- /* ok, there is pre-sucked data */
- len = (ss->pendlen > len ? len : ss->pendlen);
- memcpy(buf, ss->pendptr, len);
- ss->pendptr += len;
- ss->pendlen -= len;
- ssl_log(r->server, SSL_LOG_TRACE,
- "I/O: injecting %d bytes of pre-sucked data "
- "into Apache I/O layer", len);
- rv = len;
- }
- }
- }
- if (rv == -1)
- rv = SSL_read(ssl, buf, len);
- return rv;
-}
-
-/* override SSL_read in the following code... */
-#define SSL_read ssl_io_suck_read
-
-#endif /* !SSL_CONSERVATIVE */
-
-/* _________________________________________________________________
-**
-** I/O Hooks
-** _________________________________________________________________
-*/
-
-#ifndef NO_WRITEV
-#include <sys/types.h>
-#include <sys/uio.h>
-#endif
-
-static int ssl_io_hook_read(BUFF *fb, char *buf, int len);
-static int ssl_io_hook_write(BUFF *fb, char *buf, int len);
-#ifndef NO_WRITEV
-static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt);
-#endif
-#ifdef WIN32
-static int ssl_io_hook_recvwithtimeout(BUFF *fb, char *buf, int len);
-static int ssl_io_hook_sendwithtimeout(BUFF *fb, const char *buf, int len);
-#endif /* WIN32 */
-
-void ssl_io_register(void)
-{
- ap_hook_register("ap::buff::read", ssl_io_hook_read, AP_HOOK_NOCTX);
- ap_hook_register("ap::buff::write", ssl_io_hook_write, AP_HOOK_NOCTX);
-#ifndef NO_WRITEV
- ap_hook_register("ap::buff::writev", ssl_io_hook_writev, AP_HOOK_NOCTX);
-#endif
-#ifdef WIN32
- ap_hook_register("ap::buff::recvwithtimeout",
- ssl_io_hook_recvwithtimeout, AP_HOOK_NOCTX);
- ap_hook_register("ap::buff::sendwithtimeout",
- ssl_io_hook_sendwithtimeout, AP_HOOK_NOCTX);
-#endif
- return;
-}
-
-void ssl_io_unregister(void)
-{
- ap_hook_unregister("ap::buff::read", ssl_io_hook_read);
- ap_hook_unregister("ap::buff::write", ssl_io_hook_write);
-#ifndef NO_WRITEV
- ap_hook_unregister("ap::buff::writev", ssl_io_hook_writev);
-#endif
-#ifdef WIN32
- ap_hook_unregister("ap::buff::recvwithtimeout", ssl_io_hook_recvwithtimeout);
- ap_hook_unregister("ap::buff::sendwithtimeout", ssl_io_hook_sendwithtimeout);
-#endif
- return;
-}
-
-static int ssl_io_hook_read(BUFF *fb, char *buf, int len)
-{
- SSL *ssl;
- conn_rec *c;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
- rc = SSL_read(ssl, buf, len);
- /*
- * Simulate an EINTR in case OpenSSL wants to read more.
- * (This is usually the case when the client forces an SSL
- * renegotation which is handled implicitly by OpenSSL.)
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)
- errno = EINTR;
- /*
- * Log SSL errors
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
- c = (conn_rec *)SSL_get_app_data(ssl);
- ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "SSL error on reading data");
- }
- /*
- * read(2) returns only the generic error number -1
- */
- if (rc < 0)
- rc = -1;
- }
- else
- rc = read(fb->fd_in, buf, len);
- return rc;
-}
-
-static int ssl_io_hook_write(BUFF *fb, char *buf, int len)
-{
- SSL *ssl;
- conn_rec *c;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
- rc = SSL_write(ssl, buf, len);
- /*
- * Simulate an EINTR in case OpenSSL wants to write more.
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
- errno = EINTR;
- /*
- * Log SSL errors
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
- c = (conn_rec *)SSL_get_app_data(ssl);
- ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "SSL error on writing data");
- }
- /*
- * write(2) returns only the generic error number -1
- */
- if (rc < 0)
- rc = -1;
- }
- else
- rc = write(fb->fd, buf, len);
- return rc;
-}
-
-#ifndef NO_WRITEV
-/* the prototype for our own SSL_writev() */
-static int SSL_writev(SSL *, const struct iovec *, int);
-
-static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt)
-{
- SSL *ssl;
- conn_rec *c;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
- rc = SSL_writev(ssl, iov, iovcnt);
- /*
- * Simulate an EINTR in case OpenSSL wants to write more.
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
- errno = EINTR;
- /*
- * Log SSL errors
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
- c = (conn_rec *)SSL_get_app_data(ssl);
- ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "SSL error on writing data");
- }
- /*
- * writev(2) returns only the generic error number -1
- */
- if (rc < 0)
- rc = -1;
- }
- else
- rc = writev(fb->fd, iov, iovcnt);
- return rc;
-}
-#endif
-
-#ifdef WIN32
-
-/* these two functions are exported from buff.c under WIN32 */
-API_EXPORT(int) sendwithtimeout(int sock, const char *buf, int len, int flags);
-API_EXPORT(int) recvwithtimeout(int sock, char *buf, int len, int flags);
-
-/* and the prototypes for our SSL_xxx variants */
-static int SSL_sendwithtimeout(BUFF *fb, const char *buf, int len);
-static int SSL_recvwithtimeout(BUFF *fb, char *buf, int len);
-
-static int ssl_io_hook_recvwithtimeout(BUFF *fb, char *buf, int len)
-{
- SSL *ssl;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL)
- rc = SSL_recvwithtimeout(fb, buf, len);
- else
- rc = recvwithtimeout(fb->fd, buf, len, 0);
- return rc;
-}
-
-static int ssl_io_hook_sendwithtimeout(BUFF *fb, const char *buf, int len)
-{
- SSL *ssl;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL)
- rc = SSL_sendwithtimeout(fb, buf, len);
- else
- rc = sendwithtimeout(fb->fd, buf, len, 0);
- return rc;
-}
-
-#endif /* WIN32 */
-
-/* _________________________________________________________________
-**
-** Special Functions for OpenSSL
-** _________________________________________________________________
-*/
-
-#ifdef WIN32
-
-static int SSL_sendwithtimeout(BUFF *fb, const char *buf, int len)
-{
- int iostate = 1;
- fd_set fdset;
- struct timeval tv;
- int err = WSAEWOULDBLOCK;
- int rv;
- int retry;
- int sock = fb->fd;
- SSL *ssl;
-
- ssl = ap_ctx_get(fb->ctx, "ssl");
-
- if (!(tv.tv_sec = ap_check_alarm()))
- return (SSL_write(ssl, (char*)buf, len));
-
- rv = ioctlsocket(sock, FIONBIO, &iostate);
- iostate = 0;
- if (rv) {
- err = WSAGetLastError();
- ap_assert(0);
- }
- rv = SSL_write(ssl, (char*)buf, len);
- if (rv <= 0) {
- if (BIO_sock_should_retry(rv)) {
- do {
- retry = 0;
- FD_ZERO(&fdset);
- FD_SET((unsigned int)sock, &fdset);
- tv.tv_usec = 0;
- rv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv);
- if (rv == SOCKET_ERROR)
- err = WSAGetLastError();
- else if (rv == 0) {
- ioctlsocket(sock, FIONBIO, &iostate);
- if(ap_check_alarm() < 0) {
- WSASetLastError(EINTR); /* Simulate an alarm() */
- return (SOCKET_ERROR);
- }
- }
- else {
- rv = SSL_write(ssl, (char*)buf, len);
- if (BIO_sock_should_retry(rv)) {
- ap_log_error(APLOG_MARK,APLOG_DEBUG, NULL,
- "select claimed we could write, "
- "but in fact we couldn't. "
- "This is a bug in Windows.");
- retry = 1;
- Sleep(100);
- }
- }
- } while(retry);
- }
- }
- ioctlsocket(sock, FIONBIO, &iostate);
- if (rv == SOCKET_ERROR)
- WSASetLastError(err);
- return (rv);
-}
-
-static int SSL_recvwithtimeout(BUFF *fb, char *buf, int len)
-{
- int iostate = 1;
- fd_set fdset;
- struct timeval tv;
- int err = WSAEWOULDBLOCK;
- int rv;
- int sock = fb->fd_in;
- SSL *ssl;
- int retry;
-
- ssl = ap_ctx_get(fb->ctx, "ssl");
-
- if (!(tv.tv_sec = ap_check_alarm()))
- return (SSL_read(ssl, buf, len));
-
- rv = ioctlsocket(sock, FIONBIO, &iostate);
- iostate = 0;
- ap_assert(!rv);
- rv = SSL_read(ssl, buf, len);
- if (rv <= 0) {
- if (BIO_sock_should_retry(rv)) {
- do {
- retry = 0;
- FD_ZERO(&fdset);
- FD_SET((unsigned int)sock, &fdset);
- tv.tv_usec = 0;
- rv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
- if (rv == SOCKET_ERROR)
- err = WSAGetLastError();
- else if (rv == 0) {
- ioctlsocket(sock, FIONBIO, &iostate);
- ap_check_alarm();
- WSASetLastError(WSAEWOULDBLOCK);
- return (SOCKET_ERROR);
- }
- else {
- rv = SSL_read(ssl, buf, len);
- if (rv == SOCKET_ERROR) {
- if (BIO_sock_should_retry(rv)) {
- ap_log_error(APLOG_MARK,APLOG_DEBUG, NULL,
- "select claimed we could read, "
- "but in fact we couldn't. "
- "This is a bug in Windows.");
- retry = 1;
- Sleep(100);
- }
- else {
- err = WSAGetLastError();
- }
- }
- }
- } while(retry);
- }
- }
- ioctlsocket(sock, FIONBIO, &iostate);
- if (rv == SOCKET_ERROR)
- WSASetLastError(err);
- return (rv);
-}
-
-#endif /*WIN32*/
-
-/*
- * There is no SSL_writev() provided by OpenSSL. The reason is mainly because
- * OpenSSL has to fragment the data itself again for the SSL record layer, so a
- * writev() like interface makes not much sense. What we do is to emulate it
- * to at least being able to use the write() like interface. But keep in mind
- * that the network I/O performance is not write() like, of course.
- */
-#ifndef NO_WRITEV
-static int SSL_writev(SSL *ssl, const struct iovec *iov, int iovcnt)
-{
- int i;
- int n;
- int rc;
-
- rc = 0;
- for (i = 0; i < iovcnt; i++) {
- if ((n = SSL_write(ssl, iov[i].iov_base, iov[i].iov_len)) == -1) {
- rc = -1;
- break;
- }
- rc += n;
- }
- return rc;
-}
-#endif
-
-/* _________________________________________________________________
-**
-** I/O Data Debugging
-** _________________________________________________________________
-*/
-
-#define DUMP_WIDTH 16
-
-static void ssl_io_data_dump(server_rec *srvr, const char *s, long len)
-{
- char buf[256];
- char tmp[64];
- int i, j, rows, trunc;
- unsigned char ch;
-
- trunc = 0;
- for(; (len > 0) && ((s[len-1] == ' ') || (s[len-1] == '\0')); len--)
- trunc++;
- rows = (len / DUMP_WIDTH);
- if ((rows * DUMP_WIDTH) < len)
- rows++;
- ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
- "+-------------------------------------------------------------------------+");
- for(i = 0 ; i< rows; i++) {
- ap_snprintf(tmp, sizeof(tmp), "| %04x: ", i * DUMP_WIDTH);
- ap_cpystrn(buf, tmp, sizeof(buf));
- for (j = 0; j < DUMP_WIDTH; j++) {
- if (((i * DUMP_WIDTH) + j) >= len)
- ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
- else {
- ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;
- ap_snprintf(tmp, sizeof(tmp), "%02x%c", ch , j==7 ? '-' : ' ');
- ap_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));
- }
- }
- ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
- for (j = 0; j < DUMP_WIDTH; j++) {
- if (((i * DUMP_WIDTH) + j) >= len)
- ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
- else {
- ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;
- ap_snprintf(tmp, sizeof(tmp), "%c", ((ch >= ' ') && (ch <= '~')) ? ch : '.');
- ap_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));
- }
- }
- ap_cpystrn(buf+strlen(buf), " |", sizeof(buf)-strlen(buf));
- ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID, "%s", buf);
- }
- if (trunc > 0)
- ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
- "| %04x - <SPACES/NULS>", len + trunc);
- ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
- "+-------------------------------------------------------------------------+");
- return;
-}
-
-long ssl_io_data_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long rc)
-{
- SSL *ssl;
- conn_rec *c;
- server_rec *s;
-
- if ((ssl = (SSL *)BIO_get_callback_arg(bio)) == NULL)
- return rc;
- if ((c = (conn_rec *)SSL_get_app_data(ssl)) == NULL)
- return rc;
- s = c->server;
-
- if ( cmd == (BIO_CB_WRITE|BIO_CB_RETURN)
- || cmd == (BIO_CB_READ |BIO_CB_RETURN) ) {
- if (rc >= 0) {
- ssl_log(s, SSL_LOG_DEBUG,
- "%s: %s %ld/%d bytes %s BIO#%08X [mem: %08lX] %s",
- SSL_LIBRARY_NAME,
- (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
- rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),
- bio, argp,
- (argp != NULL ? "(BIO dump follows)" : "(Ops, no memory buffer?)"));
- if (argp != NULL)
- ssl_io_data_dump(s, argp, rc);
- }
- else {
- ssl_log(s, SSL_LOG_DEBUG,
- "%s: I/O error, %d bytes expected to %s on BIO#%08X [mem: %08lX]",
- SSL_LIBRARY_NAME, argi,
- (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
- bio, argp);
- }
- }
- return rc;
-}
-