1/*
2 * Copyright (c) 2016, 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// SunJSSE does not support dynamic system properties, no way to re-use
25// system properties in samevm/agentvm mode.
26
27/*
28 * @test
29 * @bug 8162362
30 * @summary Cannot enable previously default enabled cipher suites
31 * @run main/othervm
32 *      CustomizedCipherSuites Default true
33 *      TLS_RSA_WITH_AES_128_CBC_SHA
34 *      SSL_RSA_WITH_DES_CBC_SHA
35 * @run main/othervm
36 *      -Djdk.tls.client.cipherSuites="unknown"
37 *      CustomizedCipherSuites Default true
38 *      TLS_RSA_WITH_AES_128_CBC_SHA
39 *      SSL_RSA_WITH_DES_CBC_SHA
40 * @run main/othervm
41 *      -Djdk.tls.client.cipherSuites=""
42 *      CustomizedCipherSuites Default true
43 *      TLS_RSA_WITH_AES_128_CBC_SHA
44 *      SSL_RSA_WITH_DES_CBC_SHA
45 * @run main/othervm
46 *      -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
47 *      CustomizedCipherSuites Default true
48 *      SSL_RSA_WITH_DES_CBC_SHA
49 *      TLS_RSA_WITH_AES_128_CBC_SHA
50 * @run main/othervm
51 *      -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
52 *      CustomizedCipherSuites Default false
53 *      SSL_RSA_WITH_DES_CBC_SHA
54 *      TLS_RSA_WITH_AES_128_CBC_SHA
55 * @run main/othervm
56 *      -Djdk.tls.client.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA"
57 *      CustomizedCipherSuites Default true
58 *      SSL_RSA_WITH_DES_CBC_SHA
59 *      ""
60 * @run main/othervm
61 *      -Djdk.tls.server.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA"
62 *      CustomizedCipherSuites Default false
63 *      TLS_RSA_WITH_AES_128_CBC_SHA
64 *      ""
65 * @run main/othervm
66 *      -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
67 *      CustomizedCipherSuites Default true
68 *      TLS_RSA_WITH_AES_128_CBC_SHA
69 *      SSL_RSA_WITH_DES_CBC_SHA
70 * @run main/othervm
71 *      -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
72 *      CustomizedCipherSuites Default false
73 *      TLS_RSA_WITH_AES_128_CBC_SHA
74 *      SSL_RSA_WITH_DES_CBC_SHA
75 */
76
77import javax.net.ssl.*;
78
79/**
80 * Test the customized default cipher suites.
81 *
82 * This test is based on the behavior that SSL_RSA_WITH_DES_CBC_SHA is
83 * disabled by default, and TLS_RSA_WITH_AES_128_CBC_SHA is enabled by
84 * default in JDK.  If the behavior is changed in the future, please
85 * update the test cases above accordingly.
86 */
87public class CustomizedCipherSuites {
88
89    private static String contextProtocol;
90    private static boolean isClientMode;
91
92    private static String enabledCipherSuite;
93    private static String disabledCipherSuite;
94
95    public static void main(String[] args) throws Exception {
96
97        contextProtocol = trimQuotes(args[0]);
98        isClientMode = Boolean.parseBoolean(args[1]);
99        enabledCipherSuite = trimQuotes(args[2]);
100        disabledCipherSuite = trimQuotes(args[3]);
101
102        //
103        // Create instance of SSLContext with the specified protocol.
104        //
105        SSLContext context = SSLContext.getInstance(contextProtocol);
106
107        // Default SSLContext is initialized automatically.
108        if (!contextProtocol.equals("Default")) {
109            // Use default TK, KM and random.
110            context.init((KeyManager[])null, (TrustManager[])null, null);
111        }
112
113        // SSLContext default parameters is client mode in JDK.
114        if (isClientMode) {
115            //
116            // Check default parameters of the specified SSLContext protocol
117            //
118            SSLParameters parameters = context.getDefaultSSLParameters();
119            System.out.println("Checking SSLContext default parameters ...");
120            checkEnabledCiphers(parameters.getCipherSuites());
121        }
122
123        //
124        // Check supported parameters of the specified SSLContext protocol
125        //
126        SSLParameters parameters = context.getSupportedSSLParameters();
127        System.out.println("Checking SSLContext suppport parameters ...");
128        checkSupportedCiphers(parameters.getCipherSuites());
129
130
131        //
132        // Check the default cipher suites of SSLEngine.
133        //
134        SSLEngine engine = context.createSSLEngine();
135        engine.setUseClientMode(isClientMode);
136
137        System.out.println("Checking SSLEngine default cipher suites ...");
138        checkEnabledCiphers(engine.getEnabledCipherSuites());
139
140        //
141        // Check the supported cipher suites of SSLEngine.
142        //
143        System.out.println("Checking SSLEngine supported cipher suites ...");
144        checkSupportedCiphers(engine.getSupportedCipherSuites());
145
146        if (isClientMode) {
147            SSLSocketFactory factory = context.getSocketFactory();
148            // Use an unconnected socket.
149            try (SSLSocket socket = (SSLSocket)factory.createSocket()) {
150                //
151                // Check the default cipher suites of SSLSocket.
152                //
153                System.out.println(
154                        "Checking SSLSocket default cipher suites ...");
155                checkEnabledCiphers(socket.getEnabledCipherSuites());
156
157                //
158                // Check the supported cipher suites of SSLSocket.
159                //
160                System.out.println(
161                        "Checking SSLSocket supported cipher suites ...");
162                checkSupportedCiphers(socket.getSupportedCipherSuites());
163            }
164        } else {
165            SSLServerSocketFactory factory = context.getServerSocketFactory();
166            // Use an unbound server socket.
167            try (SSLServerSocket socket =
168                    (SSLServerSocket)factory.createServerSocket()) {
169                //
170                // Check the default cipher suites of SSLServerSocket.
171                //
172                System.out.println(
173                        "Checking SSLServerSocket default cipher suites ...");
174                checkEnabledCiphers(socket.getEnabledCipherSuites());
175
176                //
177                // Check the supported cipher suites of SSLServerSocket.
178                //
179                System.out.println(
180                        "Checking SSLServerSocket supported cipher suites ...");
181                checkSupportedCiphers(socket.getSupportedCipherSuites());
182            }
183        }
184
185        System.out.println("\t... Success");
186    }
187
188    private static void checkEnabledCiphers(
189            String[] ciphers) throws Exception {
190
191        if (ciphers.length == 0) {
192            throw new Exception("No default cipher suites");
193        }
194
195        boolean isMatch = false;
196        if (enabledCipherSuite.isEmpty()) {
197            // Don't check if not specify the expected cipher suite.
198            isMatch = true;
199        }
200
201        boolean isBroken = false;
202        for (String cipher : ciphers) {
203            System.out.println("\tdefault cipher suite " + cipher);
204            if (!enabledCipherSuite.isEmpty() &&
205                        cipher.equals(enabledCipherSuite)) {
206                isMatch = true;
207            }
208
209            if (!disabledCipherSuite.isEmpty() &&
210                        cipher.equals(disabledCipherSuite)) {
211                isBroken = true;
212            }
213        }
214
215        if (!isMatch) {
216            throw new Exception(
217                "Cipher suite " + enabledCipherSuite + " should be enabled");
218        }
219
220        if (isBroken) {
221            throw new Exception(
222                "Cipher suite " + disabledCipherSuite + " should be disabled");
223        }
224    }
225
226    private static void checkSupportedCiphers(
227            String[] ciphers) throws Exception {
228
229        if (ciphers.length == 0) {
230            throw new Exception("No supported cipher suites");
231        }
232
233        boolean hasEnabledCipherSuite = enabledCipherSuite.isEmpty();
234        boolean hasDisabledCipherSuite = disabledCipherSuite.isEmpty();
235        for (String cipher : ciphers) {
236            System.out.println("\tsupported cipher suite " + cipher);
237            if (!enabledCipherSuite.isEmpty() &&
238                        cipher.equals(enabledCipherSuite)) {
239                hasEnabledCipherSuite = true;
240            }
241
242            if (!disabledCipherSuite.isEmpty() &&
243                        cipher.equals(disabledCipherSuite)) {
244                hasDisabledCipherSuite = true;
245            }
246        }
247
248        if (!hasEnabledCipherSuite) {
249            throw new Exception(
250                "Cipher suite " + enabledCipherSuite + " should be supported");
251        }
252
253        if (!hasDisabledCipherSuite) {
254            throw new Exception(
255                "Cipher suite " + disabledCipherSuite + " should be supported");
256        }
257    }
258
259    private static String trimQuotes(String candidate) {
260        if (candidate != null && candidate.length() != 0) {
261            // Remove double quote marks from beginning/end of the string.
262            if (candidate.length() > 1 && candidate.charAt(0) == '"' &&
263                    candidate.charAt(candidate.length() - 1) == '"') {
264                return candidate.substring(1, candidate.length() - 1);
265            }
266        }
267
268        return candidate;
269    }
270}
271