001: /*
002: * @(#)ProtectionDomain.java 1.33 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.Enumeration;
031: import java.util.Vector;
032: import sun.security.util.SecurityConstants;
033:
034: /**
035: *
036: *<p>
037: * This ProtectionDomain class encapsulates the characteristics of a domain,
038: * which encloses a set of classes whose instances are granted a set
039: * of permissions when being executed on behalf of a given set of Principals.
040: * <p>
041: * A static set of permissions can be bound to a ProtectionDomain when it is
042: * constructed; such permissions are granted to the domain regardless of the
043: * Policy in force. However, to support dynamic security policies, a
044: * ProtectionDomain can also be constructed such that it is dynamically
045: * mapped to a set of permissions by the current Policy whenever a permission
046: * is checked.
047: * <p>
048: *
049: * @version 1.33, 10/10/06
050: * @author Li Gong
051: * @author Roland Schemers
052: * @author Gary Ellison
053: */
054:
055: public class ProtectionDomain {
056:
057: /* CodeSource */
058: private CodeSource codesource;
059:
060: /* ClassLoader the protection domain was consed from */
061: private ClassLoader classloader;
062:
063: /* Principals running-as within this protection domain */
064: private Principal[] principals;
065:
066: /* the rights this protection domain is granted */
067: private PermissionCollection permissions;
068:
069: /* the PermissionCollection is static (pre 1.4 constructor)
070: or dynamic (via a policy refresh) */
071: private boolean staticPermissions;
072:
073: /**
074: * Creates a new ProtectionDomain with the given CodeSource and
075: * Permissions. If the permissions object is not null, then
076: * <code>setReadOnly())</code> will be called on the passed in
077: * Permissions object. The only permissions granted to this domain
078: * are the ones specified; the current Policy will not be consulted.
079: *
080: * @param codesource the codesource associated with this domain
081: * @param permissions the permissions granted to this domain
082: */
083: public ProtectionDomain(CodeSource codesource,
084: PermissionCollection permissions) {
085: this .codesource = codesource;
086: if (permissions != null) {
087: this .permissions = permissions;
088: this .permissions.setReadOnly();
089: }
090: this .classloader = null;
091: this .principals = new Principal[0];
092: staticPermissions = true;
093: }
094:
095: /**
096: * Creates a new ProtectionDomain qualified by the given CodeSource,
097: * Permissions, ClassLoader and array of Principals. If the
098: * permissions object is not null, then <code>setReadOnly()</code>
099: * will be called on the passed in Permissions object.
100: * The permissions granted to this domain are dynamic; they include
101: * both the static permissions passed to this constructor, and any
102: * permissions granted to this domain by the current Policy at the
103: * time a permission is checked.
104: * <p>
105: * This constructor is typically used by
106: * {@link SecureClassLoader ClassLoaders}
107: * and {@link DomainCombiner DomainCombiners} which delegate to
108: * <code>Policy</code> to actively associate the permissions granted to
109: * this domain. This constructor affords the
110: * Policy provider the opportunity to augment the supplied
111: * PermissionCollection to reflect policy changes.
112: * <p>
113: *
114: * @param codesource the CodeSource associated with this domain
115: * @param permissions the permissions granted to this domain
116: * @param classloader the ClassLoader associated with this domain
117: * @param principals the array of Principals associated with this domain
118: * @see Policy#refresh
119: * @see Policy#getPermissions(ProtectionDomain)
120: * @since 1.4
121: */
122: public ProtectionDomain(CodeSource codesource,
123: PermissionCollection permissions, ClassLoader classloader,
124: Principal[] principals) {
125: this .codesource = codesource;
126: if (permissions != null) {
127: this .permissions = permissions;
128: this .permissions.setReadOnly();
129: }
130: this .classloader = classloader;
131: this .principals = (principals != null ? (Principal[]) principals
132: .clone()
133: : new Principal[0]);
134: staticPermissions = false;
135: }
136:
137: /**
138: * Returns the CodeSource of this domain.
139: * @return the CodeSource of this domain which may be null.
140: * @since 1.2
141: */
142: public final CodeSource getCodeSource() {
143: return this .codesource;
144: }
145:
146: /**
147: * Returns the ClassLoader of this domain.
148: * @return the ClassLoader of this domain which may be null.
149: *
150: * @since 1.4
151: */
152: public final ClassLoader getClassLoader() {
153: return this .classloader;
154: }
155:
156: /**
157: * Returns an array of principals for this domain.
158: * @return returns a non-null array of principals for this domain.
159: * Changes to this array will have no impact on the ProtectionDomain.
160: *
161: * @since 1.4
162: */
163: public final Principal[] getPrincipals() {
164: return (Principal[]) this .principals.clone();
165: }
166:
167: /**
168: * Returns the static permissions granted to this domain.
169: *
170: * @return the static set of permissions for this domain which may be null.
171: * @see Policy#refresh
172: * @see Policy#getPermissions(ProtectionDomain)
173: */
174: public final PermissionCollection getPermissions() {
175: return permissions;
176: }
177:
178: /**
179: * Check and see if this ProtectionDomain implies the permissions
180: * expressed in the Permission object.
181: * <p>
182: * The set of permissions evaluated is a function of whether the
183: * ProtectionDomain was constructed with a static set of permissions
184: * or it was bound to a dynamically mapped set of permissions.
185: * <p>
186: * If the ProtectionDomain was constructed to a
187: * {@link #ProtectionDomain(CodeSource, PermissionCollection)
188: * statically bound} PermissionCollection then the permission will
189: * only be checked against the PermissionCollection supplied at
190: * construction.
191: * <p>
192: * However, if the ProtectionDomain was constructed with
193: * the constructor variant which supports
194: * {@link #ProtectionDomain(CodeSource, PermissionCollection,
195: * ClassLoader, java.security.Principal[]) dynamically binding}
196: * permissions, then the permission will be checked against the
197: * combination of the PermissionCollection supplied at construction and
198: * the current Policy binding.
199: * <p>
200: *
201: * @param permission the Permission object to check.
202: *
203: * @return true if "permission" is implicit to this ProtectionDomain.
204: */
205: public boolean implies(Permission permission) {
206: if (!staticPermissions
207: && Policy.getPolicyNoCheck().implies(this , permission))
208: return true;
209: if (permissions != null)
210: return permissions.implies(permission);
211:
212: return false;
213: }
214:
215: /**
216: * Convert a ProtectionDomain to a String.
217: */
218: public String toString() {
219: String pals = "<no principals>";
220: if (principals != null && principals.length > 0) {
221: StringBuffer palBuf = new StringBuffer("(principals ");
222:
223: for (int i = 0; i < principals.length; i++) {
224: palBuf.append(principals[i].getClass().getName()
225: + " \"" + principals[i].getName() + "\"");
226: if (i < principals.length - 1)
227: palBuf.append(",\n");
228: else
229: palBuf.append(")\n");
230: }
231: pals = palBuf.toString();
232: }
233:
234: // Check if policy is set; we don't want to load
235: // the policy prematurely here
236: PermissionCollection pc = Policy.isSet() && seeAllp() ? mergePermissions()
237: : getPermissions();
238:
239: return "ProtectionDomain " + " " + codesource + "\n" + " "
240: + classloader + "\n" + " " + pals + "\n" + " " + pc
241: + "\n";
242: }
243:
244: private boolean seeAllp() {
245: SecurityManager sm = System.getSecurityManager();
246: if (sm != null) {
247: String debug = (String) java.security.AccessController
248: .doPrivileged(new sun.security.action.GetPropertyAction(
249: "java.security.debug"));
250: if (debug != null) {
251: return true;
252: }
253: try {
254: sm
255: .checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
256: } catch (SecurityException se) {
257: return false;
258: }
259: }
260:
261: return true;
262: }
263:
264: private PermissionCollection mergePermissions() {
265: if (staticPermissions)
266: return permissions;
267:
268: PermissionCollection perms = (PermissionCollection) java.security.AccessController
269: .doPrivileged(new java.security.PrivilegedAction() {
270: public Object run() {
271: Policy p = Policy.getPolicyNoCheck();
272: return p.getPermissions(ProtectionDomain.this );
273: }
274: });
275:
276: Permissions mergedPerms = new Permissions();
277: int swag = 32;
278: int vcap = 8;
279: Enumeration e;
280: Vector pdVector = new Vector(vcap);
281: Vector plVector = new Vector(swag);
282:
283: //
284: // Build a vector of domain permissions for subsequent merge
285: if (permissions != null) {
286: e = permissions.elements();
287: while (e.hasMoreElements()) {
288: Permission p = (Permission) e.nextElement();
289: pdVector.add(p);
290: }
291: }
292:
293: //
294: // Build a vector of Policy permissions for subsequent merge
295: if (perms != null) {
296: e = perms.elements();
297: while (e.hasMoreElements()) {
298: plVector.add(e.nextElement());
299: vcap++;
300: }
301: }
302:
303: if (perms != null && permissions != null) {
304: //
305: // Weed out the duplicates from the policy. Unless a refresh
306: // has occured since the pd was consed this should result in
307: // an empty vector.
308: e = permissions.elements(); // domain vs policy
309: while (e.hasMoreElements()) {
310: Permission pdp = (Permission) e.nextElement();
311: for (int i = 0; i < plVector.size(); i++) {
312: Permission pp = (Permission) plVector.elementAt(i);
313: if (pdp.getClass().isInstance(pp)) {
314: // The equals() method on some permissions
315: // have some side effects so this manual
316: // comparison is sufficient.
317: if (pdp.getName().equals(pp.getName())
318: && pdp.getActions().equals(
319: pp.getActions())) {
320: plVector.remove(i);
321: break;
322: }
323: }
324: }
325: }
326: }
327:
328: if (perms != null) {
329: // the order of adding to merged perms and permissions
330: // needs to preserve the bugfix 4301064
331:
332: for (int i = plVector.size() - 1; i >= 0; i--) {
333: mergedPerms.add((Permission) plVector.elementAt(i));
334: }
335: }
336: if (permissions != null) {
337: for (int i = pdVector.size() - 1; i >= 0; i--) {
338: mergedPerms.add((Permission) pdVector.elementAt(i));
339: }
340: }
341:
342: return mergedPerms;
343: }
344:
345: }
|