1 /*
  2  * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 import javax.net.ssl.*;
 25 import java.io.IOException;
 26 import java.net.Socket;
 27 import java.nio.charset.StandardCharsets;
 28 import java.nio.file.Path;
 29 import java.security.Security;
 30 import java.util.List;
 31 
 32 /*
 33  * @test id=Server
 34  * @bug 8301379
 35  * @summary Verify that Java will not negotiate disabled cipher suites when the
 36  * other side of the connection requests them.
 37  *
 38  * @library /javax/net/ssl/templates
 39  * @run main/othervm TLSWontNegotiateDisabledCipherAlgos server true
 40  */
 41 
 42 /*
 43  * @test id=Client
 44  * @bug 8301379
 45  * @summary Verify that Java will not negotiate disabled cipher suites when the
 46  * other side of the connection requests them.
 47  *
 48  * @library /javax/net/ssl/templates
 49  * @run main/othervm TLSWontNegotiateDisabledCipherAlgos server false
 50  */
 51 
 52 
 53 public class TLSWontNegotiateDisabledCipherAlgos {
 54 
 55     public static void main(String [] args) throws Exception {
 56         boolean useDisabledAlgo = Boolean.parseBoolean(args[1]);
 57         if (useDisabledAlgo) {
 58             Security.setProperty("jdk.tls.disabledAlgorithms", "");
 59         }
 60 
 61         if (args[0].equals("server")) {
 62             try (TLSServer server = new TLSServer(useDisabledAlgo)) {
 63                 List<String> command = List.of(
 64                         Path.of(System.getProperty("java.home"), "bin", "java").toString(),
 65                         "TLSWontNegotiateDisabledCipherAlgos",
 66                         "client",
 67                         Boolean.toString(!useDisabledAlgo),
 68                         Integer.toString(server.getListeningPort())
 69                 );
 70                 ProcessBuilder builder = new ProcessBuilder(command);
 71                 Process p = builder.inheritIO().start();
 72                 server.run();
 73                 p.destroy();
 74             }
 75         } else if (args[0].equals("client")) {
 76             try (TLSClient client = new TLSClient(Integer.parseInt(args[2]), useDisabledAlgo)) {
 77                 client.run();
 78             }
 79         }
 80     }
 81 
 82     private static class TLSClient extends SSLContextTemplate implements AutoCloseable {
 83         private final SSLSocket socket;
 84 
 85         public TLSClient(int portNumber, boolean useDisableAlgo) throws Exception {
 86             SSLContext context = createClientSSLContext();
 87             socket = (SSLSocket)context.getSocketFactory().createSocket("localhost", portNumber);
 88             if (useDisableAlgo) {
 89                 socket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES);
 90             }
 91         }
 92 
 93         public void run() throws IOException {
 94             try {
 95                 socket.getOutputStream().write("SECRET MESSAGE".getBytes(StandardCharsets.UTF_8));
 96                 throw new RuntimeException("SSL handshake completed successfully.");
 97             } catch (SSLHandshakeException exc) {
 98                 if (!exc.getMessage().equals("Received fatal alert: handshake_failure")) {
 99                     throw new RuntimeException("Expected handshake_failure message. Got: "
100                             + "\"" + exc.getMessage() + "\" message.", exc);
101                 }
102             }
103         }
104 
105         @Override
106         public void close() throws Exception {
107             socket.close();
108         }
109     }
110 
111     private static class TLSServer extends SSLContextTemplate implements AutoCloseable {
112         private SSLServerSocket serverSocket;
113 
114         public TLSServer(boolean useDisableAlgo) throws Exception {
115             SSLContext ctx = createServerSSLContext();
116             serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(0);
117             if (useDisableAlgo) {
118                 serverSocket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES);
119             }
120         }
121 
122         @Override
123         public void close() throws Exception {
124             serverSocket.close();
125         }
126 
127         public int getListeningPort() {
128             return serverSocket.getLocalPort();
129         }
130 
131         public void run() throws IOException {
132             try (Socket clientSocket = serverSocket.accept()) {
133                 try {
134                     byte[] bytes = clientSocket.getInputStream().readAllBytes();
135                     throw new RuntimeException("The expected SSLHandshakeException was not thrown.");
136                 } catch (SSLHandshakeException exc) {
137                     if (!exc.getMessage().contains("no cipher suites in common")) {
138                         throw exc;
139                     } else {
140                         System.out.println("Success: The connection could not be negotiated (as expected.)");
141                     }
142                 }
143             }
144         }
145     }
146 }