Hi Ralf

I check you patch and found out that it works except in the case where you
use apache as a proxy with https.

To fix the problem just check 'actx to be NULL' in the function
'ssl_io_suck_read'.

regards

Matthias


Ralf S. Engelschall wrote:
> 
> Ok, here is take 3 and my cleaned up and finally proposed patch which solves
> the POST problems by pre-sucking pending input data from the SSL/TLS I/O layer
> and re-injecting them after the renegotiation phase into the Apache I/O layer.
> 
> Here is an example:
> 
> [...]
> [26/Jul/1999 17:52:11] [info]  Connection: Client IP: 141.1.129.1, Protocol: SSLv3, 
>Cipher: RC4-MD5 (128/128 bits)
> [26/Jul/1999 17:52:11] [info]  Initial (No.1) HTTPS request received for child 0 
>(server en1.engelschall.com:8443)
> [26/Jul/1999 17:52:11] [trace] Reconfigured cipher suite will force renegotiation
> [26/Jul/1999 17:52:11] [info]  Requesting connection re-negotiation
> [26/Jul/1999 17:52:11] [trace] Performing full renegotiation: complete handshake 
>protocol
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Handshake: start
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSL renegotiate ciphers
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 write hello request A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 flush data
> [26/Jul/1999 17:52:11] [info]  Awaiting re-negotiation handshake
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Handshake: start
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: before accept initialization
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 read client hello A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 write server hello A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 write certificate A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 write key exchange A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 write server done A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 flush data
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 read client key exchange A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 read finished A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 write change cipher spec A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 write finished A
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Loop: SSLv3 flush data
> [26/Jul/1999 17:52:11] [trace] Inter-Process Session Cache: request=SET status=OK 
>id=4EF9E64F1BACBE87348D204B8881ED42CCFA839E5F7343F86C76F9F0BCF7987E timeout=300s 
>(session caching)
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Handshake: done
> [26/Jul/1999 17:52:11] [info]  Connection: Client IP: 141.1.129.1, Protocol: SSLv3, 
>Cipher: EXP-RC2-CBC-MD5 (40/128 bits)
> [26/Jul/1999 17:52:11] [trace] OpenSSL: Write: SSL negotiation finished successfully
> [26/Jul/1999 17:52:11] [info]  Connection to child 0 closed with standard shutdown 
>(server en1.engelschall.com:8443)
> [26/Jul/1999 17:52:14] [info]  Connection to child 0 established (server 
>en1.engelschall.com:8443)
> [26/Jul/1999 17:52:14] [trace] Seeding PRNG with 1032 bytes of entropy
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Handshake: start
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: before/accept initialization
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 read client hello A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write server hello A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write change cipher spec A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write finished A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 flush data
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 read finished A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Handshake: done
> 
> This a request to the demo HTML form over HTTPS but still without any POST
> data. Now I entered some data into the form field and pressed the SUBMIT
> button:
> 
> [26/Jul/1999 17:52:14] [info]  Connection: Client IP: 141.1.129.1, Protocol: SSLv3, 
>Cipher: EXP-RC2-CBC-MD5 (40/128 bits)
> [26/Jul/1999 17:52:14] [info]  Initial (No.1) HTTPS request received for child 0 
>(server en1.engelschall.com:8443)
> [26/Jul/1999 17:52:14] [trace] Reconfigured cipher suite will force renegotiation
> [26/Jul/1999 17:52:14] [info]  Requesting connection re-negotiation
> [26/Jul/1999 17:52:14] [trace] Performing full renegotiation: complete handshake 
>protocol
> [26/Jul/1999 17:52:14] [trace] I/O: sucked 12 bytes of input data from SSL/TLS I/O 
>layer for delayed injection into Apache I/O layer
> 
> Here you can see that before the handshake is performed the POST data is
> sucked from the SSL I/O layer into mod_ssl's buffer. Then the renegotiation is
> done:
> 
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Handshake: start
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSL renegotiate ciphers
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write hello request A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 flush data
> [26/Jul/1999 17:52:14] [info]  Awaiting re-negotiation handshake
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Handshake: start
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: before accept initialization
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 read client hello A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write server hello A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write certificate A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write key exchange A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write server done A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 flush data
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 read client key exchange A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 read finished A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write change cipher spec A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 write finished A
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Loop: SSLv3 flush data
> [26/Jul/1999 17:52:14] [trace] Inter-Process Session Cache: request=SET status=OK 
>id=C1CAB096DAEDC54E143EAA7BA03FDAB2D049090D8D88454C4316FB230EAB6727 timeout=300s 
>(session caching)
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Handshake: done
> [26/Jul/1999 17:52:14] [info]  Connection: Client IP: 141.1.129.1, Protocol: SSLv3, 
>Cipher: EXP-RC2-CBC-MD5 (40/128 bits)
> [26/Jul/1999 17:52:14] [trace] I/O: injecting 12 bytes of pre-sucked data into 
>Apache I/O layer
> [26/Jul/1999 17:52:14] [trace] OpenSSL: Write: SSL negotiation finished successfully
> [26/Jul/1999 17:52:14] [info]  Connection to child 0 closed with standard shutdown 
>(server en1.engelschall.com:8443)
> 
> Finally mod_cgi is processing my CGI script and wants to the the POST request
> body. As you can see the data is now served from mod_ssl's buffer instead
> (again) from the SSL I/O layer.
> 
> Please test the appended patch and give feedback.
> 
>                                        Ralf S. Engelschall
>                                        [EMAIL PROTECTED]
>                                        www.engelschall.com
> 
> Index: include/buff.h
> ===================================================================
> RCS file: /e/modssl/cvs/mod_ssl/pkg.apache/src/include/buff.h,v
> retrieving revision 1.6
> diff -u -r1.6 buff.h
> --- include/buff.h      1999/01/10 11:07:22     1.6
> +++ include/buff.h      1999/07/26 15:27:40
> @@ -182,6 +182,8 @@
> 
>  #ifndef CHARSET_EBCDIC
> 
> +#define ap_bpeekc(fb) ( ((fb)->incnt == 0) ? EOF : *((fb)->inptr) )
> +
>  #define ap_bgetc(fb)   ( ((fb)->incnt == 0) ? ap_bfilbuf(fb) : \
>                     ((fb)->incnt--, *((fb)->inptr++)) )
> 
> Index: modules/ssl/mod_ssl.h
> ===================================================================
> RCS file: /e/modssl/cvs/mod_ssl/pkg.apache/src/modules/ssl/mod_ssl.h,v
> retrieving revision 1.108
> diff -u -r1.108 mod_ssl.h
> --- modules/ssl/mod_ssl.h       1999/07/25 11:24:13     1.108
> +++ modules/ssl/mod_ssl.h       1999/07/26 11:30:25
> @@ -715,6 +715,7 @@
>  void         ssl_io_register(void);
>  void         ssl_io_unregister(void);
>  long         ssl_io_data_cb(BIO *, int, const char *, int, long, long);
> +void         ssl_io_suck(request_rec *, SSL *);
> 
>  /*  PRNG  */
>  int          ssl_rand_seed(server_rec *, pool *, ssl_rsctx_t);
> Index: modules/ssl/ssl_engine_io.c
> ===================================================================
> RCS file: /e/modssl/cvs/mod_ssl/pkg.apache/src/modules/ssl/ssl_engine_io.c,v
> retrieving revision 1.23
> diff -u -r1.23 ssl_engine_io.c
> --- modules/ssl/ssl_engine_io.c 1999/05/04 07:58:53     1.23
> +++ modules/ssl/ssl_engine_io.c 1999/07/26 15:51:24
> @@ -64,6 +64,159 @@
>                                              -- Unknown    */
>  #include "mod_ssl.h"
> 
> +/*  _________________________________________________________________
> +**
> +**  I/O Request Body Sucking and Re-Injection
> +**  _________________________________________________________________
> +*/
> +
> +#ifdef SSL_EXPERIMENTAL
> +
> +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 */
> +        int newlen;
> +        char *newptr;
> +        if (ss->buflen < len)
> +            newlen = ss->buflen * 2;
> +        else
> +            newlen = ss->buflen + len;
> +        newptr = ap_palloc(r->pool, newlen);
> +        memcpy(newptr, ss->bufptr, ss->buflen);
> +        ss->bufptr = newptr;
> +        ss->buflen = newlen;
> +    }
> +    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 known 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;
> +    int rv;
> +
> +    actx = (ap_ctx *)SSL_get_app_data2(ssl);
> +    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_EXPERIMENTAL */
> 
>  /*  _________________________________________________________________
>  **
> Index: modules/ssl/ssl_engine_kernel.c
> ===================================================================
> RCS file: /e/modssl/cvs/mod_ssl/pkg.apache/src/modules/ssl/ssl_engine_kernel.c,v
> retrieving revision 1.101
> diff -u -r1.101 ssl_engine_kernel.c
> --- modules/ssl/ssl_engine_kernel.c     1999/07/26 07:42:35     1.101
> +++ modules/ssl/ssl_engine_kernel.c     1999/07/26 11:00:31
> @@ -938,6 +938,7 @@
>                  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));
> +            ssl_io_suck(r, ssl);
>              SSL_renegotiate(ssl);
>              SSL_do_handshake(ssl);
>              if (SSL_get_state(ssl) != SSL_ST_OK) {
> ______________________________________________________________________
> Apache Interface to OpenSSL (mod_ssl)                   www.modssl.org
> User Support Mailing List                      [EMAIL PROTECTED]
> Automated List Manager                            [EMAIL PROTECTED]

-- 

-------------------------------------------------------------------------------
Matthias Loepfe, AdNovum Informatik AG, Roentgenstr. 22, CH-8005 Zurich
Email: [EMAIL PROTECTED]   Voice: +41 1 272 6111   Fax: +41 1 272 6312
______________________________________________________________________
Apache Interface to OpenSSL (mod_ssl)                   www.modssl.org
User Support Mailing List                      [EMAIL PROTECTED]
Automated List Manager                            [EMAIL PROTECTED]

Reply via email to