1 /* 2 * Copyright (c) 2005, 2013, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package sun.reflect.misc; 28 29 import java.lang.reflect.Member; 30 import java.lang.reflect.Method; 31 import java.lang.reflect.Modifier; 32 import java.lang.reflect.Proxy; 33 import jdk.internal.reflect.Reflection; 34 import sun.security.util.SecurityConstants; 35 36 public final class ReflectUtil { 37 38 private ReflectUtil() { 39 } 40 41 public static Class<?> forName(String name) 42 throws ClassNotFoundException { 43 checkPackageAccess(name); 44 return Class.forName(name); 45 } 46 47 /** 48 * Ensures that access to a method or field is granted and throws 49 * IllegalAccessException if not. This method is not suitable for checking 50 * access to constructors. 51 * 52 * @param currentClass the class performing the access 53 * @param memberClass the declaring class of the member being accessed 54 * @param target the target object if accessing instance field or method; 55 * or null if accessing static field or method or if target 56 * object access rights will be checked later 57 * @param modifiers the member's access modifiers 58 * @throws IllegalAccessException if access to member is denied 59 * @implNote Delegates directly to 60 * {@link Reflection#ensureMemberAccess(Class, Class, Class, int)} 61 * which should be used instead. 62 */ 63 public static void ensureMemberAccess(Class<?> currentClass, 64 Class<?> memberClass, 65 Object target, 66 int modifiers) 67 throws IllegalAccessException 68 { 69 Reflection.ensureMemberAccess(currentClass, 70 memberClass, 71 target == null ? null : target.getClass(), 72 modifiers); 73 } 74 75 /** 76 * Does a conservative approximation of member access check. Use this if 77 * you don't have an actual 'userland' caller Class/ClassLoader available. 78 * This might be more restrictive than a precise member access check where 79 * you have a caller, but should never allow a member access that is 80 * forbidden. 81 * 82 * @param m the {@code Member} about to be accessed 83 */ 84 public static void conservativeCheckMemberAccess(Member m) throws SecurityException{ 85 final SecurityManager sm = System.getSecurityManager(); 86 if (sm == null) 87 return; 88 89 // Check for package access on the declaring class. 90 // 91 // In addition, unless the member and the declaring class are both 92 // public check for access declared member permissions. 93 // 94 // This is done regardless of ClassLoader relations between the {@code 95 // Member m} and any potential caller. 96 97 final Class<?> declaringClass = m.getDeclaringClass(); 98 99 checkPackageAccess(declaringClass); 100 101 if (Modifier.isPublic(m.getModifiers()) && 102 Modifier.isPublic(declaringClass.getModifiers())) 103 return; 104 105 // Check for declared member access. 106 sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); 107 } 108 109 /** 110 * Checks package access on the given class. 111 * 112 * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements 113 * a non-public interface (i.e. may be in a non-restricted package), 114 * also check the package access on the proxy interfaces. 115 */ 116 public static void checkPackageAccess(Class<?> clazz) { 117 checkPackageAccess(clazz.getName()); 118 if (isNonPublicProxyClass(clazz)) { 119 checkProxyPackageAccess(clazz); 120 } 121 } 122 123 /** 124 * Checks package access on the given classname. 125 * This method is typically called when the Class instance is not 126 * available and the caller attempts to load a class on behalf 127 * the true caller (application). 128 */ 129 public static void checkPackageAccess(String name) { 130 SecurityManager s = System.getSecurityManager(); 131 if (s != null) { 132 String cname = name.replace('/', '.'); 133 if (cname.startsWith("[")) { 134 int b = cname.lastIndexOf('[') + 2; 135 if (b > 1 && b < cname.length()) { 136 cname = cname.substring(b); 137 } 138 } 139 int i = cname.lastIndexOf('.'); 140 if (i != -1) { 141 s.checkPackageAccess(cname.substring(0, i)); 142 } 143 } 144 } 145 146 public static boolean isPackageAccessible(Class<?> clazz) { 147 try { 148 checkPackageAccess(clazz); 149 } catch (SecurityException e) { 150 return false; 151 } 152 return true; 153 } 154 155 // Returns true if p is an ancestor of cl i.e. class loader 'p' can 156 // be found in the cl's delegation chain 157 private static boolean isAncestor(ClassLoader p, ClassLoader cl) { 158 ClassLoader acl = cl; 159 do { 160 acl = acl.getParent(); 161 if (p == acl) { 162 return true; 163 } 164 } while (acl != null); 165 return false; 166 } 167 168 /** 169 * Returns true if package access check is needed for reflective 170 * access from a class loader 'from' to classes or members in 171 * a class defined by class loader 'to'. This method returns true 172 * if 'from' is not the same as or an ancestor of 'to'. All code 173 * in a system domain are granted with all permission and so this 174 * method returns false if 'from' class loader is a class loader 175 * loading system classes. On the other hand, if a class loader 176 * attempts to access system domain classes, it requires package 177 * access check and this method will return true. 178 */ 179 public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { 180 if (from == null || from == to) 181 return false; 182 183 if (to == null) 184 return true; 185 186 return !isAncestor(from, to); 187 } 188 189 /** 190 * Check package access on the proxy interfaces that the given proxy class 191 * implements. 192 * 193 * @param clazz Proxy class object 194 */ 195 public static void checkProxyPackageAccess(Class<?> clazz) { 196 SecurityManager s = System.getSecurityManager(); 197 if (s != null) { 198 // check proxy interfaces if the given class is a proxy class 199 if (Proxy.isProxyClass(clazz)) { 200 for (Class<?> intf : clazz.getInterfaces()) { 201 checkPackageAccess(intf); 202 } 203 } 204 } 205 } 206 207 /** 208 * Access check on the interfaces that a proxy class implements and throw 209 * {@code SecurityException} if it accesses a restricted package from 210 * the caller's class loader. 211 * 212 * @param ccl the caller's class loader 213 * @param interfaces the list of interfaces that a proxy class implements 214 */ 215 public static void checkProxyPackageAccess(ClassLoader ccl, 216 Class<?>... interfaces) 217 { 218 SecurityManager sm = System.getSecurityManager(); 219 if (sm != null) { 220 for (Class<?> intf : interfaces) { 221 ClassLoader cl = intf.getClassLoader(); 222 if (needsPackageAccessCheck(ccl, cl)) { 223 checkPackageAccess(intf); 224 } 225 } 226 } 227 } 228 229 // Note that bytecode instrumentation tools may exclude 'sun.*' 230 // classes but not generated proxy classes and so keep it in com.sun.* 231 public static final String PROXY_PACKAGE = "com.sun.proxy"; 232 233 /** 234 * Test if the given class is a proxy class that implements 235 * non-public interface. Such proxy class may be in a non-restricted 236 * package that bypasses checkPackageAccess. 237 */ 238 public static boolean isNonPublicProxyClass(Class<?> cls) { 239 String name = cls.getName(); 240 int i = name.lastIndexOf('.'); 241 String pkg = (i != -1) ? name.substring(0, i) : ""; 242 return Proxy.isProxyClass(cls) && !pkg.startsWith(PROXY_PACKAGE); 243 } 244 245 /** 246 * Check if the given method is a method declared in the proxy interface 247 * implemented by the given proxy instance. 248 * 249 * @param proxy a proxy instance 250 * @param method an interface method dispatched to a InvocationHandler 251 * 252 * @throws IllegalArgumentException if the given proxy or method is invalid. 253 */ 254 public static void checkProxyMethod(Object proxy, Method method) { 255 // check if it is a valid proxy instance 256 if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) { 257 throw new IllegalArgumentException("Not a Proxy instance"); 258 } 259 if (Modifier.isStatic(method.getModifiers())) { 260 throw new IllegalArgumentException("Can't handle static method"); 261 } 262 263 Class<?> c = method.getDeclaringClass(); 264 if (c == Object.class) { 265 String name = method.getName(); 266 if (name.equals("hashCode") || name.equals("equals") || name.equals("toString")) { 267 return; 268 } 269 } 270 271 if (isSuperInterface(proxy.getClass(), c)) { 272 return; 273 } 274 275 // disallow any method not declared in one of the proxy interfaces 276 throw new IllegalArgumentException("Can't handle: " + method); 277 } 278 279 private static boolean isSuperInterface(Class<?> c, Class<?> intf) { 280 for (Class<?> i : c.getInterfaces()) { 281 if (i == intf) { 282 return true; 283 } 284 if (isSuperInterface(i, intf)) { 285 return true; 286 } 287 } 288 return false; 289 } 290 291 /** 292 * Checks if {@code Class cls} is a VM-anonymous class 293 * as defined by {@link jdk.internal.misc.Unsafe#defineAnonymousClass} 294 * (not to be confused with a Java Language anonymous inner class). 295 */ 296 public static boolean isVMAnonymousClass(Class<?> cls) { 297 return cls.getName().indexOf('/') > -1; 298 } 299 }