I have implemented a server using OpenSSL 0.9.8r. If I use s_client to open a
connection to a listenening SSL port on the server, and use the R commend to
initiate a rehandshake, the rehandshake completes successfully(as expected). I
have verified this using both SSL 3.0 and TLS 1.0.
Another client(non-OpenSSL) opens a connection to my server with a successful
initial handshake as well. The client is basically an FTP client, and it then
initiates a data transfer with a get, so my server is sending data to the
client. During this transfer, the client sends a Client Hello to renegotiate.
My server, using poll() to look for activated sockets, ends up calling
SSL_read() and reads in the Client Hello. However, OpenSSL gets an error,
“SSL3_WRITE_PENDING:bad write retry”. I’ve dug around a little in the OpenSSL
code and added some debug code to try to follow what is happening. From what I
can tell, the following is taking place:
- Client and server establish a connection and my server is sending
data with repeated calls to SSL_write()
- While server is writing data, client initiates a renegotiation, and
sends a Client Hello
- SSL_write() on the server returns -1 with SSL_ERROR_WANT_READ,
presumably after the Client Hello comes in
- Server calls SSL_read() and reads in the Client Hello
(I have info_cb functionality implemented that dump out handshake messages, the
message looks OK)
- OpenSSL calls ssl3_get_client_hello(); I added a syslog() when the
state changes to SSL3_ST_SR_CLNT_HELLO_B
- ssl3_get_client_hello() returns successfully; I added a syslog when
the state gets changed to SSL3_ST_SW_SRVR_HELLO_A to verify this.
- ssl3_send_server_hello() is called
- The ssl3_send_server_hello() will lead to calls to the following
functions, in order: ssl3_write_bytes(), do_ssl3_write(), and
ssl3_write_pending().
- Meanwhile, the previous calls to SSL_write have data left to send
and a call to ssl3_write_pending() is being made from do_ssl3_write(). I’m not
sure of the code path from the server calling SSL_write() to
do_ssl3_write()/ssl3_write_pending(), but I see do_ssl3_write() calling
ssl3_write_pending() several times during the file transfer.
Does this scenario sound like it should be working? I’m not sure what my
server could be doing wrong? A couple notes,
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is not set on my server. I’m not sure that
it should or needs to be, I did notice in the code that that mode is one of the
conditions that is checked for when throwing the SSL_R_BAD_WRITE_RETRY error.
From what I’ve read, the SSL3_WRITE_PENDING error is caused by calling
SSL_write() after getting SSL_ERROR_WANT_READ/WRITE with a different buffer
than before. However, my server is not calling SSL_write() after it gets the
SSL_ERROR_WANT_READ error when the Client Hello comes in. So it seems to me
the error is being thrown because OpenSSL is internally calling
ssl3_write_pending() incorrectly.
I have some traces of the scenario but I did not include them, they may make
things more confusing. They exists in two different places, logging in my
server before/after SSL_read and SSL_write
calls(SSL_get_error()/ERR_error_string() calls) as well as info_cb and msg_cb
message that display the SSL records coming in and going out. A separate trace
exists of some syslog() calls I added to the OpenSSL code. I know there is a
way to build OpenSSL in debug mode, but I haven’t taken the time to do this
yet. Please advise if I should look at doing that, or include the logging I do
have.
Thanks in advance.