1. /*
  2. * @(#)SecureClassLoader.java 1.73 00/02/02
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.security;
  11. import java.util.Hashtable;
  12. import java.util.ArrayList;
  13. import java.net.URL;
  14. import sun.security.util.Debug;
  15. /**
  16. * This class extends ClassLoader with additional support for defining
  17. * classes with an associated code source and permissions which are
  18. * retrieved by the system policy by default.
  19. *
  20. * @version 1.73, 02/02/00
  21. * @author Li Gong
  22. * @author Roland Schemers
  23. */
  24. public class SecureClassLoader extends ClassLoader {
  25. /*
  26. * If initialization succeed this is set to true and security checks will
  27. * succeed. Otherwise the object is not initialized and the object is
  28. * useless.
  29. */
  30. private boolean initialized = false;
  31. // Hashtable that maps CodeSource to ProtectionDomain
  32. private Hashtable pdcache = new Hashtable(11);
  33. private static final Debug debug = Debug.getInstance("scl");
  34. /**
  35. * Creates a new SecureClassLoader using the specified parent
  36. * class loader for delegation.
  37. *
  38. * <p>If there is a security manager, this method first
  39. * calls the security manager's <code>checkCreateClassLoader</code>
  40. * method to ensure creation of a class loader is allowed.
  41. * <p>
  42. * @param parent the parent ClassLoader
  43. * @exception SecurityException if a security manager exists and its
  44. * <code>checkCreateClassLoader</code> method doesn't allow
  45. * creation of a class loader.
  46. * @see SecurityManager#checkCreateClassLoader
  47. */
  48. protected SecureClassLoader(ClassLoader parent) {
  49. super(parent);
  50. // this is to make the stack depth consistent with 1.1
  51. SecurityManager security = System.getSecurityManager();
  52. if (security != null) {
  53. security.checkCreateClassLoader();
  54. }
  55. initialized = true;
  56. }
  57. /**
  58. * Creates a new SecureClassLoader using the default parent class
  59. * loader for delegation.
  60. *
  61. * <p>If there is a security manager, this method first
  62. * calls the security manager's <code>checkCreateClassLoader</code>
  63. * method to ensure creation of a class loader is allowed.
  64. *
  65. * @exception SecurityException if a security manager exists and its
  66. * <code>checkCreateClassLoader</code> method doesn't allow
  67. * creation of a class loader.
  68. * @see SecurityManager#checkCreateClassLoader
  69. */
  70. protected SecureClassLoader() {
  71. super();
  72. // this is to make the stack depth consistent with 1.1
  73. SecurityManager security = System.getSecurityManager();
  74. if (security != null) {
  75. security.checkCreateClassLoader();
  76. }
  77. initialized = true;
  78. }
  79. /**
  80. * Converts an array of bytes into an instance of class Class,
  81. * with an optional CodeSource. Before the
  82. * class can be used it must be resolved.
  83. * <p>
  84. * If a non-null CodeSource is supplied and a Policy provider is installed,
  85. * Policy.getPermissions() is invoked in order to associate a
  86. * ProtectionDomain with the class being defined.
  87. * <p>
  88. * @param name the name of the class
  89. * @param b the class bytes
  90. * @param off the start offset of the class bytes
  91. * @param len the length of the class bytes
  92. * @param cs the associated CodeSource, or null if none
  93. * @return the <code>Class</code> object created from the data,
  94. * and optional CodeSource.
  95. */
  96. protected final Class defineClass(String name, byte[] b, int off, int len,
  97. CodeSource cs)
  98. {
  99. if (cs == null)
  100. return defineClass(name, b, off, len);
  101. else
  102. return defineClass(name, b, off, len, getProtectionDomain(cs));
  103. }
  104. /**
  105. * Returns the permissions for the given CodeSource object.
  106. * The default implementation of this method invokes the
  107. * java.security.Policy.getPermissions method to get the permissions
  108. * granted by the policy to the specified CodeSource.
  109. * <p>
  110. * This method is invoked by the defineClass method which takes
  111. * a CodeSource as an argument when it is constructing the
  112. * ProtectionDomain for the class being defined.
  113. * <p>
  114. * The constructed ProtectionDomain is cached by the SecureClassLoader.
  115. * The contents of the cache persist for the lifetime of the
  116. * SecureClassLoader instance. This persistence inhibits Policy.refresh()
  117. * from influencing the protection domains already in the cache for a
  118. * given CodeSource.
  119. * <p>
  120. * @param codesource the codesource.
  121. *
  122. * @return the permissions granted to the codesource.
  123. *
  124. */
  125. protected PermissionCollection getPermissions(CodeSource codesource)
  126. {
  127. check();
  128. Policy p = Policy.getPolicyNoCheck();
  129. PermissionCollection perms;
  130. if (p == null) {
  131. return null;
  132. } else {
  133. perms = p.getPermissions(codesource);
  134. }
  135. return perms;
  136. }
  137. /*
  138. * Returned cached ProtectionDomain for the specified CodeSource.
  139. */
  140. private ProtectionDomain getProtectionDomain(CodeSource cs) {
  141. if (cs == null)
  142. return null;
  143. ProtectionDomain pd = (ProtectionDomain)pdcache.get(cs);
  144. if (pd == null) {
  145. synchronized (pdcache) {
  146. pd = (ProtectionDomain)pdcache.get(cs);
  147. if (pd == null) {
  148. PermissionCollection perms = getPermissions(cs);
  149. if (debug != null) {
  150. debug.println(" getPermissions "+ cs);
  151. debug.println(" "+perms);
  152. debug.println("");
  153. }
  154. pd = new ProtectionDomain(cs, perms);
  155. if (pd != null) {
  156. pdcache.put(cs, pd);
  157. }
  158. }
  159. }
  160. }
  161. return pd;
  162. }
  163. /*
  164. * Check to make sure the class loader has been initialized.
  165. */
  166. private void check() {
  167. if (!initialized) {
  168. throw new SecurityException("ClassLoader object not initialized");
  169. }
  170. }
  171. }