[openssl-users] Polling fd before SSL_read() and renegotiations

Tomas Mraz tmraz at redhat.com
Tue Jun 5 11:26:10 UTC 2018


On Mon, 2018-06-04 at 18:51 +0200, Stefan via openssl-users wrote:
> Hi everybody!
> 
> I am working on a program where each peer may write at any time, so
> the other side has to be able to read incoming data when it gets
> available. If the peer sent nothing my program must be able to call
> SSL_write() to send its own data to the other side. 
> 
> My code currently does this using non-blocking I/O like this:
> 
> 1. If the underlying socket is not readable go to #2 immediately to
> be
>    able to send data. If the socket is reported to be readable, call
>    SSL_read() to get that data. If that call cannot be completed due
>    to SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE, poll the fd until
> that
>    condition is met. Then repeat calling SSL_read(). So I'm
> repeatedly
>    calling SSL_read() until it reports SSL_ERROR_NONE.  With this I
>    satisfy the requirement of the OpenSSL-API to repeat an incomplete
>    call until it completes.  Although I did not read that exactly in
>    the man-pages, the non-blocking-example in "Network Security with
>    OpenSSL" by Viega et al. takes care not to interleave the calls to
>    SSL_write()/SSL_read().
> 
> 2. (The program reaches here only after SSL_read() has succeeded or
> if
>    it has not even tried to call SSL_read() as the socket was not
>    readable) If the peer has data that needs to be sent to the other
>    side, call SSL_write() for it. If that function returns with
>    SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE poll the fd
> accordingly
>    and repeat SSL_write() until it ends with SSL_ERROR_NONE. Then go
>    to #1 to check for incoming data.
> 
> The code above does what I want - except for renegotiations! 
> 
> If the peer receives a renegotiation-request its socket becomes
> readable just like if it received a normal SSL-record with user-data.
> Thus my program enters #1 and repeats SSL_read() until SSL_ERROR_NONE
> is returned. But this never happens in that case, because the other
> peer just sent the renegotiation-packet(s) but no other data. So I'm
> stuck in repeating SSL_read() and won't enter #2 until the peer that
> forced the renegotiation has sent any other data to make SSL_read()
> finish (which may take very long in my program).

You've basically answered your question yourself - you cannot do it
like this - switching phases #1 and #2, but instead you need to go to
the writing phase (i.e. start writing if you have anything to pass to
SSL_write) whenever you need to wait on data to be read to appear in
the socket.

-- 
Tomáš Mráz
No matter how far down the wrong road you've gone, turn back.
                                              Turkish proverb
[You'll know whether the road is wrong if you carefully listen to your
conscience.]



More information about the openssl-users mailing list