0N/A/*
5296N/A * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage javax.crypto;
0N/A
0N/Aimport java.security.*;
0N/Aimport java.util.Enumeration;
0N/Aimport java.util.Hashtable;
0N/Aimport java.util.Vector;
0N/Aimport java.util.NoSuchElementException;
5296N/Aimport java.util.concurrent.ConcurrentHashMap;
0N/Aimport java.io.Serializable;
0N/Aimport java.io.InputStream;
0N/Aimport java.io.InputStreamReader;
0N/Aimport java.io.BufferedReader;
5296N/Aimport java.io.ObjectStreamField;
5296N/Aimport java.io.ObjectInputStream;
5296N/Aimport java.io.ObjectInputStream.GetField;
5296N/Aimport java.io.ObjectOutputStream;
5296N/Aimport java.io.ObjectOutputStream.PutField;
0N/Aimport java.io.IOException;
0N/A
0N/A/**
0N/A * This class contains CryptoPermission objects, organized into
0N/A * PermissionCollections according to algorithm names.
0N/A *
0N/A * <p>When the <code>add</code> method is called to add a
0N/A * CryptoPermission, the CryptoPermission is stored in the
0N/A * appropriate PermissionCollection. If no such
0N/A * collection exists yet, the algorithm name associated with
0N/A * the CryptoPermission object is
0N/A * determined and the <code>newPermissionCollection</code> method
0N/A * is called on the CryptoPermission or CryptoAllPermission class to
0N/A * create the PermissionCollection and add it to the Permissions object.
0N/A *
0N/A * @see javax.crypto.CryptoPermission
0N/A * @see java.security.PermissionCollection
0N/A * @see java.security.Permissions
0N/A *
0N/A * @author Sharon Liu
0N/A * @since 1.4
0N/A */
0N/Afinal class CryptoPermissions extends PermissionCollection
0N/Aimplements Serializable {
0N/A
0N/A private static final long serialVersionUID = 4946547168093391015L;
0N/A
5296N/A /**
5296N/A * @serialField perms java.util.Hashtable
5296N/A */
5296N/A private static final ObjectStreamField[] serialPersistentFields = {
5296N/A new ObjectStreamField("perms", Hashtable.class),
5296N/A };
5296N/A
5296N/A // Switched from Hashtable to ConcurrentHashMap to improve scalability.
5296N/A // To maintain serialization compatibility, this field is made transient
5296N/A // and custom readObject/writeObject methods are used.
5296N/A private transient ConcurrentHashMap<String,PermissionCollection> perms;
0N/A
0N/A /**
0N/A * Creates a new CryptoPermissions object containing
0N/A * no CryptoPermissionCollections.
0N/A */
0N/A CryptoPermissions() {
5296N/A perms = new ConcurrentHashMap<>(7);
0N/A }
0N/A
0N/A /**
0N/A * Populates the crypto policy from the specified
0N/A * InputStream into this CryptoPermissions object.
0N/A *
0N/A * @param in the InputStream to load from.
0N/A *
0N/A * @exception SecurityException if cannot load
0N/A * successfully.
0N/A */
0N/A void load(InputStream in)
0N/A throws IOException, CryptoPolicyParser.ParsingException {
0N/A CryptoPolicyParser parser = new CryptoPolicyParser();
0N/A parser.read(new BufferedReader(new InputStreamReader(in, "UTF-8")));
0N/A
0N/A CryptoPermission[] parsingResult = parser.getPermissions();
0N/A for (int i = 0; i < parsingResult.length; i++) {
0N/A this.add(parsingResult[i]);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns true if this CryptoPermissions object doesn't
0N/A * contain any CryptoPermission objects; otherwise, returns
0N/A * false.
0N/A */
0N/A boolean isEmpty() {
0N/A return perms.isEmpty();
0N/A }
0N/A
0N/A /**
0N/A * Adds a permission object to the PermissionCollection for the
0N/A * algorithm returned by
0N/A * <code>(CryptoPermission)permission.getAlgorithm()</code>.
0N/A *
0N/A * This method creates
0N/A * a new PermissionCollection object (and adds the permission to it)
0N/A * if an appropriate collection does not yet exist. <p>
0N/A *
0N/A * @param permission the Permission object to add.
0N/A *
0N/A * @exception SecurityException if this CryptoPermissions object is
0N/A * marked as readonly.
0N/A *
0N/A * @see isReadOnly
0N/A */
0N/A public void add(Permission permission) {
0N/A
0N/A if (isReadOnly())
0N/A throw new SecurityException("Attempt to add a Permission " +
0N/A "to a readonly CryptoPermissions " +
0N/A "object");
0N/A
0N/A if (!(permission instanceof CryptoPermission))
0N/A return;
0N/A
0N/A CryptoPermission cryptoPerm = (CryptoPermission)permission;
0N/A PermissionCollection pc =
0N/A getPermissionCollection(cryptoPerm);
0N/A pc.add(cryptoPerm);
0N/A String alg = cryptoPerm.getAlgorithm();
5296N/A perms.putIfAbsent(alg, pc);
0N/A }
0N/A
0N/A /**
0N/A * Checks if this object's PermissionCollection for permissons
0N/A * of the specified permission's algorithm implies the specified
0N/A * permission. Returns true if the checking succeeded.
0N/A *
0N/A * @param permission the Permission object to check.
0N/A *
0N/A * @return true if "permission" is implied by the permissions
0N/A * in the PermissionCollection it belongs to, false if not.
0N/A *
0N/A */
0N/A public boolean implies(Permission permission) {
0N/A if (!(permission instanceof CryptoPermission)) {
0N/A return false;
0N/A }
0N/A
0N/A CryptoPermission cryptoPerm = (CryptoPermission)permission;
0N/A
0N/A PermissionCollection pc =
0N/A getPermissionCollection(cryptoPerm.getAlgorithm());
0N/A return pc.implies(cryptoPerm);
0N/A }
0N/A
0N/A /**
0N/A * Returns an enumeration of all the Permission objects in all the
0N/A * PermissionCollections in this CryptoPermissions object.
0N/A *
0N/A * @return an enumeration of all the Permissions.
0N/A */
0N/A public Enumeration elements() {
0N/A // go through each Permissions in the hash table
0N/A // and call their elements() function.
0N/A return new PermissionsEnumerator(perms.elements());
0N/A }
0N/A
0N/A /**
0N/A * Returns a CryptoPermissions object which
0N/A * represents the minimum of the specified
0N/A * CryptoPermissions object and this
0N/A * CryptoPermissions object.
0N/A *
0N/A * @param other the CryptoPermission
0N/A * object to compare with this object.
0N/A */
0N/A CryptoPermissions getMinimum(CryptoPermissions other) {
0N/A if (other == null) {
0N/A return null;
0N/A }
0N/A
0N/A if (this.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
0N/A return other;
0N/A }
0N/A
0N/A if (other.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
0N/A return this;
0N/A }
0N/A
0N/A CryptoPermissions ret = new CryptoPermissions();
0N/A
0N/A
0N/A PermissionCollection thatWildcard =
0N/A (PermissionCollection)other.perms.get(
0N/A CryptoPermission.ALG_NAME_WILDCARD);
0N/A int maxKeySize = 0;
0N/A if (thatWildcard != null) {
0N/A maxKeySize = ((CryptoPermission)
0N/A thatWildcard.elements().nextElement()).getMaxKeySize();
0N/A }
0N/A // For each algorithm in this CryptoPermissions,
0N/A // find out if there is anything we should add into
0N/A // ret.
0N/A Enumeration thisKeys = this.perms.keys();
0N/A while (thisKeys.hasMoreElements()) {
0N/A String alg = (String)thisKeys.nextElement();
0N/A
0N/A PermissionCollection thisPc =
0N/A (PermissionCollection)this.perms.get(alg);
0N/A PermissionCollection thatPc =
0N/A (PermissionCollection)other.perms.get(alg);
0N/A
0N/A CryptoPermission[] partialResult;
0N/A
0N/A if (thatPc == null) {
0N/A if (thatWildcard == null) {
0N/A // The other CryptoPermissions
0N/A // doesn't allow this given
0N/A // algorithm at all. Just skip this
0N/A // algorithm.
0N/A continue;
0N/A }
0N/A partialResult = getMinimum(maxKeySize, thisPc);
0N/A } else {
0N/A partialResult = getMinimum(thisPc, thatPc);
0N/A }
0N/A
0N/A for (int i = 0; i < partialResult.length; i++) {
0N/A ret.add(partialResult[i]);
0N/A }
0N/A }
0N/A
0N/A PermissionCollection thisWildcard =
0N/A (PermissionCollection)this.perms.get(
0N/A CryptoPermission.ALG_NAME_WILDCARD);
0N/A
0N/A // If this CryptoPermissions doesn't
0N/A // have a wildcard, we are done.
0N/A if (thisWildcard == null) {
0N/A return ret;
0N/A }
0N/A
0N/A // Deal with the algorithms only appear
0N/A // in the other CryptoPermissions.
0N/A maxKeySize =
0N/A ((CryptoPermission)
0N/A thisWildcard.elements().nextElement()).getMaxKeySize();
0N/A Enumeration thatKeys = other.perms.keys();
0N/A while (thatKeys.hasMoreElements()) {
0N/A String alg = (String)thatKeys.nextElement();
0N/A
0N/A if (this.perms.containsKey(alg)) {
0N/A continue;
0N/A }
0N/A
0N/A PermissionCollection thatPc =
0N/A (PermissionCollection)other.perms.get(alg);
0N/A
0N/A CryptoPermission[] partialResult;
0N/A
0N/A partialResult = getMinimum(maxKeySize, thatPc);
0N/A
0N/A for (int i = 0; i < partialResult.length; i++) {
0N/A ret.add(partialResult[i]);
0N/A }
0N/A }
0N/A return ret;
0N/A }
0N/A
0N/A /**
0N/A * Get the minimum of the two given PermissionCollection
0N/A * <code>thisPc</code> and <code>thatPc</code>.
0N/A *
0N/A * @param thisPc the first given PermissionColloection
0N/A * object.
0N/A *
0N/A * @param thatPc the second given PermissionCollection
0N/A * object.
0N/A */
0N/A private CryptoPermission[] getMinimum(PermissionCollection thisPc,
0N/A PermissionCollection thatPc) {
0N/A Vector permVector = new Vector(2);
0N/A
0N/A Enumeration thisPcPermissions = thisPc.elements();
0N/A
0N/A // For each CryptoPermission in
0N/A // thisPc object, do the following:
0N/A // 1) if this CryptoPermission is implied
0N/A // by thatPc, this CryptoPermission
0N/A // should be returned, and we can
0N/A // move on to check the next
0N/A // CryptoPermission in thisPc.
0N/A // 2) otherwise, we should return
0N/A // all CryptoPermissions in thatPc
0N/A // which
0N/A // are implied by this CryptoPermission.
0N/A // Then we can move on to the
0N/A // next CryptoPermission in thisPc.
0N/A while (thisPcPermissions.hasMoreElements()) {
0N/A CryptoPermission thisCp =
0N/A (CryptoPermission)thisPcPermissions.nextElement();
0N/A
0N/A Enumeration thatPcPermissions = thatPc.elements();
0N/A while (thatPcPermissions.hasMoreElements()) {
0N/A CryptoPermission thatCp =
0N/A (CryptoPermission)thatPcPermissions.nextElement();
0N/A
0N/A if (thatCp.implies(thisCp)) {
0N/A permVector.addElement(thisCp);
0N/A break;
0N/A }
0N/A if (thisCp.implies(thatCp)) {
0N/A permVector.addElement(thatCp);
0N/A }
0N/A }
0N/A }
0N/A
0N/A CryptoPermission[] ret = new CryptoPermission[permVector.size()];
0N/A permVector.copyInto(ret);
0N/A return ret;
0N/A }
0N/A
0N/A /**
0N/A * Returns all the CryptoPermission objects in the given
0N/A * PermissionCollection object
0N/A * whose maximum keysize no greater than <code>maxKeySize</code>.
0N/A * For all CryptoPermission objects with a maximum keysize greater
0N/A * than <code>maxKeySize</code>, this method constructs a
0N/A * corresponding CryptoPermission object whose maximum keysize is
0N/A * set to <code>maxKeySize</code>, and includes that in the result.
0N/A *
0N/A * @param maxKeySize the given maximum key size.
0N/A *
0N/A * @param pc the given PermissionCollection object.
0N/A */
0N/A private CryptoPermission[] getMinimum(int maxKeySize,
0N/A PermissionCollection pc) {
0N/A Vector permVector = new Vector(1);
0N/A
0N/A Enumeration enum_ = pc.elements();
0N/A
0N/A while (enum_.hasMoreElements()) {
0N/A CryptoPermission cp =
0N/A (CryptoPermission)enum_.nextElement();
0N/A if (cp.getMaxKeySize() <= maxKeySize) {
0N/A permVector.addElement(cp);
0N/A } else {
0N/A if (cp.getCheckParam()) {
0N/A permVector.addElement(
0N/A new CryptoPermission(cp.getAlgorithm(),
0N/A maxKeySize,
0N/A cp.getAlgorithmParameterSpec(),
0N/A cp.getExemptionMechanism()));
0N/A } else {
0N/A permVector.addElement(
0N/A new CryptoPermission(cp.getAlgorithm(),
0N/A maxKeySize,
0N/A cp.getExemptionMechanism()));
0N/A }
0N/A }
0N/A }
0N/A
0N/A CryptoPermission[] ret = new CryptoPermission[permVector.size()];
0N/A permVector.copyInto(ret);
0N/A return ret;
0N/A }
0N/A
0N/A /**
0N/A * Returns the PermissionCollection for the
0N/A * specified algorithm. Returns null if there
0N/A * isn't such a PermissionCollection.
0N/A *
0N/A * @param alg the algorithm name.
0N/A */
0N/A PermissionCollection getPermissionCollection(String alg) {
0N/A // If this CryptoPermissions includes CryptoAllPermission,
0N/A // we should return CryptoAllPermission.
5296N/A PermissionCollection pc = perms.get(CryptoAllPermission.ALG_NAME);
5296N/A if (pc == null) {
5296N/A pc = perms.get(alg);
0N/A
5296N/A // If there isn't a PermissionCollection for
5296N/A // the given algorithm,we should return the
5296N/A // PermissionCollection for the wildcard
5296N/A // if there is one.
5296N/A if (pc == null) {
5296N/A pc = perms.get(CryptoPermission.ALG_NAME_WILDCARD);
5296N/A }
0N/A }
0N/A return pc;
0N/A }
0N/A
0N/A /**
0N/A * Returns the PermissionCollection for the algorithm
0N/A * associated with the specified CryptoPermission
0N/A * object. Creates such a PermissionCollection
0N/A * if such a PermissionCollection does not
0N/A * exist yet.
0N/A *
0N/A * @param cryptoPerm the CryptoPermission object.
0N/A */
0N/A private PermissionCollection getPermissionCollection(
0N/A CryptoPermission cryptoPerm) {
0N/A
0N/A String alg = cryptoPerm.getAlgorithm();
0N/A
0N/A PermissionCollection pc = (PermissionCollection)perms.get(alg);
0N/A
0N/A if (pc == null) {
0N/A pc = cryptoPerm.newPermissionCollection();
0N/A }
0N/A return pc;
0N/A }
5296N/A
5296N/A private void readObject(ObjectInputStream s)
5296N/A throws IOException, ClassNotFoundException {
5296N/A ObjectInputStream.GetField fields = s.readFields();
5296N/A @SuppressWarnings("unchecked")
5296N/A Hashtable<String,PermissionCollection> permTable =
5296N/A (Hashtable<String,PermissionCollection>)
5296N/A (fields.get("perms", null));
5296N/A if (permTable != null) {
5296N/A perms = new ConcurrentHashMap<>(permTable);
5296N/A } else {
5296N/A perms = new ConcurrentHashMap<>();
5296N/A }
5296N/A }
5296N/A
5296N/A private void writeObject(ObjectOutputStream s) throws IOException {
5296N/A Hashtable<String,PermissionCollection> permTable =
5296N/A new Hashtable<>(perms);
5296N/A ObjectOutputStream.PutField fields = s.putFields();
5296N/A fields.put("perms", permTable);
5296N/A s.writeFields();
5296N/A }
0N/A}
0N/A
0N/Afinal class PermissionsEnumerator implements Enumeration {
0N/A
0N/A // all the perms
0N/A private Enumeration perms;
0N/A // the current set
0N/A private Enumeration permset;
0N/A
0N/A PermissionsEnumerator(Enumeration e) {
0N/A perms = e;
0N/A permset = getNextEnumWithMore();
0N/A }
0N/A
0N/A public synchronized boolean hasMoreElements() {
0N/A // if we enter with permissionimpl null, we know
0N/A // there are no more left.
0N/A
0N/A if (permset == null)
0N/A return false;
0N/A
0N/A // try to see if there are any left in the current one
0N/A
0N/A if (permset.hasMoreElements())
0N/A return true;
0N/A
0N/A // get the next one that has something in it...
0N/A permset = getNextEnumWithMore();
0N/A
0N/A // if it is null, we are done!
0N/A return (permset != null);
0N/A }
0N/A
0N/A public synchronized Object nextElement() {
0N/A // hasMoreElements will update permset to the next permset
0N/A // with something in it...
0N/A
0N/A if (hasMoreElements()) {
0N/A return permset.nextElement();
0N/A } else {
0N/A throw new NoSuchElementException("PermissionsEnumerator");
0N/A }
0N/A }
0N/A
0N/A private Enumeration getNextEnumWithMore() {
0N/A while (perms.hasMoreElements()) {
0N/A PermissionCollection pc =
0N/A (PermissionCollection) perms.nextElement();
0N/A Enumeration next = pc.elements();
0N/A if (next.hasMoreElements())
0N/A return next;
0N/A }
0N/A return null;
0N/A }
0N/A}