httpd-bugs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject DO NOT REPLY [Bug 46952] ssl renegotiation hangs with long ca list
Date Fri, 19 Jun 2009 11:36:16 GMT

--- Comment #8 from David Smith <>  2009-06-19 04:36:08 PST ---

I have been making some investigation of the problem - and wanted to summarise
the current understanding of the details - which I'm fairly clear about. I've
also included a tentative fix, but as I explain there are some considerations -
the wider audience here will probably have some more ideas. (I'll write a
similar report on the openssl bug list, as there are also openssl issues

Apparently the problem (dialogue stall) arrises because of the two layers of
buffering between mod_ssl's filter_out BIO and the wbio buffer BIO (i.e. a
BIO_f_buffer()), which openssl adds to the stack of wbio BIOs for most of the
handshake process. In particular s3_srvr.c (in openssl) uses this check during
the flush state:

                        /* number of bytes to be flushed */
                        if (num1 > 0)
                                if (num1 <= 0) { ret= -1; goto end; }

The BIO_CTRL_INFO call for the BIO_f_buffer (first in the list of s->wbio
stack) only checks the number of buffered outgoing bytes in that BIO; so if the
BIO_f_buffer has no bytes remaining to be written, but mod_ssl's filter_out BIO
does then BIO_flush is not called - bytes remain in the filter_out BIO and the
dialogue stalls.

e.g. observed sequence during a renegotiate sequence that stalls:

bio_filter_out_write receives 37 bytes (SSL renegotiate ciphers request)
37 bytes added to outctx->buffer: total 37 bytes

Flushed from s3_srvr.c: BIO_flush called on bio_filter out. outctx->buffer is 0

openssl adds in the BIO_f_buffer BIO to the ssl wbio (via

openssl server sends HELLO A: 101 bytes
Added to BIO_f_buffer: buffer total = 101 bytes (sending from BIO_f_buffer to
filter_out is done in  crypto routine buffer_write(), bf_buff.c)

openssl sever sends SERVER CERT A: 4325 bytes
(buffer_write()) fills BIO_f_buffer with extra 3995 bytes: total = 4096
   4096 bytes sent to bio_filter_out_write: outctx->buffer now 4096 bytes
   BIO_f_buffer: 0 bytes buffered
Remainder bytes added to BIO_f_buffer: 330 bytes buffered

openssl server sends KEY EXCHANGE A: 565 bytes
BIO_f_buffer receives 565 bytes: total 895 bytes

openssl server sends CERT REQ A: 7797 bytes

BIO_f_buffer adds 3201 to buffer making total of 4096:
  4096 bytes sent to bio_filter_out_write: All 8192 bytes flushed.
outctx->buffer is 0 again.
  BIO_f_buffer: 0 bytes buffered
Remainder of 4596 sent to bio_filter_out_write(): Added to outctx->buffer for
total of 4596 buffed bytes.

openssl server passes through SSL3_ST_SW_FLUSH state and checks wbio (i.e.
BIO_f_buffer) with BIO_CTRL_INFO: Returns 0 as there is nothing buffered, and
so no call BIO_flush on wbio. Thus no flush call to mod_ssl's filter_out BIO.

Trial fix - a change in both openssl and mod_ssl:

--- s3_srvr.c-  2009-06-17 20:44:54.000000000 +0200
+++ s3_srvr.c   2009-06-17 17:20:33.000000000 +0200
@@ -413,7 +413,7 @@

               case SSL3_ST_SW_FLUSH:
                       /* number of bytes to be flushed */
-                       num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
+                       num1=BIO_ctrl(s->wbio,BIO_CTRL_WPENDING,0,NULL);
                       if (num1 > 0)

--- ssl_engine_io.c-    2009-06-17 20:48:19.000000000 +0200
+++ ssl_engine_io.c     2009-06-17 17:41:07.000000000 +0200
@@ -260,10 +260,10 @@
      case BIO_CTRL_SET_CLOSE:
        bio->shutdown = (int)num;
-      case BIO_CTRL_WPENDING:
+      case BIO_CTRL_PENDING:
        ret = 0L;
-      case BIO_CTRL_PENDING:
+      case BIO_CTRL_WPENDING:
        ret = (long)(outctx->blen + outctx->length);
      case BIO_CTRL_FLUSH:

the change in openssl is to modify the BIO_ctrl function used in the flush
check to BIO_CTRL_WPENDING: That call on the BIO_f_buffer returns either number
of buffer outgoing bytes (similar to BIO_CTRL_INFO) or if zero calls
BIO_CTRL_WPENDING on the next_bio (e.g. mod_ssl's filter_out BIO). In the there
is no BIO_f_buffer (e.g. when the SSL renegotiate ciphers request is sent)
s3_srvr will directly call BIO_CTRL_WPENDING on the filter_out BIO.
Unfortunately it looks like BIO_CTRL_PENDING and BIO_CTRL_WPENDING are reversed
in ssl_engine_io.c:  so while I've seen the patch overall appears to work
without problem it would need to be applied to mod_ssl before or at the same
time as openssl. It also has the effect of changing the observed behavior for
any application providing their own BIO: WPENDING is called rather than
BIO_CTRL_INFO. Possibly the SSL3_ST_SW_FLUSH BIO_ctrl check in s3_srvr.c could
be explicitly made up of a BIO_CTRL_INFO call, and then a further WPENDNING
call only if zero bytes are returned.

Interestingly in the above example the stall would be avoided with only a
change in bio_filter_out_write(); to buffer bytes up to 8192, not 8191 bytes as
current check does: But this relies on the BIO_f_buffer size being 4096 bytes,
and there is still an apparent sequence of writes possible to leave the
BIO_f_buffer empty but the filter_out BIO full.


Configure bugmail:
------- You are receiving this mail because: -------
You are the assignee for the bug.

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message