Please review this patch for inclusion in openssl-0.9.8b, maybe it also
works with 0.9.7 too.
This patch maybe incomplete. As in I would like someone with more
knowledge than me to confirm that:
* s->method->ssl_dispatch_alert(s) already sets up the WANT_WRITE
situation if it returns -1 (this is an untested case)
* s->method->ssl_read_bytes(s,0,NULL,0,0); already sets up the WANT_READ
situation if it returns -1 (this is tested and working)
Where and why does the SSL_ERROR_SYSCALL occur (the man page talks
about), in my testing I correctly get WANT_READ that I expect (as per
man page) ? I have not got this to occur.
This patch allows the SSL_shutdown() to return a 0 just once, for a
non-blocking socket. It is possible for the application to obtain if a
send shutdown has sent already been signaled (to OpenSSL by application)
with SSL_get_shutdown() so there no need to keep returning 0, as its not
possible for non-blocking IO to know its waiting for IO. Unless we
start to put tricks in my application to detect it returning 0 more than
one in succession, Yuk!
Do you want me to any other versions of SSL ? I think TLS1 is SSL3 ??
and SSL2 already has a dummy function for shutdown.
Thanks
Darryl
diff -u -r -N -x '*~' openssl-0.9.8b/ssl/s3_lib.c openssl-0.9.8b-me/ssl/s3_lib.c
--- openssl-0.9.8b/ssl/s3_lib.c 2006-01-15 07:14:38.000000000 +0000
+++ openssl-0.9.8b-me/ssl/s3_lib.c 2006-06-22 17:45:46.000000000 +0100
@@ -2071,6 +2071,7 @@
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 :-) */
@@ -2093,13 +2094,21 @@
{
/* 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(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);
+ ret=s->method->ssl_read_bytes(s,0,NULL,0,0);
+ if(ret == -1)
+ return(ret);
}
if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) &&
diff -u -r -N -x '*~' openssl-0.9.8b/ssl/s3_pkt.c openssl-0.9.8b-me/ssl/s3_pkt.c
--- openssl-0.9.8b/ssl/s3_pkt.c 2005-10-01 00:38:20.000000000 +0100
+++ openssl-0.9.8b-me/ssl/s3_pkt.c 2006-06-22 17:45:46.000000000 +0100
@@ -1258,13 +1258,13 @@
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);
@@ -1273,9 +1273,10 @@
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)
diff -u -r -N -x '*~' openssl-0.9.8b/ssl/ssl_locl.h openssl-0.9.8b-me/ssl/ssl_locl.h
--- openssl-0.9.8b/ssl/ssl_locl.h 2005-08-22 00:06:51.000000000 +0100
+++ openssl-0.9.8b-me/ssl/ssl_locl.h 2006-06-22 17:45:46.000000000 +0100
@@ -780,7 +780,7 @@
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);