On Wed, Aug 30, 2023 at 1:22 PM Rainer Jung <rainer.j...@kippdata.de> wrote:
>
> OpenSSL 3 flags some abortive shutdowns as an error different to what
> 1.1.1 did. This results in info log output in httpd:
>
> [Tue Aug 29 12:33:06.787210 2023] [ssl:info] [pid 1994673:tid 1994737]
> SSL Library Error: error:0A000126:SSL routines::unexpected eof while reading
> [Tue Aug 29 12:33:06.787374 2023] [ssl:info] [pid 1994673:tid 1994737]
> [client 1.2.3.4:54790] AH01998: Connection closed to child 215 with
> abortive shutdown (server myserver:443)

The info looks legit to me (someone closed the connection with no
close_notify), possibly we want to log it at APLOG_DEBUG/TRACEx still
if it happens too often?
We don't do that though for SSL_ERROR_ZERO_RETURN in openssl < 3, but
maybe we should too like in the attached patch (instead of r1912015)?

Regards;
Yann.
Index: modules/ssl/ssl_engine_io.c
===================================================================
--- modules/ssl/ssl_engine_io.c	(revision 1911906)
+++ modules/ssl/ssl_engine_io.c	(working copy)
@@ -721,6 +721,19 @@ static apr_status_t ssl_io_input_read(bio_filter_i
             ssl_err = SSL_get_error(inctx->filter_ctx->pssl, rc);
             c = (conn_rec*)SSL_get_app_data(inctx->filter_ctx->pssl);
 
+#ifdef SSL_R_UNEXPECTED_EOF_WHILE_READING
+            if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL &&
+                ERR_GET_REASON(ERR_peek_error()) == SSL_R_UNEXPECTED_EOF_WHILE_READING) {
+                ssl_err = SSL_ERROR_ZERO_RETURN;
+            }
+#endif
+            if (ssl_err == SSL_ERROR_ZERO_RETURN) {
+                ap_log_cerror(APLOG_MARK, APLOG_TRACE1, inctx->rc, c,
+                              "SSL input filter at EOF with no close_notify.");
+                inctx->rc = APR_EOF;
+                break;
+            }
+
             if (ssl_err == SSL_ERROR_WANT_READ) {
                 /*
                  * If OpenSSL wants to read more, and we were nonblocking,
@@ -741,7 +754,8 @@ static apr_status_t ssl_io_input_read(bio_filter_i
                 }
                 continue;  /* Blocking and nothing yet?  Try again. */
             }
-            else if (ssl_err == SSL_ERROR_SYSCALL) {
+
+            if (ssl_err == SSL_ERROR_SYSCALL) {
                 if (APR_STATUS_IS_EAGAIN(inctx->rc)
                         || APR_STATUS_IS_EINTR(inctx->rc)) {
                     /* Already read something, return APR_SUCCESS instead. */
@@ -763,10 +777,6 @@ static apr_status_t ssl_io_input_read(bio_filter_i
                                   "SSL input filter read failed.");
                 }
             }
-            else if (rc == 0 && ssl_err == SSL_ERROR_ZERO_RETURN) {
-                inctx->rc = APR_EOF;
-                break;
-            }
             else /* if (ssl_err == SSL_ERROR_SSL) */ {
                 /*
                  * Log SSL errors and any unexpected conditions.
@@ -1413,17 +1423,8 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi
         apr_status_t rc = inctx->rc ? inctx->rc : outctx->rc ;
         ssl_err = SSL_get_error(filter_ctx->pssl, n);
 
-        if (ssl_err == SSL_ERROR_ZERO_RETURN) {
+        if (ssl_err == SSL_ERROR_WANT_READ) {
             /*
-             * The case where the connection was closed before any data
-             * was transferred. That's not a real error and can occur
-             * sporadically with some clients.
-             */
-            ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c, APLOGNO(02006)
-                         "SSL handshake stopped: connection was closed");
-        }
-        else if (ssl_err == SSL_ERROR_WANT_READ) {
-            /*
              * This is in addition to what was present earlier. It is
              * borrowed from openssl_state_machine.c [mod_tls].
              * TBD.
@@ -1431,8 +1432,9 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi
             outctx->rc = APR_EAGAIN;
             return APR_EAGAIN;
         }
-        else if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL &&
-                 ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
+
+        if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL &&
+            ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
             /*
              * The case where OpenSSL has recognized a HTTP request:
              * This means the client speaks plain HTTP on our HTTPS port.
@@ -1441,6 +1443,22 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi
              */
             return MODSSL_ERROR_HTTP_ON_HTTPS;
         }
+
+#ifdef SSL_R_UNEXPECTED_EOF_WHILE_READING
+        if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL &&
+            ERR_GET_REASON(ERR_peek_error()) == SSL_R_UNEXPECTED_EOF_WHILE_READING) {
+            ssl_err = SSL_ERROR_ZERO_RETURN;
+        }
+#endif
+        if (ssl_err == SSL_ERROR_ZERO_RETURN) {
+            /*
+             * The case where the connection was closed before any data
+             * was transferred. That's not a real error and can occur
+             * sporadically with some clients.
+             */
+            ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c, APLOGNO(02006)
+                         "SSL handshake stopped: connection was closed");
+        }
         else if (ssl_err == SSL_ERROR_SYSCALL) {
             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rc, c, APLOGNO(02007)
                           "SSL handshake interrupted by system "

Reply via email to