1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
32 import sun.security.jca.GetInstance;
33 import sun.security.util.Debug;
34 import sun.security.util.SecurityConstants;
35
36
37 /**
38 * A Policy object is responsible for determining whether code executing
39 * in the Java runtime environment has permission to perform a
40 * security-sensitive operation.
41 *
42 * <p> There is only one Policy object installed in the runtime at any
43 * given time. A Policy object can be installed by calling the
44 * {@code setPolicy} method. The installed Policy object can be
45 * obtained by calling the {@code getPolicy} method.
46 *
47 * <p> If no Policy object has been installed in the runtime, a call to
48 * {@code getPolicy} installs an instance of the default Policy
49 * implementation (a default subclass implementation of this abstract class).
50 * The default Policy implementation can be changed by setting the value
51 * of the {@code policy.provider} security property to the fully qualified
52 * name of the desired Policy subclass implementation.
53 *
54 * <p> Application code can directly subclass Policy to provide a custom
55 * implementation. In addition, an instance of a Policy object can be
56 * constructed by invoking one of the {@code getInstance} factory methods
57 * with a standard type. The default policy type is "JavaPolicy".
58 *
59 * <p> Once a Policy instance has been installed (either by default, or by
60 * calling {@code setPolicy}), the Java runtime invokes its
61 * {@code implies} method when it needs to
62 * determine whether executing code (encapsulated in a ProtectionDomain)
63 * can perform SecurityManager-protected operations. How a Policy object
64 * 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 to
69 * 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 configuration
72 * policy files. If a refresh operation is not supported, this method does
94
95 // Information about the system-wide policy.
96 private static class PolicyInfo {
97 // the system-wide policy
98 final Policy policy;
99 // a flag indicating if the system-wide policy has been initialized
100 final boolean initialized;
101
102 PolicyInfo(Policy policy, boolean initialized) {
103 this.policy = policy;
104 this.initialized = initialized;
105 }
106 }
107
108 // PolicyInfo is stored in an AtomicReference
109 private static AtomicReference<PolicyInfo> policy =
110 new AtomicReference<>(new PolicyInfo(null, false));
111
112 private static final Debug debug = Debug.getInstance("policy");
113
114 // Cache mapping ProtectionDomain.Key to PermissionCollection
115 private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping;
116
117 /** package private for AccessControlContext and ProtectionDomain */
118 static boolean isSet()
119 {
120 PolicyInfo pi = policy.get();
121 return pi.policy != null && pi.initialized == true;
122 }
123
124 private static void checkPermission(String type) {
125 SecurityManager sm = System.getSecurityManager();
126 if (sm != null) {
127 sm.checkPermission(new SecurityPermission("createPolicy." + type));
128 }
129 }
130
131 /**
132 * Returns the installed Policy object. This value should not be cached,
133 * as it may be changed by a call to {@code setPolicy}.
152 if (sm != null)
153 sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
154 return getPolicyNoCheck();
155 }
156
157 /**
158 * Returns the installed Policy object, skipping the security check.
159 * Used by ProtectionDomain and getPolicy.
160 *
161 * @return the installed Policy.
162 */
163 static Policy getPolicyNoCheck()
164 {
165 PolicyInfo pi = policy.get();
166 // Use double-check idiom to avoid locking if system-wide policy is
167 // already initialized
168 if (pi.initialized == false || pi.policy == null) {
169 synchronized (Policy.class) {
170 PolicyInfo pinfo = policy.get();
171 if (pinfo.policy == null) {
172 String policy_class = AccessController.doPrivileged(
173 new PrivilegedAction<String>() {
174 public String run() {
175 return Security.getProperty("policy.provider");
176 }
177 });
178 if (policy_class == null) {
179 policy_class = "sun.security.provider.PolicyFile";
180 }
181
182 try {
183 pinfo = new PolicyInfo(
184 (Policy) Class.forName(policy_class).newInstance(),
185 true);
186 } catch (Exception e) {
187 /*
188 * The policy_class seems to be an extension
189 * so we have to bootstrap loading it via a policy
190 * provider that is on the bootclasspath.
191 * If it loads then shift gears to using the configured
192 * provider.
193 */
194
195 // install the bootstrap provider to avoid recursion
196 Policy polFile = new sun.security.provider.PolicyFile();
197 pinfo = new PolicyInfo(polFile, false);
198 policy.set(pinfo);
199
200 final String pc = policy_class;
201 Policy pol = AccessController.doPrivileged(
202 new PrivilegedAction<Policy>() {
203 public Policy run() {
204 try {
205 ClassLoader cl =
206 ClassLoader.getSystemClassLoader();
207 // we want the extension loader
208 ClassLoader extcl = null;
209 while (cl != null) {
210 extcl = cl;
211 cl = cl.getParent();
212 }
213 return (extcl != null ? (Policy)Class.forName(
214 pc, true, extcl).newInstance() : null);
215 } catch (Exception e) {
216 if (debug != null) {
217 debug.println("policy provider " +
218 pc +
219 " not available");
220 e.printStackTrace();
221 }
222 return null;
223 }
224 }
225 });
226 /*
227 * if it loaded install it as the policy provider. Otherwise
228 * continue to use the system default implementation
229 */
230 if (pol != null) {
231 pinfo = new PolicyInfo(pol, true);
232 } else {
233 if (debug != null) {
234 debug.println("using sun.security.provider.PolicyFile");
235 }
236 pinfo = new PolicyInfo(polFile, true);
237 }
238 }
239 policy.set(pinfo);
240 }
241 return pinfo.policy;
242 }
243 }
244 return pi.policy;
245 }
246
247 /**
248 * Sets the system-wide Policy object. This method first calls
249 * {@code SecurityManager.checkPermission} with a
250 * {@code SecurityPermission("setPolicy")}
251 * permission to ensure it's ok to set the Policy.
252 *
253 * @param p the new system Policy object.
254 *
255 * @throws SecurityException
256 * if a security manager exists and its
257 * {@code checkPermission} method doesn't allow
258 * setting the Policy.
259 *
260 * @see SecurityManager#checkPermission(Permission)
261 * @see #getPolicy()
262 *
263 */
264 public static void setPolicy(Policy p)
|
1 /*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
32 import sun.security.jca.GetInstance;
33 import sun.security.util.Debug;
34 import sun.security.util.SecurityConstants;
35
36
37 /**
38 * A Policy object is responsible for determining whether code executing
39 * in the Java runtime environment has permission to perform a
40 * security-sensitive operation.
41 *
42 * <p> There is only one Policy object installed in the runtime at any
43 * given time. A Policy object can be installed by calling the
44 * {@code setPolicy} method. The installed Policy object can be
45 * obtained by calling the {@code getPolicy} method.
46 *
47 * <p> If no Policy object has been installed in the runtime, a call to
48 * {@code getPolicy} installs an instance of the default Policy
49 * implementation (a default subclass implementation of this abstract class).
50 * The default Policy implementation can be changed by setting the value
51 * of the {@code policy.provider} security property to the fully qualified
52 * name of the desired Policy subclass implementation. The system class loader
53 * is used to load this class.
54 *
55 * <p> Application code can directly subclass Policy to provide a custom
56 * implementation. In addition, an instance of a Policy object can be
57 * constructed by invoking one of the {@code getInstance} factory methods
58 * with a standard type. The default policy type is "JavaPolicy".
59 *
60 * <p> Once a Policy instance has been installed (either by default, or by
61 * calling {@code setPolicy}), the Java runtime invokes its
62 * {@code implies} method when it needs to
63 * determine whether executing code (encapsulated in a ProtectionDomain)
64 * can perform SecurityManager-protected operations. How a Policy object
65 * retrieves its policy data is up to the Policy implementation itself.
66 * The policy data may be stored, for example, in a flat ASCII file,
67 * in a serialized binary file of the Policy class, or in a database.
68 *
69 * <p> The {@code refresh} method causes the policy object to
70 * refresh/reload its data. This operation is implementation-dependent.
71 * For example, if the policy object stores its data in configuration files,
72 * calling {@code refresh} will cause it to re-read the configuration
73 * policy files. If a refresh operation is not supported, this method does
95
96 // Information about the system-wide policy.
97 private static class PolicyInfo {
98 // the system-wide policy
99 final Policy policy;
100 // a flag indicating if the system-wide policy has been initialized
101 final boolean initialized;
102
103 PolicyInfo(Policy policy, boolean initialized) {
104 this.policy = policy;
105 this.initialized = initialized;
106 }
107 }
108
109 // PolicyInfo is stored in an AtomicReference
110 private static AtomicReference<PolicyInfo> policy =
111 new AtomicReference<>(new PolicyInfo(null, false));
112
113 private static final Debug debug = Debug.getInstance("policy");
114
115 // Default policy provider
116 private static final String DEFAULT_POLICY =
117 "sun.security.provider.PolicyFile";
118
119 // Cache mapping ProtectionDomain.Key to PermissionCollection
120 private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping;
121
122 /** package private for AccessControlContext and ProtectionDomain */
123 static boolean isSet()
124 {
125 PolicyInfo pi = policy.get();
126 return pi.policy != null && pi.initialized == true;
127 }
128
129 private static void checkPermission(String type) {
130 SecurityManager sm = System.getSecurityManager();
131 if (sm != null) {
132 sm.checkPermission(new SecurityPermission("createPolicy." + type));
133 }
134 }
135
136 /**
137 * Returns the installed Policy object. This value should not be cached,
138 * as it may be changed by a call to {@code setPolicy}.
157 if (sm != null)
158 sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
159 return getPolicyNoCheck();
160 }
161
162 /**
163 * Returns the installed Policy object, skipping the security check.
164 * Used by ProtectionDomain and getPolicy.
165 *
166 * @return the installed Policy.
167 */
168 static Policy getPolicyNoCheck()
169 {
170 PolicyInfo pi = policy.get();
171 // Use double-check idiom to avoid locking if system-wide policy is
172 // already initialized
173 if (pi.initialized == false || pi.policy == null) {
174 synchronized (Policy.class) {
175 PolicyInfo pinfo = policy.get();
176 if (pinfo.policy == null) {
177 return loadPolicyProvider();
178 }
179 return pinfo.policy;
180 }
181 }
182 return pi.policy;
183 }
184
185 /**
186 * Loads and instantiates a Policy implementation specified by the
187 * policy.provider security property. Note that this method should only
188 * be called by getPolicyNoCheck and from within a synchronized block with
189 * an intrinsic lock on the Policy.class.
190 */
191 private static Policy loadPolicyProvider() {
192 String policyProvider =
193 AccessController.doPrivileged((PrivilegedAction<String>)
194 () -> Security.getProperty("policy.provider"));
195
196 /*
197 * If policy.provider is not set or is set to the default provider,
198 * simply instantiate it and return.
199 */
200 if (policyProvider == null || policyProvider.isEmpty() ||
201 policyProvider.equals(DEFAULT_POLICY))
202 {
203 Policy polFile = new sun.security.provider.PolicyFile();
204 policy.set(new PolicyInfo(polFile, true));
205 return polFile;
206 }
207
208 /*
209 * Locate, load, and instantiate the policy.provider impl using
210 * the system class loader. While doing so, install the bootstrap
211 * provider to avoid potential recursion.
212 */
213 Policy polFile = new sun.security.provider.PolicyFile();
214 policy.set(new PolicyInfo(polFile, false));
215
216 Policy pol = null;
217 try {
218 pol = AccessController.doPrivileged(
219 (PrivilegedExceptionAction<Policy>) () ->
220 {
221 ClassLoader scl = ClassLoader.getSystemClassLoader();
222 Class<?> c = Class.forName(policyProvider, true, scl);
223 return (Policy)c.newInstance();
224 });
225 } catch (Exception e) {
226 if (debug != null) {
227 debug.println("policy provider " + policyProvider +
228 " not available");
229 e.printStackTrace();
230 }
231 }
232 if (pol == null) {
233 // Fallback and use the system default implementation
234 if (debug != null) {
235 debug.println("using " + DEFAULT_POLICY);
236 }
237 pol = polFile;
238 }
239 policy.set(new PolicyInfo(pol, true));
240 return pol;
241 }
242
243 /**
244 * Sets the system-wide Policy object. This method first calls
245 * {@code SecurityManager.checkPermission} with a
246 * {@code SecurityPermission("setPolicy")}
247 * permission to ensure it's ok to set the Policy.
248 *
249 * @param p the new system Policy object.
250 *
251 * @throws SecurityException
252 * if a security manager exists and its
253 * {@code checkPermission} method doesn't allow
254 * setting the Policy.
255 *
256 * @see SecurityManager#checkPermission(Permission)
257 * @see #getPolicy()
258 *
259 */
260 public static void setPolicy(Policy p)
|