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