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