1 /*
2  * Copyright (c) 2001, 2018, 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 4416068 4478803 4479736
30  * @summary 4273544 JSSE request for function forceV3ClientHello()
31  *          4479736 setEnabledProtocols API does not work correctly
32  *          4478803 Need APIs to determine the protocol versions used in an SSL
33  *                  session
34  *          4701722 protocol mismatch exceptions should be consistent between
35  *                  SSLv3 and TLSv1
36  * @library /javax/net/ssl/templates
37  * @run main/othervm TestEnabledProtocols
38  * @author Ram Marti
39  */
40 
41 import java.io.InputStream;
42 import java.io.InterruptedIOException;
43 import java.io.OutputStream;
44 import java.security.Security;
45 import java.util.Arrays;
46 
47 import javax.net.ssl.SSLException;
48 import javax.net.ssl.SSLHandshakeException;
49 import javax.net.ssl.SSLServerSocket;
50 import javax.net.ssl.SSLSocket;
51 
52 public class TestEnabledProtocols extends SSLSocketTemplate {
53 
54     private final String[] serverProtocols;
55     private final String[] clientProtocols;
56     private final boolean exceptionExpected;
57     private final String selectedProtocol;
58 
TestEnabledProtocols(String[] serverProtocols, String[] clientProtocols, boolean exceptionExpected, String selectedProtocol)59     public TestEnabledProtocols(String[] serverProtocols,
60             String[] clientProtocols, boolean exceptionExpected,
61             String selectedProtocol) {
62         this.serverProtocols = serverProtocols;
63         this.clientProtocols = clientProtocols;
64         this.exceptionExpected = exceptionExpected;
65         this.selectedProtocol = selectedProtocol;
66     }
67 
68     @Override
configureServerSocket(SSLServerSocket sslServerSocket)69     protected void configureServerSocket(SSLServerSocket sslServerSocket) {
70         sslServerSocket.setEnabledProtocols(serverProtocols);
71     }
72 
73     @Override
runServerApplication(SSLSocket socket)74     protected void runServerApplication(SSLSocket socket) throws Exception {
75         try {
76             socket.startHandshake();
77 
78             InputStream in = socket.getInputStream();
79             OutputStream out = socket.getOutputStream();
80             out.write(280);
81             in.read();
82         } catch (SSLHandshakeException se) {
83             // ignore it; this is part of the testing
84             // log it for debugging
85             System.out.println("Server SSLHandshakeException:");
86             se.printStackTrace(System.out);
87         } catch (InterruptedIOException ioe) {
88             // must have been interrupted, no harm
89         } catch (SSLException ssle) {
90             // The client side may have closed the socket.
91             System.out.println("Server SSLException:");
92             ssle.printStackTrace(System.out);
93         } catch (Exception e) {
94             System.out.println("Server exception:");
95             e.printStackTrace(System.out);
96             throw new RuntimeException(e);
97         }
98     }
99 
100     @Override
runClientApplication(SSLSocket sslSocket)101     protected void runClientApplication(SSLSocket sslSocket) throws Exception {
102         try {
103             System.out.println("=== Starting new test run ===");
104             showProtocols("server", serverProtocols);
105             showProtocols("client", clientProtocols);
106 
107             sslSocket.setEnabledProtocols(clientProtocols);
108             sslSocket.startHandshake();
109 
110             String protocolName = sslSocket.getSession().getProtocol();
111             System.out.println("Protocol name after getSession is " +
112                 protocolName);
113 
114             if (protocolName.equals(selectedProtocol)) {
115                 System.out.println("** Success **");
116             } else {
117                 System.out.println("** FAILURE ** ");
118                 throw new RuntimeException
119                     ("expected protocol " + selectedProtocol +
120                      " but using " + protocolName);
121             }
122 
123             InputStream in = sslSocket.getInputStream();
124             OutputStream out = sslSocket.getOutputStream();
125             in.read();
126             out.write(280);
127         } catch (SSLHandshakeException e) {
128             if (!exceptionExpected) {
129                 System.out.println(
130                         "Client got UNEXPECTED SSLHandshakeException:");
131                 e.printStackTrace(System.out);
132                 System.out.println("** FAILURE **");
133                 throw new RuntimeException(e);
134             } else {
135                 System.out.println(
136                         "Client got expected SSLHandshakeException:");
137                 e.printStackTrace(System.out);
138                 System.out.println("** Success **");
139             }
140         } catch (Exception e) {
141             System.out.println("Client got UNEXPECTED Exception:");
142             e.printStackTrace(System.out);
143             System.out.println("** FAILURE **");
144             throw new RuntimeException(e);
145         }
146     }
147 
main(String[] args)148     public static void main(String[] args) throws Exception {
149         Security.setProperty("jdk.tls.disabledAlgorithms", "");
150 
151         runCase(new String[] { "TLSv1" },
152                 new String[] { "TLSv1" },
153                 false, "TLSv1");
154         runCase(new String[] { "TLSv1" },
155                 new String[] { "TLSv1", "SSLv2Hello" },
156                 true, null);
157         runCase(new String[] { "TLSv1" },
158                 new String[] { "TLSv1", "SSLv3" },
159                 false, "TLSv1");
160         runCase(new String[] { "TLSv1" },
161                 new String[] { "SSLv3", "SSLv2Hello" },
162                 true, null);
163         runCase(new String[] { "TLSv1" },
164                 new String[] { "SSLv3" },
165                 true, null);
166         runCase(new String[] { "TLSv1" },
167                 new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
168                 true, null);
169 
170         runCase(new String[] { "TLSv1", "SSLv2Hello" },
171                 new String[] { "TLSv1" },
172                 false, "TLSv1");
173         runCase(new String[] { "TLSv1", "SSLv2Hello" },
174                 new String[] { "TLSv1", "SSLv2Hello" },
175                 false, "TLSv1");
176         runCase(new String[] { "TLSv1", "SSLv2Hello" },
177                 new String[] { "TLSv1", "SSLv3" },
178                 false, "TLSv1");
179         runCase(new String[] { "TLSv1", "SSLv2Hello" },
180                 new String[] { "SSLv3", "SSLv2Hello" },
181                 true, null);
182         runCase(new String[] { "TLSv1", "SSLv2Hello" },
183                 new String[] { "SSLv3" },
184                 true, null);
185         runCase(new String[] { "TLSv1", "SSLv2Hello" },
186                 new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
187                 false, "TLSv1");
188 
189         runCase(new String[] { "TLSv1", "SSLv3" },
190                 new String[] { "TLSv1" },
191                 false, "TLSv1");
192         runCase(new String[] { "TLSv1", "SSLv3" },
193                 new String[] { "TLSv1", "SSLv2Hello" },
194                 true, null);
195         runCase(new String[] { "TLSv1", "SSLv3" },
196                 new String[] { "TLSv1", "SSLv3" },
197                 false, "TLSv1");
198         runCase(new String[] { "TLSv1", "SSLv3" },
199                 new String[] { "SSLv3", "SSLv2Hello" },
200                 true, null);
201         runCase(new String[] { "TLSv1", "SSLv3" },
202                 new String[] { "SSLv3" },
203                 false, "SSLv3");
204         runCase(new String[] { "TLSv1", "SSLv3" },
205                 new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
206                 true, null);
207 
208         runCase(new String[] { "SSLv3", "SSLv2Hello" },
209                 new String[] { "TLSv1" },
210                 true, null);
211         runCase(new String[] { "SSLv3", "SSLv2Hello" },
212                 new String[] { "TLSv1", "SSLv2Hello" },
213                 true, null);
214         runCase(new String[] { "SSLv3", "SSLv2Hello" },
215                 new String[] { "TLSv1", "SSLv3" },
216                 false, "SSLv3");
217         runCase(new String[] { "SSLv3", "SSLv2Hello" },
218                 new String[] { "SSLv3", "SSLv2Hello" },
219                 false, "SSLv3");
220         runCase(new String[] { "SSLv3", "SSLv2Hello" },
221                 new String[] { "SSLv3" },
222                 false, "SSLv3");
223         runCase(new String[] { "SSLv3", "SSLv2Hello" },
224                 new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
225                 false, "SSLv3");
226 
227         runCase(new String[] { "SSLv3" },
228                 new String[] { "TLSv1" },
229                 true, null);
230         runCase(new String[] { "SSLv3" },
231                 new String[] { "TLSv1", "SSLv2Hello" },
232                 true, null);
233         runCase(new String[] { "SSLv3" },
234                 new String[] { "TLSv1", "SSLv3" },
235                 false, "SSLv3");
236         runCase(new String[] { "SSLv3" },
237                 new String[] { "SSLv3", "SSLv2Hello" },
238                 true, null);
239         runCase(new String[] { "SSLv3" },
240                 new String[] { "SSLv3" },
241                 false, "SSLv3");
242         runCase(new String[] { "SSLv3" },
243                 new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
244                 true, null);
245 
246         runCase(new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
247                 new String[] { "TLSv1" },
248                 false, "TLSv1");
249         runCase(new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
250                 new String[] { "TLSv1", "SSLv2Hello" },
251                 false, "TLSv1");
252         runCase(new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
253                 new String[] { "TLSv1", "SSLv3" },
254                 false, "TLSv1");
255         runCase(new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
256                 new String[] { "SSLv3", "SSLv2Hello" },
257                 false, "SSLv3");
258         runCase(new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
259                 new String[] { "SSLv3" },
260                 false, "SSLv3");
261         runCase(new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
262                 new String[] { "TLSv1", "SSLv3", "SSLv2Hello" },
263                 false, "TLSv1");
264     }
265 
runCase( String[] serverProtocols, String[] clientProtocols, boolean exceptionExpected, String selectedProtocol)266     private static void runCase(
267             String[] serverProtocols,
268             String[] clientProtocols,
269             boolean exceptionExpected,
270             String selectedProtocol) throws Exception {
271         new TestEnabledProtocols(
272                 serverProtocols,
273                 clientProtocols,
274                 exceptionExpected,
275                 selectedProtocol).run();
276     }
277 
showProtocols(String name, String[] protocols)278     private static void showProtocols(String name, String[] protocols) {
279         System.out.printf("Enabled protocols on the %s are: %s%n",
280                 name,
281                 Arrays.asList(protocols));
282     }
283 }
284