1 /* 2 * Copyright (c) 2003, 2015, 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 /* 25 * @test 26 * @bug 8058865 27 * @summary Checks various secure ways of connecting from remote jmx client 28 * @author Olivier Lagneau 29 * @modules java.management.rmi 30 * @library /lib/testlibrary 31 * @library /test/lib 32 * @compile MBS_Light.java ServerDelegate.java TestSampleLoginModule.java 33 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=SQE_username -Dpassword=SQE_password SecurityTest -server -mapType x.password.file -client -mapType credentials 34 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=UNKNOWN_username -Dpassword=SQE_password SecurityTest -server -mapType x.password.file -client -mapType credentials -expectedThrowable java.lang.SecurityException 35 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=SQE_username -Dpassword=WRONG_password SecurityTest -server -mapType x.password.file -client -mapType credentials -expectedThrowable java.lang.SecurityException 36 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dsusername=TestJMXAuthenticatorUsername -Dspassword=TestJMXAuthenticatorPassword -Dusername=TestJMXAuthenticatorUsername -Dpassword=TestJMXAuthenticatorPassword SecurityTest -server -mapType x.authenticator -client -mapType credentials 37 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dsusername=TestJMXAuthenticatorUsername -Dspassword=TestJMXAuthenticatorPassword -Dusername=AnotherTestJMXAuthenticatorUsername -Dpassword=TestJMXAuthenticatorPassword SecurityTest -server -mapType x.authenticator -client -mapType credentials -expectedThrowable java.lang.SecurityException 38 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.PasswordFileAuthentication -client -mapType credentials 39 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config.UNKNOWN -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.PasswordFileAuthentication -client -mapType credentialss -expectedThrowable java.lang.SecurityException 40 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.UnknownAuthentication -client -mapType credentials -expectedThrowable java.lang.SecurityException 41 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dsusername=usernameSampleLoginModule -Dspassword=passwordSampleLoginModule -Dpassword.file=password.properties -Dusername=usernameSampleLoginModule -Dpassword=passwordSampleLoginModule SecurityTest -server -mapType x.login.config.SampleLoginModule -client -mapType credentials 42 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dsusername=usernameSampleLoginModule -Dspassword=passwordSampleLoginModule -Dpassword.file=password.properties -Dusername=AnotherUsernameSampleLoginModule -Dpassword=passwordSampleLoginModule SecurityTest -server -mapType x.login.config.SampleLoginModule -client -mapType credentials -expectedThrowable java.lang.SecurityException 43 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop 44 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword WRONG_password -expectedThrowable java.io.IOException 45 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 46 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 47 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -expectedThrowable java.io.IOException 48 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -keystore keystoreClient -keystorepassword glopglop -truststore truststoreClient -truststorepassword glopglop 49 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -keystore keystoreClient -keystorepassword WRONG_password -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 50 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 51 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -client -keystore keystoreClient -keystorepassword glopglop -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 52 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_MD5 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.md5 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop 53 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_SHA SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.md5 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 54 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_MD5 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.sha -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 55 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=SSLv3 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.sslv3 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop 56 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=TLSv1 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.sslv3 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 57 * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=SSLv3 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.tlsv1 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException 58 */ 59 60 import java.io.File; 61 import java.util.Map ; 62 import java.util.HashMap ; 63 import java.util.List; 64 import java.util.ArrayList; 65 import java.util.Arrays; 66 67 import javax.management.MBeanServer; 68 import javax.management.MBeanServerFactory ; 69 import javax.management.MBeanServerConnection; 70 import javax.management.remote.JMXConnector; 71 import javax.management.remote.JMXConnectorFactory; 72 import javax.management.remote.JMXConnectorServer; 73 import javax.management.remote.JMXConnectorServerFactory; 74 import javax.management.remote.JMXServiceURL; 75 76 import javax.management.Attribute ; 77 import javax.management.ObjectName ; 78 79 import javax.rmi.ssl.SslRMIClientSocketFactory; 80 import javax.rmi.ssl.SslRMIServerSocketFactory; 81 82 import java.security.Security; 83 84 import jdk.test.lib.process.ProcessTools; 85 import jdk.testlibrary.JDKToolFinder; 86 87 public class SecurityTest { 88 89 static final String SERVER_CLASS_NAME = "SecurityTest"; 90 static final String CLIENT_CLASS_NAME = "SecurityTest$ClientSide"; 91 static final String CLIENT_CLASS_MAIN = CLIENT_CLASS_NAME; 92 93 static final String USERNAME_PROPERTY = "username"; 94 static final String PASSWORD_PROPERTY = "password"; 95 96 static final String SERVER_DELEGATE_MBEAN_NAME = 97 "defaultDomain:class=ServerDelegate"; 98 99 static final String RMI_SERVER_SOCKET_FACTORY_SSL = "rmi.server.socket.factory.ssl"; 100 static final String RMI_CLIENT_SOCKET_FACTORY_SSL = "rmi.client.socket.factory.ssl"; 101 static final String KEYSTORE_PROPNAME = "javax.net.ssl.keyStore"; 102 static final String KEYSTORE_PWD_PROPNAME = "javax.net.ssl.keyStorePassword"; 103 static final String TRUSTSTORE_PROPNAME = "javax.net.ssl.trustStore"; 104 static final String TRUSTSTORE_PWD_PROPNAME = "javax.net.ssl.trustStorePassword"; 105 106 static final String RMI_SSL_CLIENT_ENABLEDCIPHERSUITES = 107 "javax.rmi.ssl.client.enabledCipherSuites"; 108 static final String RMI_SSL_CLIENT_ENABLEDPROTOCOLS = 109 "javax.rmi.ssl.client.enabledProtocols"; 110 111 private JMXConnectorServer cs; 112 113 // Construct and set keyStore properties from given map 114 static void setKeyStoreProperties(Map<String, Object> map) { 115 116 String keyStore = (String) map.get("-keystore"); 117 keyStore = buildSourcePath(keyStore); 118 System.setProperty(KEYSTORE_PROPNAME, keyStore); 119 System.out.println("keyStore location = \"" + keyStore + "\""); 120 121 String password = (String) map.get("-keystorepassword"); 122 System.setProperty(KEYSTORE_PWD_PROPNAME, password); 123 System.out.println("keyStore password = " + password); 124 125 } 126 127 // Construct and set trustStore properties from given map 128 static void setTrustStoreProperties(Map<String, Object> map) { 129 130 String trustStore = (String) map.get("-truststore"); 131 trustStore = buildSourcePath(trustStore); 132 System.setProperty(TRUSTSTORE_PROPNAME, trustStore); 133 System.out.println("trustStore location = \"" + trustStore + "\""); 134 135 String password = (String) map.get("-truststorepassword"); 136 System.setProperty(TRUSTSTORE_PWD_PROPNAME, password); 137 System.out.println("trustStore password = " + password); 138 139 } 140 141 /* 142 * First Debug properties and arguments are collect in expected 143 * map (argName, value) format, then calls original test's run method. 144 */ 145 public static void main(String args[]) throws Exception { 146 147 System.out.println("================================================="); 148 149 // Parses parameters 150 Utils.parseDebugProperties(); 151 152 // Supported parameters list format is : 153 // "MainClass [-server <param-spec> ...] [-client <param-spec> ...] 154 // with <param-spec> either "-parami valuei" or "-parami" 155 HashMap<String, Object> serverMap = new HashMap<>() ; 156 int clientArgsIndex = 157 Utils.parseServerParameters(args, SERVER_CLASS_NAME, serverMap); 158 159 // Extract and records client params 160 String[] clientParams = null; 161 if (clientArgsIndex < args.length) { 162 int clientParamsSize = args.length - clientArgsIndex; 163 clientParams = new String[clientParamsSize]; 164 System.arraycopy(args, clientArgsIndex, clientParams, 0, clientParamsSize); 165 } else { 166 clientParams = new String[0]; 167 } 168 169 // Run test 170 SecurityTest test = new SecurityTest(); 171 test.run(serverMap, clientParams); 172 173 } 174 175 // Return full path of filename in the test sopurce directory 176 private static String buildSourcePath(String filename) { 177 return System.getProperty("test.src") + File.separator + filename; 178 } 179 180 /* 181 * Collects security run params for server side. 182 */ 183 private HashMap<String, Object> setServerSecurityEnv(Map<String, Object> map) 184 throws Exception { 185 186 // Creates Authentication environment from server side params 187 HashMap<String, Object> env = new HashMap<>(); 188 189 // Retrieve and set keystore and truststore config if any 190 if (map.containsKey("-keystore") && 191 map.get("-keystore") != null) { 192 setKeyStoreProperties(map); 193 } 194 System.out.println("Done keystore properties"); 195 196 if (map.containsKey("-truststore") && 197 map.get("-truststore") != null) { 198 setTrustStoreProperties(map); 199 } 200 System.out.println("Done truststore properties"); 201 202 String value = null; 203 if ((value = (String)map.get("-mapType")) != null) { 204 205 // Case of remote password file with all authorized credentials 206 if (value.contains("x.password.file")) { 207 String passwordFileStr = buildSourcePath("password.properties"); 208 env.put("jmx.remote.x.password.file", passwordFileStr); 209 System.out.println("Added " + passwordFileStr + 210 " file as jmx.remote.x.password.file"); 211 } 212 213 // Case of dedicated authenticator class : TestJMXAuthenticator 214 if (value.contains("x.authenticator")) { 215 env.put("jmx.remote.authenticator", new TestJMXAuthenticator()) ; 216 System.out.println( 217 "Added \"jmx.remote.authenticator\" = TestJMXAuthenticator"); 218 } 219 220 // Case of security config file with standard Authentication 221 if (value.contains("x.login.config.PasswordFileAuthentication")) { 222 String loginConfig = System.getProperty("login.config.file"); 223 224 // Override the default JAAS configuration 225 System.setProperty("java.security.auth.login.config", 226 "file:" + loginConfig); 227 System.out.println("Overrided default JAAS configuration with " + 228 "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ; 229 230 env.put("jmx.remote.x.login.config", "PasswordFileAuthentication") ; 231 System.out.println( 232 "Added \"jmx.remote.x.login.config\" = " + 233 "\"PasswordFileAuthentication\"") ; 234 235 // redirects "password.file" property to file in ${test.src} 236 String passwordFileStr = 237 buildSourcePath(System.getProperty("password.file")); 238 System.setProperty("password.file", passwordFileStr); 239 System.out.println( 240 "Redirected \"password.file\" property value to = " + 241 passwordFileStr) ; 242 } 243 244 // Case of security config file with unexisting athentication config 245 if (value.contains("x.login.config.UnknownAuthentication")) { 246 String loginConfig = System.getProperty("login.config.file"); 247 248 // Override the default JAAS configuration 249 System.setProperty("java.security.auth.login.config", 250 "file:" + loginConfig); 251 System.out.println("Overrided default JAAS configuration with " + 252 "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ; 253 254 env.put("jmx.remote.x.login.config", "UnknownAuthentication") ; 255 System.out.println( 256 "Added \"jmx.remote.x.login.config\" = " + 257 "\"UnknownAuthentication\"") ; 258 259 // redirects "password.file" property to file in ${test.src} 260 String passwordFileStr = 261 buildSourcePath(System.getProperty("password.file")); 262 System.setProperty("password.file", passwordFileStr); 263 System.out.println( 264 "Redirected \"password.file\" property value to = " + 265 passwordFileStr) ; 266 } 267 268 // Case of security config file with dedicated login module 269 if (value.contains("x.login.config.SampleLoginModule")) { 270 String loginConfig = System.getProperty("login.config.file"); 271 272 // Override the default JAAS configuration 273 System.setProperty("java.security.auth.login.config", 274 "file:" + loginConfig); 275 System.out.println("Overrided default JAAS configuration with " + 276 "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ; 277 278 env.put("jmx.remote.x.login.config", "SampleLoginModule") ; 279 System.out.println( 280 "Added \"jmx.remote.x.login.config\" = " + 281 "\"SampleLoginModule\"") ; 282 } 283 284 // Simple rmi ssl authentication 285 if (value.contains(RMI_CLIENT_SOCKET_FACTORY_SSL)) { 286 env.put("jmx.remote.rmi.client.socket.factory", 287 new SslRMIClientSocketFactory()) ; 288 System.out.println( 289 "Added \"jmx.remote.rmi.client.socket.factory\"" + 290 " = SslRMIClientSocketFactory") ; 291 } 292 293 if (value.contains(RMI_SERVER_SOCKET_FACTORY_SSL)) { 294 if (value.contains( 295 "rmi.server.socket.factory.ssl.need.client.authentication")) { 296 // rmi ssl authentication with client authentication 297 env.put("jmx.remote.rmi.server.socket.factory", 298 new SslRMIServerSocketFactory(null, null, true)) ; 299 System.out.println( 300 "Added \"jmx.remote.rmi.server.socket.factory\"" + 301 " = SslRMIServerSocketFactory with client authentication") ; 302 303 } else if (value.contains("rmi.server.socket.factory.ssl.enabled.cipher.suites.md5")) { 304 // Allows all ciphering and protocols for testing purpose 305 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 306 307 env.put("jmx.remote.rmi.server.socket.factory", 308 new SslRMIServerSocketFactory( 309 new String[] {"SSL_RSA_WITH_RC4_128_MD5"}, null, false)); 310 System.out.println( 311 "Added \"jmx.remote.rmi.server.socket.factory\"" + 312 " = SslRMIServerSocketFactory with SSL_RSA_WITH_RC4_128_MD5 cipher suite"); 313 314 } else if (value.contains("rmi.server.socket.factory.ssl.enabled.cipher.suites.sha")) { 315 // Allows all ciphering and protocols for testing purpose 316 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 317 318 env.put("jmx.remote.rmi.server.socket.factory", 319 new SslRMIServerSocketFactory( 320 new String[] { "SSL_RSA_WITH_RC4_128_SHA" }, null, false)) ; 321 System.out.println( 322 "Added \"jmx.remote.rmi.server.socket.factory\"" + 323 " = SslRMIServerSocketFactory with SSL_RSA_WITH_RC4_128_SHA cipher suite") ; 324 325 } else if (value.contains("rmi.server.socket.factory.ssl.enabled.protocols.sslv3")) { 326 // Allows all ciphering and protocols for testing purpose 327 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 328 329 env.put("jmx.remote.rmi.server.socket.factory", 330 new SslRMIServerSocketFactory(null, new String[] {"SSLv3"}, false)) ; 331 System.out.println( 332 "Added \"jmx.remote.rmi.server.socket.factory\"" + 333 " = SslRMIServerSocketFactory with SSLv3 protocol") ; 334 335 } else if (value.contains("rmi.server.socket.factory.ssl.enabled.protocols.tlsv1")) { 336 // Allows all ciphering and protocols for testing purpose 337 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 338 339 env.put("jmx.remote.rmi.server.socket.factory", 340 new SslRMIServerSocketFactory(null, new String[] {"TLSv1"}, false)) ; 341 System.out.println( 342 "Added \"jmx.remote.rmi.server.socket.factory\"" + 343 " = SslRMIServerSocketFactory with TLSv1 protocol") ; 344 345 } else { 346 env.put("jmx.remote.rmi.server.socket.factory", 347 new SslRMIServerSocketFactory()); 348 System.out.println( 349 "Added \"jmx.remote.rmi.server.socket.factory\"" + 350 " = SslRMIServerSocketFactory"); 351 } 352 } 353 } 354 355 return env; 356 } 357 358 /* 359 * Create the MBeansServer side of the test and returns its address 360 */ 361 private JMXServiceURL createServerSide(Map<String, Object> serverMap) 362 throws Exception { 363 final int NINETY_SECONDS = 90; 364 365 System.out.println("SecurityTest::createServerSide: Start") ; 366 367 // Prepare server side security env 368 HashMap<String, Object> env = setServerSecurityEnv(serverMap); 369 370 // Create and start mbean server and connector server 371 MBeanServer mbs = MBeanServerFactory.newMBeanServer(); 372 JMXServiceURL url = new JMXServiceURL("rmi", null, 0); 373 cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); 374 cs.start(); 375 376 // Waits availibility of connector server 377 Utils.waitReady(cs, NINETY_SECONDS); 378 379 JMXServiceURL addr = cs.getAddress(); 380 381 System.out.println("SecurityTest::createServerSide: Done.") ; 382 383 return addr; 384 } 385 386 /* 387 * Creating command-line for running subprocess JVM: 388 * 389 * JVM command line is like: 390 * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main 391 * 392 * {defaultopts} are the default java options set by the framework. 393 * 394 */ 395 private List<String> buildCommandLine(String args[]) { 396 397 System.out.println("SecurityTest::buildCommandLine: Start") ; 398 399 List<String> opts = new ArrayList<>(); 400 opts.add(JDKToolFinder.getJDKTool("java")); 401 opts.addAll(Arrays.asList(jdk.testlibrary.Utils.getTestJavaOpts())); 402 403 // We need to forward some properties to the client side 404 opts.add("-Dtest.src=" + System.getProperty("test.src")); 405 406 String usernameValue = System.getProperty(USERNAME_PROPERTY); 407 if (usernameValue != null) { 408 System.out.println("SecurityTest::buildCommandLine: "+ 409 " forward username property to client side"); 410 opts.add("-D" + USERNAME_PROPERTY + "=" + usernameValue); 411 } 412 String passwordValue = System.getProperty(PASSWORD_PROPERTY); 413 if (passwordValue != null) { 414 System.out.println("SecurityTest::buildCommandLine: "+ 415 " forward password property to client side"); 416 opts.add("-D" + PASSWORD_PROPERTY + "=" + passwordValue); 417 } 418 419 String enabledCipherSuites = 420 System.getProperty(RMI_SSL_CLIENT_ENABLEDCIPHERSUITES); 421 if (enabledCipherSuites != null) { 422 System.out.println("SecurityTest::buildCommandLine: "+ 423 " forward enabledCipherSuites property to client side"); 424 opts.add("-D" + RMI_SSL_CLIENT_ENABLEDCIPHERSUITES + 425 "=" + enabledCipherSuites); 426 } 427 428 String enabledProtocols = 429 System.getProperty(RMI_SSL_CLIENT_ENABLEDPROTOCOLS); 430 if (enabledProtocols != null) { 431 System.out.println("SecurityTest::buildCommandLine: "+ 432 " forward enabledProtocols property to client side"); 433 opts.add("-D" + RMI_SSL_CLIENT_ENABLEDPROTOCOLS + 434 "=" + enabledProtocols); 435 } 436 437 opts.add("-cp"); 438 opts.add(System.getProperty("test.class.path", "test.class.path")); 439 opts.add(CLIENT_CLASS_MAIN); 440 opts.addAll(Arrays.asList(args)); 441 442 System.out.println("SecurityTest::buildCommandLine: Done.") ; 443 444 return opts; 445 } 446 447 /** 448 * Runs SecurityTest$ClientSide with the passed options and redirects 449 * subprocess standard I/O to the current (parent) process. This provides a 450 * trace of what happens in the subprocess while it is runnning (and before 451 * it terminates). 452 * 453 * @param serviceUrlStr string representing the JMX service Url to connect to. 454 */ 455 private int runClientSide(String args[], String serviceUrlStr) throws Exception { 456 457 System.out.println("SecurityTest::runClientSide: Start") ; 458 459 // Building command-line 460 List<String> opts = buildCommandLine(args); 461 opts.add("-serviceUrl"); 462 opts.add(serviceUrlStr); 463 464 // Launch separate JVM subprocess 465 int exitCode = 0; 466 String[] optsArray = opts.toArray(new String[0]); 467 ProcessBuilder pb = new ProcessBuilder(optsArray); 468 Process p = ProcessTools.startProcess("SecurityTest$ClientSide", pb); 469 470 // Handling end of subprocess 471 try { 472 exitCode = p.waitFor(); 473 if (exitCode != 0) { 474 System.out.println( 475 "Subprocess unexpected exit value of [" + exitCode + 476 "]. Expected 0.\n"); 477 } 478 } catch (InterruptedException e) { 479 System.out.println("Parent process interrupted with exception : \n " + e + " :" ); 480 481 // Parent thread unknown state, killing subprocess. 482 p.destroyForcibly(); 483 484 throw new RuntimeException( 485 "Parent process interrupted with exception : \n " + e + " :" ); 486 487 } finally { 488 if (p.isAlive()) { 489 p.destroyForcibly(); 490 } 491 492 System.out.println("SecurityTest::runClientSide: Done") ; 493 494 return exitCode; 495 } 496 497 } 498 499 public void run(Map<String, Object> serverArgs, String clientArgs[]) { 500 501 System.out.println("SecurityTest::run: Start") ; 502 int errorCount = 0; 503 504 try { 505 // Initialise the server side 506 JMXServiceURL urlToUse = createServerSide(serverArgs); 507 508 // Run client side 509 errorCount = runClientSide(clientArgs, urlToUse.toString()); 510 511 if ( errorCount == 0 ) { 512 System.out.println("SecurityTest::run: Done without any error") ; 513 } else { 514 System.out.println( 515 "SecurityTest::run: Done with " + errorCount + " error(s)"); 516 throw new RuntimeException("errorCount = " + errorCount); 517 } 518 519 cs.stop(); 520 521 } catch(Exception e) { 522 throw new RuntimeException(e); 523 } 524 525 } 526 527 private static class ClientSide { 528 529 private JMXConnector cc = null; 530 private MBeanServerConnection mbsc = null; 531 532 public static void main(String args[]) throws Exception { 533 534 // Parses parameters 535 Utils.parseDebugProperties(); 536 537 // Supported parameters list format is : "MainClass [-client <param-spec> ...] 538 // with <param-spec> either "-parami valuei" or "-parami" 539 HashMap<String, Object> clientMap = new HashMap<>() ; 540 Utils.parseClientParameters(args, CLIENT_CLASS_NAME, clientMap); 541 542 // Run test 543 ClientSide test = new ClientSide(); 544 test.run(clientMap); 545 } 546 547 public void run(Map<String, Object> args) { 548 549 System.out.println("ClientSide::run: Start"); 550 int errorCount = 0; 551 552 try { 553 // Setup client side parameters 554 HashMap<String, Object> env = new HashMap<>(); 555 556 // If needed allows all ciphering and protocols for testing purpose 557 if (System.getProperty(RMI_SSL_CLIENT_ENABLEDCIPHERSUITES) != null) { 558 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 559 } 560 561 // If needed allows all ciphering and protocols for testing purpose 562 if (System.getProperty(RMI_SSL_CLIENT_ENABLEDPROTOCOLS) != null) { 563 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 564 } 565 566 // Retrieve and set keystore and truststore config if any 567 if (args.containsKey("-keystore") && 568 args.get("-keystore") != null) { 569 SecurityTest.setKeyStoreProperties(args); 570 } 571 if (args.containsKey("-truststore") && 572 args.get("-truststore") != null) { 573 SecurityTest.setTrustStoreProperties(args); 574 } 575 576 Object value = args.get("-mapType"); 577 if ((value != null) && 578 value.equals("credentials")) { 579 String username = System.getProperty("username"); 580 String password = System.getProperty("password"); 581 Utils.debug(Utils.DEBUG_STANDARD, 582 "add \"jmx.remote.credentials\" = \"" + 583 username + "\", \"" + password + "\""); 584 env.put("jmx.remote.credentials", 585 new String[] { username , password }); 586 } 587 588 String expectedThrowable = (String) args.get("-expectedThrowable"); 589 590 String authCallCountName = "-expectedAuthenticatorCallCount"; 591 int authCallCountValue = 0; 592 if (args.containsKey(authCallCountName)) { 593 authCallCountValue = 594 (new Integer((String) args.get(authCallCountName))).intValue(); 595 } 596 597 try { 598 // Get a connection to remote mbean server 599 JMXServiceURL addr = new JMXServiceURL((String)args.get("-serviceUrl")); 600 cc = JMXConnectorFactory.connect(addr,env); 601 mbsc = cc.getMBeanServerConnection(); 602 603 // In case we should have got an exception 604 if (expectedThrowable != null) { 605 System.out.println("ClientSide::run: (ERROR) " + 606 " Connect did not fail with expected " + expectedThrowable); 607 errorCount++; 608 } else { 609 System.out.println("ClientSide::run: (OK) Connect succeed"); 610 } 611 } catch (Throwable e) { 612 Utils.printThrowable(e, true); 613 if (expectedThrowable != null) { 614 if (Utils.compareThrowable(e, expectedThrowable)) { 615 System.out.println("ClientSide::run: (OK) " + 616 "Connect failed with expected " + expectedThrowable); 617 } else { 618 System.out.println("ClientSide::run: (ERROR) Connect failed with " + 619 e.getClass() + " instead of expected " + 620 expectedThrowable); 621 errorCount++; 622 } 623 } else { 624 System.out.println("ClientSide::run: (ERROR) " + 625 "Connect failed with exception"); 626 errorCount++; 627 } 628 } 629 630 // Depending on the client state, 631 // perform some requests 632 if (mbsc != null && errorCount == 0) { 633 // Perform some little JMX requests 634 System.out.println("ClientSide::run: Start sending requests"); 635 636 doRequests(); 637 638 // In case authentication has been used we check how it did. 639 if (authCallCountValue != 0) { 640 errorCount += checkAuthenticator(mbsc, authCallCountValue); 641 } 642 } 643 } catch (Exception e) { 644 Utils.printThrowable(e, true); 645 errorCount++; 646 } finally { 647 // Terminate the JMX Client if any 648 if (cc != null) { 649 try { 650 cc.close(); 651 } catch (Exception e) { 652 Utils.printThrowable(e, true) ; 653 errorCount++; 654 } 655 } 656 } 657 658 System.out.println("ClientSide::run: Done"); 659 660 // Handle result 661 if (errorCount != 0) { 662 throw new RuntimeException(); 663 } 664 } 665 666 private void doRequests() throws Exception { 667 668 // Send some requests to the remote JMX server 669 ObjectName objName1 = 670 new ObjectName("TestDomain:class=MBS_Light,rank=1"); 671 String mbeanClass = "MBS_Light"; 672 Exception exception = new Exception("MY TEST EXCEPTION"); 673 Attribute attException = new Attribute("AnException", exception); 674 Error error = new Error("MY TEST ERROR"); 675 Attribute attError = new Attribute("AnError", error); 676 String opParamString = "TOTORO"; 677 RjmxMBeanParameter opParam = new RjmxMBeanParameter(opParamString); 678 Object[] params1 = {opParamString}; 679 String[] sig1 = {"java.lang.String"}; 680 Object[] params2 = {opParam}; 681 String[] sig2 = {"RjmxMBeanParameter"}; 682 683 // Create and register the MBean 684 Utils.debug(Utils.DEBUG_STANDARD, 685 "ClientSide::doRequests: Create and register the MBean"); 686 mbsc.createMBean(mbeanClass, objName1); 687 if (!mbsc.isRegistered(objName1)) { 688 throw new Exception("Unable to register an MBean"); 689 } 690 691 // Set attributes of the MBean 692 Utils.debug(Utils.DEBUG_STANDARD, 693 "ClientSide::doRequests: Set attributes of the MBean"); 694 mbsc.setAttribute(objName1, attException); 695 mbsc.setAttribute(objName1, attError); 696 697 // Get attributes of the MBean 698 Utils.debug(Utils.DEBUG_STANDARD, 699 "ClientSide::doRequests: Get attributes of the MBean"); 700 Exception retException = 701 (Exception) mbsc.getAttribute(objName1,"AnException"); 702 if (!retException.getMessage().equals(exception.getMessage())) { 703 System.out.println("Expected = " + exception); 704 System.out.println("Got = " + retException); 705 throw new Exception("Attribute AnException not as expected"); 706 } 707 Error retError = (Error) mbsc.getAttribute(objName1, "AnError"); 708 if (!retError.getMessage().equals(error.getMessage())) { 709 System.out.println("Expected = " + error); 710 System.out.println("Got = " + retError); 711 throw new Exception("Attribute AnError not as expected"); 712 } 713 714 // Invoke operations on the MBean 715 Utils.debug(Utils.DEBUG_STANDARD, 716 "ClientSide::doRequests: Invoke operations on the MBean"); 717 RjmxMBeanParameter res1 = 718 (RjmxMBeanParameter) mbsc.invoke(objName1, "operate1", params1, sig1); 719 if (!res1.equals(opParam)) { 720 System.out.println("Expected = " + opParam); 721 System.out.println("Got = " + res1); 722 throw new Exception("Operation operate1 behaved badly"); 723 } 724 String res2 = 725 (String) mbsc.invoke(objName1, "operate2", params2, sig2); 726 if (!res2.equals(opParamString)) { 727 System.out.println("Expected = " + opParamString); 728 System.out.println("Got = " + res2); 729 throw new Exception("Operation operate2 behaved badly"); 730 } 731 732 // Unregister the MBean 733 Utils.debug(Utils.DEBUG_STANDARD, 734 "ClientSide::doRequests: Unregister the MBean"); 735 mbsc.unregisterMBean(objName1); 736 if (mbsc.isRegistered(objName1)) { 737 throw new Exception("Unable to unregister an MBean"); 738 } 739 } 740 741 /** 742 * Make some check about the instance of TestJMXAuthenticator. 743 * The authenticator is supposed to have set some properties on 744 * a ServerDelegate MBean. 745 * We compare the number of times it has been called with the expected value. 746 * We also check the Principal that has been given to the authenticator 747 * was not null. 748 * That method is of use to authentication with the JSR 262. 749 * @param mbs 750 * @param expectedAuthenticatorCallCount 751 * @return The number of errors encountered. 752 * @throws java.lang.Exception 753 */ 754 protected int checkAuthenticator(MBeanServerConnection mbs, 755 int expectedAuthenticatorCallCount) throws Exception { 756 int errorCount = 0; 757 758 // Ensure the authenticator has been called the right number 759 // of times. 760 int callCount = 761 ((Integer) mbs.getAttribute( 762 new ObjectName(SERVER_DELEGATE_MBEAN_NAME), 763 "TestJMXAuthenticatorCallCount")).intValue(); 764 765 if (callCount == expectedAuthenticatorCallCount) { 766 System.out.println("---- OK Authenticator has been called " 767 + expectedAuthenticatorCallCount + " time"); 768 } else { 769 errorCount++; 770 System.out.println("---- ERROR Authenticator has been called " + callCount 771 + " times in place of " + expectedAuthenticatorCallCount); 772 } 773 774 // Ensure the provider has been called with 775 // a non null Principal. 776 String principalString = 777 (String) mbs.getAttribute( 778 new ObjectName(SERVER_DELEGATE_MBEAN_NAME), 779 "TestJMXAuthenticatorPrincipalString"); 780 781 if (principalString == null) { 782 errorCount++; 783 System.out.println("---- ERROR Authenticator has been called" 784 + " with a null Principal"); 785 } else { 786 if (principalString.length() > 0) { 787 System.out.println("---- OK Authenticator has been called" 788 + " with the Principal " + principalString); 789 } else { 790 errorCount++; 791 System.out.println("---- ERROR Authenticator has been called" 792 + " with an empty Principal"); 793 } 794 } 795 796 return errorCount; 797 } 798 799 } 800 801 }