Polling fd before SSL_read() and renegotiations

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Polling fd before SSL_read() and renegotiations

OpenSSL - User mailing list
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).

Well, I can force that behavior only using "openssl s_client/s_server"
as peer. And if other peers do it exactly like my code, a
renogatioation can only be initiated by calling SSL_write(). So some
data will be sent after the renegotiation to prevent the described
situation.

But can I really trust on that behavior for other peers? Even if they
are using other SSL-libraries? And what if the other side detects an
session-timeout while it waits on data and immediately intiates a
renegotiation without sending data?

If not, how can I use the OpenSSL-API and not stuck in SSL_read() when
there is no data available for read?

Thanks a lot for your help!

Stefan

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: Polling fd before SSL_read() and renegotiations

OpenSSL - User mailing list
>    The code above does what I want - except for renegotiations!
 
Do you absolutely, positively, HAVE TO support renegotiation?

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: Polling fd before SSL_read() and renegotiations

OpenSSL - User mailing list
The connection is open for verly long time (>24h), so I thought that
the peer may force a renogatioation due to the session timeout. Or
have I got something wrong and a renogatioation is not necessary for
long-running sessions?
--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: Polling fd before SSL_read() and renegotiations

Tomas Mraz-2
In reply to this post by OpenSSL - User mailing list
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.]

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users