1 /*
   2  * Copyright (c) 1998, 2017, 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 
  26 package javax.security.auth;
  27 
  28 import java.security.Security;
  29 import java.security.AccessController;
  30 import java.security.PrivilegedAction;
  31 import java.security.PrivilegedExceptionAction;
  32 import java.util.Objects;
  33 import 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 {@code subject}, and granted to the code specified
  55  * by the provided {@code codeSource}.
  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.UnixPrincipal "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 UnixPrincipal} 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.UnixPrincipal "duke",
 111  *            Principal com.sun.security.auth.UnixNumericUserPrincipal "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  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  * This class is subject to removal in a future version of Java SE.
 156  *
 157  * @since 1.4
 158  * @see java.security.Security security properties
 159  */
 160 @Deprecated(since="1.4", forRemoval=true)
 161 public abstract class Policy {
 162 
 163     private static Policy policy;
 164     private static final String AUTH_POLICY =
 165         "sun.security.provider.AuthPolicyFile";
 166 
 167     private final java.security.AccessControlContext acc =
 168             java.security.AccessController.getContext();
 169 
 170     // true if a custom (not AUTH_POLICY) system-wide policy object is set
 171     private static boolean isCustomPolicy;
 172 
 173     /**
 174      * Sole constructor.  (For invocation by subclass constructors, typically
 175      * implicit.)
 176      */
 177     protected Policy() { }
 178 
 179     /**
 180      * Returns the installed Policy object.
 181      * This method first calls
 182      * {@code SecurityManager.checkPermission} with the
 183      * {@code AuthPermission("getPolicy")} permission
 184      * to ensure the caller has permission to get the Policy object.
 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      * @param policy the new system Policy object.
 267      *
 268      * @exception java.lang.SecurityException if the current thread does not
 269      *          have permission to set the Policy.
 270      *
 271      * @see #getPolicy
 272      */
 273     public static void setPolicy(Policy policy) {
 274         java.lang.SecurityManager sm = System.getSecurityManager();
 275         if (sm != null) sm.checkPermission(new AuthPermission("setPolicy"));
 276         Policy.policy = policy;
 277         // all non-null policy objects are assumed to be custom
 278         isCustomPolicy = policy != null ? true : false;
 279     }
 280 
 281     /**
 282      * Returns true if a custom (not AUTH_POLICY) system-wide policy object
 283      * has been set or installed. This method is called by
 284      * SubjectDomainCombiner to provide backwards compatibility for
 285      * developers that provide their own javax.security.auth.Policy
 286      * implementations.
 287      *
 288      * @return true if a custom (not AUTH_POLICY) system-wide policy object
 289      * has been set; false otherwise
 290      */
 291     static boolean isCustomPolicySet(Debug debug) {
 292         if (policy != null) {
 293             if (debug != null && isCustomPolicy) {
 294                 debug.println("Providing backwards compatibility for " +
 295                               "javax.security.auth.policy implementation: " +
 296                               policy.toString());
 297             }
 298             return isCustomPolicy;
 299         }
 300         // check if custom policy has been set using auth.policy.provider prop
 301         String policyClass = java.security.AccessController.doPrivileged
 302             (new java.security.PrivilegedAction<String>() {
 303                 public String run() {
 304                     return Security.getProperty("auth.policy.provider");
 305                 }
 306         });
 307         if (policyClass != null && !policyClass.equals(AUTH_POLICY)) {
 308             if (debug != null) {
 309                 debug.println("Providing backwards compatibility for " +
 310                               "javax.security.auth.policy implementation: " +
 311                               policyClass);
 312             }
 313             return true;
 314         }
 315         return false;
 316     }
 317 
 318     /**
 319      * Retrieve the Permissions granted to the Principals associated with
 320      * the specified {@code CodeSource}.
 321      *
 322      * @param subject the {@code Subject}
 323      *                  whose associated Principals,
 324      *                  in conjunction with the provided
 325      *                  {@code CodeSource}, determines the Permissions
 326      *                  returned by this method.  This parameter
 327      *                  may be {@code null}.
 328      *
 329      * @param cs the code specified by its {@code CodeSource}
 330      *                  that determines, in conjunction with the provided
 331      *                  {@code Subject}, the Permissions
 332      *                  returned by this method.  This parameter may be
 333      *                  {@code null}.
 334      *
 335      * @return the Collection of Permissions granted to all the
 336      *                  {@code Subject} and code specified in
 337      *                  the provided <i>subject</i> and <i>cs</i>
 338      *                  parameters.
 339      */
 340     public abstract java.security.PermissionCollection getPermissions
 341                                         (Subject subject,
 342                                         java.security.CodeSource cs);
 343 
 344     /**
 345      * Refresh and reload the Policy.
 346      *
 347      * <p>This method causes this object to refresh/reload its current
 348      * Policy. This is implementation-dependent.
 349      * For example, if the Policy object is stored in
 350      * a file, calling {@code refresh} will cause the file to be re-read.
 351      *
 352      * @exception SecurityException if the caller does not have permission
 353      *                          to refresh the Policy.
 354      */
 355     public abstract void refresh();
 356 }