Policy.java revision 11099:678faa7d1a6a
1/*
2 * Copyright (c) 1998, 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
23 * questions.
24 */
25
26package javax.security.auth;
27
28import java.security.Security;
29import java.security.AccessController;
30import java.security.PrivilegedAction;
31import java.security.PrivilegedExceptionAction;
32import java.util.Objects;
33import sun.security.util.Debug;
34
35/**
36 * <p> This is an abstract class for representing the system policy for
37 * Subject-based authorization.  A subclass implementation
38 * of this class provides a means to specify a Subject-based
39 * access control {@code Policy}.
40 *
41 * <p> A {@code Policy} object can be queried for the set of
42 * Permissions granted to code running as a
43 * {@code Principal} in the following manner:
44 *
45 * <pre>
46 *      policy = Policy.getPolicy();
47 *      PermissionCollection perms = policy.getPermissions(subject,
48 *                                                      codeSource);
49 * </pre>
50 *
51 * The {@code Policy} object consults the local policy and returns
52 * and appropriate {@code Permissions} object with the
53 * Permissions granted to the Principals associated with the
54 * provided <i>subject</i>, and granted to the code specified
55 * by the provided <i>codeSource</i>.
56 *
57 * <p> A {@code Policy} contains the following information.
58 * Note that this example only represents the syntax for the default
59 * {@code Policy} implementation. Subclass implementations of this class
60 * may implement alternative syntaxes and may retrieve the
61 * {@code Policy} from any source such as files, databases,
62 * or servers.
63 *
64 * <p> Each entry in the {@code Policy} is represented as
65 * a <b><i>grant</i></b> entry.  Each <b><i>grant</i></b> entry
66 * specifies a codebase, code signers, and Principals triplet,
67 * as well as the Permissions granted to that triplet.
68 *
69 * <pre>
70 *      grant CodeBase ["URL"], Signedby ["signers"],
71 *            Principal [Principal_Class] "Principal_Name" {
72 *          Permission Permission_Class ["Target_Name"]
73 *                                      [, "Permission_Actions"]
74 *                                      [, signedBy "SignerName"];
75 *      };
76 * </pre>
77 *
78 * The CodeBase and Signedby components of the triplet name/value pairs
79 * are optional.  If they are not present, then any codebase will match,
80 * and any signer (including unsigned code) will match.
81 * For Example,
82 *
83 * <pre>
84 *      grant CodeBase "foo.com", Signedby "foo",
85 *            Principal com.sun.security.auth.SolarisPrincipal "duke" {
86 *          permission java.io.FilePermission "/home/duke", "read, write";
87 *      };
88 * </pre>
89 *
90 * This <b><i>grant</i></b> entry specifies that code from "foo.com",
91 * signed by "foo', and running as a {@code SolarisPrincipal} with the
92 * name, duke, has one {@code Permission}.  This {@code Permission}
93 * permits the executing code to read and write files in the directory,
94 * "/home/duke".
95 *
96 * <p> To "run" as a particular {@code Principal},
97 * code invokes the {@code Subject.doAs(subject, ...)} method.
98 * After invoking that method, the code runs as all the Principals
99 * associated with the specified {@code Subject}.
100 * Note that this {@code Policy} (and the Permissions
101 * granted in this {@code Policy}) only become effective
102 * after the call to {@code Subject.doAs} has occurred.
103 *
104 * <p> Multiple Principals may be listed within one <b><i>grant</i></b> entry.
105 * All the Principals in the grant entry must be associated with
106 * the {@code Subject} provided to {@code Subject.doAs}
107 * for that {@code Subject} to be granted the specified Permissions.
108 *
109 * <pre>
110 *      grant Principal com.sun.security.auth.SolarisPrincipal "duke",
111 *            Principal com.sun.security.auth.SolarisNumericUserPrincipal "0" {
112 *          permission java.io.FilePermission "/home/duke", "read, write";
113 *          permission java.net.SocketPermission "duke.com", "connect";
114 *      };
115 * </pre>
116 *
117 * This entry grants any code running as both "duke" and "0"
118 * permission to read and write files in duke's home directory,
119 * as well as permission to make socket connections to "duke.com".
120 *
121 * <p> Note that non Principal-based grant entries are not permitted
122 * in this {@code Policy}.  Therefore, grant entries such as:
123 *
124 * <pre>
125 *      grant CodeBase "foo.com", Signedby "foo" {
126 *          permission java.io.FilePermission "/tmp/scratch", "read, write";
127 *      };
128 * </pre>
129 *
130 * are rejected.  Such permission must be listed in the
131 * {@code java.security.Policy}.
132 *
133 * <p> The default {@code Policy} implementation can be changed by
134 * setting the value of the {@code auth.policy.provider} security property to
135 * the fully qualified name of the desired {@code Policy} implementation class.
136 *
137 * @deprecated  as of JDK version 1.4 -- Replaced by java.security.Policy.
138 *              java.security.Policy has a method:
139 * <pre>
140 *      public PermissionCollection getPermissions
141 *          (java.security.ProtectionDomain pd)
142 *
143 * </pre>
144 * and ProtectionDomain has a constructor:
145 * <pre>
146 *      public ProtectionDomain
147 *          (CodeSource cs,
148 *           PermissionCollection permissions,
149 *           ClassLoader loader,
150 *           Principal[] principals)
151 * </pre>
152 *
153 * These two APIs provide callers the means to query the
154 * Policy for Principal-based Permission entries.
155 *
156 * @see java.security.Security security properties
157 */
158@Deprecated
159public abstract class Policy {
160
161    private static Policy policy;
162    private final static String AUTH_POLICY =
163        "sun.security.provider.AuthPolicyFile";
164
165    private final java.security.AccessControlContext acc =
166            java.security.AccessController.getContext();
167
168    // true if a custom (not AUTH_POLICY) system-wide policy object is set
169    private static boolean isCustomPolicy;
170
171    /**
172     * Sole constructor.  (For invocation by subclass constructors, typically
173     * implicit.)
174     */
175    protected Policy() { }
176
177    /**
178     * Returns the installed Policy object.
179     * This method first calls
180     * {@code SecurityManager.checkPermission} with the
181     * {@code AuthPermission("getPolicy")} permission
182     * to ensure the caller has permission to get the Policy object.
183     *
184     * <p>
185     *
186     * @return the installed Policy.  The return value cannot be
187     *          {@code null}.
188     *
189     * @exception java.lang.SecurityException if the current thread does not
190     *      have permission to get the Policy object.
191     *
192     * @see #setPolicy
193     */
194    public static Policy getPolicy() {
195        java.lang.SecurityManager sm = System.getSecurityManager();
196        if (sm != null) sm.checkPermission(new AuthPermission("getPolicy"));
197        return getPolicyNoCheck();
198    }
199
200    /**
201     * Returns the installed Policy object, skipping the security check.
202     *
203     * @return the installed Policy.
204     *
205     */
206    static Policy getPolicyNoCheck() {
207        if (policy == null) {
208
209            synchronized(Policy.class) {
210
211                if (policy == null) {
212                    String policy_class = null;
213                    policy_class = AccessController.doPrivileged
214                        (new PrivilegedAction<String>() {
215                        public String run() {
216                            return java.security.Security.getProperty
217                                ("auth.policy.provider");
218                        }
219                    });
220                    if (policy_class == null) {
221                        policy_class = AUTH_POLICY;
222                    }
223
224                    try {
225                        final String finalClass = policy_class;
226
227                        Policy untrustedImpl = AccessController.doPrivileged(
228                                new PrivilegedExceptionAction<Policy>() {
229                                    public Policy run() throws ClassNotFoundException,
230                                            InstantiationException,
231                                            IllegalAccessException {
232                                        Class<? extends Policy> implClass = Class.forName(
233                                                finalClass, false,
234                                                Thread.currentThread().getContextClassLoader()
235                                        ).asSubclass(Policy.class);
236                                        return implClass.newInstance();
237                                    }
238                                });
239                        AccessController.doPrivileged(
240                                new PrivilegedExceptionAction<Void>() {
241                                    public Void run() {
242                                        setPolicy(untrustedImpl);
243                                        isCustomPolicy = !finalClass.equals(AUTH_POLICY);
244                                        return null;
245                                    }
246                                }, Objects.requireNonNull(untrustedImpl.acc)
247                        );
248                    } catch (Exception e) {
249                        throw new SecurityException
250                                (sun.security.util.ResourcesMgr.getString
251                                ("unable.to.instantiate.Subject.based.policy"));
252                    }
253                }
254            }
255        }
256        return policy;
257    }
258
259
260    /**
261     * Sets the system-wide Policy object. This method first calls
262     * {@code SecurityManager.checkPermission} with the
263     * {@code AuthPermission("setPolicy")}
264     * permission to ensure the caller has permission to set the Policy.
265     *
266     * <p>
267     *
268     * @param policy the new system Policy object.
269     *
270     * @exception java.lang.SecurityException if the current thread does not
271     *          have permission to set the Policy.
272     *
273     * @see #getPolicy
274     */
275    public static void setPolicy(Policy policy) {
276        java.lang.SecurityManager sm = System.getSecurityManager();
277        if (sm != null) sm.checkPermission(new AuthPermission("setPolicy"));
278        Policy.policy = policy;
279        // all non-null policy objects are assumed to be custom
280        isCustomPolicy = policy != null ? true : false;
281    }
282
283    /**
284     * Returns true if a custom (not AUTH_POLICY) system-wide policy object
285     * has been set or installed. This method is called by
286     * SubjectDomainCombiner to provide backwards compatibility for
287     * developers that provide their own javax.security.auth.Policy
288     * implementations.
289     *
290     * @return true if a custom (not AUTH_POLICY) system-wide policy object
291     * has been set; false otherwise
292     */
293    static boolean isCustomPolicySet(Debug debug) {
294        if (policy != null) {
295            if (debug != null && isCustomPolicy) {
296                debug.println("Providing backwards compatibility for " +
297                              "javax.security.auth.policy implementation: " +
298                              policy.toString());
299            }
300            return isCustomPolicy;
301        }
302        // check if custom policy has been set using auth.policy.provider prop
303        String policyClass = java.security.AccessController.doPrivileged
304            (new java.security.PrivilegedAction<String>() {
305                public String run() {
306                    return Security.getProperty("auth.policy.provider");
307                }
308        });
309        if (policyClass != null && !policyClass.equals(AUTH_POLICY)) {
310            if (debug != null) {
311                debug.println("Providing backwards compatibility for " +
312                              "javax.security.auth.policy implementation: " +
313                              policyClass);
314            }
315            return true;
316        }
317        return false;
318    }
319
320    /**
321     * Retrieve the Permissions granted to the Principals associated with
322     * the specified {@code CodeSource}.
323     *
324     * <p>
325     *
326     * @param subject the {@code Subject}
327     *                  whose associated Principals,
328     *                  in conjunction with the provided
329     *                  {@code CodeSource}, determines the Permissions
330     *                  returned by this method.  This parameter
331     *                  may be {@code null}. <p>
332     *
333     * @param cs the code specified by its {@code CodeSource}
334     *                  that determines, in conjunction with the provided
335     *                  {@code Subject}, the Permissions
336     *                  returned by this method.  This parameter may be
337     *                  {@code null}.
338     *
339     * @return the Collection of Permissions granted to all the
340     *                  {@code Subject} and code specified in
341     *                  the provided <i>subject</i> and <i>cs</i>
342     *                  parameters.
343     */
344    public abstract java.security.PermissionCollection getPermissions
345                                        (Subject subject,
346                                        java.security.CodeSource cs);
347
348    /**
349     * Refresh and reload the Policy.
350     *
351     * <p>This method causes this object to refresh/reload its current
352     * Policy. This is implementation-dependent.
353     * For example, if the Policy object is stored in
354     * a file, calling {@code refresh} will cause the file to be re-read.
355     *
356     * <p>
357     *
358     * @exception SecurityException if the caller does not have permission
359     *                          to refresh the Policy.
360     */
361    public abstract void refresh();
362}
363