Thor Lancelot Simon wrote:
> I think I've discovered another problem with the current non-blocking API.
>
> I have an application which reads data into fixed-size buffers which it
> maintains per session.  It uses non-blocking IO and select() when a read
> returns SSL_ERROR_WANT_{READ,WRITE}.
>
> To conserve memory I reduced the buffer size from 16384 to 8192 and saw
> sessions suddenly hang.  A coworker diagnosed this as follows:
>
> 1) The peer sends a SSL record larger than the buffer size.
>
> 2) We receive the SSL record.  The socket selects as ready to read.
>
> 3) We call SSL_read with our 8k buffer.  The received data does not fit,
>    so OpenSSL buffers it internally and returns 8K with SSL_ERROR_WANT_READ.
>   
The record size of the SSL record is predetermined by the sender with
16k being the maximum size specified by the protocol.

In order to return the (decrytped and authenticated) data to the
application, the full record must have been received as the MAC
(Message Authentication Code) is at the end of the record and
checking it requires to calculate the hash over the complete record
anyway. Hence, SSL_read() will only return and provide data once
the full record has been recevied from the underlying socket.

As the SSL communication just like TCP is stream oriented there is no
way for an application to know what is the size of a record, whether
data are split over several records or sent in one or whether more
information inside the stream was combined to just one record.

Hence you have to read from the stream with SSL_read() until there is
no more data to be retrieved. As long as there are bytes available
SSL_read() will return the number of bytes written to the buffer.
A following call to SSL_get_errror(ssl, <number of bytes>) will return
SSL_ERROR_NONE. The logic here is quite simple: the first test in
ssl/ssl_lib.c:SSL_get_error() is:
  if (i > 0) return(SSL_ERROR_NONE);

Hence the scenario you describe here (returned 8k and
SSL_ERROR_WANT_READ at the same time) is technically impossible as
long as you did call SSL_get_error() with the correct return value of
SSL_read().

To find out whether there actually is decrypted data available to be read
you may use SSL_pending() before calling SSL_read().

I have written quite some amount of applications using non-blocking I/O
and while especially the shutdown behavior is questionable at least, the
actual
state machine never made any trouble to me.

Note: I did not invent the API, I just wrote the manual pages :-)

Best regards,
    Lutz
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       openssl-dev@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to