Antoine Pitrou wrote:
Well, in our case, and unless I'm mistaken,
ret == -1, ERR_get_error() == 0 and then errno (the Unix errno) == 0.

SSL_shutdown() by virtue of its unique mechanic you will not see "ret == 0" (in the way the SSL_get_error man page describes) since that has a different and special meaning. It means the first point that ((SSL_get_shutdown() & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN) would be true.


Unlike for example SSL_read() which can return 0, which does mean EOF. For which you can then do ((SSL_get_shutdown() & SSL_RECEIVED_SHUTDOWN) == SSL_RECEIVED_SHUTDOWN) to find out if it was a "secure EOF".



=== RANT MODE ====
If the OpenSSL SSL_shutdown() API could have been made better this is certainly one area that could be better. i.e. make SSL_shutdown() return the current state like SSL_get_shutdown() does (which means non-zero states). Then reuse the return of 0 state to mean EOF on transport and keep -1/WANT_READ/WANT_WRITE/ERROR_SYSCALL as-is.

This would mean (simplified understanding) :
 * old version returned 0, new version returns 1 (SSL_SENT_SHUTDOWN).
* old version returned 1, new version returns 3 (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN).


Unfortunately this would have broken historical compatibility; it took quite a while to get the minimum breakage patch in to achieve my goals by the end of that time thinking about improving OpenSSL (rather than bug fixing it) was long out of my mind.

I'm all for breaking APIs to make things better, providing its done in a responsible way. A poorly thought out API call can't hog a popular API symbol forever, otherwise the whole product starts to weaken.
=== RANT MODE ====


Perhaps errno gets cleared by another operation... I may try to
investigate if I get some time.

Well now I've looked at the Python Module/_ssl.c to understand the context of your usage, you are using standard stuff for BIO.

I know that errno==0 is getting set by OpenSSL before it makes the read() system call (openssl-1.0.0/crypto/bio/bss_fd.c:150 function fd_read() calls clear_sys_error() which does "errno=0;" from openssl-1.0.0/e_os.h).

Then (I presume) it gets a read()==0 from kernel (bss_fd.c:151). Of course a read()==0 does not modify errno in libc.

So in openssl-1.0.0/ssl/s3_lib.c:3191 inside the SSL_shutdown() implementation you can see the error return is ignored. Since returning 0 from here has a different documented meaning.

I think this is the sequence of events you observe.


Unfortunately I can't confirm it to be so since I can't get the test cases to run from Python's SVN.



Darryl
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to