httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From do...@apache.org
Subject cvs commit: httpd-2.0/modules/ssl mod_ssl.h ssl_engine_io.c ssl_engine_kernel.c
Date Thu, 17 Jan 2002 00:54:33 GMT
dougm       02/01/16 16:54:33

  Modified:    .        CHANGES
               modules/ssl mod_ssl.h ssl_engine_io.c ssl_engine_kernel.c
  Log:
  rewrite of mod_ssl input filter for better performance and less memory usage
  Reviewed by:	Justin Erenkrantz
  
  Revision  Changes    Path
  1.522     +3 -0      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.521
  retrieving revision 1.522
  diff -u -r1.521 -r1.522
  --- CHANGES	16 Jan 2002 04:29:10 -0000	1.521
  +++ CHANGES	17 Jan 2002 00:54:32 -0000	1.522
  @@ -1,4 +1,7 @@
   Changes with Apache 2.0.31-dev
  +  *) rewrite of mod_ssl input filter for better performance and less
  +     memory usage [Doug MacEachern]
  +
     *) allow quick_handler to be run on subrequests. [Ian Holsman]
   
     *) mod_dav now asks its provider to place content directly into the
  
  
  
  1.54      +0 -2      httpd-2.0/modules/ssl/mod_ssl.h
  
  Index: mod_ssl.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/mod_ssl.h,v
  retrieving revision 1.53
  retrieving revision 1.54
  diff -u -r1.53 -r1.54
  --- mod_ssl.h	11 Jan 2002 06:05:18 -0000	1.53
  +++ mod_ssl.h	17 Jan 2002 00:54:33 -0000	1.54
  @@ -466,8 +466,6 @@
       BIO                *pbioWrite;
       ap_filter_t        *pInputFilter;
       ap_filter_t        *pOutputFilter;
  -    apr_bucket_brigade *rawb;               /* encrypted input */
  -    apr_bucket_brigade *b;                  /* decrypted input */
   } SSLFilterRec;
   
   typedef enum {
  
  
  
  1.49      +331 -265  httpd-2.0/modules/ssl/ssl_engine_io.c
  
  Index: ssl_engine_io.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_io.c,v
  retrieving revision 1.48
  retrieving revision 1.49
  diff -u -r1.48 -r1.49
  --- ssl_engine_io.c	2 Dec 2001 01:26:45 -0000	1.48
  +++ ssl_engine_io.c	17 Jan 2002 00:54:33 -0000	1.49
  @@ -284,6 +284,172 @@
       return &bio_bucket_method;
   }
   
  +typedef struct {
  +    int length;
  +    char *value;
  +} char_buffer_t;
  +
  +typedef struct {
  +    ap_filter_t *f;
  +    apr_status_t rc;
  +    ap_input_mode_t mode;
  +    int getline;
  +    apr_bucket_brigade *bb;
  +    apr_bucket *bucket;
  +    char_buffer_t cbuf;
  +} BIO_bucket_in_t;
  +
  +typedef struct {
  +    BIO_bucket_in_t inbio;
  +    char_buffer_t cbuf;
  +    apr_pool_t *pool;
  +    char buffer[AP_IOBUFSIZE];
  +    SSLFilterRec *frec;
  +} ssl_io_input_ctx_t;
  +
  +/*
  + * this char_buffer api might seem silly, but we don't need to copy
  + * any of this data and we need to remember the length.
  + */
  +static int char_buffer_read(char_buffer_t *buffer, char *in, int inl)
  +{
  +    if (!buffer->length) {
  +        return 0;
  +    }
  +
  +    if (buffer->length >= inl) {
  +        /* we have have enough to fill the caller's buffer */
  +        memcpy(in, buffer->value, inl);
  +        buffer->value += inl;
  +        buffer->length -= inl;
  +    }
  +    else {
  +        /* swallow remainder of the buffer */
  +        memcpy(in, buffer->value, buffer->length);
  +        inl = buffer->length;
  +        buffer->value = NULL;
  +        buffer->length = 0;
  +    }
  +
  +    return inl;
  +}
  +
  +static int char_buffer_write(char_buffer_t *buffer, char *in, int inl)
  +{
  +    buffer->value = in;
  +    buffer->length = inl;
  +    return inl;
  +}
  +
  +/*
  + * this is the function called by SSL_read()
  + */
  +#define BIO_bucket_in_ptr(bio) (BIO_bucket_in_t *)bio->ptr
  +
  +static int bio_bucket_in_read(BIO *bio, char *in, int inl)
  +{
  +    BIO_bucket_in_t *inbio = BIO_bucket_in_ptr(bio);
  +    int len = 0;
  +    apr_off_t readbytes = inl;
  +
  +    inbio->rc = APR_SUCCESS;
  +
  +    /* first use data already read from socket if any */
  +    if ((len = char_buffer_read(&inbio->cbuf, in, inl))) {
  +        if ((len <= inl) || inbio->getline) {
  +            return len;
  +        }
  +    }
  +
  +    while (1) {
  +        const char *buf;
  +        apr_size_t buf_len = 0;
  +
  +        if (inbio->bucket) {
  +            /* all of the data in this bucket has been read,
  +             * so we can delete it now.
  +             */
  +            apr_bucket_delete(inbio->bucket);
  +            inbio->bucket = NULL;
  +        }
  +
  +        if (APR_BRIGADE_EMPTY(inbio->bb)) {
  +            inbio->rc = ap_get_brigade(inbio->f->next, inbio->bb,
  +                                       inbio->mode, &readbytes);
  +
  +            if ((inbio->rc != APR_SUCCESS) || APR_BRIGADE_EMPTY(inbio->bb))
  +            {
  +                break;
  +            }
  +        }
  +
  +        inbio->bucket = APR_BRIGADE_FIRST(inbio->bb);
  +
  +        inbio->rc = apr_bucket_read(inbio->bucket,
  +                                    &buf, &buf_len, inbio->mode);
  +
  +        if (inbio->rc != APR_SUCCESS) {
  +            apr_bucket_delete(inbio->bucket);
  +            inbio->bucket = NULL;
  +            return len;
  +        }
  +
  +        if (buf_len) {
  +            if ((len + buf_len) >= inl) {
  +                /* we have enough to fill the buffer.
  +                 * append if we have already written to the buffer.
  +                 */
  +                int nibble = inl - len;
  +                char *value = (char *)buf+nibble;
  +
  +                int length = buf_len - nibble;
  +                memcpy((void*)in+len, buf, nibble);
  +
  +                char_buffer_write(&inbio->cbuf, value, length);
  +                len += nibble;
  +
  +                break;
  +            }
  +            else {
  +                /* not enough data,
  +                 * save what we have and try to read more.
  +                 */
  +                memcpy((void*)in+len, buf, buf_len);
  +                len += buf_len;
  +            }
  +        }
  +
  +        if (inbio->getline) {
  +            /* only read from the socket once in getline mode.
  +             * since callers buffer size is likely much larger than
  +             * the request headers.  caller can always come back for more
  +             * if first read didn't get all the headers.
  +             */
  +            break;
  +        }
  +    }
  +
  +    return len;
  +}
  +
  +static BIO_METHOD bio_bucket_in_method = {
  +    BIO_TYPE_MEM,
  +    "APR input bucket brigade",
  +    NULL,                       /* write is never called */
  +    bio_bucket_in_read,
  +    NULL,                       /* puts is never called */
  +    NULL,                       /* gets is never called */
  +    NULL,                       /* ctrl is never called */
  +    bio_bucket_new,
  +    bio_bucket_free,
  +    NULL,
  +};
  +
  +static BIO_METHOD *BIO_s_in_bucket(void)
  +{
  +    return &bio_bucket_in_method;
  +}
  +
   static const char ssl_io_filter[] = "SSL/TLS Filter";
   
   static int ssl_io_hook_read(SSL *ssl, char *buf, int len)
  @@ -389,187 +555,6 @@
       return APR_SUCCESS;
   }
   
  -#define bio_is_renegotiating(bio) \
  -(((int)BIO_get_callback_arg(bio)) == SSL_ST_RENEGOTIATE)
  -#define HTTP_ON_HTTPS_PORT "GET /mod_ssl:error:HTTP-request HTTP/1.0\r\n"
  -
  -static apr_status_t churn_input(SSLFilterRec *pRec, ap_input_mode_t eMode, 
  -                                apr_off_t *readbytes)
  -{
  -    ap_filter_t *f = pRec->pInputFilter;
  -    SSLFilterRec *ctx = pRec;
  -    conn_rec *c = f->c;
  -    apr_pool_t *p = c->pool;
  -    apr_bucket *e;
  -    int found_eos = 0, n;
  -    char buf[1024];
  -    apr_status_t rv;
  -    int do_handshake = (eMode == AP_MODE_INIT);
  - 
  -    if (do_handshake) {
  -        /* protocol module needs to handshake before sending
  -         * data to client (e.g. NNTP or FTP)
  -         */
  -        *readbytes = AP_IOBUFSIZE;
  -        eMode = AP_MODE_NONBLOCKING;
  -    }
  -
  -    /* We have something in the processed brigade.  Use that first. */
  -    if (!APR_BRIGADE_EMPTY(ctx->b)) {
  -        return APR_SUCCESS;
  -    }
  -
  -    /* If we have nothing in the raw brigade, get some more. */
  -    if (APR_BRIGADE_EMPTY(ctx->rawb)) {
  -        if (do_handshake) {
  -            /* 
  -             * ap_get_brigade with AP_MODE_INIT should always be called
  -             * in non-blocking mode, but we need to block here
  -             */
  -            eMode = AP_MODE_BLOCKING;
  -        }
  -        rv = ap_get_brigade(f->next, ctx->rawb, eMode, readbytes);
  -
  -        if (rv != APR_SUCCESS)
  -            return rv;
  -
  -        /* Can't make any progress here. */
  -        if (*readbytes == 0)
  -        {
  -            /* This means that we have nothing else to read ever. */
  -            if (eMode == AP_MODE_BLOCKING) {
  -                APR_BRIGADE_INSERT_TAIL(ctx->b, apr_bucket_eos_create());
  -            }
  -            return APR_SUCCESS;
  -        }
  -    }
  -
  -    /* Process anything we have that we haven't done so already. */
  -    while (!APR_BRIGADE_EMPTY(ctx->rawb)) {
  -        const char *data;
  -        apr_size_t len;
  -
  -        e = APR_BRIGADE_FIRST(ctx->rawb);
  -
  -        if (APR_BUCKET_IS_EOS(e)) {
  -            apr_bucket_delete(e);
  -            found_eos = 1;
  -            break;
  -        }
  -
  -        /* read from the bucket */
  -        rv = apr_bucket_read(e, &data, &len, eMode);
  -
  -        if (rv != APR_SUCCESS)
  -            return rv;
  -
  -        /* Write it to our BIO */
  -	    n = BIO_write(pRec->pbioRead, data, len);
  -        
  -        if ((apr_size_t)n != len) {
  -            /* this should never really happen, since we're just writing
  -             * into a memory buffer, unless, of course, we run out of 
  -             * memory
  -             */
  -            ssl_log(c->base_server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
  -                    "attempting to write %d bytes to rbio, only wrote %d",
  -                    len, n);
  -            return APR_ENOMEM;
  -        }
  -
  -        /* If we reached here, we read the bucket successfully, so toss
  -         * it from the raw brigade. */
  -        apr_bucket_delete(e);
  -
  -    }
  -
  -    /* Note: ssl_engine_kernel.c calls ap_get_brigade when it wants to 
  -     * renegotiate.  Therefore, we must handle this by reading from
  -     * the socket and *NOT* reading into ctx->b from the BIO.  This is a 
  -     * very special case and needs to be treated as such.
  -     *
  -     * We need to tell all of the higher level filters that we didn't
  -     * return anything.  OpenSSL will know that we did anyway and try to
  -     * read directly via our BIO.
  -     */
  -    if (bio_is_renegotiating(pRec->pbioRead)) {
  -        return APR_SUCCESS;
  -    }
  -
  -    /* Before we actually read any unencrypted data, go ahead and
  -     * let ssl_hook_process_connection have a shot at it. 
  -     */
  -    rv = ssl_hook_process_connection(pRec);
  -
  -    if (do_handshake && (rv == APR_SUCCESS)) {
  -        /* don't block after the handshake */
  -        eMode = AP_MODE_NONBLOCKING;
  -    }
  -
  -    if (rv != APR_SUCCESS) {
  -        /* if process connection says HTTP_BAD_REQUEST, we've seen a 
  -         * HTTP on HTTPS error.
  -         *
  -         * The case where OpenSSL has recognized a HTTP request:
  -         * This means the client speaks plain HTTP on our HTTPS port.
  -         * Hmmmm...  At least for this error we can be more friendly
  -         * and try to provide him with a HTML error page. We have only
  -         * one problem:OpenSSL has already read some bytes from the HTTP
  -         * request. So we have to skip the request line manually and
  -         * instead provide a faked one in order to continue the internal
  -         * Apache processing.
  -         *
  -         */
  -        if (rv == HTTP_BAD_REQUEST) {
  -            /* log the situation */
  -            ssl_log(c->base_server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
  -                    "SSL handshake failed: HTTP spoken on HTTPS port; "
  -                    "trying to send HTML error page");
  -
  -            /* fake the request line */
  -            e = apr_bucket_immortal_create(HTTP_ON_HTTPS_PORT,
  -                                           sizeof(HTTP_ON_HTTPS_PORT) - 1);
  -            APR_BRIGADE_INSERT_TAIL(ctx->b, e);
  -            e = apr_bucket_immortal_create(CRLF, sizeof(CRLF) - 1);
  -            APR_BRIGADE_INSERT_TAIL(ctx->b, e);
  -
  -            return APR_SUCCESS;
  -        }
  -        if (rv == SSL_ERROR_WANT_READ) {
  -            /* if eMode was originally AP_MODE_INIT,
  -             * need to reset before we recurse
  -             */
  -            ap_input_mode_t mode = do_handshake ? AP_MODE_INIT : eMode;
  -            apr_off_t tempread = AP_IOBUFSIZE;
  -            return churn_input(pRec, mode, &tempread);
  -        }
  -        return rv;
  -    }
  -
  -    /* try to pass along all of the current BIO to ctx->b */
  -    /* FIXME: If there's an error and there was EOS, we may not really
  -     * reach EOS.
  -     */
  -    while ((n = ssl_io_hook_read(pRec->pssl, buf, sizeof(buf))) > 0) {
  -        char *pbuf;
  -
  -        pbuf = apr_pmemdup(p, buf, n);
  -        e = apr_bucket_pool_create(pbuf, n, p);
  -        APR_BRIGADE_INSERT_TAIL(ctx->b, e);
  -    }
  -
  -    if (n < 0 && errno == EINTR && APR_BRIGADE_EMPTY(ctx->b)) {
  -        apr_off_t tempread = AP_IOBUFSIZE;
  -        return churn_input(pRec, eMode, &tempread);
  -    }
  -
  -    if (found_eos) {
  -        APR_BRIGADE_INSERT_TAIL(ctx->b, apr_bucket_eos_create());
  -    }
  -
  -    return APR_SUCCESS;
  -}
  -
   static apr_status_t ssl_io_filter_Output(ap_filter_t *f,
                                            apr_bucket_brigade *bb)
   {
  @@ -623,104 +608,186 @@
       return ret;
   }
   
  +/*
  + * ctx->cbuf is leftover plaintext from ssl_io_input_getline,
  + * use what we have there first if any,
  + * then go for more by calling ssl_io_hook_read.
  + */
  +static apr_status_t ssl_io_input_read(ssl_io_input_ctx_t *ctx,
  +                                      char *buf,
  +                                      apr_size_t *len)
  +{
  +    int wanted = *len;
  +    int bytes = 0, rc;
  +
  +    *len = 0;
  +
  +    if ((bytes = char_buffer_read(&ctx->cbuf, buf, wanted))) {
  +        *len = bytes;
  +        if ((*len >= wanted) || ctx->inbio.getline) {
  +            return APR_SUCCESS;
  +        }
  +    }
  +
  +    rc = ssl_io_hook_read(ctx->frec->pssl, buf+bytes, wanted-bytes);
  +
  +    if (rc > 0) {
  +        *len += rc;
  +    }
  +
  +    return ctx->inbio.rc;
  +}
  +
  +static apr_status_t ssl_io_input_getline(ssl_io_input_ctx_t *ctx,
  +                                         char *buf,
  +                                         apr_size_t *len)
  +{
  +    const char *pos;
  +    apr_status_t status;
  +
  +    ctx->inbio.getline = 1;
  +    status = ssl_io_input_read(ctx, buf, len);
  +    ctx->inbio.getline = 0;
  +
  +    if (status != APR_SUCCESS) {
  +        return status;
  +    }
  +
  +    if ((pos = memchr(buf, APR_ASCII_LF, *len))) {
  +        char *value;
  +        int length;
  +        apr_size_t bytes = pos - buf;
  +
  +        bytes += 1;
  +        value = buf + bytes;
  +        length = *len - bytes;
  +
  +        char_buffer_write(&ctx->cbuf, value, length);
  +
  +        *len = bytes;
  +    }
  +
  +    return APR_SUCCESS;
  +}
  +
  +#define HTTP_ON_HTTPS_PORT \
  +    "GET /mod_ssl:error:HTTP-request HTTP/1.0\r\n\r\n"
  +
  +#define HTTP_ON_HTTPS_PORT_BUCKET() \
  +    apr_bucket_immortal_create(HTTP_ON_HTTPS_PORT, \
  +                               sizeof(HTTP_ON_HTTPS_PORT) - 1)
  +
  +static apr_status_t ssl_io_filter_error(ap_filter_t *f,
  +                                        apr_bucket_brigade *bb,
  +                                        apr_status_t status)
  +{
  +    apr_bucket *bucket;
  +
  +    switch (status) {
  +      case HTTP_BAD_REQUEST:
  +            /* log the situation */
  +            ssl_log(f->c->base_server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
  +                    "SSL handshake failed: HTTP spoken on HTTPS port; "
  +                    "trying to send HTML error page");
  +
  +            /* fake the request line */
  +            bucket = HTTP_ON_HTTPS_PORT_BUCKET();
  +            break;
  +
  +      default:
  +        return status;
  +    }
  +
  +    APR_BRIGADE_INSERT_TAIL(bb, bucket);
  +
  +    return APR_SUCCESS;
  +}
  +
   static apr_status_t ssl_io_filter_Input(ap_filter_t *f,
  -                                        apr_bucket_brigade *pbbOut,
  +                                        apr_bucket_brigade *bb,
                                           ap_input_mode_t mode,
                                           apr_off_t *readbytes)
   {
  -    apr_status_t ret;
  -    SSLFilterRec *ctx = f->ctx;
  -    apr_status_t rv;
  -    apr_bucket *e;
  -    apr_off_t tempread;
  +    apr_status_t status;
  +    ssl_io_input_ctx_t *ctx = f->ctx;
  +
  +    apr_size_t len = sizeof(ctx->buffer);
  +    apr_off_t bytes = *readbytes;
  +    int is_init = (mode == AP_MODE_INIT);
   
       /* XXX: we don't currently support peek or readbytes == -1 */
       if (mode == AP_MODE_PEEK || *readbytes == -1) {
           return APR_ENOTIMPL;
       }
   
  -    /* Return the requested amount or less. */
  -    if (*readbytes)
  -    {
  -        apr_bucket_brigade *newbb;
  -
  -        /* ### This is bad. */
  -        APR_BRIGADE_NORMALIZE(ctx->b);
  +    ctx->inbio.mode = is_init ? AP_MODE_BLOCKING : mode;
   
  -        /* churn the state machine */
  -        ret = churn_input(ctx, mode, readbytes);
  +    /* XXX: we could actually move ssl_hook_process_connection to an
  +     * ap_hook_process_connection but would still need to call it for
  +     * AP_MODE_INIT for protocols that may upgrade the connection
  +     * rather than have SSLEngine On configured.
  +     */
  +    status = ssl_hook_process_connection(ctx->frec);
   
  -        if (ret != APR_SUCCESS)
  -	        return ret;
  +    if (status != APR_SUCCESS) {
  +        return ssl_io_filter_error(f, bb, status);
  +    }
   
  -        apr_brigade_length(ctx->b, 0, &tempread);
  +    if (is_init) {
  +        /* protocol module needs to handshake before sending
  +         * data to client (e.g. NNTP or FTP)
  +         */
  +        return APR_SUCCESS;
  +    }
   
  -        if (*readbytes < tempread) {
  -            tempread = *readbytes;
  -        } 
  -        else {
  -            *readbytes = tempread;
  +    if (bytes > 0) {
  +        if (bytes < len) {
  +            len = bytes;
           }
  -        
  -        apr_brigade_partition(ctx->b, tempread, &e);
  -        newbb = apr_brigade_split(ctx->b, e);
  -        APR_BRIGADE_CONCAT(pbbOut, ctx->b);
  -        APR_BRIGADE_CONCAT(ctx->b, newbb);
  +        ctx->inbio.getline = 0;
  +        status = ssl_io_input_read(ctx, ctx->buffer, &len);
  +    }
  +    else {
  +        status = ssl_io_input_getline(ctx, ctx->buffer, &len);
  +    }
   
  -        return APR_SUCCESS;
  +    if (status != APR_SUCCESS) {
  +        return ssl_io_filter_error(f, bb, status);
       }
  -   
  -    /* Readbytes == 0 implies we only want a LF line. */
  -    if (APR_BRIGADE_EMPTY(ctx->b)) {
  -        tempread = AP_IOBUFSIZE;
  -        rv = churn_input(ctx, mode, &tempread);
  -        if (rv != APR_SUCCESS)
  -            return rv;
  -        /* We have already blocked. */
  -        mode = AP_MODE_NONBLOCKING;
  +
  +    if (len > 0) {
  +        apr_bucket *bucket =
  +            apr_bucket_transient_create(ctx->buffer, len);
  +        APR_BRIGADE_INSERT_TAIL(bb, bucket);
       }
  -    while (!APR_BRIGADE_EMPTY(ctx->b)) {
  -        const char *pos, *str;
  -        apr_size_t len;
   
  -        e = APR_BRIGADE_FIRST(ctx->b);
  +    *readbytes = len;
   
  -        /* Sure, we'll call this is a line.  Whatever. */
  -        if (APR_BUCKET_IS_EOS(e)) {
  -            APR_BUCKET_REMOVE(e);
  -            APR_BRIGADE_INSERT_TAIL(pbbOut, e);
  -            break;
  -        }
  +    return APR_SUCCESS;
  +}
   
  -        if ((rv = apr_bucket_read(e, &str, &len, 
  -                                  AP_MODE_NONBLOCKING)) != APR_SUCCESS) {
  -            return rv;
  -        }
  +static void ssl_io_input_add_filter(SSLFilterRec *frec, conn_rec *c,
  +                                    SSL *ssl)
  +{
  +    ssl_io_input_ctx_t *ctx;
   
  -        pos = memchr(str, APR_ASCII_LF, len);
  -        /* We found a match. */
  -        if (pos != NULL) {
  -            apr_bucket_split(e, pos - str + 1);
  -            APR_BUCKET_REMOVE(e);
  -            APR_BRIGADE_INSERT_TAIL(pbbOut, e);
  -            *readbytes += pos - str;
  -            return APR_SUCCESS;
  -        }
  -        APR_BUCKET_REMOVE(e);
  -        APR_BRIGADE_INSERT_TAIL(pbbOut, e);
  -        *readbytes += len;
  -
  -        /* Hey, we're about to be starved - go fetch more data. */
  -        if (APR_BRIGADE_EMPTY(ctx->b)) {
  -            tempread = AP_IOBUFSIZE;
  -            ret = churn_input(ctx, mode, &tempread);
  -            if (ret != APR_SUCCESS)
  -	            return ret;
  -            mode = AP_MODE_NONBLOCKING;
  -        }
  -    }
  +    ctx = apr_palloc(c->pool, sizeof(*ctx));
   
  -    return APR_SUCCESS;
  +    frec->pInputFilter = ap_add_input_filter(ssl_io_filter, ctx, NULL, c);
  +
  +    frec->pbioRead = BIO_new(BIO_s_in_bucket());
  +    frec->pbioRead->ptr = &ctx->inbio;
  +
  +    ctx->frec = frec;
  +    ctx->inbio.f = frec->pInputFilter;
  +    ctx->inbio.bb = apr_brigade_create(c->pool);
  +    ctx->inbio.bucket = NULL;
  +    ctx->inbio.getline = 0;
  +    ctx->inbio.cbuf.length = 0;
  +
  +    ctx->cbuf.length = 0;
  +
  +    ctx->pool = c->pool;
   }
   
   static apr_status_t ssl_io_filter_cleanup (void *data)
  @@ -746,14 +813,16 @@
       SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
       SSLFilterRec *filter;
   
  -    filter = apr_pcalloc(c->pool, sizeof(SSLFilterRec));
  -    filter->pInputFilter    = ap_add_input_filter(ssl_io_filter, filter, NULL, c);
  -    filter->pOutputFilter   = ap_add_output_filter(ssl_io_filter, filter, NULL, c);
  -    filter->b               = apr_brigade_create(c->pool);
  -    filter->rawb            = apr_brigade_create(c->pool);
  -    filter->pbioRead        = BIO_new(BIO_s_mem());
  +    filter = apr_palloc(c->pool, sizeof(SSLFilterRec));
  +
  +    ssl_io_input_add_filter(filter, c, ssl);
  +
  +    filter->pOutputFilter   = ap_add_output_filter(ssl_io_filter,
  +                                                   filter, NULL, c);
  +
       filter->pbioWrite       = BIO_new(BIO_s_bucket());
       filter->pbioWrite->ptr  = BIO_bucket_new(filter, c);
  +
       SSL_set_bio(ssl, filter->pbioRead, filter->pbioWrite);
       filter->pssl            = ssl;
   
  @@ -761,9 +830,6 @@
                                 ssl_io_filter_cleanup, apr_pool_cleanup_null);
   
       if (sc->nLogLevel >= SSL_LOG_DEBUG) {
  -        /* XXX: this will currently get wiped out if renegotiation
  -         * happens in ssl_hook_Access
  -         */
           BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
           BIO_set_callback_arg(SSL_get_rbio(ssl), ssl);
       }
  
  
  
  1.39      +0 -82     httpd-2.0/modules/ssl/ssl_engine_kernel.c
  
  Index: ssl_engine_kernel.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_kernel.c,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- ssl_engine_kernel.c	10 Jan 2002 04:55:19 -0000	1.38
  +++ ssl_engine_kernel.c	17 Jan 2002 00:54:33 -0000	1.39
  @@ -292,84 +292,6 @@
       return HTTP_BAD_REQUEST;
   }
   
  -typedef long bio_hook_t (BIO *, int, const char *, int, long, long);
  -
  -static void bio_hook_set(BIO *b, bio_hook_t *hook, void *data)
  -{
  -    while (b) {
  -        BIO_set_callback(b, hook);
  -        BIO_set_callback_arg(b, data);
  -        b = BIO_next(b);
  -    }
  -}
  -
  -/* XXX: save/restore current callbacks if any? */
  -#define ssl_bio_hooks_set(ssl, hook, data) \
  -    bio_hook_set(SSL_get_wbio(ssl), hook, data); \
  -    bio_hook_set(SSL_get_rbio(ssl), hook, data)
  -
  -#define ssl_bio_renegotiate_hook_set(ssl, data) \
  -ssl_bio_hooks_set(ssl, ssl_renegotiate_hook, data)
  -
  -#define ssl_bio_hooks_unset(ssl) \
  -ssl_bio_hooks_set(ssl, NULL, NULL)
  -
  -#define bio_mem_length(b) ((BUF_MEM *)b->ptr)->length
  -
  -/* if we need to renegotiate in the access phase
  - * data needs to be pushed to / pulled from the filter chain
  - * otherwise, a BIO_write just sits in memory and theres nothing
  - * to BIO_read
  - */
  -
  -static long ssl_renegotiate_hook(BIO *bio, int cmd, const char *argp,
  -                                 int argi, long argl, long rc)
  -{
  -    request_rec *r = (request_rec *)BIO_get_callback_arg(bio);
  -    SSLConnRec *sslconn = myConnConfig(r->connection);
  -    SSL *ssl = sslconn->ssl;
  -
  -    int is_failed_read = (cmd == (BIO_CB_READ|BIO_CB_RETURN) && (rc == -1));
  -    int is_flush       = ((cmd == BIO_CB_CTRL) && (argi == BIO_CTRL_FLUSH));
  -
  -    if (is_flush || is_failed_read) {
  -        /* disable this callback to prevent recursion
  -         * and leave a "note" so the input filter leaves the rbio
  -         * as-as
  -         */
  -        ssl_bio_hooks_set(ssl, NULL, (void*)SSL_ST_RENEGOTIATE);
  -    }
  -    else {
  -        return rc;
  -    }
  -
  -    if (is_flush) {
  -        /* flush what was written into wbio to the client */
  -        ssl_log(r->server, SSL_LOG_DEBUG,
  -                "flushing %d bytes to the client",
  -                bio_mem_length(bio));
  -        ap_rflush(r);
  -    }
  -    else {
  -        /* force read from the client socket */
  -        apr_bucket_brigade *bb = apr_brigade_create(r->connection->pool);
  -        apr_off_t bytes = argi;
  -        ap_get_brigade(r->input_filters, bb,
  -                       AP_MODE_BLOCKING, &bytes);
  -
  -        rc = BIO_read(bio, (void *)argp, argi);
  -
  -        ssl_log(r->server, SSL_LOG_DEBUG,
  -                "retry read: wanted %d, got %d, %d remain\n",
  -                argi, rc, bio_mem_length(bio));
  -    }
  -
  -    /* reset this bio hook for further read/writes */
  -    ssl_bio_renegotiate_hook_set(ssl, r);
  -
  -    return rc;
  -}
  -
   /*
    *  Access Handler
    */
  @@ -784,22 +706,18 @@
               else
                   SSL_set_session_id_context(ssl, (unsigned char *)&r, sizeof(r));
               /* will need to push to / pull from filters to renegotiate */
  -            ssl_bio_renegotiate_hook_set(ssl, r);
               SSL_renegotiate(ssl);
               SSL_do_handshake(ssl);
   
               if (SSL_get_state(ssl) != SSL_ST_OK) {
                   ssl_log(r->server, SSL_LOG_ERROR,
                           "Re-negotiation request failed");
  -                ssl_bio_hooks_unset(ssl);
                   return HTTP_FORBIDDEN;
               }
               ssl_log(r->server, SSL_LOG_INFO,
                       "Awaiting re-negotiation handshake");
               SSL_set_state(ssl, SSL_ST_ACCEPT);
               SSL_do_handshake(ssl);
  -
  -            ssl_bio_hooks_unset(ssl);
   
               if (SSL_get_state(ssl) != SSL_ST_OK) {
                   ssl_log(r->server, SSL_LOG_ERROR,
  
  
  

Mime
View raw message