ssl_engine_io.c revision 249ab52ef73a2b33446ae07904e3526b57251411
369N/A/* Licensed to the Apache Software Foundation (ASF) under one or more 369N/A * contributor license agreements. See the NOTICE file distributed with 369N/A * this work for additional information regarding copyright ownership. 369N/A * The ASF licenses this file to You under the Apache License, Version 2.0 369N/A * (the "License"); you may not use this file except in compliance with 369N/A * the License. You may obtain a copy of the License at 369N/A * Unless required by applicable law or agreed to in writing, software 369N/A * distributed under the License is distributed on an "AS IS" BASIS, 369N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 369N/A * See the License for the specific language governing permissions and 369N/A * limitations under the License. 369N/A * _ __ ___ ___ __| | ___ ___| | mod_ssl 369N/A * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL 369N/A * | | | | | | (_) | (_| | \__ \__ \ | 844N/A * |_| |_| |_|\___/ \__,_|___|___/___/_| 369N/A /* ``MY HACK: This universe. 369N/A Just one little problem: 369N/A/* _________________________________________________________________ 369N/A** _________________________________________________________________ 369N/A/* This file is designed to be the bridge between OpenSSL and httpd. 369N/A * However, we really don't expect anyone (let alone ourselves) to 369N/A * remember what is in this file. So, first, a quick overview. 369N/A * In this file, you will find: 369N/A * - ssl_io_filter_input (Apache input filter) 369N/A * - ssl_io_filter_output (Apache output filter) 369N/A * - bio_filter_in_* (OpenSSL input filter) 369N/A * - bio_filter_out_* (OpenSSL output filter) 369N/A * The input chain is roughly: 369N/A * ssl_io_filter_input->ssl_io_input_read->SSL_read->... 369N/A * In mortal terminology, we do the following: 369N/A * - Receive a request for data to the SSL input filter 369N/A * - Call a helper function once we know we should perform a read 369N/A * - Call OpenSSL's SSL_read() 369N/A * - SSL_read() will then call bio_filter_in_read 369N/A * - bio_filter_in_read will then try to fetch data from the next httpd filter 369N/A * - bio_filter_in_read will flatten that data and return it to SSL_read 369N/A * - SSL_read will then decrypt the data 369N/A * - ssl_io_input_read will then receive decrypted data as a char* and 369N/A * ensure that there were no read errors 369N/A * - The char* is placed in a brigade and returned 369N/A * Since connection-level input filters in httpd need to be able to 369N/A * handle AP_MODE_GETLINE calls (namely identifying LF-terminated strings), 369N/A * ssl_io_input_getline which will handle this special case. 369N/A * Due to AP_MODE_GETLINE and AP_MODE_SPECULATIVE, we may sometimes have 369N/A * 'leftover' decoded data which must be setaside for the next read. That 369N/A * is currently handled by the char_buffer_{read|write} functions. So, 369N/A * ssl_io_input_read may be able to fulfill reads without invoking * Note that the filter context of ssl_io_filter_input and bio_filter_in_* * are shared as bio_filter_in_ctx_t. * Note that the filter is by choice limited to reading at most * AP_IOBUFSIZE (8192 bytes) per call. /* this custom BIO allows us to hook SSL_write directly into * an apr_bucket_brigade and use transient buckets with the SSL * malloc-ed buffer, rather than copying into a mem BIO. * also allows us to pass the brigade as data is being written * rather than buffering up the entire response in the mem BIO. * when SSL needs to flush (e.g. SSL_accept()), it will call BIO_flush() * which will trigger a call to bio_filter_out_ctrl() -> bio_filter_out_flush(). * so we only need to flush the output ourselves if we receive an * EOS or FLUSH bucket. this was not possible with the mem BIO where we * had to flush all over the place not really knowing when it was required /* Pass an output brigade down the filter stack; returns 1 on success /* Fail if the connection was reset: */ /* Send a FLUSH bucket down the output filter stack; returns 1 on * success, -1 on failure. */ * apache will destroy the bucket brigade for us /* this is never called */ "BUG: %s() should not be called",
"bio_filter_out_read");
/* Abort early if the client has initiated a renegotiation. */ /* when handshaking we'll have a small number of bytes. * max size SSL will pass us here is about 16k. * (16413 bytes to be exact) /* Use a transient bucket for the output data - any downstream * filter must setaside if necessary. */ "output bio: unhandled control %d",
cmd);
/* this is never called */ "BUG: %s() should not be called",
"bio_filter_out_gets");
/* this is never called */ "BUG: %s() should not be called",
"bio_filter_out_puts");
* this char_buffer api might seem silly, but we don't need to copy * any of this data and we need to remember the length. /* Copy up to INL bytes from the char_buffer BUFFER into IN. Note * that due to the strange way this API is designed/used, the * char_buffer object is used to cache a segment of inctx->buffer, and * then this function called to copy (part of) that segment to the * beginning of inctx->buffer. So the segments to copy cannot be * presumed to be non-overlapping, and memmove must be used. */ /* we have have enough to fill the caller's buffer */ /* swallow remainder of the buffer */ /* This function will read from a brigade and discard the read buckets as it * proceeds. It will read at most *len bytes. /* Justin points out this is an http-ism that might * not fit if brigade_consume is added to APR. Perhaps * apr_bucket_read(eos_bucket) should return APR_EOF? * Then this becomes mainline instead of a one-off. /* The reason I'm not offering brigade_consume yet * across to apr-util is that the following call * illustrates how borked that API really is. For * this sort of case (caller provided buffer) it * would be much more trivial for apr_bucket_consume * to do all the work that follows, based on the * particular characteristics of the bucket we are /* This stream bucket was consumed */ /* Do not block once some data has been consumed */ /* Assure we don't overflow. */ /* This physical bucket was consumed */ /* Only part of this physical bucket was consumed */ /* This could probably be actual == *len, but be safe from stray * this is the function called by SSL_read() /* OpenSSL catches this case, so should we. */ /* Abort early if the client has initiated a renegotiation. */ /* In theory, OpenSSL should flush as necessary, but it is known * not to do so correctly in some cases; see PR 46952. * Historically, this flush call was performed only for an SSLv2 * connection or for a proxy connection. Calling _out_flush * should be very cheap in cases where it is unnecessary (and no * output is buffered) so the performance impact of doing it * unconditionally should be minimal. /* If the read returns EAGAIN or success with an empty * brigade, return an error after setting the retry flag; * SSL_read() will then return -1, and SSL_get_error() will * indicate SSL_ERROR_WANT_READ. */ /* Unexpected errors discard the brigade */ /* Unexpected errors and APR_EOF clean out the brigade. * Subsequent calls will return APR_EOF. /* Provide the results of this read pass, * without resetting the BIO retry_read flag "BUG: %s() should not be called",
"bio_filter_in_write");
"BUG: %s() should not be called",
"bio_filter_in_puts");
"BUG: %s() should not be called",
"bio_filter_in_gets");
"BUG: %s() should not be called",
"bio_filter_in_ctrl");
/* If we have something leftover from last time, try that first. */ /* We want to rollback this read. */ /* This could probably be *len == wanted, but be safe from stray /* Down to a nonblock pattern as we have some data already /* Ensure a non-zero error code is returned */ /* SSL_read may not read because we haven't taken enough data * from the stack. This is where we want to consider all of * the blocking and SPECULATIVE semantics /* We want to rollback this read. */ /* If EAGAIN, we will loop given a blocking read, * otherwise consider ourselves at EOF. /* Already read something, return APR_SUCCESS instead. * On win32 in particular, but perhaps on other kernels, * a blocking call isn't 'always' blocking. * If OpenSSL wants to read more, and we were nonblocking, * report as an EAGAIN. Otherwise loop, pulling more * data from network filter. * (This is usually the case when the client forces an SSL * renegotiation which is handled implicitly by OpenSSL.) continue;
/* Blocking and nothing yet? Try again. */ /* Already read something, return APR_SUCCESS instead. */ continue;
/* Blocking and nothing yet? Try again. */ "SSL input filter read failed.");
else /* if (ssl_err == SSL_ERROR_SSL) */ {
* Log SSL errors and any unexpected conditions. "SSL library error %d reading data",
ssl_err);
/* Read a line of input from the SSL input layer into buffer BUF of * length *LEN; updating *len to reflect the length of the line * including the LF character. */ * in most cases we get all the headers on the first SSL_read. * however, in certain cases SSL_read will only get a partial * chunk of the headers, so we try to read until LF is seen. /* Save the part of the line we already got */ * If OpenSSL wants to write more, and we were nonblocking, * report as an EAGAIN. Otherwise loop, pushing more * data at the network filter. * (This is usually the case when the client forces an SSL * renegotiation which is handled implicitly by OpenSSL.) * If OpenSSL wants to read during write, and we were * nonblocking, set the sense explicitly to read and * (This is usually the case when the client forces an SSL * renegotiation which is handled implicitly by OpenSSL.) "Want read during nonblocking write");
"SSL output filter write failed.");
else /* if (ssl_err == SSL_ERROR_SSL) */ {
"SSL library error %d writing data",
ssl_err);
char *
reason =
"reason unknown";
/* XXX: probably a better way to determine this */ reason =
"likely due to failed renegotiation";
/* Just use a simple request. Any request will work for this, because * we use a flag in the conn_rec->conn_vector now. The fake request just * gets the request back to the Apache core so that a response can be sent. * Since we use an HTTP/1.x request, we also have to inject the empty line * that terminates the headers, or the core will read more data from the /* Custom apr_status_t error code, used when a plain HTTP request is * recevied on an SSL port. */ /* Custom apr_status_t error code, used when the proxy cannot * establish an outgoing SSL connection. */ "SSL handshake failed: HTTP spoken on HTTPS port; " "trying to send HTML error page");
/* fake the request line */ /* Send an error bucket, though the proxy currently has no * special handling for error buckets and ignores this. */ "SSL handshake failed: sending 502");
* Close the SSL part of the socket connection * (called immediately _before_ the socket is closed) * Now close the SSL layer of the connection. We've to take * the TLSv1 standard into account here: * | 7.2.1. Closure alerts * | The client and the server must share knowledge that the connection is * | ending in order to avoid a truncation attack. Either party may * | initiate the exchange of closing messages. * | This message notifies the recipient that the sender will not send * | any more messages on this connection. The session becomes * | unresumable if any connection is terminated without proper * | close_notify messages with level equal to warning. * | Either party may initiate a close by sending a close_notify alert. * | Any data received after a closure alert is ignored. * | Each party is required to send a close_notify alert before closing * | the write side of the connection. It is required that the other party * | respond with a close_notify alert of its own and close down the * | connection immediately, discarding any pending writes. It is not * | required for the initiator of the close to wait for the responding * | close_notify alert before closing the read side of the connection. * This means we've to send a close notify message, but haven't to wait * for the close notify of the client. Actually we cannot wait for the * close notify of the client because some clients (including Netscape * 4.x) don't send one, so we would hang. * exchange close notify messages, but allow the user * to force the type of handshake via SetEnvIf directive /* perform no close notify handshake at all (violates the SSL/TLS standard!) */ /* send close notify and wait for clients close notify (standard compliant, but usually causes connection hangs) */ * case SSL_SHUTDOWN_TYPE_UNSET: * case SSL_SHUTDOWN_TYPE_STANDARD: /* send close notify, but don't wait for clients close notify (standard compliant and safe, so it's the DEFAULT!) */ /* and finally log the fact that we've closed the connection */ "%sConnection closed to child %ld with %s shutdown " /* deallocate the SSL connection */ /* prevent any further I/O */ * The hook is NOT registered with ap_hook_process_connection. Instead, it is * called manually from the churn () before it tries to read any data. * There is some problem if I accept conn_rec *. Still investigating.. * Adv. if conn_rec * can be accepted is we can hook this function using the * ap_hook_process_connection hook. /* Perform the SSL handshake (whether in client or server mode), if * necessary, for the given connection. */ "proxy-request-hostname");
* Enable SNI for backend requests. Make sure we don't do it for * pure SSLv3 connections, and also prevent IP addresses * from being included in the SNI extension. (OpenSSL would simply * pass them on, but RFC 6066 is quite clear on this: "Literal * IPv4 and IPv6 addresses are not permitted".) "SNI extension for SSL Proxy request set to '%s'",
"Failed to set SNI extension for SSL Proxy " "SSL Proxy connect failed");
/* ensure that the SSL structures etc are freed, etc: */ "SSL Proxy: Peer certificate is expired");
"SSL Proxy: Peer certificate does not match " /* Do string match or simplest wildcard match if that "SSL Proxy: Peer certificate CN mismatch:" " Certificate CN: %s Requested hostname: %s",
/* another chance to fail */ /* ensure that the SSL structures etc are freed, etc: */ * The case where the connection was closed before any data * was transferred. That's not a real error and can occur * sporadically with some clients. "SSL handshake stopped: connection was closed");
* This is in addition to what was present earlier. It is * The case where OpenSSL has recognized a HTTP request: * This means the client speaks plain HTTP on our HTTPS port. * ssl_io_filter_error will disable the ssl filters when it "SSL handshake interrupted by system " "[Hint: Stop button pressed in browser?!]");
else /* if (ssl_err == SSL_ERROR_SSL) */ {
* Log SSL errors and any unexpected conditions. "SSL library error %d in handshake " * Check for failed client authentication /* leaving this log message as an error for the moment, * according to the mod_ssl docs: * "level optional_no_ca is actually against the idea * of authentication (but can be used to establish * optional_no_ca doesn't appear to work as advertised "SSL client authentication failed, " "accepting certificate based on " "\"SSLVerifyClient optional_no_ca\" " "SSL client authentication failed: %s",
* Remember the peer certificate's DN * Make really sure that when a peer certificate * is required we really got one... (be paranoid) "No acceptable peer certificate available");
/* XXX: Ok, if we aborted, we ARE at the EOS. We also have * aborted. This 'double protection' is probably redundant, * but also effective against just about anything. /* XXX: we don't currently support anything other than these modes. */ /* XXX: we could actually move ssl_io_filter_handshake to an * ap_hook_process_connection but would still need to call it for * AP_MODE_INIT for protocols that may upgrade the connection * rather than have SSLEngine On configured. /* protocol module needs to handshake before sending * data to client (e.g. NNTP or FTP) /* Protected from truncation, readbytes < MAX_SIZE_T * FIXME: No, it's *not* protected. -- jre */ /* Satisfy the read directly out of the buffer if possible; * invoking ssl_io_input_getline will mean the entire buffer * is copied once (unnecessarily) for each GETLINE call. */ /* Buffer contents now consumed. */ /* Otherwise fall back to the hard way. */ /* We have no idea what you are talking about, so return an error. */ /* It is possible for mod_ssl's BIO to be used outside of the * direct control of mod_ssl's input or output filter -- notably, * when mod_ssl initiates a renegotiation. Switching the BIO mode * back to "blocking" here ensures such operations don't fail with * SSL_ERROR_WANT_READ. */ /* Handle custom errors. */ /* Create a transient bucket out of the decrypted data. */ /* By this point, Next Protocol Negotiation (NPN) should be completed (if * our version of OpenSSL supports it). If we haven't already, find out * which protocol was decided upon and inform other modules by calling * npn_proto_negotiated_hook. */ APLOGNO(0
2306)
"SSL NPN negotiated protocol: '%*s'",
/* ssl_io_filter_output() produces one SSL/TLS message per bucket * passed down the output filter stack. This results in a high * overhead (network packets) for any output comprising many small * buckets. SSI page applied through the HTTP chunk filter, for * example, may produce many brigades containing small buckets - * [chunk-size CRLF] [chunk-data] [CRLF]. * The coalescing filter merges many small buckets into larger buckets * where possible, allowing the SSL I/O output filter to handle them /* The brigade consists of zero-or-more small data buckets which * can be coalesced (the prefix), followed by the remainder of the * Find the last bucket - if any - of that prefix. count gives * the number of buckets in the prefix. The "prefix" must contain * only data buckets with known length, and must be of a total * size which fits into the buffer. * N.B.: The process here could be repeated throughout the brigade * (coalesce any run of consecutive data buckets) but this would * add significant complexity, particularly to memory if (e->
length)
count++;
/* don't count zero-length buckets */ /* Coalesce the prefix, if: * a) more than one bucket is found to coalesce, or * b) the brigade contains only a single data bucket, or /* If coalescing some bytes, ensure a context has been /* Iterate through the prefix segment. For non-fatal errors * in this loop it is safe to break out and fall back to the * normal path of sending the buffer + remaining buckets in "unexpected bucket type during coalesce");
break;
/* non-fatal error; break out */ /* A blocking read should be fine here for a * known-length data bucket, rather than the usual "coalesce failed to read from data bucket");
"unexpected coalesced bucket data length");
break;
/* non-fatal error; break out */ /* If the brigade is now empty, our work here is done. */ /* If anything remains in the brigade, it must now be passed down * the filter stack, first prepending anything that has been ctx->
bytes = 0;
/* buffer now emptied. */ /* ssl_filter_io_shutdown was called */ /* When we are the writer, we must initialize the inctx * mode so that we block for any required ssl input, because * output filtering is always nonblocking. /* If it is a flush or EOS, we need to pass this down. * These types do not require translation by OpenSSL. * By definition, nothing can come after EOS. * which also means we can pass the rest of this brigade * without creating a new one since it only contains the /* bio_filter_out_flush() already passed down a flush bucket * if there was any data to be flushed. /* The EOC bucket indicates connection closure, so SSL * shutdown must now be performed. */ /* No data available: flush... */ continue;
/* and try again with a blocking read. */ int eos = 0;
/* non-zero once EOS is seen */ /* Create the context which will be passed to the input filter; * containing a setaside pool and a brigade which constrain the * lifetime of the buffered data. */ /* ... and a temporary brigade. */ /* The request body is read from the protocol-level input * filters; the buffering filter will reinject it from that "could not read request body for SSL buffer");
/* Iterate through the returned brigade: setaside each bucket * into the context's pool and move it into the brigade. */ "could not read bucket for SSL buffer");
"could not setaside bucket for SSL buffer");
/* Fail if this exceeds the maximum buffer size. */ /* After consuming all protocol-level input, remove all protocol-level * filters. It should strictly only be necessary to remove filters * at exactly ftype == AP_FTYPE_PROTOCOL, since this filter will * precede all > AP_FTYPE_PROTOCOL anyway. */ /* Insert the filter which will supply the buffered content. */ /* This input filter supplies the buffered request body to the caller * from the brigade stored in f->ctx. Note that the placement of this * filter in the filter stack is important; it must be the first * r->proto_input_filter; lower-typed filters will not be preserved * across internal redirects (see PR 43738). */ "read from buffered SSL brigade, mode %d, " /* Suprisingly (and perhaps, wrongly), the request body can be * pulled from the input filter stack more than once; a * handler may read it, and ap_discard_request_body() will * attempt to do so again after *every* request. So input * filters must be prepared to give up an EOS if invoked after * initially reading the request. The HTTP_IN filter does this * with its ->eos_sent flag. */ /* Partition the buffered brigade. */ "could not partition buffered SSL brigade");
/* If the buffered brigade contains less then the requested * length, just pass it all back. */ /* Unsplice the partitioned segment and move it into the * passed-in brigade; no convenient way to do this with * the APR_BRIGADE_* macros. */ /* Split a line into the passed-in brigade. */ "could not split line from buffered SSL brigade");
/* Ensure that the brigade is terminated by an EOS if the * buffered request body has been entirely consumed. */ "buffered SSL brigade exhausted");
/* Note that the filter must *not* be removed here; it may be * invoked again, see comment above. */ /* The request_rec pointer is passed in here only to ensure that the * filter chain is modified correctly when doing a TLS upgrade. It * must *not* be used otherwise. */ /* The request_rec pointer is passed in here only to ensure that the * filter chain is modified correctly when doing a TLS upgrade. It * must *not* be used otherwise. */ /* write is non blocking for the benefit of async mpm */ "Enabling non-blocking writes");
/* _________________________________________________________________ ** _________________________________________________________________ for(; (
len > 0) && ((b[
len-
1] ==
' ') || (b[
len-
1] ==
'\0'));
len--)
"+-------------------------------------------------------------------------+");
for(i = 0 ; i<
rows; i++) {
#
endif /* APR_CHARSET_EBCDIC */ ch = ((
unsigned char)*((
char *)(b) + i *
DUMP_WIDTH + j)) &
0xff;
ch = ((
unsigned char)*((
char *)(b) + i *
DUMP_WIDTH + j)) &
0xff;
#
else /* APR_CHARSET_EBCDIC */#
endif /* APR_CHARSET_EBCDIC */ "+-------------------------------------------------------------------------+");
dump =
"(BIO dump follows)";
dump =
"(Oops, no memory buffer?)";
"%s: %s %ld/%d bytes %s BIO#%pp [mem: %pp] %s",
"%s: I/O error, %d bytes expected to %s on BIO#%pp [mem: %pp]",