001: /*
002: * @(#)SecureClassLoader.java 1.80 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.security;
029:
030: import java.util.HashMap;
031: import java.util.ArrayList;
032: import java.net.URL;
033:
034: import sun.security.util.Debug;
035:
036: /**
037: * This class extends ClassLoader with additional support for defining
038: * classes with an associated code source and permissions which are
039: * retrieved by the system policy by default.
040: *
041: * @version 1.73, 02/02/00
042: * @author Li Gong
043: * @author Roland Schemers
044: */
045: public class SecureClassLoader extends ClassLoader {
046: /*
047: * If initialization succeed this is set to true and security checks will
048: * succeed. Otherwise the object is not initialized and the object is
049: * useless.
050: */
051: private boolean initialized = false;
052:
053: // HashMap that maps CodeSource to ProtectionDomain
054: private HashMap pdcache = new HashMap(11);
055:
056: private static final Debug debug = Debug.getInstance("scl");
057:
058: /**
059: * Creates a new SecureClassLoader using the specified parent
060: * class loader for delegation.
061: *
062: * <p>If there is a security manager, this method first
063: * calls the security manager's <code>checkCreateClassLoader</code>
064: * method to ensure creation of a class loader is allowed.
065: * <p>
066: * @param parent the parent ClassLoader
067: * @exception SecurityException if a security manager exists and its
068: * <code>checkCreateClassLoader</code> method doesn't allow
069: * creation of a class loader.
070: * @see SecurityManager#checkCreateClassLoader
071: */
072: protected SecureClassLoader(ClassLoader parent) {
073: super (parent);
074: // this is to make the stack depth consistent with 1.1
075: SecurityManager security = System.getSecurityManager();
076: if (security != null) {
077: security.checkCreateClassLoader();
078: }
079: initialized = true;
080: }
081:
082: /**
083: * Creates a new SecureClassLoader using the default parent class
084: * loader for delegation.
085: *
086: * <p>If there is a security manager, this method first
087: * calls the security manager's <code>checkCreateClassLoader</code>
088: * method to ensure creation of a class loader is allowed.
089: *
090: * @exception SecurityException if a security manager exists and its
091: * <code>checkCreateClassLoader</code> method doesn't allow
092: * creation of a class loader.
093: * @see SecurityManager#checkCreateClassLoader
094: */
095: protected SecureClassLoader() {
096: super ();
097: // this is to make the stack depth consistent with 1.1
098: SecurityManager security = System.getSecurityManager();
099: if (security != null) {
100: security.checkCreateClassLoader();
101: }
102: initialized = true;
103: }
104:
105: /**
106: * Converts an array of bytes into an instance of class Class,
107: * with an optional CodeSource. Before the
108: * class can be used it must be resolved.
109: * <p>
110: * If a non-null CodeSource is supplied a ProtectionDomain is
111: * constructed and associated with the class being defined.
112: * <p>
113: * @param name the expected name of the class, or <code>null</code>
114: * if not known, using '.' and not '/' as the separator
115: * and without a trailing ".class" suffix.
116: * @param b the bytes that make up the class data. The bytes in
117: * positions <code>off</code> through <code>off+len-1</code>
118: * should have the format of a valid class file as defined
119: * by the
120: * <a href="http://java.sun.com/docs/books/vmspec/">Java
121: * Virtual Machine Specification</a>.
122: * @param off the start offset in <code>b</code> of the class data
123: * @param len the length of the class data
124: * @param cs the associated CodeSource, or <code>null</code> if none
125: * @return the <code>Class</code> object created from the data,
126: * and optional CodeSource.
127: * @exception ClassFormatError if the data did not contain a valid class
128: * @exception IndexOutOfBoundsException if either <code>off</code> or
129: * <code>len</code> is negative, or if
130: * <code>off+len</code> is greater than <code>b.length</code>.
131: *
132: * @exception SecurityException if an attempt is made to add this class
133: * to a package that contains classes that were signed by
134: * a different set of certificates than this class, or if
135: * the class name begins with "java.".
136: */
137: protected final Class defineClass(String name, byte[] b, int off,
138: int len, CodeSource cs) {
139: if (cs == null)
140: return defineClass(name, b, off, len);
141: else
142: return defineClass(name, b, off, len,
143: getProtectionDomain(cs));
144: }
145:
146: /**
147: * Returns the permissions for the given CodeSource object.
148: * <p>
149: * This method is invoked by the defineClass method which takes
150: * a CodeSource as an argument when it is constructing the
151: * ProtectionDomain for the class being defined.
152: * <p>
153: * @param codesource the codesource.
154: *
155: * @return the permissions granted to the codesource.
156: *
157: */
158: protected PermissionCollection getPermissions(CodeSource codesource) {
159: check();
160: return new Permissions(); // ProtectionDomain defers the binding
161: }
162:
163: /*
164: * Returned cached ProtectionDomain for the specified CodeSource.
165: */
166: private ProtectionDomain getProtectionDomain(CodeSource cs) {
167: if (cs == null)
168: return null;
169:
170: ProtectionDomain pd = null;
171: synchronized (pdcache) {
172: pd = (ProtectionDomain) pdcache.get(cs);
173: if (pd == null) {
174: PermissionCollection perms = getPermissions(cs);
175: pd = new ProtectionDomain(cs, perms, this , null);
176: if (pd != null) {
177: pdcache.put(cs, pd);
178: if (debug != null) {
179: debug.println(" getPermissions " + pd);
180: debug.println("");
181: }
182: }
183: }
184: }
185: return pd;
186: }
187:
188: /*
189: * Check to make sure the class loader has been initialized.
190: */
191: private void check() {
192: if (!initialized) {
193: throw new SecurityException(
194: "ClassLoader object not initialized");
195: }
196: }
197:
198: }
|