On 02/02/16 07:52, Jakob Bohm wrote: > I am trying to upgrade an existing 3rd party multithreaded server > from OpenSSL 1.0.2c to 1.0.2f . However when I do so, it starts > mishandling the close_notify "alert". > > 1.0.2f seems to send the close_notify alert unencrypted followed > by an encrypted decrypt_failed alert, where 1.0.2c correctly > sends just an encrypted close_notify alert. > > I am unsure if this exposed a bug in the daemon or in OpenSSL > itself.
I have a theory. Previous versions of 1.0.2 handled an SSL_shutdown() call while in the middle of a handshake by ignoring it and returning 1 immediately (meaning everything shutdown successfully). Clearly everything did not shutdown successfully so the return value is not correct. 1.0.2f "fixed" this to attempt to more appropriately shutdown the connection. It now attempts to send a close_notify alert immediately (and will return 0 - meaning more work to do), it will then fail with a -1 return on a second call to SSL_shutdown (meaning we failed to complete a bi-directional shutdown). The reason is that completing a full bi-directional shutdown while mid-handshake is problematic (e.g. if the peer has sent a CCS before it receives our close_notify). My theory as to what is happening in this case is that SSL_shutdown is being called mid-handshake. Could that be the case do you think? It doesn't entirely match with the description you gave (i.e. 1.0.2c would not send an encrypted close_notify...it wouldn't send anything in this scenario)...but its the only change I can think of that might have a bearing on this. If so then I could see a situation where the server has not yet processed a CCS from the client and SSL_shutdown is called. It therefore sends its close_notify in the clear. In the meantime the client has sent its CCS before processing the close_notify. The client then expects the next message from the server to be encrypted...which it obviously isn't. It's not entirely clear to me what the correct behaviour is in that situation, but it is certainly unexpected and a change from what happened before. It looks to me that trying to send a close_notify mid-handshake was probably a bad idea. Perhaps a better fix is just to have SSL_shutdown() return -1 and do nothing if called mid-handshake. I've attached a 1.0.2 patch that does this. Would you be able to try it, and see if that corrects your problem? Thanks Matt
From d9a741175bfe83c36fcb6660f9052e58983eb9ff Mon Sep 17 00:00:00 2001 From: Matt Caswell <m...@openssl.org> Date: Tue, 2 Feb 2016 10:05:43 +0000 Subject: [PATCH] Handle SSL_shutdown while in init more appropriately #2 Previous commit f73c737c7 attempted to "fix" a problem with the way SSL_shutdown() behaved whilst in mid-handshake. The original behaviour had SSL_shutdown() return immediately having taken no action if called mid- handshake with a return value of 1 (meaning everything was shutdown successfully). In fact the shutdown has not been successful. Commit f73c737c7 changed that to send a close_notify anyway and then return. This seems to be causing some problems for some applications so perhaps a better (much simpler) approach is revert to the previous behaviour (no attempt at a shutdown), but return -1 (meaning the shutdown was not successful). --- ssl/s3_lib.c | 15 --------------- ssl/ssl.h | 1 - ssl/ssl_err.c | 1 - ssl/ssl_lib.c | 7 ++++++- 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index f846cb5..6a06625 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -4326,21 +4326,6 @@ int ssl3_shutdown(SSL *s) } #endif } else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) { - if (SSL_in_init(s)) { - /* - * We can't shutdown properly if we are in the middle of a - * handshake. Doing so is problematic because the peer may send a - * CCS before it acts on our close_notify. However we should not - * continue to process received handshake messages or CCS once our - * close_notify has been sent. Therefore any close_notify from - * the peer will be unreadable because we have not moved to the next - * cipher state. Its best just to avoid this can-of-worms. Return - * an error if we are wanting to wait for a close_notify from the - * peer and we are in init. - */ - SSLerr(SSL_F_SSL3_SHUTDOWN, SSL_R_SHUTDOWN_WHILE_IN_INIT); - return -1; - } /* * If we are waiting for a close from our peer, we are closed */ diff --git a/ssl/ssl.h b/ssl/ssl.h index ae8c925..04d4007 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -2713,7 +2713,6 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL3_SETUP_KEY_BLOCK 157 # define SSL_F_SSL3_SETUP_READ_BUFFER 156 # define SSL_F_SSL3_SETUP_WRITE_BUFFER 291 -# define SSL_F_SSL3_SHUTDOWN 396 # define SSL_F_SSL3_WRITE_BYTES 158 # define SSL_F_SSL3_WRITE_PENDING 159 # define SSL_F_SSL_ADD_CERT_CHAIN 318 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index dd3b2af..704088d 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -206,7 +206,6 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "ssl3_setup_key_block"}, {ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER), "ssl3_setup_read_buffer"}, {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER), "ssl3_setup_write_buffer"}, - {ERR_FUNC(SSL_F_SSL3_SHUTDOWN), "ssl3_shutdown"}, {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "ssl3_write_bytes"}, {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "ssl3_write_pending"}, {ERR_FUNC(SSL_F_SSL_ADD_CERT_CHAIN), "ssl_add_cert_chain"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 2744be8..7c23f9e 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1060,7 +1060,12 @@ int SSL_shutdown(SSL *s) return -1; } - return s->method->ssl_shutdown(s); + if (!SSL_in_init(s)) { + return s->method->ssl_shutdown(s); + } else { + SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_SHUTDOWN_WHILE_IN_INIT); + return -1; + } } int SSL_renegotiate(SSL *s) -- 2.5.0
_______________________________________________ openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users