Submitted by: Darryl Miles <darryl-mailinglists@netbauds.net>
authorDr. Stephen Henson <steve@openssl.org>
Tue, 7 Apr 2009 16:28:30 +0000 (16:28 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 7 Apr 2009 16:28:30 +0000 (16:28 +0000)
Approved by: steve@openssl.org

Handle non-blocking I/O properly in SSL_shutdown() call.

CHANGES
ssl/s3_lib.c
ssl/s3_pkt.c
ssl/ssl_locl.h

diff --git a/CHANGES b/CHANGES
index 53abadc0236b126a5a955ea339a6e4f3881377e1..ac0266caf131b92ab83b6349c1e8a375fd2de1a0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,9 @@
 
  Changes between 0.9.8k and 0.9.8l  [xx XXX xxxx]
 
+  *) Handle non-blocking I/O properly in SSL_shutdown() call.
+     [Darryl Miles <darryl-mailinglists@netbauds.net>]
+
   *) Add 2.5.4.* OIDs
      [Ilya O. <vrghost@gmail.com>]
 
index 8916a0b1b3c718b7fd9fd4be273ff3630c070f71..8fa4ab02c367e35ad83cba16cbff17a59ae5f33b 100644 (file)
@@ -2458,6 +2458,7 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
 
 int ssl3_shutdown(SSL *s)
        {
+       int ret;
 
        /* Don't do anything much if we have not done the handshake or
         * we don't want to send messages :-) */
@@ -2475,18 +2476,32 @@ int ssl3_shutdown(SSL *s)
 #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(-1);     /* return WANT_WRITE */
                }
        else if (s->s3->alert_dispatch)
                {
                /* resend it if not sent */
 #if 1
-               s->method->ssl_dispatch_alert(s);
+               ret=s->method->ssl_dispatch_alert(s);
+               if(ret == -1)
+                       {
+                       /* we only get to return -1 here the 2nd/Nth
+                        * invocation, we must  have already signalled
+                        * return 0 upon a previous invoation,
+                        * return WANT_WRITE */
+                       return(ret);
+                       }
 #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);
+               if(!(s->shutdown & SSL_RECEIVED_SHUTDOWN))
+                       {
+                       return(-1);     /* return WANT_READ */
+                       }
                }
 
        if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) &&
index 9476dcddf6e958f6f3c566c3279f3f44bf74c4d7..60135ff9acb04a5c352efa553c5b3612597617c6 100644 (file)
@@ -1268,13 +1268,13 @@ int ssl3_do_change_cipher_spec(SSL *s)
        return(1);
        }
 
-void ssl3_send_alert(SSL *s, int level, int desc)
+int ssl3_send_alert(SSL *s, int level, int desc)
        {
        /* Map tls/ssl alert value to correct one */
        desc=s->method->ssl3_enc->alert_value(desc);
        if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
                desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have protocol_version alerts */
-       if (desc < 0) return;
+       if (desc < 0) return -1;
        /* If a fatal one, remove from cache */
        if ((level == 2) && (s->session != NULL))
                SSL_CTX_remove_session(s->ctx,s->session);
@@ -1283,9 +1283,10 @@ void ssl3_send_alert(SSL *s, int level, int desc)
        s->s3->send_alert[0]=level;
        s->s3->send_alert[1]=desc;
        if (s->s3->wbuf.left == 0) /* data still being written out? */
-               s->method->ssl_dispatch_alert(s);
+               return s->method->ssl_dispatch_alert(s);
        /* else data is still being written out, we will get written
         * some time in the future */
+       return -1;
        }
 
 int ssl3_dispatch_alert(SSL *s)
index 7637d0c1325add01b06dc001c0a021d713e59080..fa51bf3ab9ce9576ae0930f76364081b10117f8b 100644 (file)
@@ -789,7 +789,7 @@ int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b);
 int ssl3_change_cipher_state(SSL *s,int which);
 void ssl3_cleanup_key_block(SSL *s);
 int ssl3_do_write(SSL *s,int type);
-void ssl3_send_alert(SSL *s,int level, int desc);
+int ssl3_send_alert(SSL *s,int level, int desc);
 int ssl3_generate_master_secret(SSL *s, unsigned char *out,
        unsigned char *p, int len);
 int ssl3_get_req_cert_type(SSL *s,unsigned char *p);