diff options
Diffstat (limited to '2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch')
-rw-r--r-- | 2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch | 332 |
1 files changed, 0 insertions, 332 deletions
diff --git a/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch b/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch deleted file mode 100644 index 8833481..0000000 --- a/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch +++ /dev/null @@ -1,332 +0,0 @@ ---- - modules/ssl/mod_ssl.h | 4 - modules/ssl/ssl_engine_io.c | 185 ++++++++++++++++++++++++++++++++++++++++ - modules/ssl/ssl_engine_kernel.c | 96 ++++++-------------- - 3 files changed, 218 insertions(+), 67 deletions(-) - ---- a/modules/ssl/mod_ssl.h -+++ b/modules/ssl/mod_ssl.h -@@ -682,6 +682,10 @@ void ssl_io_filter_init(conn_rec - void ssl_io_filter_register(apr_pool_t *); - long ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long); - -+/* ssl_io_buffer_fill fills the setaside buffering of the HTTP request -+ * to allow an SSL renegotiation to take place. */ -+int ssl_io_buffer_fill(request_rec *r); -+ - /* PRNG */ - int ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *); - ---- a/modules/ssl/ssl_engine_io.c -+++ b/modules/ssl/ssl_engine_io.c -@@ -880,6 +880,7 @@ static apr_status_t ssl_io_filter_error( - } - - static const char ssl_io_filter[] = "SSL/TLS Filter"; -+static const char ssl_io_buffer[] = "SSL/TLS Buffer"; - - /* - * Close the SSL part of the socket connection -@@ -1373,6 +1374,187 @@ static apr_status_t ssl_io_filter_output - return status; - } - -+/* 128K maximum buffer size by default. */ -+#ifndef SSL_MAX_IO_BUFFER -+#define SSL_MAX_IO_BUFFER (128 * 1024) -+#endif -+ -+struct modssl_buffer_ctx { -+ apr_bucket_brigade *bb; -+ apr_pool_t *pool; -+}; -+ -+int ssl_io_buffer_fill(request_rec *r) -+{ -+ conn_rec *c = r->connection; -+ struct modssl_buffer_ctx *ctx; -+ apr_bucket_brigade *tempb; -+ apr_off_t total = 0; /* total length buffered */ -+ 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. */ -+ ctx = apr_palloc(r->pool, sizeof *ctx); -+ apr_pool_create(&ctx->pool, r->pool); -+ ctx->bb = apr_brigade_create(ctx->pool, c->bucket_alloc); -+ -+ /* ... and a temporary brigade. */ -+ tempb = apr_brigade_create(r->pool, c->bucket_alloc); -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "filling buffer"); -+ -+ do { -+ apr_status_t rv; -+ apr_bucket *e, *next; -+ -+ /* The request body is read from the protocol-level input -+ * filters; the buffering filter will reinject it from that -+ * level, allowing content/resource filters to run later, if -+ * necessary. */ -+ -+ rv = ap_get_brigade(r->proto_input_filters, tempb, AP_MODE_READBYTES, -+ APR_BLOCK_READ, 8192); -+ if (rv) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, -+ "could not read request body for SSL buffer"); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ -+ /* Iterate through the returned brigade: setaside each bucket -+ * into the context's pool and move it into the brigade. */ -+ for (e = APR_BRIGADE_FIRST(tempb); -+ e != APR_BRIGADE_SENTINEL(tempb) && !eos; e = next) { -+ const char *data; -+ apr_size_t len; -+ -+ next = APR_BUCKET_NEXT(e); -+ -+ if (APR_BUCKET_IS_EOS(e)) { -+ eos = 1; -+ } else if (!APR_BUCKET_IS_METADATA(e)) { -+ rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ); -+ if (rv != APR_SUCCESS) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, -+ "could not read bucket for SSL buffer"); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ total += len; -+ } -+ -+ rv = apr_bucket_setaside(e, ctx->pool); -+ if (rv != APR_SUCCESS) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, -+ "could not setaside bucket for SSL buffer"); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ -+ APR_BUCKET_REMOVE(e); -+ APR_BRIGADE_INSERT_TAIL(ctx->bb, e); -+ } -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, -+ "total of %" APR_OFF_T_FMT " bytes in buffer, eos=%d", -+ total, eos); -+ -+ /* Fail if this exceeds the maximum buffer size. */ -+ if (total > SSL_MAX_IO_BUFFER) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "request body exceeds maximum size for SSL buffer"); -+ return HTTP_REQUEST_ENTITY_TOO_LARGE; -+ } -+ -+ } while (!eos); -+ -+ apr_brigade_destroy(tempb); -+ -+ /* Insert the filter which will supply the buffered data. */ -+ ap_add_input_filter(ssl_io_buffer, ctx, r, c); -+ -+ return 0; -+} -+ -+/* This input filter supplies the buffered request body to the caller -+ * from the brigade stored in f->ctx. */ -+static apr_status_t ssl_io_filter_buffer(ap_filter_t *f, -+ apr_bucket_brigade *bb, -+ ap_input_mode_t mode, -+ apr_read_type_e block, -+ apr_off_t bytes) -+{ -+ struct modssl_buffer_ctx *ctx = f->ctx; -+ apr_status_t rv; -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, -+ "read from buffered SSL brigade, mode %d, " -+ "%" APR_OFF_T_FMT " bytes", -+ mode, bytes); -+ -+ if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) { -+ return APR_ENOTIMPL; -+ } -+ -+ if (mode == AP_MODE_READBYTES) { -+ apr_bucket *e; -+ -+ /* Partition the buffered brigade. */ -+ rv = apr_brigade_partition(ctx->bb, bytes, &e); -+ if (rv && rv != APR_INCOMPLETE) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, -+ "could not partition buffered SSL brigade"); -+ ap_remove_input_filter(f); -+ return rv; -+ } -+ -+ /* If the buffered brigade contains less then the requested -+ * length, just pass it all back. */ -+ if (rv == APR_INCOMPLETE) { -+ APR_BRIGADE_CONCAT(bb, ctx->bb); -+ } else { -+ apr_bucket *d = APR_BRIGADE_FIRST(ctx->bb); -+ -+ e = APR_BUCKET_PREV(e); -+ -+ /* Unsplice the partitioned segment and move it into the -+ * passed-in brigade; no convenient way to do this with -+ * the APR_BRIGADE_* macros. */ -+ APR_RING_UNSPLICE(d, e, link); -+ APR_RING_SPLICE_HEAD(&bb->list, d, e, apr_bucket, link); -+ -+ APR_BRIGADE_CHECK_CONSISTENCY(bb); -+ APR_BRIGADE_CHECK_CONSISTENCY(ctx->bb); -+ } -+ } -+ else { -+ /* Split a line into the passed-in brigade. */ -+ rv = apr_brigade_split_line(bb, ctx->bb, mode, bytes); -+ -+ if (rv) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, -+ "could not split line from buffered SSL brigade"); -+ ap_remove_input_filter(f); -+ return rv; -+ } -+ } -+ -+ if (APR_BRIGADE_EMPTY(ctx->bb)) { -+ apr_bucket *e = APR_BRIGADE_LAST(bb); -+ -+ /* Ensure that the brigade is terminated by an EOS if the -+ * buffered request body has been entirely consumed. */ -+ if (e == APR_BRIGADE_SENTINEL(bb) || !APR_BUCKET_IS_EOS(e)) { -+ e = apr_bucket_eos_create(f->c->bucket_alloc); -+ APR_BRIGADE_INSERT_TAIL(bb, e); -+ } -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, -+ "buffered SSL brigade now exhausted; removing filter"); -+ ap_remove_input_filter(f); -+ } -+ -+ return APR_SUCCESS; -+} -+ - static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c, - SSL *ssl) - { -@@ -1430,6 +1612,9 @@ void ssl_io_filter_register(apr_pool_t * - { - ap_register_input_filter (ssl_io_filter, ssl_io_filter_input, NULL, AP_FTYPE_CONNECTION + 5); - ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5); -+ -+ ap_register_input_filter (ssl_io_buffer, ssl_io_filter_buffer, NULL, AP_FTYPE_PROTOCOL - 1); -+ - return; - } - ---- a/modules/ssl/ssl_engine_kernel.c -+++ b/modules/ssl/ssl_engine_kernel.c -@@ -483,73 +483,35 @@ int ssl_hook_Access(request_rec *r) - } - #endif /* HAVE_SSL_SET_CERT_STORE */ - -- /* -- * SSL renegotiations in conjunction with HTTP -- * requests using the POST method are not supported. -- * -- * 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. -- * -- * !! BUT ALL THIS IS STILL NOT RE-IMPLEMENTED FOR APACHE 2.0 !! -- */ -- if (renegotiate && !renegotiate_quick && (r->method_number == M_POST)) { -- ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, -- "SSL Re-negotiation in conjunction " -- "with POST method not supported! " -- "hint: try SSLOptions +OptRenegotiate"); -- -- return HTTP_METHOD_NOT_ALLOWED; -+ /* If a renegotiation is now required for this location, and the -+ * request includes a message body (and the client has not -+ * requested a "100 Continue" response), then the client will be -+ * streaming the request body over the wire already. In that -+ * case, it is not possible to stop and perform a new SSL -+ * handshake immediately; once the SSL library moves to the -+ * "accept" state, it will reject the SSL packets which the client -+ * is sending for the request body. -+ * -+ * To allow authentication to complete in this auth hook, the -+ * solution used here is to fill a (bounded) buffer with the -+ * request body, and then to reinject that request body later. -+ */ -+ if (renegotiate && !renegotiate_quick -+ && (apr_table_get(r->headers_in, "transfer-encoding") -+ || (apr_table_get(r->headers_in, "content-length") -+ && strcmp(apr_table_get(r->headers_in, "content-length"), "0"))) -+ && !r->expecting_100) { -+ int rv; -+ -+ /* Fill the I/O buffer with the request body if possible. */ -+ rv = ssl_io_buffer_fill(r); -+ -+ if (rv) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "could not buffer message body to allow " -+ "SSL renegotiation to proceed"); -+ return rv; -+ } - } - - /* |