]> granicus.if.org Git - apache/commitdiff
Axe out SSL_CONSERVATIVE stuff which for Apache 1.3 did I/O data
authorRalf S. Engelschall <rse@apache.org>
Sat, 5 May 2001 16:23:00 +0000 (16:23 +0000)
committerRalf S. Engelschall <rse@apache.org>
Sat, 5 May 2001 16:23:00 +0000 (16:23 +0000)
pre-sucking on POST requests and I/O re-injection in case of SSL
renegotiations. This all either cannot be solved any longer or at least
has to be implemented totally different through I/O layering/filtering.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@89017 13f79535-47bb-0310-9956-ffa450edef68

modules/ssl/README
modules/ssl/mod_ssl.h
modules/ssl/ssl_engine_io.c
modules/ssl/ssl_engine_kernel.c

index 8f337076120c699a1076ea49e1af490b7bc8cf42..f2bcfefc28bf53d05762304b8bdc27cf6f5eaf77 100644 (file)
  o The complete EAPI-based SSL_VENDOR stuff was removed.
  o The complete EAPI-based SSL_COMPAT stuff was removed.
  o The <IfDefine> variable MOD_SSL is no longer provided automatically 
+ o The complete SSL_CONSERVATIVE stuff was removed, i.e.,
+   SSL renegotiations in combination with POST request are not supported
+   unless the problem is solved again, but this time through layered I/O.
 
  MAJOR CHANGES 
 
index 823df609d2a2dab6de926b656105df194ed4e398..59c40b776c10dca6f4c92899b170caec11593f22 100644 (file)
@@ -778,9 +778,6 @@ char        *ssl_var_lookup(pool *, server_rec *, conn_rec *, request_rec *, cha
 void         ssl_io_register(void);
 void         ssl_io_unregister(void);
 long         ssl_io_data_cb(BIO *, int, const char *, int, long, long);
-#ifndef SSL_CONSERVATIVE
-void         ssl_io_suck(request_rec *, SSL *);
-#endif
 
 /*  PRNG  */
 int          ssl_rand_seed(server_rec *, pool *, ssl_rsctx_t, char *);
index 3b0334337263f097b1d34a53b128cc556bc9eb0e..e56901415e0b90389bff88ccacbbaf5bedaef115 100644 (file)
 
 #if 0 /* XXX */
 
-/*  _________________________________________________________________
-**
-**  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
index d0c9e1d7b2b98a09b8462cbb5759925f95601d9b..5566c9b64f86ca2212c0ff8a9e47536faeb9e7fe 100644 (file)
@@ -857,19 +857,71 @@ int ssl_hook_Access(request_rec *r)
     }
 #endif /* SSL_EXPERIMENTAL_PERDIRCA */
 
-#ifdef SSL_CONSERVATIVE 
     /* 
-     *  SSL renegotiations in conjunction with HTTP
-     *  requests using the POST method are not supported.
+     * 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 && r->method_number == M_POST) {
         ssl_log(r->server, SSL_LOG_ERROR,
                 "SSL Re-negotiation in conjunction with POST method not supported!");
-        ssl_log(r->server, SSL_LOG_INFO,
-                "You have to compile without -DSSL_CONSERVATIVE to enabled support for this.");
         return METHOD_NOT_ALLOWED;
     }
-#endif /* SSL_CONSERVATIVE */
 
     /*
      * now do the renegotiation if anything was actually reconfigured
@@ -922,9 +974,6 @@ int ssl_hook_Access(request_rec *r)
                 SSL_set_session_id_context(ssl, (unsigned char *)&(r->main), sizeof(r->main));
             else
                 SSL_set_session_id_context(ssl, (unsigned char *)&r, sizeof(r));
-#ifndef SSL_CONSERVATIVE
-            ssl_io_suck(r, ssl);
-#endif
             SSL_renegotiate(ssl);
             SSL_do_handshake(ssl);
             if (SSL_get_state(ssl) != SSL_ST_OK) {