1 /* 2 * Copyright (c) 2013, 2016, 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 7150256 27 * @summary Permissions Tests for the DiagnosticCommandMBean 28 * @author Frederic Parain 29 * 30 * @run main/othervm DcmdMBeanPermissionsTest 31 */ 32 33 import java.lang.management.ManagementFactory; 34 import java.lang.reflect.Constructor; 35 import java.lang.reflect.InvocationTargetException; 36 import java.lang.reflect.ReflectPermission; 37 import java.security.Permission; 38 import java.util.HashSet; 39 import java.util.Iterator; 40 import javax.management.Descriptor; 41 import javax.management.InstanceNotFoundException; 42 import javax.management.IntrospectionException; 43 import javax.management.MBeanException; 44 import javax.management.MBeanInfo; 45 import javax.management.MBeanOperationInfo; 46 import javax.management.MBeanPermission; 47 import javax.management.MBeanServer; 48 import javax.management.MalformedObjectNameException; 49 import javax.management.ObjectName; 50 import javax.management.ReflectionException; 51 import javax.management.RuntimeMBeanException; 52 53 /** 54 * 55 * @author fparain 56 */ 57 public class DcmdMBeanPermissionsTest { 58 59 private static String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME = 60 "com.sun.management:type=DiagnosticCommand"; 61 62 static public class CustomSecurityManager extends SecurityManager { 63 64 private HashSet<Permission> grantedPermissions; 65 66 public CustomSecurityManager() { 67 grantedPermissions = new HashSet<Permission>(); 68 } 69 70 public final void grantPermission(final Permission perm) { 71 grantedPermissions.add(perm); 72 } 73 74 public final void denyPermission(final Permission perm) { 75 Iterator<Permission> it = grantedPermissions.iterator(); 76 while (it.hasNext()) { 77 Permission p = it.next(); 78 if (p.equals(perm)) { 79 it.remove(); 80 } 81 } 82 } 83 84 public final void checkPermission(final Permission perm) { 85 for (Permission p : grantedPermissions) { 86 if (p.implies(perm)) { 87 return; 88 } 89 } 90 throw new SecurityException(perm.toString()); 91 } 92 }; 93 94 static Permission createPermission(String classname, String name, 95 String action) { 96 Permission permission = null; 97 try { 98 Class c = Class.forName(classname); 99 if (action == null) { 100 try { 101 Constructor constructor = c.getConstructor(String.class); 102 permission = (Permission) constructor.newInstance(name); 103 104 } catch (InstantiationException | IllegalAccessException 105 | IllegalArgumentException | InvocationTargetException 106 | NoSuchMethodException | SecurityException ex) { 107 ex.printStackTrace(); 108 throw new RuntimeException("TEST FAILED"); 109 } 110 } 111 if (permission == null) { 112 try { 113 Constructor constructor = c.getConstructor(String.class, 114 String.class); 115 permission = (Permission) constructor.newInstance( 116 name, 117 action); 118 } catch (InstantiationException | IllegalAccessException 119 | IllegalArgumentException | InvocationTargetException 120 | NoSuchMethodException | SecurityException ex) { 121 ex.printStackTrace(); 122 throw new RuntimeException("TEST FAILED"); 123 } 124 } 125 } catch (ClassNotFoundException ex) { 126 ex.printStackTrace(); 127 throw new RuntimeException("TEST FAILED"); 128 } 129 if (permission == null) { 130 throw new RuntimeException("TEST FAILED"); 131 } 132 return permission; 133 } 134 135 // return true if invokation triggered a SecurityException 136 static boolean invokeOperation(MBeanServer mbs, ObjectName on, 137 MBeanOperationInfo opInfo) { 138 try { 139 if (opInfo.getSignature().length == 0) { 140 mbs.invoke(on, opInfo.getName(), 141 new Object[0], new String[0]); 142 } else { 143 mbs.invoke(on, opInfo.getName(), 144 new Object[1], new String[]{ String[].class.getName()}); 145 } 146 } catch (SecurityException ex) { 147 ex.printStackTrace(); 148 return true; 149 } catch (RuntimeMBeanException ex) { 150 if (ex.getCause() instanceof SecurityException) { 151 //ex.printStackTrace(); 152 return true; 153 } 154 } catch (MBeanException | InstanceNotFoundException 155 | ReflectionException ex) { 156 throw new RuntimeException("TEST FAILED"); 157 } 158 return false; 159 } 160 161 static void testOperation(MBeanServer mbs, CustomSecurityManager sm, 162 ObjectName on, MBeanOperationInfo opInfo) { 163 System.out.println("Testing " + opInfo.getName()); 164 Descriptor desc = opInfo.getDescriptor(); 165 if (desc.getFieldValue("dcmd.permissionClass") == null) { 166 // No special permission required, execution should not trigger 167 // any security exception 168 if (invokeOperation(mbs, on, opInfo)) { 169 throw new RuntimeException("TEST FAILED"); 170 } 171 } else { 172 // Building the required permission 173 Permission reqPerm = createPermission( 174 (String)desc.getFieldValue("dcmd.permissionClass"), 175 (String)desc.getFieldValue("dcmd.permissionName"), 176 (String)desc.getFieldValue("dcmd.permissionAction")); 177 // Paranoid mode: check that the SecurityManager has not already 178 // been granted the permission 179 sm.denyPermission(reqPerm); 180 // A special permission is required for this operation, 181 // invoking it without the permission granted must trigger 182 // a security exception 183 if(!invokeOperation(mbs, on, opInfo)) { 184 throw new RuntimeException("TEST FAILED"); 185 } 186 // grant the permission and re-try invoking the operation 187 sm.grantPermission(reqPerm); 188 if(invokeOperation(mbs, on, opInfo)) { 189 throw new RuntimeException("TEST FAILED"); 190 } 191 // Clean up 192 sm.denyPermission(reqPerm); 193 } 194 } 195 196 public static void main(final String[] args) { 197 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 198 ObjectName on = null; 199 try { 200 on = new ObjectName(HOTSPOT_DIAGNOSTIC_MXBEAN_NAME); 201 } catch (MalformedObjectNameException ex) { 202 ex.printStackTrace(); 203 throw new RuntimeException("TEST FAILED"); 204 } 205 MBeanInfo info = null; 206 try { 207 info = mbs.getMBeanInfo(on); 208 } catch (InstanceNotFoundException | IntrospectionException 209 | ReflectionException ex) { 210 ex.printStackTrace(); 211 throw new RuntimeException("TEST FAILED"); 212 } 213 CustomSecurityManager sm = new CustomSecurityManager(); 214 System.setSecurityManager(sm); 215 // Set of permission required to run the test cleanly 216 // Some permissions are required by the MBeanServer and other 217 // platform services (RuntimePermission("createClassLoader"), 218 // ReflectPermission("suppressAccessChecks"), 219 // java.util.logging.LoggingPermission("control"), 220 // RuntimePermission("exitVM.97")). 221 // Other permissions are required by commands being invoked 222 // in the test (for instance, RuntimePermission("modifyThreadGroup") 223 // and RuntimePermission("modifyThread") are checked when 224 // runFinalization() is invoked by the gcRunFinalization command. 225 sm.grantPermission(new RuntimePermission("createClassLoader")); 226 sm.grantPermission(new ReflectPermission("suppressAccessChecks")); 227 sm.grantPermission(new java.util.logging.LoggingPermission("control", "")); 228 sm.grantPermission(new java.lang.RuntimePermission("exitVM.*")); 229 sm.grantPermission(new java.lang.RuntimePermission("modifyThreadGroup")); 230 sm.grantPermission(new java.lang.RuntimePermission("modifyThread")); 231 sm.grantPermission(new java.security.SecurityPermission("getProperty.jdk.jar.disabledAlgorithms")); 232 for(MBeanOperationInfo opInfo : info.getOperations()) { 233 Permission opPermission = new MBeanPermission(info.getClassName(), 234 opInfo.getName(), 235 on, 236 "invoke"); 237 sm.grantPermission(opPermission); 238 testOperation(mbs, sm, on, opInfo); 239 sm.denyPermission(opPermission); 240 } 241 System.out.println("TEST PASSED"); 242 } 243 }