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]

Reply via email to