1421 lines · 53.3 KB · Java
RawDownload
/* * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.security.auth; import java.util.*;import java.io.*;import java.lang.reflect.*;import java.text.MessageFormat;import java.security.AccessController;import java.security.AccessControlContext;import java.security.DomainCombiner;import java.security.Permission;import java.security.PermissionCollection;import java.security.Principal;import java.security.PrivilegedAction;import java.security.PrivilegedExceptionAction;import java.security.PrivilegedActionException;import java.security.ProtectionDomain;import sun.security.util.ResourcesMgr; /** * <p> A <code>Subject</code> represents a grouping of related information * for a single entity, such as a person. * Such information includes the Subject's identities as well as * its security-related attributes * (passwords and cryptographic keys, for example). * * <p> Subjects may potentially have multiple identities. * Each identity is represented as a <code>Principal</code> * within the <code>Subject</code>.  Principals simply bind names to a * <code>Subject</code>.  For example, a <code>Subject</code> that happens * to be a person, Alice, might have two Principals: * one which binds "Alice Bar", the name on her driver license, * to the <code>Subject</code>, and another which binds, * "999-99-9999", the number on her student identification card, * to the <code>Subject</code>.  Both Principals refer to the same * <code>Subject</code> even though each has a different name. * * <p> A <code>Subject</code> may also own security-related attributes, * which are referred to as credentials. * Sensitive credentials that require special protection, such as * private cryptographic keys, are stored within a private credential * <code>Set</code>.  Credentials intended to be shared, such as * public key certificates or Kerberos server tickets are stored * within a public credential <code>Set</code>.  Different permissions * are required to access and modify the different credential Sets. * * <p> To retrieve all the Principals associated with a <code>Subject</code>, * invoke the <code>getPrincipals</code> method.  To retrieve * all the public or private credentials belonging to a <code>Subject</code>, * invoke the <code>getPublicCredentials</code> method or * <code>getPrivateCredentials</code> method, respectively. * To modify the returned <code>Set</code> of Principals and credentials, * use the methods defined in the <code>Set</code> class. * For example: * <pre> *      Subject subject; *      Principal principal; *      Object credential; * *      // add a Principal and credential to the Subject *      subject.getPrincipals().add(principal); *      subject.getPublicCredentials().add(credential); * </pre> * * <p> This <code>Subject</code> class implements <code>Serializable</code>. * While the Principals associated with the <code>Subject</code> are serialized, * the credentials associated with the <code>Subject</code> are not. * Note that the <code>java.security.Principal</code> class * does not implement <code>Serializable</code>.  Therefore all concrete * <code>Principal</code> implementations associated with Subjects * must implement <code>Serializable</code>. * * @see java.security.Principal * @see java.security.DomainCombiner */public final class Subject implements java.io.Serializable {     private static final long serialVersionUID = -8308522755600156056L;     /**     * A <code>Set</code> that provides a view of all of this     * Subject's Principals     *     * <p>     *     * @serial Each element in this set is a     *          <code>java.security.Principal</code>.     *          The set is a <code>Subject.SecureSet</code>.     */    Set<Principal> principals;     /**     * Sets that provide a view of all of this     * Subject's Credentials     */    transient Set<Object> pubCredentials;    transient Set<Object> privCredentials;     /**     * Whether this Subject is read-only     *     * @serial     */    private volatile boolean readOnly = false;     private static final int PRINCIPAL_SET = 1;    private static final int PUB_CREDENTIAL_SET = 2;    private static final int PRIV_CREDENTIAL_SET = 3;     private static final ProtectionDomain[] NULL_PD_ARRAY        = new ProtectionDomain[0];     /**     * Create an instance of a <code>Subject</code>     * with an empty <code>Set</code> of Principals and empty     * Sets of public and private credentials.     *     * <p> The newly constructed Sets check whether this <code>Subject</code>     * has been set read-only before permitting subsequent modifications.     * The newly created Sets also prevent illegal modifications     * by ensuring that callers have sufficient permissions.     *     * <p> To modify the Principals Set, the caller must have     * <code>AuthPermission("modifyPrincipals")</code>.     * To modify the public credential Set, the caller must have     * <code>AuthPermission("modifyPublicCredentials")</code>.     * To modify the private credential Set, the caller must have     * <code>AuthPermission("modifyPrivateCredentials")</code>.     */    public Subject() {         this.principals = Collections.synchronizedSet                        (new SecureSet<Principal>(this, PRINCIPAL_SET));        this.pubCredentials = Collections.synchronizedSet                        (new SecureSet<Object>(this, PUB_CREDENTIAL_SET));        this.privCredentials = Collections.synchronizedSet                        (new SecureSet<Object>(this, PRIV_CREDENTIAL_SET));    }     /**     * Create an instance of a <code>Subject</code> with     * Principals and credentials.     *     * <p> The Principals and credentials from the specified Sets     * are copied into newly constructed Sets.     * These newly created Sets check whether this <code>Subject</code>     * has been set read-only before permitting subsequent modifications.     * The newly created Sets also prevent illegal modifications     * by ensuring that callers have sufficient permissions.     *     * <p> To modify the Principals Set, the caller must have     * <code>AuthPermission("modifyPrincipals")</code>.     * To modify the public credential Set, the caller must have     * <code>AuthPermission("modifyPublicCredentials")</code>.     * To modify the private credential Set, the caller must have     * <code>AuthPermission("modifyPrivateCredentials")</code>.     * <p>     *     * @param readOnly true if the <code>Subject</code> is to be read-only,     *          and false otherwise. <p>     *     * @param principals the <code>Set</code> of Principals     *          to be associated with this <code>Subject</code>. <p>     *     * @param pubCredentials the <code>Set</code> of public credentials     *          to be associated with this <code>Subject</code>. <p>     *     * @param privCredentials the <code>Set</code> of private credentials     *          to be associated with this <code>Subject</code>.     *     * @exception NullPointerException if the specified     *          <code>principals</code>, <code>pubCredentials</code>,     *          or <code>privCredentials</code> are <code>null</code>.     */    public Subject(boolean readOnly, Set<? extends Principal> principals,                   Set<?> pubCredentials, Set<?> privCredentials)    {         if (principals == null ||            pubCredentials == null ||            privCredentials == null)            throw new NullPointerException                (ResourcesMgr.getString("invalid.null.input.s."));         this.principals = Collections.synchronizedSet(new SecureSet<Principal>                                (this, PRINCIPAL_SET, principals));        this.pubCredentials = Collections.synchronizedSet(new SecureSet<Object>                                (this, PUB_CREDENTIAL_SET, pubCredentials));        this.privCredentials = Collections.synchronizedSet(new SecureSet<Object>                                (this, PRIV_CREDENTIAL_SET, privCredentials));        this.readOnly = readOnly;    }     /**     * Set this <code>Subject</code> to be read-only.     *     * <p> Modifications (additions and removals) to this Subject's     * <code>Principal</code> <code>Set</code> and     * credential Sets will be disallowed.     * The <code>destroy</code> operation on this Subject's credentials will     * still be permitted.     *     * <p> Subsequent attempts to modify the Subject's <code>Principal</code>     * and credential Sets will result in an     * <code>IllegalStateException</code> being thrown.     * Also, once a <code>Subject</code> is read-only,     * it can not be reset to being writable again.     *     * <p>     *     * @exception SecurityException if the caller does not have permission     *          to set this <code>Subject</code> to be read-only.     */    public void setReadOnly() {        java.lang.SecurityManager sm = System.getSecurityManager();        if (sm != null) {            sm.checkPermission(AuthPermissionHolder.SET_READ_ONLY_PERMISSION);        }         this.readOnly = true;    }     /**     * Query whether this <code>Subject</code> is read-only.     *     * <p>     *     * @return true if this <code>Subject</code> is read-only, false otherwise.     */    public boolean isReadOnly() {        return this.readOnly;    }     /**     * Get the <code>Subject</code> associated with the provided     * <code>AccessControlContext</code>.     *     * <p> The <code>AccessControlContext</code> may contain many     * Subjects (from nested <code>doAs</code> calls).     * In this situation, the most recent <code>Subject</code> associated     * with the <code>AccessControlContext</code> is returned.     *     * <p>     *     * @param  acc the <code>AccessControlContext</code> from which to retrieve     *          the <code>Subject</code>.     *     * @return  the <code>Subject</code> associated with the provided     *          <code>AccessControlContext</code>, or <code>null</code>     *          if no <code>Subject</code> is associated     *          with the provided <code>AccessControlContext</code>.     *     * @exception SecurityException if the caller does not have permission     *          to get the <code>Subject</code>. <p>     *     * @exception NullPointerException if the provided     *          <code>AccessControlContext</code> is <code>null</code>.     */    public static Subject getSubject(final AccessControlContext acc) {         java.lang.SecurityManager sm = System.getSecurityManager();        if (sm != null) {            sm.checkPermission(AuthPermissionHolder.GET_SUBJECT_PERMISSION);        }         if (acc == null) {            throw new NullPointerException(ResourcesMgr.getString                ("invalid.null.AccessControlContext.provided"));        }         // return the Subject from the DomainCombiner of the provided context        return AccessController.doPrivileged            (new java.security.PrivilegedAction<Subject>() {            public Subject run() {                DomainCombiner dc = acc.getDomainCombiner();                if (!(dc instanceof SubjectDomainCombiner))                    return null;                SubjectDomainCombiner sdc = (SubjectDomainCombiner)dc;                return sdc.getSubject();            }        });    }     /**     * Perform work as a particular <code>Subject</code>.     *     * <p> This method first retrieves the current Thread's     * <code>AccessControlContext</code> via     * <code>AccessController.getContext</code>,     * and then instantiates a new <code>AccessControlContext</code>     * using the retrieved context along with a new     * <code>SubjectDomainCombiner</code> (constructed using     * the provided <code>Subject</code>).     * Finally, this method invokes <code>AccessController.doPrivileged</code>,     * passing it the provided <code>PrivilegedAction</code>,     * as well as the newly constructed <code>AccessControlContext</code>.     *     * <p>     *     * @param subject the <code>Subject</code> that the specified     *                  <code>action</code> will run as.  This parameter     *                  may be <code>null</code>. <p>     *     * @param action the code to be run as the specified     *                  <code>Subject</code>. <p>     *     * @return the value returned by the PrivilegedAction's     *                  <code>run</code> method.     *     * @exception NullPointerException if the <code>PrivilegedAction</code>     *                  is <code>null</code>. <p>     *     * @exception SecurityException if the caller does not have permission     *                  to invoke this method.     */    public static <T> T doAs(final Subject subject,                        final java.security.PrivilegedAction<T> action) {         java.lang.SecurityManager sm = System.getSecurityManager();        if (sm != null) {            sm.checkPermission(AuthPermissionHolder.DO_AS_PERMISSION);        }        if (action == null)            throw new NullPointerException                (ResourcesMgr.getString("invalid.null.action.provided"));         // set up the new Subject-based AccessControlContext        // for doPrivileged        final AccessControlContext currentAcc = AccessController.getContext();         // call doPrivileged and push this new context on the stack        return java.security.AccessController.doPrivileged                                        (action,                                        createContext(subject, currentAcc));    }     /**     * Perform work as a particular <code>Subject</code>.     *     * <p> This method first retrieves the current Thread's     * <code>AccessControlContext</code> via     * <code>AccessController.getContext</code>,     * and then instantiates a new <code>AccessControlContext</code>     * using the retrieved context along with a new     * <code>SubjectDomainCombiner</code> (constructed using     * the provided <code>Subject</code>).     * Finally, this method invokes <code>AccessController.doPrivileged</code>,     * passing it the provided <code>PrivilegedExceptionAction</code>,     * as well as the newly constructed <code>AccessControlContext</code>.     *     * <p>     *     * @param subject the <code>Subject</code> that the specified     *                  <code>action</code> will run as.  This parameter     *                  may be <code>null</code>. <p>     *     * @param action the code to be run as the specified     *                  <code>Subject</code>. <p>     *     * @return the value returned by the     *                  PrivilegedExceptionAction's <code>run</code> method.     *     * @exception PrivilegedActionException if the     *                  <code>PrivilegedExceptionAction.run</code>     *                  method throws a checked exception. <p>     *     * @exception NullPointerException if the specified     *                  <code>PrivilegedExceptionAction</code> is     *                  <code>null</code>. <p>     *     * @exception SecurityException if the caller does not have permission     *                  to invoke this method.     */    public static <T> T doAs(final Subject subject,                        final java.security.PrivilegedExceptionAction<T> action)                        throws java.security.PrivilegedActionException {         java.lang.SecurityManager sm = System.getSecurityManager();        if (sm != null) {            sm.checkPermission(AuthPermissionHolder.DO_AS_PERMISSION);        }         if (action == null)            throw new NullPointerException                (ResourcesMgr.getString("invalid.null.action.provided"));         // set up the new Subject-based AccessControlContext for doPrivileged        final AccessControlContext currentAcc = AccessController.getContext();         // call doPrivileged and push this new context on the stack        return java.security.AccessController.doPrivileged                                        (action,                                        createContext(subject, currentAcc));    }     /**     * Perform privileged work as a particular <code>Subject</code>.     *     * <p> This method behaves exactly as <code>Subject.doAs</code>,     * except that instead of retrieving the current Thread's     * <code>AccessControlContext</code>, it uses the provided     * <code>AccessControlContext</code>.  If the provided     * <code>AccessControlContext</code> is <code>null</code>,     * this method instantiates a new <code>AccessControlContext</code>     * with an empty collection of ProtectionDomains.     *     * <p>     *     * @param subject the <code>Subject</code> that the specified     *                  <code>action</code> will run as.  This parameter     *                  may be <code>null</code>. <p>     *     * @param action the code to be run as the specified     *                  <code>Subject</code>. <p>     *     * @param acc the <code>AccessControlContext</code> to be tied to the     *                  specified <i>subject</i> and <i>action</i>. <p>     *     * @return the value returned by the PrivilegedAction's     *                  <code>run</code> method.     *     * @exception NullPointerException if the <code>PrivilegedAction</code>     *                  is <code>null</code>. <p>     *     * @exception SecurityException if the caller does not have permission     *                  to invoke this method.     */    public static <T> T doAsPrivileged(final Subject subject,                        final java.security.PrivilegedAction<T> action,                        final java.security.AccessControlContext acc) {         java.lang.SecurityManager sm = System.getSecurityManager();        if (sm != null) {            sm.checkPermission(AuthPermissionHolder.DO_AS_PRIVILEGED_PERMISSION);        }         if (action == null)            throw new NullPointerException                (ResourcesMgr.getString("invalid.null.action.provided"));         // set up the new Subject-based AccessControlContext        // for doPrivileged        final AccessControlContext callerAcc =                (acc == null ?                new AccessControlContext(NULL_PD_ARRAY) :                acc);         // call doPrivileged and push this new context on the stack        return java.security.AccessController.doPrivileged                                        (action,                                        createContext(subject, callerAcc));    }     /**     * Perform privileged work as a particular <code>Subject</code>.     *     * <p> This method behaves exactly as <code>Subject.doAs</code>,     * except that instead of retrieving the current Thread's     * <code>AccessControlContext</code>, it uses the provided     * <code>AccessControlContext</code>.  If the provided     * <code>AccessControlContext</code> is <code>null</code>,     * this method instantiates a new <code>AccessControlContext</code>     * with an empty collection of ProtectionDomains.     *     * <p>     *     * @param subject the <code>Subject</code> that the specified     *                  <code>action</code> will run as.  This parameter     *                  may be <code>null</code>. <p>     *     * @param action the code to be run as the specified     *                  <code>Subject</code>. <p>     *     * @param acc the <code>AccessControlContext</code> to be tied to the     *                  specified <i>subject</i> and <i>action</i>. <p>     *

Lines 1–500 of 1421.