1 /*
2  * Copyright (c) 2020, 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 java.io.IOException;
25 import java.net.URI;
26 import java.net.http.HttpClient;
27 import java.net.http.HttpRequest;
28 import java.net.http.HttpResponse;
29 import java.util.List;
30 import javax.net.ssl.SSLContext;
31 import jdk.test.lib.net.URIBuilder;
32 import jdk.test.lib.security.KeyEntry;
33 import jdk.test.lib.security.KeyStoreUtils;
34 import jdk.test.lib.security.SSLContextBuilder;
35 import static java.net.http.HttpResponse.BodyHandlers.ofString;
36 import static java.net.http.HttpClient.Builder.NO_PROXY;
37 
38 /*
39  * @test
40  * @bug 8239594 8239595
41  * @library /test/lib
42  * @build Server TlsVersionTest
43  * @run main/othervm
44  *      -Djdk.internal.httpclient.disableHostnameVerification
45  *       TlsVersionTest false
46  *
47  * @run main/othervm
48  *      -Djdk.internal.httpclient.disableHostnameVerification
49  *      -Djdk.tls.client.protocols="TLSv1.2"
50  *       TlsVersionTest true
51  */
52 
53 /**
54  * The test uses a valid self-signed certificate
55  * that is installed in the trust store (so is trusted) and the same cert
56  * is supplied by the server for its own identity.
57  *
58  * The test sets the context TLS Version 1.2 for client and 1.3
59  * for the server, as per the bug, the server checks for the
60  * negotiated protocol version, it should adhere to the protocol
61  * version value used in SSL Context for client and the server should
62  * be able to downgrade to 1.2 during the handshake. The test would
63  * fail if the negotiated protocol version is different from the one set in
64  * SSL Context for the client as it is the lower version.
65  */
66 
67 public class TlsVersionTest {
68 
69     private static Cert cert;
70     // parameter to distinguish scenarios where system property is set and unset
71     static String tlsVersion;
72     static Server server;
73     static int port;
74 
main(String[] args)75     public static void main(String[] args) throws Exception {
76         try {
77             tlsVersion = args[0];
78             // certificate name set to be accepted by dummy server
79             cert = Cert.valueOf("LOOPBACK_CERT");
80             server = new Server(getServerSSLContext(cert));
81             port = server.getPort();
82             test(cert);
83         } finally {
84             if (server != null) {
85                 server.stop();
86             }
87         }
88     }
89 
getServerSSLContext(Cert cert)90     private static SSLContext getServerSSLContext(Cert cert) throws Exception {
91         SSLContextBuilder builder = SSLContextBuilder.builder();
92         builder.trustStore(
93                 KeyStoreUtils.createTrustStore(new String[] { cert.certStr }));
94         builder.keyStore(KeyStoreUtils.createKeyStore(
95                 new KeyEntry[] { new KeyEntry(cert.keyAlgo,
96                         cert.keyStr, new String[] { cert.certStr }) }));
97             builder.protocol("TLSv1.3");
98         return builder.build();
99     }
100 
getClientSSLContext(Cert cert)101     private static SSLContext getClientSSLContext(Cert cert) throws Exception {
102         SSLContextBuilder builder = SSLContextBuilder.builder();
103         builder.trustStore(
104                 KeyStoreUtils.createTrustStore(new String[] { cert.certStr }));
105         builder.keyStore(KeyStoreUtils.createKeyStore(
106                 new KeyEntry[] { new KeyEntry(cert.keyAlgo,
107                         cert.keyStr, new String[] { cert.certStr }) }));
108         if(tlsVersion.equals("false"))
109             builder.protocol("TLSv1.2");
110         return builder.build();
111     }
112 
test(Cert cert)113     static void test(Cert cert) throws Exception {
114         URI serverURI = URIBuilder.newBuilder()
115                                   .scheme("https")
116                                   .loopback()
117                                   .port(server.getPort())
118                                   .path("/foo")
119                                   .build();
120         String error = null;
121         System.out.println("Making request to " + serverURI.getPath());
122         SSLContext ctx = getClientSSLContext(cert);
123         HttpClient client = HttpClient.newBuilder()
124                                       .proxy(NO_PROXY)
125                                       .sslContext(ctx)
126                                       .build();
127 
128         for (var version : List.of(HttpClient.Version.HTTP_2, HttpClient.Version.HTTP_1_1)) {
129             HttpRequest request = HttpRequest.newBuilder(serverURI)
130                                              .version(version)
131                                              .GET()
132                                              .build();
133             System.out.println("Using version: " + version);
134             try {
135                 HttpResponse<String> response = client.send(request, ofString());
136                 String protocol = response.sslSession().get().getProtocol();
137                 System.out.println("TLS version negotiated is: " + protocol);
138                 if (!(protocol.equals("TLSv1.2"))) {
139                     error = "Test failed : TLS version should be " + "TLSv1.2";
140                     throw new RuntimeException(error);
141                 }
142             } catch (IOException e) {
143                 System.out.println("Caught Exception " + e);
144                 throw e;
145             }
146         }
147     }
148 }
149