changeset 803:1671f2eb130b monetdbs

Send NUL bytes on non-TLS connect This avoids a hang if we accidentally make a non-TLS connection to a TLS server. The hang occurs because in that situation, the MAPI client ends up waiting for the server to send a MAPI challenge, while the TLS server ends up waiting for the client to send a TLS Client Hello message. The NUL bytes are illegal as a Client Hello and a no-op as a MAPI message.
author Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com>
date Mon, 11 Dec 2023 14:47:41 +0100 (16 months ago)
parents 5d04490bc58b
children 361441253305
files src/main/java/org/monetdb/mcl/net/MapiSocket.java tests/TLSTester.java
diffstat 2 files changed, 15 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/monetdb/mcl/net/MapiSocket.java
+++ b/src/main/java/org/monetdb/mcl/net/MapiSocket.java
@@ -86,6 +86,7 @@ import org.monetdb.mcl.parser.MCLParseEx
  * @see org.monetdb.mcl.io.BufferedMCLWriter
  */
 public final class MapiSocket {
+	public static final byte[] NUL_BYTES = new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, };
 	private static final String[][] KNOWN_ALGORITHMS = new String[][] {
 			{"SHA512", "SHA-512"},
 			{"SHA384", "SHA-384"},
@@ -348,8 +349,18 @@ public final class MapiSocket {
 	private Socket wrapTLS(Socket sock, Target.Validated validated) throws IOException {
         if (validated.getTls())
             return SecureSocket.wrap(validated, sock);
-        else
-            return sock;
+        else {
+			// Send an even number of NUL bytes.
+			// We expect the server to speak MAPI and in that case, it's a NOP.
+			// If we're accidentally connecting to a TLS server, the bytes are
+			// invalid as a Client Hello message and most TLS implementations
+			// drop the connection.
+			// This is nice because otherwise we would hang, as the TLS server
+			// is waiting for us to send a TLS CLient Hello, and we are waiting
+			// for a MAPI server to send a server challenge.
+			sock.getOutputStream().write(NUL_BYTES);
+		}
+        return sock;
     }
 
 	private boolean handshake(Target.Validated validated, OptionsCallback callback, ArrayList<String> warnings) throws IOException, MCLException {
--- a/tests/TLSTester.java
+++ b/tests/TLSTester.java
@@ -131,7 +131,7 @@ public class TLSTester {
 //        test_connect_client_auth1();
 //        test_connect_client_auth2();
         test_fail_tls_to_plain();
-//        test_fail_plain_to_tls();
+        test_fail_plain_to_tls();
 //        test_connect_server_name();
 //        test_connect_alpn_mapi9();
         test_connect_trusted();
@@ -193,7 +193,7 @@ public class TLSTester {
     }
 
     private void test_fail_plain_to_tls() throws IOException, SQLException {
-        attempt("fail_plain_to_tls", "server1").with(Parameter.TLS, false).expectFailure("asdf");
+        attempt("fail_plain_to_tls", "server1").with(Parameter.TLS, false).expectFailure("Cannot connect");
     }
 
     private void test_connect_server_name() throws IOException, SQLException {