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                       openssl-dev@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to