https://issues.apache.org/bugzilla/show_bug.cgi?id=46952
--- Comment #8 from David Smith <[email protected]> 2009-06-19 04:36:08 PST --- Hello, 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 raised). 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: case SSL3_ST_SW_FLUSH: /* number of bytes to be flushed */ num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL); if (num1 > 0) { s->rwstate=SSL_WRITING; num1=BIO_flush(s->wbio); if (num1 <= 0) { ret= -1; goto end; } s->rwstate=SSL_NOTHING; } 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 again. openssl adds in the BIO_f_buffer BIO to the ssl wbio (via ssl_init_wbio_buffer()) 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) { s->rwstate=SSL_WRITING; --- 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; break; - case BIO_CTRL_WPENDING: + case BIO_CTRL_PENDING: ret = 0L; break; - case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: ret = (long)(outctx->blen + outctx->length); break; 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. David -- Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
