I'll give this a try as well given that I'm giving a demo tomorrow morning
:)
Thanks
Jeff
On Mon, 26 Jul 1999, Ralf S. Engelschall wrote:
>
> As Matthias L. found out, the problems with POST requests in conjunction with
> per-directory/location SSL renegotiations is that the pending POST request
> body in the SSL BIO caused problems for the handshake. I've today spended four
> hours in the morning and hacked together an experimental patch which does the
> following: before the SSL handshake for renegotiations is performed it sucks
> in all received data from the SSL BIO. Then the handshake is performed and
> when Apache's BUFF code wants to read more from the BIO SSL we are aware of
> the pre-sucked data. With this patch I was able to get a form working which
> POSTs its data to a CGI (I was also to reproduce the I/O error problem before,
> of course).
>
> Matthias, can you try this out, too? I'm still not convinced whether this is
> the correct way (perhaps we can also maipulate the SSL BIO or whatever), but
> it at least is a solution. I've less time these days and weeks, so I would
> appreciate when you investigate more for us - starting from this first cut of
> a solution. Thanks.
>
> Greetings,
> 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 09:26:06
> @@ -227,6 +227,10 @@
>
> /* enable non-blocking operations */
> API_EXPORT(int) ap_bnonblock(BUFF *fb, int direction);
> +/* enable blocking operations */
> +API_EXPORT(int) ap_bblock(BUFF *fb, int direction);
> +/* check for blocking mode */
> +API_EXPORT(int) ap_bisblock(BUFF *fb, int direction);
> /* and get an fd to select() on */
> API_EXPORT(int) ap_bfileno(BUFF *fb, int direction);
>
> Index: main/buff.c
> ===================================================================
> RCS file: /e/modssl/cvs/mod_ssl/pkg.apache/src/main/buff.c,v
> retrieving revision 1.14
> diff -u -r1.14 buff.c
> --- main/buff.c 1999/03/21 12:00:11 1.14
> +++ main/buff.c 1999/07/26 09:25:30
> @@ -580,6 +580,44 @@
> #endif
> }
>
> +API_EXPORT(int) ap_bblock(BUFF *fb, int direction)
> +{
> + int fd;
> + int mode;
> +
> + fd = (direction == B_RD) ? fb->fd_in : fb->fd;
> + mode = fcntl(fd, F_GETFL, NULL);
> +#if defined(O_NONBLOCK)
> + return fcntl(fd, F_SETFL, mode&~(O_NONBLOCK));
> +#elif defined(O_NDELAY)
> + return fcntl(fd, F_SETFL, mode&~(O_NDELAY));
> +#elif defined(FNDELAY)
> + return fcntl(fd, F_SETFL, mode&~(FNDELAY));
> +#else
> + /* XXXX: this breaks things, but an alternative isn't obvious...*/
> + return 0;
> +#endif
> +}
> +
> +API_EXPORT(int) ap_bisblock(BUFF *fb, int direction)
> +{
> + int fd;
> + int mode;
> +
> + fd = (direction == B_RD) ? fb->fd_in : fb->fd;
> + mode = fcntl(fd, F_GETFL, NULL);
> +#if defined(O_NONBLOCK)
> + return (mode & O_NONBLOCK) ? FALSE : TRUE;
> +#elif defined(O_NDELAY)
> + return (mode & O_NDELAY) ? FALSE : TRUE;
> +#elif defined(FNDELAY)
> + return (mode & FNDELAY) ? FALSE : TRUE;
> +#else
> + /* XXXX: this breaks things, but an alternative isn't obvious...*/
> + return FALSE;
> +#endif
> +}
> +
> API_EXPORT(int) ap_bfileno(BUFF *fb, int direction)
> {
> return (direction == B_RD) ? fb->fd_in : fb->fd;
> 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 08:02:23
> @@ -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(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 09:53:23
> @@ -64,6 +64,138 @@
> -- Unknown */
> #include "mod_ssl.h"
>
> +/* _________________________________________________________________
> +**
> +** I/O Sucking
> +** _________________________________________________________________
> +*/
> +
> +static char *suck_buf = NULL;
> +static int suck_len = 0;
> +
> +static char *suck_ptr = NULL;
> +static int suck_pend = 0;
> +
> +int ssl_io_suck_in(SSL *ssl, int n);
> +int ssl_io_suck_read(SSL *ssl, char *buf, int len);
> +
> +void ssl_io_suck(SSL *ssl)
> +{
> + conn_rec *c;
> + BUFF *b;
> + int wasblocking;
> +
> + c = (conn_rec *)SSL_get_app_data(ssl);
> + b = c->client;
> +
> + /* set socket to non-blocking mode */
> + wasblocking = ap_bisblock(b, B_RD);
> + ap_bnonblock(b, B_RD);
> +
> + /* suck in data by chunks of 4KB */
> + while (ssl_io_suck_in(ssl, 4096) > 0) ;
> +
> + /* restore socket operation mode */
> + if (wasblocking)
> + ap_bblock(b, B_RD);
> + return;
> +}
> +
> +int ssl_io_suck_in(SSL *ssl, int n)
> +{
> + conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
> + int rc;
> +
> + if (suck_buf == NULL) {
> + /* the first time: start with a fresh buffer */
> + suck_len = (n > 1024 ? n : 1024);
> + suck_buf = malloc(suck_len);
> + suck_ptr = suck_buf;
> + suck_pend = 0;
> + rc = SSL_read(ssl, suck_buf, suck_len);
> + ssl_log(c->server, SSL_LOG_TRACE, "%d = SSL_read(0, %d)", rc, suck_len);
> + if (rc >= 0) {
> + suck_pend = rc;
> + ssl_log(c->server, SSL_LOG_TRACE,
> + "SSL I/O: sucking %d/%d bytes into fresh buffer (%d: %d/%d)",
> + suck_pend, n, suck_len, 0, suck_pend);
> + }
> + return rc;
> + }
> + else if ((suck_buf+suck_len) - (suck_ptr+suck_pend) >= n) {
> + /* fill more data into existing buffer */
> + rc = SSL_read(ssl, suck_ptr+suck_pend, n);
> + ssl_log(c->server, SSL_LOG_TRACE, "%d = SSL_read(%d, %d)", rc, suck_pend,
>n);
> + if (rc >= 0) {
> + suck_pend += rc;
> + ssl_log(c->server, SSL_LOG_TRACE,
> + "SSL I/O: sucking %d/%d additional bytes to end of buffer (%d:
>%d/%d)",
> + rc, n, suck_len, suck_ptr-suck_buf,
>suck_ptr-suck_buf+suck_pend);
> + }
> + return rc;
> + }
> + else {
> + /* resize buffer and fill in additional data */
> + suck_len += n - ((suck_buf+suck_len) - (suck_ptr+suck_pend));
> + suck_buf = realloc(suck_buf, suck_len);
> + rc = SSL_read(ssl, suck_ptr+suck_pend, n);
> + ssl_log(c->server, SSL_LOG_TRACE, "%d = SSL_read(%d, %d)", rc, suck_pend,
>n);
> + if (rc >= 0) {
> + suck_pend += rc;
> + ssl_log(c->server, SSL_LOG_TRACE,
> + "SSL I/O: sucking %d/%d bytes while expanding buffer (%d:
>%d/%d)",
> + rc, n, suck_len, suck_ptr-suck_buf,
>suck_ptr-suck_buf+suck_pend);
> + }
> + return rc;
> + }
> +}
> +
> +int ssl_io_suck_read(SSL *ssl, char *buf, int len)
> +{
> + conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
> + int rv;
> +
> + ssl_log(c->server, SSL_LOG_TRACE, "ssl_io_suck_read(%d)", len);
> +
> + if (suck_pend >= len) {
> + /* more data than requestd */
> + memcpy(buf, suck_ptr, len);
> + suck_ptr += len;
> + suck_pend -= len;
> + ssl_log(c->server, SSL_LOG_TRACE,
> + "SSL I/O: reading %d bytes from suck buffer", len);
> + ssl_log(c->server, SSL_LOG_TRACE, "%d = my_SSL_read()", len);
> + if (suck_pend == 0)
> + suck_ptr = suck_buf;
> + return len;
> + }
> + else if (suck_pend > 0) {
> + /* less data than requested */
> + ssl_log(c->server, SSL_LOG_TRACE,
> + "SSL I/O: reading remaining %d bytes from suck buffer", suck_pend);
> + memcpy(buf, suck_ptr, suck_pend);
> + buf += suck_pend;
> + len -= suck_pend;
> + rv = suck_pend;
> + suck_ptr = suck_buf;
> + suck_pend = 0;
> + ssl_log(c->server, SSL_LOG_TRACE,
> + "SSL I/O: reading additional %d bytes from SSL stream", len);
> + return rv;
> + }
> + else {
> + /* nothing pre-sucked, so do standard operation */
> + rv = SSL_read(ssl, buf, len);
> + if (rv >= 0)
> + ssl_log(c->server, SSL_LOG_TRACE,
> + "SSL I/O: reading %d bytes from SSL stream", rv);
> + ssl_log(c->server, SSL_LOG_TRACE, "%d = my_SSL_read()", rv);
> + return rv;
> + }
> +}
> +
> +/* override SSL_read in following code */
> +#define SSL_read ssl_io_suck_read
>
> /* _________________________________________________________________
> **
> 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 08:02:42
> @@ -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(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]
>
______________________________________________________________________
Apache Interface to OpenSSL (mod_ssl) www.modssl.org
User Support Mailing List [EMAIL PROTECTED]
Automated List Manager [EMAIL PROTECTED]