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