Would it be possible to make SSL_shutdown() on non-blocking BIOs, conform to the documentation and aligned to SSL_read, SSL_write, ...?
http://www.openssl.org/docs/ssl/SSL_shutdown.html I cooked a tentative patch below, that seems to be working here. It definitely need double check from someone that has openssl source code in sight by more than a few minutes (like myself). The first shutdown will return (modulo other errors) either <0 with SSL_get_error=WANT_WRITE, or 0 with SSL_get_error=WANT_SHUTDOWN. The second shutdown will return (modulo other errors) either <0 with SSL_get_error=WANT_READ, or 1 with SSL_get_error=NONE. - Davide --- ssl/s3_lib.c | 18 +++++++++--------- ssl/ssl.h | 1 + ssl/ssl_lib.c | 9 +++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) Index: openssl-0.9.8e/ssl/s3_lib.c =================================================================== --- openssl-0.9.8e.orig/ssl/s3_lib.c 2007-09-27 23:56:00.000000000 -0700 +++ openssl-0.9.8e/ssl/s3_lib.c 2007-09-28 15:02:23.000000000 -0700 @@ -2241,6 +2241,7 @@ int ssl3_shutdown(SSL *s) { + int err; /* Don't do anything much if we have not done the handshake or * we don't want to send messages :-) */ @@ -2258,25 +2259,24 @@ #endif /* our shutdown alert has been sent now, and if it still needs * to be written, s->s3->alert_dispatch will be true */ + if (!s->s3->alert_dispatch) + return s->shutdown & SSL_RECEIVED_SHUTDOWN ? 1: 0; } - else if (s->s3->alert_dispatch) + if (s->s3->alert_dispatch) { /* resend it if not sent */ #if 1 - s->method->ssl_dispatch_alert(s); + err = s->method->ssl_dispatch_alert(s); #endif } else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) { /* If we are waiting for a close from our peer, we are closed */ - s->method->ssl_read_bytes(s,0,NULL,0,0); + err = s->method->ssl_read_bytes(s,0,NULL,0,0); } - - if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) && - !s->s3->alert_dispatch) - return(1); - else - return(0); + if (err < 0) + return err; + return s->shutdown & SSL_RECEIVED_SHUTDOWN ? 1: 0; } int ssl3_write(SSL *s, const void *buf, int len) Index: openssl-0.9.8e/ssl/ssl.h =================================================================== --- openssl-0.9.8e.orig/ssl/ssl.h 2007-09-27 23:56:00.000000000 -0700 +++ openssl-0.9.8e/ssl/ssl.h 2007-09-28 12:26:16.000000000 -0700 @@ -1128,6 +1128,7 @@ #define SSL_ERROR_ZERO_RETURN 6 #define SSL_ERROR_WANT_CONNECT 7 #define SSL_ERROR_WANT_ACCEPT 8 +#define SSL_ERROR_WANT_SHUTDOWN 9 #define SSL_CTRL_NEED_TMP_RSA 1 #define SSL_CTRL_SET_TMP_RSA 2 Index: openssl-0.9.8e/ssl/ssl_lib.c =================================================================== --- openssl-0.9.8e.orig/ssl/ssl_lib.c 2007-09-27 23:56:00.000000000 -0700 +++ openssl-0.9.8e/ssl/ssl_lib.c 2007-09-28 12:26:16.000000000 -0700 @@ -2017,6 +2017,15 @@ } else { + /* + * SSL_get_error() may be called with code==0 due to the + * a partially completed SSL_shutdown() returning 0. + * This is a state where the shutdown packet has been + * successfully sent, but we didn't get the peer one yet. + */ + if ((s->shutdown & SSL_SENT_SHUTDOWN) && !s->s3->alert_dispatch && + (s->shutdown & SSL_RECEIVED_SHUTDOWN) == 0) + return SSL_ERROR_WANT_SHUTDOWN; if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) return(SSL_ERROR_ZERO_RETURN); ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List [email protected] Automated List Manager [EMAIL PROTECTED]
