diff options
Diffstat (limited to 'src/libutil/ssl_util.c')
-rw-r--r-- | src/libutil/ssl_util.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/src/libutil/ssl_util.c b/src/libutil/ssl_util.c index f4fe3b31c..3e8f25910 100644 --- a/src/libutil/ssl_util.c +++ b/src/libutil/ssl_util.c @@ -433,14 +433,35 @@ rspamd_ssl_connection_dtor (struct rspamd_ssl_connection *conn) static void rspamd_ssl_shutdown (struct rspamd_ssl_connection *conn) { - gint ret; + gint ret = 0, retries; + static const gint max_retries = 5; + + /* + * Fucking openssl... + * From the manual, 0 means: "The shutdown is not yet finished. + * Call SSL_shutdown() for a second time, + * if a bidirectional shutdown shall be performed. + * The output of SSL_get_error(3) may be misleading, + * as an erroneous SSL_ERROR_SYSCALL may be flagged + * even though no error occurred." + * + * What is `second`, what if `second` also returns 0? + * What a retarded behaviour! + */ + for (retries = 0; retries < max_retries; retries ++) { + ret = SSL_shutdown (conn->ssl); + + if (ret != 0) { + break; + } + } - if ((ret = SSL_shutdown (conn->ssl)) == 1) { + if (ret == 1) { /* All done */ msg_debug_ssl ("ssl shutdown: all done"); rspamd_ssl_connection_dtor (conn); } - else { + else if (ret < 0) { short what; ret = SSL_get_error (conn->ssl, ret); @@ -451,7 +472,7 @@ rspamd_ssl_shutdown (struct rspamd_ssl_connection *conn) what = EV_READ; } else if (ret == SSL_ERROR_WANT_WRITE) { - msg_debug_ssl ("ssl shutdown: need read"); + msg_debug_ssl ("ssl shutdown: need write"); what = EV_WRITE; } else { @@ -480,6 +501,12 @@ rspamd_ssl_shutdown (struct rspamd_ssl_connection *conn) conn->state = ssl_next_shutdown; } + else if (ret == 0) { + /* What can we do here?? */ + msg_debug_ssl ("ssl shutdown: openssl failed to initiate shutdown after " + "%d attempts!", max_retries); + rspamd_ssl_connection_dtor (conn); + } } static void |