1 /* 2 * Copyright (c) 2004, 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 5025141 27 * @summary Tests that MBeanServerFileAccessController supports 28 * principals other than JMXPrincipal. 29 * @author Luis-Miguel Alventosa 30 * @modules java.management 31 * @run clean NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean 32 * @run build NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean 33 * @run main NonJMXPrincipalsTest 34 */ 35 36 import java.io.File; 37 import java.io.Serializable; 38 import java.security.Principal; 39 import java.util.HashMap; 40 import javax.management.Attribute; 41 import javax.management.MBeanServer; 42 import javax.management.MBeanServerConnection; 43 import javax.management.MBeanServerFactory; 44 import javax.management.MBeanServerInvocationHandler; 45 import javax.management.Notification; 46 import javax.management.NotificationListener; 47 import javax.management.ObjectName; 48 import javax.management.remote.JMXAuthenticator; 49 import javax.management.remote.JMXConnector; 50 import javax.management.remote.JMXConnectorFactory; 51 import javax.management.remote.JMXConnectorServer; 52 import javax.management.remote.JMXConnectorServerFactory; 53 import javax.management.remote.JMXPrincipal; 54 import javax.management.remote.JMXServiceURL; 55 import javax.security.auth.Subject; 56 57 public class NonJMXPrincipalsTest { 58 59 private static class OtherPrincipal implements Principal, Serializable { 60 61 private String name; 62 63 public OtherPrincipal(String name) { 64 if (name == null) 65 throw new NullPointerException("illegal null input"); 66 this.name = name; 67 } 68 69 public String getName() { 70 return name; 71 } 72 73 public String toString() { 74 return("OtherPrincipal: " + name); 75 } 76 77 public boolean equals(Object o) { 78 if (o == null) 79 return false; 80 if (this == o) 81 return true; 82 if (!(o instanceof OtherPrincipal)) 83 return false; 84 OtherPrincipal that = (OtherPrincipal)o; 85 return (this.getName().equals(that.getName())); 86 } 87 88 public int hashCode() { 89 return name.hashCode(); 90 } 91 } 92 93 private static class OtherPrincipalAuthenticator 94 implements JMXAuthenticator { 95 public Subject authenticate(Object credentials) { 96 final String[] aCredentials = (String[]) credentials; 97 final String username = (String) aCredentials[0]; 98 final Subject subject = new Subject(); 99 subject.getPrincipals().add(new JMXPrincipal("dummy")); 100 subject.getPrincipals().add(new OtherPrincipal(username)); 101 return subject; 102 } 103 } 104 105 private static class NoPrincipalAuthenticator 106 implements JMXAuthenticator { 107 public Subject authenticate(Object credentials) { 108 return new Subject(); 109 } 110 } 111 112 public static void runTest(JMXAuthenticator authenticator) 113 throws Exception { 114 //------------------------------------------------------------------ 115 // SERVER 116 //------------------------------------------------------------------ 117 118 // Instantiate the MBean server 119 // 120 System.out.println("Create the MBean server"); 121 MBeanServer mbs = MBeanServerFactory.createMBeanServer(); 122 123 // Create SimpleStandard MBean 124 // 125 ObjectName mbeanName = new ObjectName("MBeans:type=SimpleStandard"); 126 System.out.println("Create SimpleStandard MBean..."); 127 mbs.createMBean("SimpleStandard", mbeanName, null, null); 128 129 // Server's environment map 130 // 131 System.out.println(">>> Initialize the server's environment map"); 132 HashMap sEnv = new HashMap(); 133 134 // Provide a JMX Authenticator 135 // 136 sEnv.put("jmx.remote.authenticator", authenticator); 137 138 // Provide the access level file used by the connector server to 139 // perform user authorization. The access level file is a properties 140 // based text file specifying username/access level pairs where 141 // access level is either "readonly" or "readwrite" access to the 142 // MBeanServer operations. This properties based access control 143 // checker has been implemented using the MBeanServerForwarder 144 // interface which wraps the real MBean server inside an access 145 // controller MBean server which performs the access control checks 146 // before forwarding the requests to the real MBean server. 147 // 148 // This property is implementation-dependent and might not be 149 // supported by all implementations of the JMX Remote API. 150 // 151 sEnv.put("jmx.remote.x.access.file", 152 System.getProperty("test.src") + 153 File.separator + 154 "access.properties"); 155 156 // Create an RMI connector server 157 // 158 System.out.println("Create an RMI connector server"); 159 JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); 160 JMXConnectorServer cs = 161 JMXConnectorServerFactory.newJMXConnectorServer(url, sEnv, mbs); 162 163 // Start the RMI connector server 164 // 165 System.out.println("Start the RMI connector server"); 166 cs.start(); 167 System.out.println("RMI connector server successfully started"); 168 System.out.println("Waiting for incoming connections..."); 169 170 //------------------------------------------------------------------ 171 // CLIENT (admin) 172 //------------------------------------------------------------------ 173 174 // Admin client environment map 175 // 176 String[] adminCreds = new String[] { "admin" , "adminPassword" }; 177 System.out.println(">>> Initialize the client environment map for" + 178 " user [" + adminCreds[0] + "] with " + 179 "password [" + adminCreds[1] + "]"); 180 HashMap adminEnv = new HashMap(); 181 adminEnv.put("jmx.remote.credentials", adminCreds); 182 183 // Create an RMI connector client and 184 // connect it to the RMI connector server 185 // 186 System.out.println("Create an RMI connector client and " + 187 "connect it to the RMI connector server"); 188 JMXConnector adminConnector = 189 JMXConnectorFactory.connect(cs.getAddress(), adminEnv); 190 191 // Get an MBeanServerConnection 192 // 193 System.out.println("Get an MBeanServerConnection"); 194 MBeanServerConnection adminConnection = 195 adminConnector.getMBeanServerConnection(); 196 197 // Get the proxy for the Simple MBean 198 // 199 SimpleStandardMBean adminProxy = (SimpleStandardMBean) 200 MBeanServerInvocationHandler.newProxyInstance( 201 adminConnection, 202 mbeanName, 203 SimpleStandardMBean.class, 204 false); 205 206 // Get State attribute 207 // 208 System.out.println("State = " + adminProxy.getState()); 209 210 // Set State attribute 211 // 212 adminProxy.setState("changed state"); 213 214 // Get State attribute 215 // 216 System.out.println("State = " + adminProxy.getState()); 217 218 // Invoke "reset" in SimpleStandard MBean 219 // 220 System.out.println("Invoke reset() in SimpleStandard MBean..."); 221 adminProxy.reset(); 222 223 // Close MBeanServer connection 224 // 225 System.out.println("Close the admin connection to the server"); 226 adminConnector.close(); 227 228 //------------------------------------------------------------------ 229 // CLIENT (user) 230 //------------------------------------------------------------------ 231 232 // User client environment map 233 // 234 String[] userCreds = new String[] { "user" , "userPassword" }; 235 System.out.println(">>> Initialize the client environment map for" + 236 " user [" + userCreds[0] + "] with " + 237 "password [" + userCreds[1] + "]"); 238 HashMap userEnv = new HashMap(); 239 userEnv.put("jmx.remote.credentials", userCreds); 240 241 // Create an RMI connector client and 242 // connect it to the RMI connector server 243 // 244 System.out.println("Create an RMI connector client and " + 245 "connect it to the RMI connector server"); 246 JMXConnector userConnector = 247 JMXConnectorFactory.connect(cs.getAddress(), userEnv); 248 249 // Get an MBeanServerConnection 250 // 251 System.out.println("Get an MBeanServerConnection"); 252 MBeanServerConnection userConnection = 253 userConnector.getMBeanServerConnection(); 254 255 // Get the proxy for the Simple MBean 256 // 257 SimpleStandardMBean userProxy = (SimpleStandardMBean) 258 MBeanServerInvocationHandler.newProxyInstance( 259 userConnection, 260 mbeanName, 261 SimpleStandardMBean.class, 262 false); 263 264 // Get State attribute 265 // 266 System.out.println("State = " + userProxy.getState()); 267 268 // Set State attribute 269 // 270 try { 271 userProxy.setState("changed state"); 272 } catch (SecurityException e) { 273 System.out.println("Got expected security exception: " + e); 274 } catch (Exception e) { 275 System.out.println("Got unexpected exception: " + e); 276 e.printStackTrace(System.out); 277 } 278 279 // Get State attribute 280 // 281 System.out.println("State = " + userProxy.getState()); 282 283 // Invoke "reset" in SimpleStandard MBean 284 // 285 try { 286 System.out.println("Invoke reset() in SimpleStandard MBean..."); 287 userProxy.reset(); 288 } catch (SecurityException e) { 289 System.out.println("Got expected security exception: " + e); 290 } catch (Exception e) { 291 System.out.println("Got unexpected exception: " + e); 292 e.printStackTrace(System.out); 293 } 294 295 // Close MBeanServer connection 296 // 297 System.out.println("Close the user connection to the server"); 298 userConnector.close(); 299 300 //------------------------------------------------------------------ 301 // SERVER 302 //------------------------------------------------------------------ 303 304 // Stop the connector server 305 // 306 System.out.println(">>> Stop the connector server"); 307 cs.stop(); 308 } 309 310 public static void main(String[] args) { 311 int errorCount = 0; 312 // Runt tests 313 // 314 System.out.println("\n>>> Run NoPrincipalAuthenticator test..."); 315 try { 316 NonJMXPrincipalsTest.runTest(new NoPrincipalAuthenticator()); 317 System.out.println("Did not get expected SecurityException"); 318 errorCount++; 319 } catch (Exception e) { 320 if (e instanceof SecurityException) { 321 System.out.println("Got expected exception: " + e); 322 } else { 323 System.out.println("Got unexpected exception: " + e); 324 errorCount++; 325 } 326 e.printStackTrace(System.out); 327 } 328 System.out.println("\n>>> Run OtherPrincipalAuthenticator test..."); 329 try { 330 NonJMXPrincipalsTest.runTest(new OtherPrincipalAuthenticator()); 331 } catch (Exception e) { 332 errorCount++; 333 System.out.println("Got unexpected exception: " + e); 334 e.printStackTrace(System.out); 335 } 336 337 if (errorCount > 0) { 338 System.out.println("\nTEST FAILED! Error count = " + errorCount); 339 System.exit(1); 340 } 341 342 System.out.println("\nTEST PASSED!"); 343 System.out.println("\nBye! Bye!"); 344 } 345 }