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.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.security.Security;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 
33 /*
34  * A JDK client process.
35  */
36 public class JdkProcClient extends AbstractClient {
37 
38     private final Jdk jdk;
39     private final Map<String, String> props = new HashMap<>();
40 
41     private Process process;
42 
JdkProcClient(Builder builder)43     public JdkProcClient(Builder builder) {
44         this.jdk = builder.getJdk();
45 
46         if (builder.getSecPropsFile() != null) {
47             props.put(JdkProcUtils.PROP_SEC_PROPS_FILE,
48                     builder.getSecPropsFile().toString());
49         }
50 
51         if (builder.getCertTuple() != null) {
52             props.put(JdkProcUtils.PROP_TRUSTED_CERTS,
53                     JdkProcUtils.certsToStr(builder.getCertTuple().trustedCerts));
54             props.put(JdkProcUtils.PROP_EE_CERTS,
55                     JdkProcUtils.certsToStr(builder.getCertTuple().endEntityCerts));
56         }
57 
58         if (builder.getProtocols() != null) {
59             props.put(JdkProcUtils.PROP_PROTOCOLS,
60                     Utilities.join(Utilities.enumsToStrs(builder.getProtocols())));
61         }
62 
63         if (builder.getCipherSuites() != null) {
64             props.put(JdkProcUtils.PROP_CIPHER_SUITES,
65                     Utilities.join(Utilities.enumsToStrs(builder.getCipherSuites())));
66         }
67 
68         if (builder.getServerNames() != null) {
69             props.put(JdkProcUtils.PROP_SERVER_NAMES,
70                     Utilities.join(builder.getServerNames()));
71         }
72 
73         if (builder.getAppProtocols() != null) {
74             props.put(JdkProcUtils.PROP_APP_PROTOCOLS,
75                     Utilities.join(builder.getAppProtocols()));
76         }
77 
78         if (builder.getNamedGroups() != null) {
79             props.put(JdkProcUtils.PROP_NAMED_GROUPS,
80                     Utilities.join(Utilities.namedGroupsToStrs(
81                             builder.getNamedGroups())));
82         }
83 
84         props.put("test.src", Utilities.TEST_SRC);
85         if (Utilities.DEBUG) {
86             props.put("javax.net.debug", "all");
87         }
88     }
89 
90     public static class Builder extends AbstractClient.Builder {
91 
92         private Jdk jdk;
93 
94         private Path secPropsFile;
95 
getJdk()96         public Jdk getJdk() {
97             return jdk;
98         }
99 
setJdk(Jdk jdk)100         public Builder setJdk(Jdk jdk) {
101             this.jdk = jdk;
102             return this;
103         }
104 
getSecPropsFile()105         public Path getSecPropsFile() {
106             return secPropsFile;
107         }
108 
setSecPropsFile(Path secPropsFile)109         public Builder setSecPropsFile(Path secPropsFile) {
110             this.secPropsFile = secPropsFile;
111             return this;
112         }
113 
114         @Override
build()115         public JdkProcClient build() {
116             return new JdkProcClient(this);
117         }
118     }
119 
120     @Override
getProduct()121     public Jdk getProduct() {
122         return jdk;
123     }
124 
125     @Override
connect(String host, int port)126     public void connect(String host, int port) throws IOException {
127         props.put(JdkProcUtils.PROP_HOST, host);
128         props.put(JdkProcUtils.PROP_PORT, port + "");
129 
130         process = JdkProcUtils.java(getProduct().getPath(), getClass(), props,
131                 getLogPath());
132         try {
133             process.waitFor();
134         } catch (InterruptedException e) {
135             throw new RuntimeException("Client was interrupted!", e);
136         }
137 
138         if (process.exitValue() != 0) {
139             throw new SSLTestException("Client exited abnormally!");
140         }
141     }
142 
143     @Override
getLogPath()144     protected Path getLogPath() {
145         return Paths.get("client.log");
146     }
147 
148     @Override
close()149     public void close() throws IOException {
150         printLog();
151         deleteLog();
152     }
153 
main(String[] args)154     public static void main(String[] args) throws Exception {
155         String trustedCertsStr = System.getProperty(JdkProcUtils.PROP_TRUSTED_CERTS);
156         String eeCertsStr = System.getProperty(JdkProcUtils.PROP_EE_CERTS);
157 
158         String protocolsStr = System.getProperty(JdkProcUtils.PROP_PROTOCOLS);
159         String cipherSuitesStr = System.getProperty(JdkProcUtils.PROP_CIPHER_SUITES);
160 
161         String serverNamesStr = System.getProperty(JdkProcUtils.PROP_SERVER_NAMES);
162         String appProtocolsStr = System.getProperty(JdkProcUtils.PROP_APP_PROTOCOLS);
163 
164         // Re-enable TLSv1 and TLSv1.1 since client depends on them
165         removeFromDisabledTlsAlgs("TLSv1", "TLSv1.1");
166 
167         JdkClient.Builder builder = new JdkClient.Builder();
168         builder.setCertTuple(JdkProcUtils.createCertTuple(
169                 trustedCertsStr, eeCertsStr));
170         if (!Utilities.isEmpty(protocolsStr)) {
171             builder.setProtocols(Utilities.strToEnums(
172                     Protocol.class, protocolsStr));
173         }
174         if (!Utilities.isEmpty(cipherSuitesStr)) {
175             builder.setCipherSuites(Utilities.strToEnums(
176                     CipherSuite.class, cipherSuitesStr));
177         }
178         if (!Utilities.isEmpty(serverNamesStr)) {
179             builder.setServerNames(Utilities.split(serverNamesStr));
180         }
181         if (!Utilities.isEmpty(appProtocolsStr)) {
182             builder.setAppProtocols(Utilities.split(appProtocolsStr));
183         }
184 
185         String host = System.getProperty(JdkProcUtils.PROP_HOST);
186         int port = Integer.getInteger(JdkProcUtils.PROP_PORT);
187 
188         try(JdkClient client = builder.build()) {
189             client.connect(host, port);
190         }
191     }
192 
193     /**
194      * Removes the specified protocols from the jdk.tls.disabledAlgorithms
195      * security property.
196      */
removeFromDisabledTlsAlgs(String... algs)197     private static void removeFromDisabledTlsAlgs(String... algs) {
198         List<String> algList = Arrays.asList(algs);
199         String value = Security.getProperty("jdk.tls.disabledAlgorithms");
200         StringBuilder newValue = new StringBuilder();
201         for (String constraint : value.split(",")) {
202             String tmp = constraint.trim();
203             if (!algList.contains(tmp)) {
204                 newValue.append(tmp);
205                 newValue.append(",");
206             }
207         }
208         Security.setProperty("jdk.tls.disabledAlgorithms", newValue.toString());
209     }
210 }
211