479 lines · 15.9 KB · Java
RawDownload
/* * Copyright (c) 1999, 2007, 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.crypto; import java.security.*;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;import java.util.NoSuchElementException;import java.io.Serializable;import java.io.InputStream;import java.io.InputStreamReader;import java.io.BufferedReader;import java.io.IOException; /** * This class contains CryptoPermission objects, organized into * PermissionCollections according to algorithm names. * * <p>When the <code>add</code> method is called to add a * CryptoPermission, the CryptoPermission is stored in the * appropriate PermissionCollection. If no such * collection exists yet, the algorithm name associated with * the CryptoPermission object is * determined and the <code>newPermissionCollection</code> method * is called on the CryptoPermission or CryptoAllPermission class to * create the PermissionCollection and add it to the Permissions object. * * @see javax.crypto.CryptoPermission * @see java.security.PermissionCollection * @see java.security.Permissions * * @author Sharon Liu * @since 1.4 */final class CryptoPermissions extends PermissionCollectionimplements Serializable {     private static final long serialVersionUID = 4946547168093391015L;     // This class is similar to java.security.Permissions    private Hashtable perms;     /**     * Creates a new CryptoPermissions object containing     * no CryptoPermissionCollections.     */    CryptoPermissions() {        perms = new Hashtable(7);    }     /**     * Populates the crypto policy from the specified     * InputStream into this CryptoPermissions object.     *     * @param in the InputStream to load from.     *     * @exception SecurityException if cannot load     * successfully.     */    void load(InputStream in)        throws IOException, CryptoPolicyParser.ParsingException {        CryptoPolicyParser parser = new CryptoPolicyParser();        parser.read(new BufferedReader(new InputStreamReader(in, "UTF-8")));         CryptoPermission[] parsingResult = parser.getPermissions();        for (int i = 0; i < parsingResult.length; i++) {            this.add(parsingResult[i]);        }    }     /**     * Returns true if this CryptoPermissions object doesn't     * contain any CryptoPermission objects; otherwise, returns     * false.     */    boolean isEmpty() {        return perms.isEmpty();    }     /**     * Adds a permission object to the PermissionCollection for the     * algorithm returned by     * <code>(CryptoPermission)permission.getAlgorithm()</code>.     *     * This method creates     * a new PermissionCollection object (and adds the permission to it)     * if an appropriate collection does not yet exist. <p>     *     * @param permission the Permission object to add.     *     * @exception SecurityException if this CryptoPermissions object is     * marked as readonly.     *     * @see isReadOnly     */    public void add(Permission permission) {         if (isReadOnly())            throw new SecurityException("Attempt to add a Permission " +                                        "to a readonly CryptoPermissions " +                                        "object");         if (!(permission instanceof CryptoPermission))            return;         CryptoPermission cryptoPerm = (CryptoPermission)permission;        PermissionCollection pc =                        getPermissionCollection(cryptoPerm);        pc.add(cryptoPerm);        String alg = cryptoPerm.getAlgorithm();        if (!perms.containsKey(alg)) {            perms.put(alg, pc);        }    }     /**     * Checks if this object's PermissionCollection for permissons     * of the specified permission's algorithm implies the specified     * permission. Returns true if the checking succeeded.     *     * @param permission the Permission object to check.     *     * @return true if "permission" is implied by the permissions     * in the PermissionCollection it belongs to, false if not.     *     */    public boolean implies(Permission permission) {        if (!(permission instanceof CryptoPermission)) {            return false;        }         CryptoPermission cryptoPerm = (CryptoPermission)permission;         PermissionCollection pc =            getPermissionCollection(cryptoPerm.getAlgorithm());        return pc.implies(cryptoPerm);    }     /**     * Returns an enumeration of all the Permission objects in all the     * PermissionCollections in this CryptoPermissions object.     *     * @return an enumeration of all the Permissions.     */    public Enumeration elements() {        // go through each Permissions in the hash table        // and call their elements() function.        return new PermissionsEnumerator(perms.elements());    }     /**     * Returns a CryptoPermissions object which     * represents the minimum of the specified     * CryptoPermissions object and this     * CryptoPermissions object.     *     * @param other the CryptoPermission     * object to compare with this object.     */    CryptoPermissions getMinimum(CryptoPermissions other) {        if (other == null) {            return null;        }         if (this.perms.containsKey(CryptoAllPermission.ALG_NAME)) {            return other;        }         if (other.perms.containsKey(CryptoAllPermission.ALG_NAME)) {            return this;        }         CryptoPermissions ret = new CryptoPermissions();          PermissionCollection thatWildcard =            (PermissionCollection)other.perms.get(                                        CryptoPermission.ALG_NAME_WILDCARD);        int maxKeySize = 0;        if (thatWildcard != null) {            maxKeySize = ((CryptoPermission)                    thatWildcard.elements().nextElement()).getMaxKeySize();        }        // For each algorithm in this CryptoPermissions,        // find out if there is anything we should add into        // ret.        Enumeration thisKeys = this.perms.keys();        while (thisKeys.hasMoreElements()) {            String alg = (String)thisKeys.nextElement();             PermissionCollection thisPc =                (PermissionCollection)this.perms.get(alg);            PermissionCollection thatPc =                (PermissionCollection)other.perms.get(alg);             CryptoPermission[] partialResult;             if (thatPc == null) {                if (thatWildcard == null) {                    // The other CryptoPermissions                    // doesn't allow this given                    // algorithm at all. Just skip this                    // algorithm.                    continue;                }                partialResult = getMinimum(maxKeySize, thisPc);            } else {                partialResult = getMinimum(thisPc, thatPc);            }             for (int i = 0; i < partialResult.length; i++) {                ret.add(partialResult[i]);            }        }         PermissionCollection thisWildcard =            (PermissionCollection)this.perms.get(                                      CryptoPermission.ALG_NAME_WILDCARD);         // If this CryptoPermissions doesn't        // have a wildcard, we are done.        if (thisWildcard == null) {            return ret;        }         // Deal with the algorithms only appear        // in the other CryptoPermissions.        maxKeySize =            ((CryptoPermission)                    thisWildcard.elements().nextElement()).getMaxKeySize();        Enumeration thatKeys = other.perms.keys();        while (thatKeys.hasMoreElements()) {            String alg = (String)thatKeys.nextElement();             if (this.perms.containsKey(alg)) {                continue;            }             PermissionCollection thatPc =                (PermissionCollection)other.perms.get(alg);             CryptoPermission[] partialResult;             partialResult = getMinimum(maxKeySize, thatPc);             for (int i = 0; i < partialResult.length; i++) {                ret.add(partialResult[i]);            }        }        return ret;    }     /**     * Get the minimum of the two given PermissionCollection     * <code>thisPc</code> and <code>thatPc</code>.     *     * @param thisPc the first given PermissionColloection     * object.     *     * @param thatPc the second given PermissionCollection     * object.     */    private CryptoPermission[] getMinimum(PermissionCollection thisPc,                                          PermissionCollection thatPc) {        Vector permVector = new Vector(2);         Enumeration thisPcPermissions = thisPc.elements();         // For each CryptoPermission in        // thisPc object, do the following:        // 1) if this CryptoPermission is implied        //     by thatPc, this CryptoPermission        //     should be returned, and we can        //     move on to check the next        //     CryptoPermission in thisPc.        // 2) otherwise, we should return        //     all CryptoPermissions in thatPc        //     which        //     are implied by this CryptoPermission.        //     Then we can move on to the        //     next CryptoPermission in thisPc.        while (thisPcPermissions.hasMoreElements()) {            CryptoPermission thisCp =                (CryptoPermission)thisPcPermissions.nextElement();             Enumeration thatPcPermissions = thatPc.elements();            while (thatPcPermissions.hasMoreElements()) {                CryptoPermission thatCp =                    (CryptoPermission)thatPcPermissions.nextElement();                 if (thatCp.implies(thisCp)) {                    permVector.addElement(thisCp);                    break;                }                if (thisCp.implies(thatCp)) {                    permVector.addElement(thatCp);                }            }        }         CryptoPermission[] ret = new CryptoPermission[permVector.size()];        permVector.copyInto(ret);        return ret;    }     /**     * Returns all the CryptoPermission objects in the given     * PermissionCollection object     * whose maximum keysize no greater than <code>maxKeySize</code>.     * For all CryptoPermission objects with a maximum keysize greater     * than <code>maxKeySize</code>, this method constructs a     * corresponding CryptoPermission object whose maximum keysize is     * set to <code>maxKeySize</code>, and includes that in the result.     *     * @param maxKeySize the given maximum key size.     *     * @param pc the given PermissionCollection object.     */    private CryptoPermission[] getMinimum(int maxKeySize,                                          PermissionCollection pc) {        Vector permVector = new Vector(1);         Enumeration enum_ = pc.elements();         while (enum_.hasMoreElements()) {            CryptoPermission cp =                (CryptoPermission)enum_.nextElement();            if (cp.getMaxKeySize() <= maxKeySize) {                permVector.addElement(cp);            } else {                if (cp.getCheckParam()) {                    permVector.addElement(                           new CryptoPermission(cp.getAlgorithm(),                                                maxKeySize,                                                cp.getAlgorithmParameterSpec(),                                                cp.getExemptionMechanism()));                } else {                    permVector.addElement(                           new CryptoPermission(cp.getAlgorithm(),                                                maxKeySize,                                                cp.getExemptionMechanism()));                }            }        }         CryptoPermission[] ret = new CryptoPermission[permVector.size()];        permVector.copyInto(ret);        return ret;    }     /**     * Returns the PermissionCollection for the     * specified algorithm. Returns null if there     * isn't such a PermissionCollection.     *     * @param alg the algorithm name.     */    PermissionCollection getPermissionCollection(String alg) {        // If this CryptoPermissions includes CryptoAllPermission,        // we should return CryptoAllPermission.        if (perms.containsKey(CryptoAllPermission.ALG_NAME)) {            return                (PermissionCollection)(perms.get(CryptoAllPermission.ALG_NAME));        }         PermissionCollection pc = (PermissionCollection)perms.get(alg);         // If there isn't a PermissionCollection for        // the given algorithm,we should return the        // PermissionCollection for the wildcard        // if there is one.        if (pc == null) {            pc = (PermissionCollection)perms.get(                                       CryptoPermission.ALG_NAME_WILDCARD);        }        return pc;    }     /**     * Returns the PermissionCollection for the algorithm     * associated with the specified CryptoPermission     * object. Creates such a PermissionCollection     * if such a PermissionCollection does not     * exist yet.     *     * @param cryptoPerm the CryptoPermission object.     */    private PermissionCollection getPermissionCollection(                                          CryptoPermission cryptoPerm) {         String alg = cryptoPerm.getAlgorithm();         PermissionCollection pc = (PermissionCollection)perms.get(alg);         if (pc == null) {            pc = cryptoPerm.newPermissionCollection();        }        return pc;    }} final class PermissionsEnumerator implements Enumeration {     // all the perms    private Enumeration perms;    // the current set    private Enumeration permset;     PermissionsEnumerator(Enumeration e) {        perms = e;        permset = getNextEnumWithMore();    }     public synchronized boolean hasMoreElements() {        // if we enter with permissionimpl null, we know        // there are no more left.         if (permset == null)            return  false;         // try to see if there are any left in the current one         if (permset.hasMoreElements())            return true;         // get the next one that has something in it...        permset = getNextEnumWithMore();         // if it is null, we are done!        return (permset != null);    }     public synchronized Object nextElement() {        // hasMoreElements will update permset to the next permset        // with something in it...         if (hasMoreElements()) {            return permset.nextElement();        } else {            throw new NoSuchElementException("PermissionsEnumerator");        }     }     private Enumeration getNextEnumWithMore() {        while (perms.hasMoreElements()) {            PermissionCollection pc =                (PermissionCollection) perms.nextElement();            Enumeration next = pc.elements();            if (next.hasMoreElements())                return next;        }        return null;    }}