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]