Path: blob/master/src/java.base/share/classes/java/security/Policy.java
41152 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526package java.security;2728import java.util.Enumeration;29import java.util.WeakHashMap;30import java.util.Objects;31import sun.security.jca.GetInstance;32import sun.security.util.Debug;33import sun.security.util.SecurityConstants;343536/**37* A Policy object is responsible for determining whether code executing38* in the Java runtime environment has permission to perform a39* security-sensitive operation.40*41* <p> There is only one Policy object installed in the runtime at any42* given time. A Policy object can be installed by calling the43* {@code setPolicy} method. The installed Policy object can be44* obtained by calling the {@code getPolicy} method.45*46* <p> If no Policy object has been installed in the runtime, a call to47* {@code getPolicy} installs an instance of the default Policy48* implementation (a default subclass implementation of this abstract class).49* The default Policy implementation can be changed by setting the value50* of the {@code policy.provider} security property to the fully qualified51* name of the desired Policy subclass implementation. The system class loader52* is used to load this class.53*54* <p> Application code can directly subclass Policy to provide a custom55* implementation. In addition, an instance of a Policy object can be56* constructed by invoking one of the {@code getInstance} factory methods57* with a standard type. The default policy type is "JavaPolicy".58*59* <p> Once a Policy instance has been installed (either by default, or by60* calling {@code setPolicy}), the Java runtime invokes its61* {@code implies} method when it needs to62* determine whether executing code (encapsulated in a ProtectionDomain)63* can perform SecurityManager-protected operations. How a Policy object64* retrieves its policy data is up to the Policy implementation itself.65* The policy data may be stored, for example, in a flat ASCII file,66* in a serialized binary file of the Policy class, or in a database.67*68* <p> The {@code refresh} method causes the policy object to69* refresh/reload its data. This operation is implementation-dependent.70* For example, if the policy object stores its data in configuration files,71* calling {@code refresh} will cause it to re-read the configuration72* policy files. If a refresh operation is not supported, this method does73* nothing. Note that refreshed policy may not have an effect on classes74* in a particular ProtectionDomain. This is dependent on the Policy75* provider's implementation of the {@code implies}76* method and its PermissionCollection caching strategy.77*78* @author Roland Schemers79* @author Gary Ellison80* @since 1.281* @see java.security.Provider82* @see java.security.ProtectionDomain83* @see java.security.Permission84* @see java.security.Security security properties85* @deprecated This class is only useful in conjunction with86* {@linkplain SecurityManager the Security Manager}, which is deprecated87* and subject to removal in a future release. Consequently, this class88* is also deprecated and subject to removal. There is no replacement for89* the Security Manager or this class.90*/9192@Deprecated(since="17", forRemoval=true)93public abstract class Policy {9495/**96* Constructor for subclasses to call.97*/98public Policy() {}99100/**101* A read-only empty PermissionCollection instance.102* @since 1.6103*/104public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION =105new UnsupportedEmptyCollection();106107// Information about the system-wide policy.108private static class PolicyInfo {109// the system-wide policy110final Policy policy;111// a flag indicating if the system-wide policy has been initialized112final boolean initialized;113114PolicyInfo(Policy policy, boolean initialized) {115this.policy = policy;116this.initialized = initialized;117}118}119120// PolicyInfo is volatile since we apply DCL during initialization.121// For correctness, care must be taken to read the field only once and only122// write to it after any other initialization action has taken place.123private static volatile PolicyInfo policyInfo = new PolicyInfo(null, false);124125private static final Debug debug = Debug.getInstance("policy");126127// Default policy provider128private static final String DEFAULT_POLICY =129"sun.security.provider.PolicyFile";130131// Cache mapping ProtectionDomain.Key to PermissionCollection132private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping;133134/** package private for AccessControlContext and ProtectionDomain */135static boolean isSet() {136PolicyInfo pi = policyInfo;137return pi.policy != null && pi.initialized == true;138}139140private static void checkPermission(String type) {141@SuppressWarnings("removal")142SecurityManager sm = System.getSecurityManager();143if (sm != null) {144sm.checkPermission(new SecurityPermission("createPolicy." + type));145}146}147148/**149* Returns the installed Policy object. This value should not be cached,150* as it may be changed by a call to {@code setPolicy}.151* This method first calls152* {@code SecurityManager.checkPermission} with a153* {@code SecurityPermission("getPolicy")} permission154* to ensure it's ok to get the Policy object.155*156* @return the installed Policy.157*158* @throws SecurityException159* if a security manager exists and its160* {@code checkPermission} method doesn't allow161* getting the Policy object.162*163* @see SecurityManager#checkPermission(Permission)164* @see #setPolicy(java.security.Policy)165*/166public static Policy getPolicy()167{168@SuppressWarnings("removal")169SecurityManager sm = System.getSecurityManager();170if (sm != null)171sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);172return getPolicyNoCheck();173}174175/**176* Returns the installed Policy object, skipping the security check.177* Used by ProtectionDomain and getPolicy.178*179* @return the installed Policy.180*/181static Policy getPolicyNoCheck()182{183PolicyInfo pi = policyInfo;184// Use double-check idiom to avoid locking if system-wide policy is185// already initialized186if (pi.initialized == false || pi.policy == null) {187synchronized (Policy.class) {188pi = policyInfo;189if (pi.policy == null) {190return loadPolicyProvider();191}192}193}194return pi.policy;195}196197/**198* Loads and instantiates a Policy implementation specified by the199* policy.provider security property. Note that this method should only200* be called by getPolicyNoCheck and from within a synchronized block with201* an intrinsic lock on the Policy.class.202*/203private static Policy loadPolicyProvider() {204@SuppressWarnings("removal")205String policyProvider =206AccessController.doPrivileged(new PrivilegedAction<>() {207@Override208public String run() {209return Security.getProperty("policy.provider");210}211});212213/*214* If policy.provider is not set or is set to the default provider,215* simply instantiate it and return.216*/217if (policyProvider == null || policyProvider.isEmpty() ||218policyProvider.equals(DEFAULT_POLICY))219{220Policy polFile = new sun.security.provider.PolicyFile();221policyInfo = new PolicyInfo(polFile, true);222return polFile;223}224225/*226* Locate, load, and instantiate the policy.provider impl using227* the system class loader. While doing so, install the bootstrap228* provider to avoid potential recursion.229*/230Policy polFile = new sun.security.provider.PolicyFile();231policyInfo = new PolicyInfo(polFile, false);232233@SuppressWarnings("removal")234Policy pol = AccessController.doPrivileged(new PrivilegedAction<>() {235@Override236public Policy run() {237try {238ClassLoader scl = ClassLoader.getSystemClassLoader();239@SuppressWarnings("deprecation")240Object o = Class.forName(policyProvider, true, scl).newInstance();241return (Policy)o;242} catch (Exception e) {243if (debug != null) {244debug.println("policy provider " + policyProvider +245" not available");246e.printStackTrace();247}248return null;249}250}251});252253if (pol == null) {254// Fallback and use the system default implementation255if (debug != null) {256debug.println("using " + DEFAULT_POLICY);257}258pol = polFile;259}260policyInfo = new PolicyInfo(pol, true);261return pol;262}263264/**265* Sets the system-wide Policy object. This method first calls266* {@code SecurityManager.checkPermission} with a267* {@code SecurityPermission("setPolicy")}268* permission to ensure it's ok to set the Policy.269*270* @param p the new system Policy object.271*272* @throws SecurityException273* if a security manager exists and its274* {@code checkPermission} method doesn't allow275* setting the Policy.276*277* @see SecurityManager#checkPermission(Permission)278* @see #getPolicy()279*280*/281public static void setPolicy(Policy p)282{283@SuppressWarnings("removal")284SecurityManager sm = System.getSecurityManager();285if (sm != null) sm.checkPermission(286new SecurityPermission("setPolicy"));287if (p != null) {288initPolicy(p);289}290synchronized (Policy.class) {291policyInfo = new PolicyInfo(p, p != null);292}293}294295/**296* Initialize superclass state such that a legacy provider can297* handle queries for itself.298*299* @since 1.4300*/301private static void initPolicy (final Policy p) {302/*303* A policy provider not on the bootclasspath could trigger304* security checks fulfilling a call to either Policy.implies305* or Policy.getPermissions. If this does occur the provider306* must be able to answer for it's own ProtectionDomain307* without triggering additional security checks, otherwise308* the policy implementation will end up in an infinite309* recursion.310*311* To mitigate this, the provider can collect it's own312* ProtectionDomain and associate a PermissionCollection while313* it is being installed. The currently installed policy314* provider (if there is one) will handle calls to315* Policy.implies or Policy.getPermissions during this316* process.317*318* This Policy superclass caches away the ProtectionDomain and319* statically binds permissions so that legacy Policy320* implementations will continue to function.321*/322323@SuppressWarnings("removal")324ProtectionDomain policyDomain =325AccessController.doPrivileged(new PrivilegedAction<>() {326public ProtectionDomain run() {327return p.getClass().getProtectionDomain();328}329});330331/*332* Collect the permissions granted to this protection domain333* so that the provider can be security checked while processing334* calls to Policy.implies or Policy.getPermissions.335*/336PermissionCollection policyPerms = null;337synchronized (p) {338if (p.pdMapping == null) {339p.pdMapping = new WeakHashMap<>();340}341}342343if (policyDomain.getCodeSource() != null) {344Policy pol = policyInfo.policy;345if (pol != null) {346policyPerms = pol.getPermissions(policyDomain);347}348349if (policyPerms == null) { // assume it has all350policyPerms = new Permissions();351policyPerms.add(SecurityConstants.ALL_PERMISSION);352}353354synchronized (p.pdMapping) {355// cache of pd to permissions356p.pdMapping.put(policyDomain.key, policyPerms);357}358}359return;360}361362363/**364* Returns a Policy object of the specified type.365*366* <p> This method traverses the list of registered security providers,367* starting with the most preferred Provider.368* A new Policy object encapsulating the369* PolicySpi implementation from the first370* Provider that supports the specified type is returned.371*372* <p> Note that the list of registered providers may be retrieved via373* the {@link Security#getProviders() Security.getProviders()} method.374*375* @implNote376* The JDK Reference Implementation additionally uses the377* {@code jdk.security.provider.preferred}378* {@link Security#getProperty(String) Security} property to determine379* the preferred provider order for the specified algorithm. This380* may be different than the order of providers returned by381* {@link Security#getProviders() Security.getProviders()}.382*383* @param type the specified Policy type. See the Policy section in the384* <a href=385* "{@docRoot}/../specs/security/standard-names.html#policy-types">386* Java Security Standard Algorithm Names Specification</a>387* for a list of standard Policy types.388*389* @param params parameters for the Policy, which may be null.390*391* @return the new {@code Policy} object392*393* @throws IllegalArgumentException if the specified parameters394* are not understood by the {@code PolicySpi} implementation395* from the selected {@code Provider}396*397* @throws NoSuchAlgorithmException if no {@code Provider} supports398* a {@code PolicySpi} implementation for the specified type399*400* @throws NullPointerException if {@code type} is {@code null}401*402* @throws SecurityException if the caller does not have permission403* to get a {@code Policy} instance for the specified type.404*405* @see Provider406* @since 1.6407*/408@SuppressWarnings("removal")409public static Policy getInstance(String type, Policy.Parameters params)410throws NoSuchAlgorithmException {411Objects.requireNonNull(type, "null type name");412checkPermission(type);413try {414GetInstance.Instance instance = GetInstance.getInstance("Policy",415PolicySpi.class,416type,417params);418return new PolicyDelegate((PolicySpi)instance.impl,419instance.provider,420type,421params);422} catch (NoSuchAlgorithmException nsae) {423return handleException(nsae);424}425}426427/**428* Returns a Policy object of the specified type.429*430* <p> A new Policy object encapsulating the431* PolicySpi implementation from the specified provider432* is returned. The specified provider must be registered433* in the provider list.434*435* <p> Note that the list of registered providers may be retrieved via436* the {@link Security#getProviders() Security.getProviders()} method.437*438* @param type the specified Policy type. See the Policy section in the439* <a href=440* "{@docRoot}/../specs/security/standard-names.html#policy-types">441* Java Security Standard Algorithm Names Specification</a>442* for a list of standard Policy types.443*444* @param params parameters for the Policy, which may be null.445*446* @param provider the provider.447*448* @return the new {@code Policy} object449*450* @throws IllegalArgumentException if the specified provider451* is {@code null} or empty, or if the specified parameters are452* not understood by the {@code PolicySpi} implementation from453* the specified provider454*455* @throws NoSuchAlgorithmException if the specified provider does not456* support a {@code PolicySpi} implementation for the specified457* type458*459* @throws NoSuchProviderException if the specified provider is not460* registered in the security provider list461*462* @throws NullPointerException if {@code type} is {@code null}463*464* @throws SecurityException if the caller does not have permission465* to get a {@code Policy} instance for the specified type466*467* @see Provider468* @since 1.6469*/470@SuppressWarnings("removal")471public static Policy getInstance(String type,472Policy.Parameters params,473String provider)474throws NoSuchProviderException, NoSuchAlgorithmException {475476Objects.requireNonNull(type, "null type name");477if (provider == null || provider.isEmpty()) {478throw new IllegalArgumentException("missing provider");479}480481checkPermission(type);482try {483GetInstance.Instance instance = GetInstance.getInstance("Policy",484PolicySpi.class,485type,486params,487provider);488return new PolicyDelegate((PolicySpi)instance.impl,489instance.provider,490type,491params);492} catch (NoSuchAlgorithmException nsae) {493return handleException(nsae);494}495}496497/**498* Returns a Policy object of the specified type.499*500* <p> A new Policy object encapsulating the501* PolicySpi implementation from the specified Provider502* object is returned. Note that the specified Provider object503* does not have to be registered in the provider list.504*505* @param type the specified Policy type. See the Policy section in the506* <a href=507* "{@docRoot}/../specs/security/standard-names.html#policy-types">508* Java Security Standard Algorithm Names Specification</a>509* for a list of standard Policy types.510*511* @param params parameters for the Policy, which may be null.512*513* @param provider the Provider.514*515* @return the new {@code Policy} object516*517* @throws IllegalArgumentException if the specified {@code Provider}518* is {@code null}, or if the specified parameters are not519* understood by the {@code PolicySpi} implementation from the520* specified {@code Provider}521*522* @throws NoSuchAlgorithmException if the specified {@code Provider}523* does not support a {@code PolicySpi} implementation for524* the specified type525*526* @throws NullPointerException if {@code type} is {@code null}527*528* @throws SecurityException if the caller does not have permission529* to get a {@code Policy} instance for the specified type530*531* @see Provider532* @since 1.6533*/534@SuppressWarnings("removal")535public static Policy getInstance(String type,536Policy.Parameters params,537Provider provider)538throws NoSuchAlgorithmException {539540Objects.requireNonNull(type, "null type name");541if (provider == null) {542throw new IllegalArgumentException("missing provider");543}544545checkPermission(type);546try {547GetInstance.Instance instance = GetInstance.getInstance("Policy",548PolicySpi.class,549type,550params,551provider);552return new PolicyDelegate((PolicySpi)instance.impl,553instance.provider,554type,555params);556} catch (NoSuchAlgorithmException nsae) {557return handleException(nsae);558}559}560561private static Policy handleException(NoSuchAlgorithmException nsae)562throws NoSuchAlgorithmException {563Throwable cause = nsae.getCause();564if (cause instanceof IllegalArgumentException) {565throw (IllegalArgumentException)cause;566}567throw nsae;568}569570/**571* Return the Provider of this Policy.572*573* <p> This Policy instance will only have a Provider if it574* was obtained via a call to {@code Policy.getInstance}.575* Otherwise this method returns null.576*577* @return the Provider of this Policy, or null.578*579* @since 1.6580*/581public Provider getProvider() {582return null;583}584585/**586* Return the type of this Policy.587*588* <p> This Policy instance will only have a type if it589* was obtained via a call to {@code Policy.getInstance}.590* Otherwise this method returns null.591*592* @return the type of this Policy, or null.593*594* @since 1.6595*/596public String getType() {597return null;598}599600/**601* Return Policy parameters.602*603* <p> This Policy instance will only have parameters if it604* was obtained via a call to {@code Policy.getInstance}.605* Otherwise this method returns null.606*607* @return Policy parameters, or null.608*609* @since 1.6610*/611public Policy.Parameters getParameters() {612return null;613}614615/**616* Return a PermissionCollection object containing the set of617* permissions granted to the specified CodeSource.618*619* <p> Applications are discouraged from calling this method620* since this operation may not be supported by all policy implementations.621* Applications should solely rely on the {@code implies} method622* to perform policy checks. If an application absolutely must call623* a getPermissions method, it should call624* {@code getPermissions(ProtectionDomain)}.625*626* <p> The default implementation of this method returns627* Policy.UNSUPPORTED_EMPTY_COLLECTION. This method can be628* overridden if the policy implementation can return a set of629* permissions granted to a CodeSource.630*631* @param codesource the CodeSource to which the returned632* PermissionCollection has been granted.633*634* @return a set of permissions granted to the specified CodeSource.635* If this operation is supported, the returned636* set of permissions must be a new mutable instance637* and it must support heterogeneous Permission types.638* If this operation is not supported,639* Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.640*/641public PermissionCollection getPermissions(CodeSource codesource) {642return Policy.UNSUPPORTED_EMPTY_COLLECTION;643}644645/**646* Return a PermissionCollection object containing the set of647* permissions granted to the specified ProtectionDomain.648*649* <p> Applications are discouraged from calling this method650* since this operation may not be supported by all policy implementations.651* Applications should rely on the {@code implies} method652* to perform policy checks.653*654* <p> The default implementation of this method first retrieves655* the permissions returned via {@code getPermissions(CodeSource)}656* (the CodeSource is taken from the specified ProtectionDomain),657* as well as the permissions located inside the specified ProtectionDomain.658* All of these permissions are then combined and returned in a new659* PermissionCollection object. If {@code getPermissions(CodeSource)}660* returns Policy.UNSUPPORTED_EMPTY_COLLECTION, then this method661* returns the permissions contained inside the specified ProtectionDomain662* in a new PermissionCollection object.663*664* <p> This method can be overridden if the policy implementation665* supports returning a set of permissions granted to a ProtectionDomain.666*667* @param domain the ProtectionDomain to which the returned668* PermissionCollection has been granted.669*670* @return a set of permissions granted to the specified ProtectionDomain.671* If this operation is supported, the returned672* set of permissions must be a new mutable instance673* and it must support heterogeneous Permission types.674* If this operation is not supported,675* Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.676*677* @since 1.4678*/679public PermissionCollection getPermissions(ProtectionDomain domain) {680PermissionCollection pc = null;681682if (domain == null)683return new Permissions();684685if (pdMapping == null) {686initPolicy(this);687}688689synchronized (pdMapping) {690pc = pdMapping.get(domain.key);691}692693if (pc != null) {694Permissions perms = new Permissions();695synchronized (pc) {696for (Enumeration<Permission> e = pc.elements() ; e.hasMoreElements() ;) {697perms.add(e.nextElement());698}699}700return perms;701}702703pc = getPermissions(domain.getCodeSource());704if (pc == null || pc == UNSUPPORTED_EMPTY_COLLECTION) {705pc = new Permissions();706}707708addStaticPerms(pc, domain.getPermissions());709return pc;710}711712/**713* add static permissions to provided permission collection714*/715private void addStaticPerms(PermissionCollection perms,716PermissionCollection statics) {717if (statics != null) {718synchronized (statics) {719Enumeration<Permission> e = statics.elements();720while (e.hasMoreElements()) {721perms.add(e.nextElement());722}723}724}725}726727/**728* Evaluates the global policy for the permissions granted to729* the ProtectionDomain and tests whether the permission is730* granted.731*732* @param domain the ProtectionDomain to test733* @param permission the Permission object to be tested for implication.734*735* @return true if "permission" is a proper subset of a permission736* granted to this ProtectionDomain.737*738* @see java.security.ProtectionDomain739* @since 1.4740*/741public boolean implies(ProtectionDomain domain, Permission permission) {742PermissionCollection pc;743744if (pdMapping == null) {745initPolicy(this);746}747748synchronized (pdMapping) {749pc = pdMapping.get(domain.key);750}751752if (pc != null) {753return pc.implies(permission);754}755756pc = getPermissions(domain);757if (pc == null) {758return false;759}760761synchronized (pdMapping) {762// cache it763pdMapping.put(domain.key, pc);764}765766return pc.implies(permission);767}768769/**770* Refreshes/reloads the policy configuration. The behavior of this method771* depends on the implementation. For example, calling {@code refresh}772* on a file-based policy will cause the file to be re-read.773*774* <p> The default implementation of this method does nothing.775* This method should be overridden if a refresh operation is supported776* by the policy implementation.777*/778public void refresh() { }779780/**781* This subclass is returned by the getInstance calls. All Policy calls782* are delegated to the underlying PolicySpi.783*/784private static class PolicyDelegate extends Policy {785786@SuppressWarnings("removal")787private PolicySpi spi;788private Provider p;789private String type;790private Policy.Parameters params;791792private PolicyDelegate(@SuppressWarnings("removal") PolicySpi spi, Provider p,793String type, Policy.Parameters params) {794this.spi = spi;795this.p = p;796this.type = type;797this.params = params;798}799800@Override public String getType() { return type; }801802@Override public Policy.Parameters getParameters() { return params; }803804@Override public Provider getProvider() { return p; }805806@Override807public PermissionCollection getPermissions(CodeSource codesource) {808return spi.engineGetPermissions(codesource);809}810@Override811public PermissionCollection getPermissions(ProtectionDomain domain) {812return spi.engineGetPermissions(domain);813}814@Override815public boolean implies(ProtectionDomain domain, Permission perm) {816return spi.engineImplies(domain, perm);817}818@Override819public void refresh() {820spi.engineRefresh();821}822}823824/**825* This represents a marker interface for Policy parameters.826*827* @since 1.6828* @deprecated This class is only useful in conjunction with829* {@linkplain SecurityManager the Security Manager}, which is830* deprecated and subject to removal in a future release.831* Consequently, this class is also deprecated and subject to removal.832* There is no replacement for the Security Manager or this class.833*/834@Deprecated(since="17", forRemoval=true)835public static interface Parameters { }836837/**838* This class represents a read-only empty PermissionCollection object that839* is returned from the {@code getPermissions(CodeSource)} and840* {@code getPermissions(ProtectionDomain)}841* methods in the Policy class when those operations are not842* supported by the Policy implementation.843*/844private static class UnsupportedEmptyCollection845extends PermissionCollection {846847@java.io.Serial848private static final long serialVersionUID = -8492269157353014774L;849850private Permissions perms;851852/**853* Create a read-only empty PermissionCollection object.854*/855public UnsupportedEmptyCollection() {856this.perms = new Permissions();857perms.setReadOnly();858}859860/**861* Adds a permission object to the current collection of permission862* objects.863*864* @param permission the Permission object to add.865*866* @throws SecurityException if this PermissionCollection object867* has been marked readonly868*/869@Override public void add(Permission permission) {870perms.add(permission);871}872873/**874* Checks to see if the specified permission is implied by the875* collection of Permission objects held in this PermissionCollection.876*877* @param permission the Permission object to compare.878*879* @return true if "permission" is implied by the permissions in880* the collection, false if not.881*/882@Override public boolean implies(Permission permission) {883return perms.implies(permission);884}885886/**887* Returns an enumeration of all the Permission objects in the888* collection.889*890* @return an enumeration of all the Permissions.891*/892@Override public Enumeration<Permission> elements() {893return perms.elements();894}895}896}897898899