From: Ken Hornstein Date: Fri, 30 Sep 2016 19:07:03 +0000 (-0400) Subject: Make sure we retry if possible upon a TLS read, and give a more meaningful X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/f9494c69a257858a68635a3e98c189dcf1f2ec20?hp=a590575b8a6bfc7288e4047c39955ba6df81fa06 Make sure we retry if possible upon a TLS read, and give a more meaningful error if we can't. --- diff --git a/sbr/netsec.c b/sbr/netsec.c index 29a65914..2f4cdcce 100644 --- a/sbr/netsec.c +++ b/sbr/netsec.c @@ -510,9 +510,9 @@ netsec_fillread(netsec_context *nsc, char **errstr) nsc->ns_inptr = nsc->ns_inbuffer; } -#ifdef CYRUS_SASL +#if defined(CYRUS_SASL) || defined(TLS_SUPPORT) retry: -#endif /* CYRUS_SASL */ +#endif /* CYRUS_SASL || TLS_SUPPORT */ /* * If we are using TLS and there's anything pending, then skip the * select call @@ -562,11 +562,34 @@ retry: if (nsc->tls_active) { rc = BIO_read(nsc->ssl_io, end, remaining); if (rc == 0) { + SSL *ssl; + int errcode; + + /* + * Check to see if we're supposed to retry; if so, + * then go back and read again. + */ + + if (BIO_should_retry(nsc->ssl_io)) + goto retry; + /* - * Either EOF, or possibly an error. Either way, it was probably - * unexpected, so treat as error. + * Okay, fine. Get the real error out of the SSL context. */ - netsec_err(errstr, "TLS peer aborted connection"); + + if (BIO_get_ssl(nsc->ssl_io, &ssl) < 1) { + netsec_err(errstr, "SSL_read() returned 0, but cannot " + "retrieve SSL context"); + return NOTOK; + } + + errcode = SSL_get_error(ssl, rc); + if (errcode == SSL_ERROR_ZERO_RETURN) { + netsec_err(errstr, "TLS peer closed remote connection"); + } else { + netsec_err(errstr, "TLS network read failed: %s", + ERR_error_string(errcode, NULL)); + } return NOTOK; } else if (rc < 0) { /* Definitely an error */