Allow an endpoint to read the alert data before closing the socket
authorMatt Caswell <matt@openssl.org>
Mon, 4 Sep 2017 10:20:27 +0000 (11:20 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 8 Sep 2017 12:18:45 +0000 (13:18 +0100)
If an alert gets sent and then we close the connection immediately with
data still in the input buffer then a TCP-RST gets sent. Some OSs
immediately abandon data in their input buffer if a TCP-RST is received -
meaning the alert data itself gets ditched. Sending a TCP-FIN before the
TCP-RST seems to avoid this.

This was causing test failures in MSYS2 builds.

Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/4333)

(cherry picked from commit bac6abe18d28373e0d2d0666c411020404197337)

apps/s_socket.c

index 7f01112afb912b943d937485f2e954d86b126ab9..2af1b4b2039f10d2f9465eace913a71003abf364 100644 (file)
@@ -178,6 +178,23 @@ int do_server(int *accept_sock, const char *host, const char *port,
                 break;
             }
             i = (*cb)(sock, type, context);
+            /*
+             * If we ended with an alert being sent, but still with data in the
+             * network buffer to be read, then calling BIO_closesocket() will
+             * result in a TCP-RST being sent. On some platforms (notably
+             * Windows) then this will result in the peer immediately abandoning
+             * the connection including any buffered alert data before it has
+             * had a chance to be read. Shutting down the sending side first,
+             * and then closing the socket sends TCP-FIN first followed by
+             * TCP-RST. This seems to allow the peer to read the alert data.
+             */
+#ifdef _WIN32
+# ifdef SD_SEND
+            shutdown(sock, SD_SEND);
+# endif
+#elif defined(SHUT_WR)
+            shutdown(sock, SHUT_WR);
+#endif
             BIO_closesocket(sock);
         } else {
             i = (*cb)(asock, type, context);