Nanno Langstraat wrote:
It turns out that the problem does *not* directly involve SSL_shutdown(), but it *is* attributable to OpenSSL, and specifically OpenSSL's non-blocking shutdown semantics.

Okat thats cleared that up, it is indeed unrelated to the OP of this thread. Please move replies (if any) to a new thread :).



Details: the application's event loop is built analogous to a regular TCP event loop. Meaning that the event loop tracks the upstream direction and the downstream independently: the event loop handles the possibility that the downstream direction gets shut down [SSL_read() returned 0] while the upstream direction stays open a while longer [we might still make a few SSL_write() calls]. Just like TCP.

This goes pear-shaped as follows:

   * The SSL connection is made and used
   * The remote side closes its file descriptor (e.g. process killed,
     TCP shutdown(RD))
   * Local SSL_read() returns 0. The app event loop sets a flag and
     makes sure it never calls SSL_read() again.
   * The app event loop prepares for poll() by calling SSL_want_read()
     and SSL_want_write().
   * SSL_want_read() returns 'true'. This is erroneous.
   * poll() returns immediately.
   * Repeat the last 3 steps indefinitely. Uses 100% CPU.

I can't say I've used those SSL_want_xxxxx() methods before. So lets look at the docs.


man 3 SSL_want

"Unlike SSL_get_error(3), which also evaluates the error queue, the results are obtained by examining an internal state flag only. The information must therefore only be used for normal operation under non-blocking I/O."


Oh so we bypass all considerations and simply look at the "internal state flag" because we are expected to be used for a "normal operation". Well handling an end-of-stream condition is not a normal operation or situation in my book for a start.


So the question remains, is end-of-stream considered an error condition ? What does SSL_get_error() return in the situation in step 5 above ?

I understand the gist if your problem from your point of view.


But more detail is needed over step 2 in exactly what you are saying as "process killed" is not the same condition as "TCP shutdown(RD)". One results in a unusable socket (for any purpose, be it read or write) and the other results in a still usable socket. So you can't just get away with lumping those two situations as if either would do.

I will spare you the details of why the "process killed" condition is obviously an error no matter what.

It would be incorrect for the remote end to issue a "TCP shutdown(RD)" unless that was the result of receiving a "shutdown notify packet" otherwise you just pulled the rug out from under OpenSSL by denying it the ability to securely signal its own end-of-stream condition (it requires to convey data to do that).

But if your peer called "TCP shutdown(RD)" as a direct result of receiving a "shutdown notify packet" then you can claim the local end has a bug for SSL_want_write() returning 'true' after it has written its last piece of data to the BIO layer (the "shutdown notify packet"). Since it should already know that it can no longer send any data (not even a re-negotiation response) from the state of its "internal state flags". If there isn't such a flag for this situation then one should exist.


So please clarify your step 2, it does matter what and why the other end did what it did, did, did!


Darryl
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to