Subject: (BUG?) mod_ssl/openssl hangs on POST-Request with false Content-Length

From: Dimitri Rebrikov <[email-masked]>
Date: Fri, 28 Feb 2003 18:56:30 +0100

Hi,

We have problems with broken POST-Requests that our Partner
sends to us over HTTPS.
They are using the Software wrote by they own.(Not a Web-Browser).
We are using Apache, mod_ssl/openssl, mod_jk, Tomcat und servlets to Process they Requests.
The POST-Requests they sends have from time to time too big Content-Length
declaration that the Requests' Bodies real have.
Such requests hangs as long as the Partner shut it down (long time!).
The httpd.conf Timeout parameter seems to dont play any role here.
Many such requests from many partner's instanzes paralyze our System.

Our enviroment:
-----
SunOS #### 5.8 Generic_108528-18 sun4u sparc SUNW,Sun-Blade-1000
-----
[Fri Feb 28 16:47:01 2003] [notice] Apache/1.3.27 (Unix) mod_jk/1.2.0 mod_ssl/2.8.12 OpenSSL/0.9.7 configured -- resuming normal operations
-----
EAPI_MM="../mm-1.2.2" \
SSL_BASE="/export/schufa05/toschuel/Software/openssl-0.9.7" \
./configure \
"--with-layout=Apache" \
"--prefix=/usr/local/apache" \
"--enable-shared=ssl" \
"--enable-module=so" \
"--disable-module=imap" \
"--disable-module=include" \
"--disable-module=cgi" \
"--disable-module=actions" \
"--disable-module=userdir" \
"--enable-module=ssl" \
"$@"
-----
Apache Tomcat/4.0.4
-----

I have analyzed the Sorce Code from mod_jk/Apache/mod_ssl and log-Outputs with following results:

It hangs as the mod_jk try to read out the encrypted Body of the Request. Hiere is the Function-Call-Chain.

ws_read(mod_jk.c)
ap_get_client_block(apache/http_protokol.c)
ap_bread(apache/buff.c)
read_with_errors(same)
saferead(same)
saferead_guts(same)
buff_read(same)
ap_read(same)
"ap::buff::read" hook
ssl_io_hook_read(mod_ssl/ssl_engine_io.c)
SSL_read() - hangs !

I have inserted a short select()-Checking just before SSL_read in the ssl_io_hook_read
and the Problem gone!
Here is a changed ssl_io_hook_read - Code:
----------------------------------------------------------------------
static int ssl_io_hook_read(BUFF *fb, char *buf, int len)
{
     SSL *ssl;
     conn_rec *c;
     int rc;

     if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
       {
         /*
          * +++---+++
          *
          * Check/Wait for Nonblocking-Data
          *
          */
         int rv;
         fd_set fds;
         struct timeval tv;
         FD_ZERO(&fds);
         FD_SET(fb->fd_in, &fds);
         c = (conn_rec *)SSL_get_app_data(ssl);
         tv.tv_sec = c->server->timeout;
         tv.tv_usec = 0;
         rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
         if(rv <= 0) {
           return -1;
         }
       }

         rc = SSL_read(ssl, buf, len);
         /*
          * Simulate an EINTR in case OpenSSL wants to read more.
          * (This is usually the case when the client forces an SSL
          * renegotation which is handled implicitly by OpenSSL.)
          */
         if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)
             errno = EINTR;
         /*
          * Log SSL errors
          */
         if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
             c = (conn_rec *)SSL_get_app_data(ssl);
             ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
                     "SSL error on reading data");
         }
         /*
          * read(2) returns only the generic error number -1
          */
         if (rc < 0)
             rc = -1;
     }
     else
         rc = read(fb->fd_in, buf, len);
     return rc;
}
----------------------------------------------------------------------

Is that a BUG in mod_ssl/openssl?

Although our Problems could be solved with this mod_sll-Modification
i don have 100% sureness this is a right solution.

Any suggesstion and opinion would be wery appericated.

Best regards
Dimitri

PS

mod_ssl bug database is not working...
-----------------------------------------------------------
Index of /support/bugdb

       Name                    Last modified       Size  Description

[DIR] Parent Directory        22-Dec-2002 11:50      -
[TXT] footer.html             15-Dec-2002 14:47     1k
[TXT] header.html             15-Dec-2002 14:47     8k
[TXT] index.cgi               19-Apr-1999 18:04     1k
[   ] private.cgi             19-Apr-1999 18:04     1k
[   ] template.sh             31-Aug-1998 15:03     1k
[TXT] template.wml            30-Apr-1999 22:09     1k

Apache/1.3.27 Server at www.modssl.org Port 80
---------------------------------------------------------------
-- 

------------------------------------------------------------------------
Dimitri Rebrikov
*T-Systems GEI GmbH*
Projektentwickler
Postanschrift: Prager Straße 15, D-04103 Leipzig
Telefon:         (0341) 1275-439
Telefax:         (0341) 1275-333
E-Mail:          [email-masked]
<mailto:[email-masked]>
Internet:         http://www.t-systems.com
------------------------------------------------------------------------

______________________________________________________________________
Apache Interface to OpenSSL (mod_ssl)                   www.modssl.org
User Support Mailing List                      [email-masked]
Automated List Manager                            [email-masked]

---

From: Dimitri Rebrikov <[email-masked]>
Date: Mon, 03 Mar 2003 11:24:29 +0100

Hi,
i just have readed the decription of SSL_read() in openssl-0.9.7.

If count of bytes to read is higher than the data avaible to read,
the SSL_read will block if the underlying BIO is in blocking mode.
(IMHO that is the akutell situation in Apache/mod_ssl).

It is possible to make underlying BIO nonblocking...
(i have tried this with fcntl() just befor SSL_read-call)
But if underlying BIO is non-blocking the SSL_read will return
(unter the same circumstances as above) the -1 Errorcode and
SSL_ERROR_WANT_READ SSL-error. The mod_ssl(ssl_io_hook_read)
casts this Error as EINTR. The reaction of Apache on EINTR is
to recall of read operation (apache/buff.c/saferead_guts()).
This leads finally to dead loop (without timeout) beetwen Apache
and mod_ssl.

Perhaps, the mod_ssl schould check in which mode (blocking/nonblocking)
the underlying BIO is (f.e. with fcntl()), and do correspond pre-read-checking
(select() or nothing) and post-read-handling (EINTR-Casting oder nothing)...

What do you think about that?

Best regards
Dimitri
--