561 lines · 18.7 KB · Java
RawDownload
/* * Copyright (c) 1999, 2011, 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.text.MessageFormat;import java.security.Permission;import java.security.PermissionCollection;import java.security.Principal;import sun.security.util.ResourcesMgr; /** * This class is used to protect access to private Credentials * belonging to a particular <code>Subject</code>.  The <code>Subject</code> * is represented by a Set of Principals. * * <p> The target name of this <code>Permission</code> specifies * a Credential class name, and a Set of Principals. * The only valid value for this Permission's actions is, "read". * The target name must abide by the following syntax: * * <pre> *      CredentialClass {PrincipalClass "PrincipalName"}* * </pre> * * For example, the following permission grants access to the * com.sun.PrivateCredential owned by Subjects which have * a com.sun.Principal with the name, "duke".  Note that although * this example, as well as all the examples below, do not contain * Codebase, SignedBy, or Principal information in the grant statement * (for simplicity reasons), actual policy configurations should * specify that information when appropriate. * * <pre> * *    grant { *      permission javax.security.auth.PrivateCredentialPermission *              "com.sun.PrivateCredential com.sun.Principal \"duke\"", *              "read"; *    }; * </pre> * * If CredentialClass is "*", then access is granted to * all private Credentials belonging to the specified * <code>Subject</code>. * If "PrincipalName" is "*", then access is granted to the * specified Credential owned by any <code>Subject</code> that has the * specified <code>Principal</code> (the actual PrincipalName doesn't matter). * For example, the following grants access to the * a.b.Credential owned by any <code>Subject</code> that has * an a.b.Principal. * * <pre> *    grant { *      permission javax.security.auth.PrivateCredentialPermission *              "a.b.Credential a.b.Principal "*"", *              "read"; *    }; * </pre> * * If both the PrincipalClass and "PrincipalName" are "*", * then access is granted to the specified Credential owned by * any <code>Subject</code>. * * <p> In addition, the PrincipalClass/PrincipalName pairing may be repeated: * * <pre> *    grant { *      permission javax.security.auth.PrivateCredentialPermission *              "a.b.Credential a.b.Principal "duke" c.d.Principal "dukette"", *              "read"; *    }; * </pre> * * The above grants access to the private Credential, "a.b.Credential", * belonging to a <code>Subject</code> with at least two associated Principals: * "a.b.Principal" with the name, "duke", and "c.d.Principal", with the name, * "dukette". * */public final class PrivateCredentialPermission extends Permission {     private static final long serialVersionUID = 5284372143517237068L;     private static final CredOwner[] EMPTY_PRINCIPALS = new CredOwner[0];     /**     * @serial     */    private String credentialClass;     /**     * @serial The Principals associated with this permission.     *          The set contains elements of type,     *          <code>PrivateCredentialPermission.CredOwner</code>.     */    private Set principals;  // ignored - kept around for compatibility    private transient CredOwner[] credOwners;     /**     * @serial     */    private boolean testing = false;     /**     * Create a new <code>PrivateCredentialPermission</code>     * with the specified <code>credentialClass</code> and Principals.     */    PrivateCredentialPermission(String credentialClass,                        Set<Principal> principals) {         super(credentialClass);        this.credentialClass = credentialClass;         synchronized(principals) {            if (principals.size() == 0) {                this.credOwners = EMPTY_PRINCIPALS;            } else {                this.credOwners = new CredOwner[principals.size()];                int index = 0;                Iterator<Principal> i = principals.iterator();                while (i.hasNext()) {                    Principal p = i.next();                    this.credOwners[index++] = new CredOwner                                                (p.getClass().getName(),                                                p.getName());                }            }        }    }     /**     * Creates a new <code>PrivateCredentialPermission</code>     * with the specified <code>name</code>.  The <code>name</code>     * specifies both a Credential class and a <code>Principal</code> Set.     *     * <p>     *     * @param name the name specifying the Credential class and     *          <code>Principal</code> Set. <p>     *     * @param actions the actions specifying that the Credential can be read.     *     * @throws IllegalArgumentException if <code>name</code> does not conform     *          to the correct syntax or if <code>actions</code> is not "read".     */    public PrivateCredentialPermission(String name, String actions) {        super(name);         if (!"read".equalsIgnoreCase(actions))            throw new IllegalArgumentException                (ResourcesMgr.getString("actions.can.only.be.read."));        init(name);    }     /**     * Returns the Class name of the Credential associated with this     * <code>PrivateCredentialPermission</code>.     *     * <p>     *     * @return the Class name of the Credential associated with this     *          <code>PrivateCredentialPermission</code>.     */    public String getCredentialClass() {        return credentialClass;    }     /**     * Returns the <code>Principal</code> classes and names     * associated with this <code>PrivateCredentialPermission</code>.     * The information is returned as a two-dimensional array (array[x][y]).     * The 'x' value corresponds to the number of <code>Principal</code>     * class and name pairs.  When (y==0), it corresponds to     * the <code>Principal</code> class value, and when (y==1),     * it corresponds to the <code>Principal</code> name value.     * For example, array[0][0] corresponds to the class name of     * the first <code>Principal</code> in the array.  array[0][1]     * corresponds to the <code>Principal</code> name of the     * first <code>Principal</code> in the array.     *     * <p>     *     * @return the <code>Principal</code> class and names associated     *          with this <code>PrivateCredentialPermission</code>.     */    public String[][] getPrincipals() {         if (credOwners == null || credOwners.length == 0) {            return new String[0][0];        }         String[][] pArray = new String[credOwners.length][2];        for (int i = 0; i < credOwners.length; i++) {            pArray[i][0] = credOwners[i].principalClass;            pArray[i][1] = credOwners[i].principalName;        }        return pArray;    }     /**     * Checks if this <code>PrivateCredentialPermission</code> implies     * the specified <code>Permission</code>.     *     * <p>     *     * This method returns true if:     * <p><ul>     * <li> <i>p</i> is an instanceof PrivateCredentialPermission and <p>     * <li> the target name for <i>p</i> is implied by this object's     *          target name.  For example:     * <pre>     *  [* P1 "duke"] implies [a.b.Credential P1 "duke"].     *  [C1 P1 "duke"] implies [C1 P1 "duke" P2 "dukette"].     *  [C1 P2 "dukette"] implies [C1 P1 "duke" P2 "dukette"].     * </pre>     * </ul>     *     * <p>     *     * @param p the <code>Permission</code> to check against.     *     * @return true if this <code>PrivateCredentialPermission</code> implies     * the specified <code>Permission</code>, false if not.     */    public boolean implies(Permission p) {         if (p == null || !(p instanceof PrivateCredentialPermission))            return false;         PrivateCredentialPermission that = (PrivateCredentialPermission)p;         if (!impliesCredentialClass(credentialClass, that.credentialClass))            return false;         return impliesPrincipalSet(credOwners, that.credOwners);    }     /**     * Checks two <code>PrivateCredentialPermission</code> objects for     * equality.  Checks that <i>obj</i> is a     * <code>PrivateCredentialPermission</code>,     * and has the same credential class as this object,     * as well as the same Principals as this object.     * The order of the Principals in the respective Permission's     * target names is not relevant.     *     * <p>     *     * @param obj the object we are testing for equality with this object.     *     * @return true if obj is a <code>PrivateCredentialPermission</code>,     *          has the same credential class as this object,     *          and has the same Principals as this object.     */    public boolean equals(Object obj) {        if (obj == this)            return true;         if (! (obj instanceof PrivateCredentialPermission))            return false;         PrivateCredentialPermission that = (PrivateCredentialPermission)obj;         return (this.implies(that) && that.implies(this));    }     /**     * Returns the hash code value for this object.     *     * @return a hash code value for this object.     */    public int hashCode() {        return this.credentialClass.hashCode();    }     /**     * Returns the "canonical string representation" of the actions.     * This method always returns the String, "read".     *     * <p>     *     * @return the actions (always returns "read").     */    public String getActions() {        return "read";    }     /**     * Return a homogeneous collection of PrivateCredentialPermissions     * in a <code>PermissionCollection</code>.     * No such <code>PermissionCollection</code> is defined,     * so this method always returns <code>null</code>.     *     * <p>     *     * @return null in all cases.     */    public PermissionCollection newPermissionCollection() {        return null;    }     private void init(String name) {         if (name == null || name.trim().length() == 0) {            throw new IllegalArgumentException("invalid empty name");        }         ArrayList<CredOwner> pList = new ArrayList<>();        StringTokenizer tokenizer = new StringTokenizer(name, " ", true);        String principalClass = null;        String principalName = null;         if (testing)            System.out.println("whole name = " + name);         // get the Credential Class        credentialClass = tokenizer.nextToken();        if (testing)            System.out.println("Credential Class = " + credentialClass);         if (tokenizer.hasMoreTokens() == false) {            MessageFormat form = new MessageFormat(ResourcesMgr.getString                ("permission.name.name.syntax.invalid."));            Object[] source = {name};            throw new IllegalArgumentException                (form.format(source) + ResourcesMgr.getString                        ("Credential.Class.not.followed.by.a.Principal.Class.and.Name"));        }         while (tokenizer.hasMoreTokens()) {             // skip delimiter            tokenizer.nextToken();             // get the Principal Class            principalClass = tokenizer.nextToken();            if (testing)                System.out.println("    Principal Class = " + principalClass);             if (tokenizer.hasMoreTokens() == false) {                MessageFormat form = new MessageFormat(ResourcesMgr.getString                        ("permission.name.name.syntax.invalid."));                Object[] source = {name};                throw new IllegalArgumentException                        (form.format(source) + ResourcesMgr.getString                        ("Principal.Class.not.followed.by.a.Principal.Name"));            }             // skip delimiter            tokenizer.nextToken();             // get the Principal Name            principalName = tokenizer.nextToken();             if (!principalName.startsWith("\"")) {                MessageFormat form = new MessageFormat(ResourcesMgr.getString                        ("permission.name.name.syntax.invalid."));                Object[] source = {name};                throw new IllegalArgumentException                        (form.format(source) + ResourcesMgr.getString                        ("Principal.Name.must.be.surrounded.by.quotes"));            }             if (!principalName.endsWith("\"")) {                 // we have a name with spaces in it --                // keep parsing until we find the end quote,                // and keep the spaces in the name                 while (tokenizer.hasMoreTokens()) {                    principalName = principalName + tokenizer.nextToken();                    if (principalName.endsWith("\""))                        break;                }                 if (!principalName.endsWith("\"")) {                    MessageFormat form = new MessageFormat                        (ResourcesMgr.getString                        ("permission.name.name.syntax.invalid."));                    Object[] source = {name};                    throw new IllegalArgumentException                        (form.format(source) + ResourcesMgr.getString                                ("Principal.Name.missing.end.quote"));                }            }             if (testing)                System.out.println("\tprincipalName = '" + principalName + "'");             principalName = principalName.substring                                        (1, principalName.length() - 1);             if (principalClass.equals("*") &&                !principalName.equals("*")) {                    throw new IllegalArgumentException(ResourcesMgr.getString                        ("PrivateCredentialPermission.Principal.Class.can.not.be.a.wildcard.value.if.Principal.Name.is.not.a.wildcard.value"));            }             if (testing)                System.out.println("\tprincipalName = '" + principalName + "'");             pList.add(new CredOwner(principalClass, principalName));        }         this.credOwners = new CredOwner[pList.size()];        pList.toArray(this.credOwners);    }     private boolean impliesCredentialClass(String thisC, String thatC) {         // this should never happen        if (thisC == null || thatC == null)            return false;         if (testing)            System.out.println("credential class comparison: " +                                thisC + "/" + thatC);         if (thisC.equals("*"))            return true;         /**         * XXX let's not enable this for now --         *      if people want it, we'll enable it later         */        /*        if (thisC.endsWith("*")) {            String cClass = thisC.substring(0, thisC.length() - 2);            return thatC.startsWith(cClass);        }        */         return thisC.equals(thatC);    }     private boolean impliesPrincipalSet(CredOwner[] thisP, CredOwner[] thatP) {         // this should never happen        if (thisP == null || thatP == null)            return false;         if (thatP.length == 0)            return true;         if (thisP.length == 0)            return false;         for (int i = 0; i < thisP.length; i++) {            boolean foundMatch = false;            for (int j = 0; j < thatP.length; j++) {                if (thisP[i].implies(thatP[j])) {                    foundMatch = true;                    break;                }            }            if (!foundMatch) {                return false;            }        }        return true;    }     /**     * Reads this object from a stream (i.e., deserializes it)     */    private void readObject(java.io.ObjectInputStream s) throws                                        java.io.IOException,                                        ClassNotFoundException {         s.defaultReadObject();         // perform new initialization from the permission name         if (getName().indexOf(" ") == -1 && getName().indexOf("\"") == -1) {             // name only has a credential class specified

Lines 1–500 of 561.