1. /*
  2. * @(#)ProtectionDomain.java 1.41 03/01/23
  3. *
  4. * Copyright 2003 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.Enumeration;
  9. import java.util.Vector;
  10. import sun.security.util.SecurityConstants;
  11. /**
  12. *
  13. *<p>
  14. * This ProtectionDomain class encapsulates the characteristics of a domain,
  15. * which encloses a set of classes whose instances are granted a set
  16. * of permissions when being executed on behalf of a given set of Principals.
  17. * <p>
  18. * A static set of permissions can be bound to a ProtectionDomain when it is
  19. * constructed; such permissions are granted to the domain regardless of the
  20. * Policy in force. However, to support dynamic security policies, a
  21. * ProtectionDomain can also be constructed such that it is dynamically
  22. * mapped to a set of permissions by the current Policy whenever a permission
  23. * is checked.
  24. * <p>
  25. *
  26. * @version 1.41, 01/23/03
  27. * @author Li Gong
  28. * @author Roland Schemers
  29. * @author Gary Ellison
  30. */
  31. public class ProtectionDomain {
  32. /* CodeSource */
  33. private CodeSource codesource ;
  34. /* ClassLoader the protection domain was consed from */
  35. private ClassLoader classloader;
  36. /* Principals running-as within this protection domain */
  37. private Principal[] principals;
  38. /* the rights this protection domain is granted */
  39. private PermissionCollection permissions;
  40. /* the PermissionCollection is static (pre 1.4 constructor)
  41. or dynamic (via a policy refresh) */
  42. private boolean staticPermissions;
  43. /**
  44. * Creates a new ProtectionDomain with the given CodeSource and
  45. * Permissions. If the permissions object is not null, then
  46. * <code>setReadOnly())</code> will be called on the passed in
  47. * Permissions object. The only permissions granted to this domain
  48. * are the ones specified; the current Policy will not be consulted.
  49. *
  50. * @param codesource the codesource associated with this domain
  51. * @param permissions the permissions granted to this domain
  52. */
  53. public ProtectionDomain(CodeSource codesource,
  54. PermissionCollection permissions) {
  55. this.codesource = codesource;
  56. if (permissions != null) {
  57. this.permissions = permissions;
  58. this.permissions.setReadOnly();
  59. }
  60. this.classloader = null;
  61. this.principals = new Principal[0];
  62. staticPermissions = true;
  63. }
  64. /**
  65. * Creates a new ProtectionDomain qualified by the given CodeSource,
  66. * Permissions, ClassLoader and array of Principals. If the
  67. * permissions object is not null, then <code>setReadOnly()</code>
  68. * will be called on the passed in Permissions object.
  69. * The permissions granted to this domain are dynamic; they include
  70. * both the static permissions passed to this constructor, and any
  71. * permissions granted to this domain by the current Policy at the
  72. * time a permission is checked.
  73. * <p>
  74. * This constructor is typically used by
  75. * {@link SecureClassLoader ClassLoaders}
  76. * and {@link DomainCombiner DomainCombiners} which delegate to
  77. * <code>Policy</code> to actively associate the permissions granted to
  78. * this domain. This constructor affords the
  79. * Policy provider the opportunity to augment the supplied
  80. * PermissionCollection to reflect policy changes.
  81. * <p>
  82. *
  83. * @param codesource the CodeSource associated with this domain
  84. * @param permissions the permissions granted to this domain
  85. * @param classloader the ClassLoader associated with this domain
  86. * @param principals the array of Principals associated with this domain
  87. * @see Policy#refresh
  88. * @see Policy#getPermissions(ProtectionDomain)
  89. * @since 1.4
  90. */
  91. public ProtectionDomain(CodeSource codesource,
  92. PermissionCollection permissions,
  93. ClassLoader classloader,
  94. Principal[] principals) {
  95. this.codesource = codesource;
  96. if (permissions != null) {
  97. this.permissions = permissions;
  98. this.permissions.setReadOnly();
  99. }
  100. this.classloader = classloader;
  101. this.principals = (principals != null ?
  102. (Principal[])principals.clone():
  103. new Principal[0]);
  104. staticPermissions = false;
  105. }
  106. /**
  107. * Returns the CodeSource of this domain.
  108. * @return the CodeSource of this domain which may be null.
  109. * @since 1.2
  110. */
  111. public final CodeSource getCodeSource() {
  112. return this.codesource;
  113. }
  114. /**
  115. * Returns the ClassLoader of this domain.
  116. * @return the ClassLoader of this domain which may be null.
  117. *
  118. * @since 1.4
  119. */
  120. public final ClassLoader getClassLoader() {
  121. return this.classloader;
  122. }
  123. /**
  124. * Returns an array of principals for this domain.
  125. * @return returns a non-null array of principals for this domain.
  126. * Changes to this array will have no impact on the ProtectionDomain.
  127. *
  128. * @since 1.4
  129. */
  130. public final Principal[] getPrincipals() {
  131. return (Principal[])this.principals.clone();
  132. }
  133. /**
  134. * Returns the static permissions granted to this domain.
  135. *
  136. * @return the static set of permissions for this domain which may be null.
  137. * @see Policy#refresh
  138. * @see Policy#getPermissions(ProtectionDomain)
  139. */
  140. public final PermissionCollection getPermissions() {
  141. return permissions;
  142. }
  143. /**
  144. * Check and see if this ProtectionDomain implies the permissions
  145. * expressed in the Permission object.
  146. * <p>
  147. * The set of permissions evaluated is a function of whether the
  148. * ProtectionDomain was constructed with a static set of permissions
  149. * or it was bound to a dynamically mapped set of permissions.
  150. * <p>
  151. * If the ProtectionDomain was constructed to a
  152. * {@link #ProtectionDomain(CodeSource, PermissionCollection)
  153. * statically bound} PermissionCollection then the permission will
  154. * only be checked against the PermissionCollection supplied at
  155. * construction.
  156. * <p>
  157. * However, if the ProtectionDomain was constructed with
  158. * the constructor variant which supports
  159. * {@link #ProtectionDomain(CodeSource, PermissionCollection,
  160. * ClassLoader, java.security.Principal[]) dynamically binding}
  161. * permissions, then the permission will be checked against the
  162. * combination of the PermissionCollection supplied at construction and
  163. * the current Policy binding.
  164. * <p>
  165. *
  166. * @param permission the Permission object to check.
  167. *
  168. * @return true if "permission" is implicit to this ProtectionDomain.
  169. */
  170. public boolean implies(Permission permission) {
  171. if (!staticPermissions &&
  172. Policy.getPolicyNoCheck().implies(this, permission))
  173. return true;
  174. if (permissions != null)
  175. return permissions.implies(permission);
  176. return false;
  177. }
  178. /**
  179. * Convert a ProtectionDomain to a String.
  180. */
  181. public String toString() {
  182. String pals = "<no principals>";
  183. if (principals != null && principals.length > 0) {
  184. StringBuffer palBuf = new StringBuffer("(principals ");
  185. for (int i = 0; i < principals.length; i++) {
  186. palBuf.append(principals[i].getClass().getName() +
  187. " \"" + principals[i].getName() +
  188. "\"");
  189. if (i < principals.length-1)
  190. palBuf.append(",\n");
  191. else
  192. palBuf.append(")\n");
  193. }
  194. pals = palBuf.toString();
  195. }
  196. // Check if policy is set; we don't want to load
  197. // the policy prematurely here
  198. PermissionCollection pc = Policy.isSet() && seeAllp() ?
  199. mergePermissions():
  200. getPermissions();
  201. return "ProtectionDomain "+
  202. " "+codesource+"\n"+
  203. " "+classloader+"\n"+
  204. " "+pals+"\n"+
  205. " "+pc+"\n";
  206. }
  207. private boolean seeAllp() {
  208. SecurityManager sm = System.getSecurityManager();
  209. if (sm != null) {
  210. String debug =
  211. (String) java.security.AccessController.doPrivileged(
  212. new sun.security.action.GetPropertyAction("java.security.debug"));
  213. if (debug != null) {
  214. return true;
  215. }
  216. try {
  217. sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
  218. } catch (SecurityException se) {
  219. return false;
  220. }
  221. }
  222. return true;
  223. }
  224. private PermissionCollection mergePermissions() {
  225. if (staticPermissions)
  226. return permissions;
  227. PermissionCollection perms = (PermissionCollection)
  228. java.security.AccessController.doPrivileged
  229. (new java.security.PrivilegedAction() {
  230. public Object run() {
  231. Policy p = Policy.getPolicyNoCheck();
  232. return p.getPermissions(ProtectionDomain.this);
  233. }
  234. });
  235. Permissions mergedPerms = new Permissions();
  236. int swag = 32;
  237. int vcap = 8;
  238. Enumeration e;
  239. Vector pdVector = new Vector(vcap);
  240. Vector plVector = new Vector(swag);
  241. //
  242. // Build a vector of domain permissions for subsequent merge
  243. if (permissions != null) {
  244. e = permissions.elements();
  245. while (e.hasMoreElements()) {
  246. Permission p = (Permission)e.nextElement();
  247. pdVector.add(p);
  248. }
  249. }
  250. //
  251. // Build a vector of Policy permissions for subsequent merge
  252. if (perms != null) {
  253. e = perms.elements();
  254. while (e.hasMoreElements()) {
  255. plVector.add(e.nextElement());
  256. vcap++;
  257. }
  258. }
  259. if (perms != null && permissions != null) {
  260. //
  261. // Weed out the duplicates from the policy. Unless a refresh
  262. // has occured since the pd was consed this should result in
  263. // an empty vector.
  264. e = permissions.elements(); // domain vs policy
  265. while (e.hasMoreElements()) {
  266. Permission pdp = (Permission)e.nextElement();
  267. for (int i = 0; i < plVector.size(); i++) {
  268. Permission pp = (Permission) plVector.elementAt(i);
  269. if (pdp.getClass().isInstance(pp)) {
  270. // The equals() method on some permissions
  271. // have some side effects so this manual
  272. // comparison is sufficient.
  273. if (pdp.getName().equals(pp.getName()) &&
  274. pdp.getActions().equals(pp.getActions())) {
  275. plVector.remove(i);
  276. break;
  277. }
  278. }
  279. }
  280. }
  281. }
  282. if (perms !=null) {
  283. // the order of adding to merged perms and permissions
  284. // needs to preserve the bugfix 4301064
  285. for (int i = plVector.size()-1; i >= 0; i--) {
  286. mergedPerms.add((Permission)plVector.elementAt(i));
  287. }
  288. }
  289. if (permissions != null) {
  290. for (int i = pdVector.size()-1; i >= 0; i--) {
  291. mergedPerms.add((Permission)pdVector.elementAt(i));
  292. }
  293. }
  294. return mergedPerms;
  295. }
  296. }