jdk/src/java.base/share/classes/java/security/ProtectionDomain.java
Shawn M Emery 7da274ded4 8361961: Typo in ProtectionDomain.implies
Reviewed-by: mullan, jpai, hchao
2025-07-18 10:02:25 +00:00

279 lines
10 KiB
Java

/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.security;
/**
* The {@code ProtectionDomain} class encapsulates the characteristics of a
* domain, which encloses a set of classes whose instances are granted a set
* of permissions.
* <p>
* A static set of permissions can be bound to a {@code ProtectionDomain}
* when it is constructed; such permissions are granted to the domain
* regardless of the policy in force. However, to support dynamic security
* policies, a {@code ProtectionDomain} can also be constructed such that it
* is dynamically mapped to a set of permissions by the current policy.
*
* @apiNote Installing a system-wide {@link Policy} object is
* no longer supported. The {@linkplain Policy#getPolicy current policy}
* is always a {@code Policy} object that grants no permissions.
*
* @author Li Gong
* @author Roland Schemers
* @author Gary Ellison
* @since 1.2
*/
public class ProtectionDomain {
/* CodeSource */
private final CodeSource codesource ;
/* ClassLoader the protection domain was consed from */
private final ClassLoader classloader;
/* Principals running-as within this protection domain */
private final Principal[] principals;
/* the rights this protection domain is granted */
private PermissionCollection permissions;
/* if the permissions object has AllPermission */
private boolean hasAllPerm = false;
/* the PermissionCollection is static (pre 1.4 constructor)
or dynamic (via a policy refresh) */
private final boolean staticPermissions;
/**
* Creates a new {@code ProtectionDomain} with the given {@code CodeSource}
* and permissions. If permissions is not {@code null}, then
* {@code setReadOnly()} will be called on the passed in
* permissions.
* <p>
* The permissions granted to this domain are static, i.e.
* invoking the {@link #staticPermissionsOnly()} method returns
* {@code true}.
* They contain only the ones passed to this constructor and
* the current policy will not be consulted.
*
* @apiNote Installing a system-wide {@link Policy} object is
* no longer supported. The {@linkplain Policy#getPolicy current policy}
* is always a {@code Policy} object that grants no permissions.
*
* @param codesource the codesource associated with this domain
* @param permissions the permissions granted to this domain
*/
public ProtectionDomain(CodeSource codesource,
PermissionCollection permissions) {
this.codesource = codesource;
if (permissions != null) {
this.permissions = permissions;
this.permissions.setReadOnly();
if (permissions instanceof Permissions &&
((Permissions)permissions).allPermission != null) {
hasAllPerm = true;
}
}
this.classloader = null;
this.principals = new Principal[0];
staticPermissions = true;
}
/**
* Creates a new {@code ProtectionDomain} qualified by the given
* {@code CodeSource}, permissions, {@code ClassLoader} and array
* of principals. If permissions is not {@code null}, then
* {@code setReadOnly()} will be called on the passed in permissions.
* <p>
* The permissions granted to this domain are dynamic, i.e.
* invoking the {@link #staticPermissionsOnly()} method returns
* {@code false}.
* They include both the static permissions passed to this constructor,
* and any permissions granted to this domain by the current policy.
*
* @apiNote Installing a system-wide {@link Policy} object is
* no longer supported. The {@linkplain Policy#getPolicy current policy}
* is always a {@code Policy} object that grants no permissions.
*
* @param codesource the {@code CodeSource} associated with this domain
* @param permissions the permissions granted to this domain
* @param classloader the {@code ClassLoader} associated with this domain
* @param principals the array of {@code Principal} objects associated
* with this domain. The contents of the array are copied to protect against
* subsequent modification.
* @see Policy#getPermissions(ProtectionDomain)
* @since 1.4
*/
public ProtectionDomain(CodeSource codesource,
PermissionCollection permissions,
ClassLoader classloader,
Principal[] principals) {
this.codesource = codesource;
if (permissions != null) {
this.permissions = permissions;
this.permissions.setReadOnly();
if (permissions instanceof Permissions &&
((Permissions)permissions).allPermission != null) {
hasAllPerm = true;
}
}
this.classloader = classloader;
this.principals = (principals != null ? principals.clone():
new Principal[0]);
staticPermissions = false;
}
/**
* Returns the {@code CodeSource} of this domain.
* @return the {@code CodeSource} of this domain which may be {@code null}.
* @since 1.2
*/
public final CodeSource getCodeSource() {
return this.codesource;
}
/**
* Returns the {@code ClassLoader} of this domain.
* @return the {@code ClassLoader} of this domain which may be {@code null}.
*
* @since 1.4
*/
public final ClassLoader getClassLoader() {
return this.classloader;
}
/**
* Returns an array of principals for this domain.
* @return a non-null array of principals for this domain.
* Returns a new array each time this method is called.
*
* @since 1.4
*/
public final Principal[] getPrincipals() {
return this.principals.clone();
}
/**
* Returns the static permissions granted to this domain.
*
* @return the static set of permissions for this domain which may be
* {@code null}.
* @see Policy#refresh
* @see Policy#getPermissions(ProtectionDomain)
*/
public final PermissionCollection getPermissions() {
return permissions;
}
/**
* Returns {@code true} if this domain contains only static permissions
* and does not check the current {@code Policy}.
*
* @apiNote Installing a system-wide {@link Policy} object is
* no longer supported. The {@linkplain Policy#getPolicy current policy}
* is always a {@code Policy} object that grants no permissions.
*
* @return {@code true} if this domain contains only static permissions.
*
* @since 9
*/
public final boolean staticPermissionsOnly() {
return this.staticPermissions;
}
/**
* Check and see if this {@code ProtectionDomain} implies the permissions
* expressed in the {@code Permission} object.
* <p>
* The set of permissions evaluated is a function of whether the
* {@code ProtectionDomain} was constructed with a static set of permissions
* or it was bound to a dynamically mapped set of permissions.
* <p>
* If the {@link #staticPermissionsOnly()} method returns
* {@code true}, then the permission will only be checked against the
* {@code PermissionCollection} supplied at construction.
* <p>
* Otherwise, the permission will be checked against the combination
* of the {@code PermissionCollection} supplied at construction and
* the current policy.
*
* @apiNote Installing a system-wide {@link Policy} object is
* no longer supported. The {@linkplain Policy#getPolicy current policy}
* is always a {@code Policy} object that grants no permissions.
*
* @param perm the {@code Permission} object to check.
*
* @return {@code true} if {@code perm} is implied by this
* {@code ProtectionDomain}.
*/
@SuppressWarnings("removal")
public boolean implies(Permission perm) {
if (hasAllPerm) {
// internal permission collection already has AllPermission -
// no need to go to policy
return true;
}
if (!staticPermissions &&
Policy.getPolicy().implies(this, perm)) {
return true;
}
if (permissions != null) {
return permissions.implies(perm);
}
return false;
}
/**
* Convert a {@code ProtectionDomain} to a {@code String}.
*/
@Override public String toString() {
String pals = "<no principals>";
if (principals != null && principals.length > 0) {
StringBuilder palBuf = new StringBuilder("(principals ");
for (int i = 0; i < principals.length; i++) {
palBuf.append(principals[i].getClass().getName() +
" \"" + principals[i].getName() +
"\"");
if (i < principals.length-1)
palBuf.append(",\n");
else
palBuf.append(")\n");
}
pals = palBuf.toString();
}
return "ProtectionDomain "+
" "+codesource+"\n"+
" "+classloader+"\n"+
" "+pals+"\n"+
" "+permissions+"\n";
}
}