1 /* 2 * Copyright (c) 1997, 2011, 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 package java.security; 27 28 import java.util.HashMap; 29 import java.util.ArrayList; 30 import java.net.URL; 31 32 import sun.security.util.Debug; 33 34 /** 35 * This class extends ClassLoader with additional support for defining 36 * classes with an associated code source and permissions which are 37 * retrieved by the system policy by default. 38 * 39 * @author Li Gong 40 * @author Roland Schemers 41 */ 42 public class SecureClassLoader extends ClassLoader { 43 /* 44 * If initialization succeed this is set to true and security checks will 45 * succeed. Otherwise the object is not initialized and the object is 46 * useless. 47 */ 48 private final boolean initialized; 49 50 // HashMap that maps CodeSource to ProtectionDomain 51 // @GuardedBy("pdcache") 52 private final HashMap<CodeSource, ProtectionDomain> pdcache = 53 new HashMap<>(11); 54 55 private static final Debug debug = Debug.getInstance("scl"); 56 57 static { 58 ClassLoader.registerAsParallelCapable(); 59 } 60 61 /** 62 * Creates a new SecureClassLoader using the specified parent 63 * class loader for delegation. 64 * 65 * <p>If there is a security manager, this method first 66 * calls the security manager's <code>checkCreateClassLoader</code> 67 * method to ensure creation of a class loader is allowed. 68 * <p> 69 * @param parent the parent ClassLoader 70 * @exception SecurityException if a security manager exists and its 71 * <code>checkCreateClassLoader</code> method doesn't allow 72 * creation of a class loader. 73 * @see SecurityManager#checkCreateClassLoader 74 */ 75 protected SecureClassLoader(ClassLoader parent) { 76 super(parent); 77 // this is to make the stack depth consistent with 1.1 78 SecurityManager security = System.getSecurityManager(); 79 if (security != null) { 80 security.checkCreateClassLoader(); 81 } 82 initialized = true; 83 } 84 85 /** 86 * Creates a new SecureClassLoader using the default parent class 87 * loader for delegation. 88 * 89 * <p>If there is a security manager, this method first 90 * calls the security manager's <code>checkCreateClassLoader</code> 91 * method to ensure creation of a class loader is allowed. 92 * 93 * @exception SecurityException if a security manager exists and its 94 * <code>checkCreateClassLoader</code> method doesn't allow 95 * creation of a class loader. 96 * @see SecurityManager#checkCreateClassLoader 97 */ 98 protected SecureClassLoader() { 99 super(); 100 // this is to make the stack depth consistent with 1.1 101 SecurityManager security = System.getSecurityManager(); 102 if (security != null) { 103 security.checkCreateClassLoader(); 104 } 105 initialized = true; 106 } 107 108 /** 109 * Converts an array of bytes into an instance of class Class, 110 * with an optional CodeSource. Before the 111 * class can be used it must be resolved. 112 * <p> 113 * If a non-null CodeSource is supplied a ProtectionDomain is 114 * constructed and associated with the class being defined. 115 * <p> 116 * @param name the expected name of the class, or <code>null</code> 117 * if not known, using '.' and not '/' as the separator 118 * and without a trailing ".class" suffix. 119 * @param b the bytes that make up the class data. The bytes in 120 * positions <code>off</code> through <code>off+len-1</code> 121 * should have the format of a valid class file as defined 122 * by the 123 * <a href="http://java.sun.com/docs/books/vmspec/">Java 124 * Virtual Machine Specification</a>. 125 * @param off the start offset in <code>b</code> of the class data 126 * @param len the length of the class data 127 * @param cs the associated CodeSource, or <code>null</code> if none 128 * @return the <code>Class</code> object created from the data, 129 * and optional CodeSource. 130 * @exception ClassFormatError if the data did not contain a valid class 131 * @exception IndexOutOfBoundsException if either <code>off</code> or 132 * <code>len</code> is negative, or if 133 * <code>off+len</code> is greater than <code>b.length</code>. 134 * 135 * @exception SecurityException if an attempt is made to add this class 136 * to a package that contains classes that were signed by 137 * a different set of certificates than this class, or if 138 * the class name begins with "java.". 139 */ 140 protected final Class<?> defineClass(String name, 141 byte[] b, int off, int len, 142 CodeSource cs) 143 { 144 return defineClass(name, b, off, len, getProtectionDomain(cs)); 145 } 146 147 /** 148 * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>} 149 * into an instance of class <tt>Class</tt>, with an optional CodeSource. 150 * Before the class can be used it must be resolved. 151 * <p> 152 * If a non-null CodeSource is supplied a ProtectionDomain is 153 * constructed and associated with the class being defined. 154 * <p> 155 * @param name the expected name of the class, or <code>null</code> 156 * if not known, using '.' and not '/' as the separator 157 * and without a trailing ".class" suffix. 158 * @param b the bytes that make up the class data. The bytes from positions 159 * <tt>b.position()</tt> through <tt>b.position() + b.limit() -1</tt> 160 * should have the format of a valid class file as defined by the 161 * <a href="http://java.sun.com/docs/books/vmspec/">Java Virtual 162 * Machine Specification</a>. 163 * @param cs the associated CodeSource, or <code>null</code> if none 164 * @return the <code>Class</code> object created from the data, 165 * and optional CodeSource. 166 * @exception ClassFormatError if the data did not contain a valid class 167 * @exception SecurityException if an attempt is made to add this class 168 * to a package that contains classes that were signed by 169 * a different set of certificates than this class, or if 170 * the class name begins with "java.". 171 * 172 * @since 1.5 173 */ 174 protected final Class<?> defineClass(String name, java.nio.ByteBuffer b, 175 CodeSource cs) 176 { 177 return defineClass(name, b, getProtectionDomain(cs)); 178 } 179 180 /** 181 * Returns the permissions for the given CodeSource object. 182 * <p> 183 * This method is invoked by the defineClass method which takes 184 * a CodeSource as an argument when it is constructing the 185 * ProtectionDomain for the class being defined. 186 * <p> 187 * @param codesource the codesource. 188 * 189 * @return the permissions granted to the codesource. 190 * 191 */ 192 protected PermissionCollection getPermissions(CodeSource codesource) 193 { 194 check(); 195 return new Permissions(); // ProtectionDomain defers the binding 196 } 197 198 /* 199 * Returned cached ProtectionDomain for the specified CodeSource. 200 */ 201 private ProtectionDomain getProtectionDomain(CodeSource cs) { 202 if (cs == null) 203 return null; 204 205 ProtectionDomain pd = null; 206 synchronized (pdcache) { 207 pd = pdcache.get(cs); 208 if (pd == null) { 209 PermissionCollection perms = getPermissions(cs); 210 pd = new ProtectionDomain(cs, perms, this, null); 211 pdcache.put(cs, pd); 212 if (debug != null) { 213 debug.println(" getPermissions "+ pd); 214 debug.println(""); 215 } 216 } 217 } 218 return pd; 219 } 220 221 /* 222 * Check to make sure the class loader has been initialized. 223 */ 224 private void check() { 225 if (!initialized) { 226 throw new SecurityException("ClassLoader object not initialized"); 227 } 228 } 229 230 }