| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package javax.crypto;  | 
 | 
 | 
 | 
import java.security.*;  | 
 | 
import java.util.Enumeration;  | 
 | 
import java.util.Hashtable;  | 
 | 
import java.util.Vector;  | 
 | 
import java.util.NoSuchElementException;  | 
 | 
import java.util.concurrent.ConcurrentHashMap;  | 
 | 
import java.io.Serializable;  | 
 | 
import java.io.InputStream;  | 
 | 
import java.io.InputStreamReader;  | 
 | 
import java.io.BufferedReader;  | 
 | 
import java.io.ObjectStreamField;  | 
 | 
import java.io.ObjectInputStream;  | 
 | 
import java.io.ObjectInputStream.GetField;  | 
 | 
import java.io.ObjectOutputStream;  | 
 | 
import java.io.ObjectOutputStream.PutField;  | 
 | 
import java.io.IOException;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
final class CryptoPermissions extends PermissionCollection  | 
 | 
implements Serializable { | 
 | 
 | 
 | 
    private static final long serialVersionUID = 4946547168093391015L;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private static final ObjectStreamField[] serialPersistentFields = { | 
 | 
        new ObjectStreamField("perms", Hashtable.class), | 
 | 
    };  | 
 | 
 | 
 | 
    // Switched from Hashtable to ConcurrentHashMap to improve scalability.  | 
 | 
    // To maintain serialization compatibility, this field is made transient  | 
 | 
      | 
 | 
    private transient ConcurrentHashMap<String,PermissionCollection> perms;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    CryptoPermissions() { | 
 | 
        perms = new ConcurrentHashMap<>(7);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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]);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    boolean isEmpty() { | 
 | 
        return perms.isEmpty();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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();  | 
 | 
        perms.putIfAbsent(alg, pc);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public boolean implies(Permission permission) { | 
 | 
        if (!(permission instanceof CryptoPermission)) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
        CryptoPermission cryptoPerm = (CryptoPermission)permission;  | 
 | 
 | 
 | 
        PermissionCollection pc =  | 
 | 
            getPermissionCollection(cryptoPerm.getAlgorithm());  | 
 | 
        return pc.implies(cryptoPerm);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Enumeration<Permission> elements() { | 
 | 
        // go through each Permissions in the hash table  | 
 | 
          | 
 | 
        return new PermissionsEnumerator(perms.elements());  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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 =  | 
 | 
                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  | 
 | 
          | 
 | 
        Enumeration<String> thisKeys = this.perms.keys();  | 
 | 
        while (thisKeys.hasMoreElements()) { | 
 | 
            String alg = thisKeys.nextElement();  | 
 | 
 | 
 | 
            PermissionCollection thisPc = this.perms.get(alg);  | 
 | 
            PermissionCollection thatPc = 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  | 
 | 
                      | 
 | 
                    continue;  | 
 | 
                }  | 
 | 
                partialResult = getMinimum(maxKeySize, thisPc);  | 
 | 
            } else { | 
 | 
                partialResult = getMinimum(thisPc, thatPc);  | 
 | 
            }  | 
 | 
 | 
 | 
            for (int i = 0; i < partialResult.length; i++) { | 
 | 
                ret.add(partialResult[i]);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        PermissionCollection thisWildcard =  | 
 | 
                this.perms.get(CryptoPermission.ALG_NAME_WILDCARD);  | 
 | 
 | 
 | 
        // If this CryptoPermissions doesn't  | 
 | 
          | 
 | 
        if (thisWildcard == null) { | 
 | 
            return ret;  | 
 | 
        }  | 
 | 
 | 
 | 
        // Deal with the algorithms only appear  | 
 | 
          | 
 | 
        maxKeySize =  | 
 | 
            ((CryptoPermission)  | 
 | 
                    thisWildcard.elements().nextElement()).getMaxKeySize();  | 
 | 
        Enumeration<String> thatKeys = other.perms.keys();  | 
 | 
        while (thatKeys.hasMoreElements()) { | 
 | 
            String alg = thatKeys.nextElement();  | 
 | 
 | 
 | 
            if (this.perms.containsKey(alg)) { | 
 | 
                continue;  | 
 | 
            }  | 
 | 
 | 
 | 
            PermissionCollection thatPc = other.perms.get(alg);  | 
 | 
 | 
 | 
            CryptoPermission[] partialResult;  | 
 | 
 | 
 | 
            partialResult = getMinimum(maxKeySize, thatPc);  | 
 | 
 | 
 | 
            for (int i = 0; i < partialResult.length; i++) { | 
 | 
                ret.add(partialResult[i]);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return ret;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private CryptoPermission[] getMinimum(PermissionCollection thisPc,  | 
 | 
                                          PermissionCollection thatPc) { | 
 | 
        Vector<CryptoPermission> permVector = new Vector<>(2);  | 
 | 
 | 
 | 
        Enumeration<Permission> 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  | 
 | 
          | 
 | 
        while (thisPcPermissions.hasMoreElements()) { | 
 | 
            CryptoPermission thisCp =  | 
 | 
                (CryptoPermission)thisPcPermissions.nextElement();  | 
 | 
 | 
 | 
            Enumeration<Permission> 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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private CryptoPermission[] getMinimum(int maxKeySize,  | 
 | 
                                          PermissionCollection pc) { | 
 | 
        Vector<CryptoPermission> permVector = new Vector<>(1);  | 
 | 
 | 
 | 
        Enumeration<Permission> 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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    PermissionCollection getPermissionCollection(String alg) { | 
 | 
        // If this CryptoPermissions includes CryptoAllPermission,  | 
 | 
          | 
 | 
        PermissionCollection pc = perms.get(CryptoAllPermission.ALG_NAME);  | 
 | 
        if (pc == null) { | 
 | 
            pc = perms.get(alg);  | 
 | 
 | 
 | 
            // If there isn't a PermissionCollection for  | 
 | 
            // the given algorithm,we should return the  | 
 | 
            // PermissionCollection for the wildcard  | 
 | 
              | 
 | 
            if (pc == null) { | 
 | 
                pc = perms.get(CryptoPermission.ALG_NAME_WILDCARD);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return pc;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private PermissionCollection getPermissionCollection(  | 
 | 
                                          CryptoPermission cryptoPerm) { | 
 | 
 | 
 | 
        String alg = cryptoPerm.getAlgorithm();  | 
 | 
 | 
 | 
        PermissionCollection pc = perms.get(alg);  | 
 | 
 | 
 | 
        if (pc == null) { | 
 | 
            pc = cryptoPerm.newPermissionCollection();  | 
 | 
        }  | 
 | 
        return pc;  | 
 | 
    }  | 
 | 
 | 
 | 
    private void readObject(ObjectInputStream s)  | 
 | 
        throws IOException, ClassNotFoundException { | 
 | 
        ObjectInputStream.GetField fields = s.readFields();  | 
 | 
        @SuppressWarnings("unchecked") | 
 | 
        Hashtable<String,PermissionCollection> permTable =  | 
 | 
                (Hashtable<String,PermissionCollection>)  | 
 | 
                (fields.get("perms", null)); | 
 | 
        if (permTable != null) { | 
 | 
            perms = new ConcurrentHashMap<>(permTable);  | 
 | 
        } else { | 
 | 
            perms = new ConcurrentHashMap<>();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void writeObject(ObjectOutputStream s) throws IOException { | 
 | 
        Hashtable<String,PermissionCollection> permTable =  | 
 | 
                new Hashtable<>(perms);  | 
 | 
        ObjectOutputStream.PutField fields = s.putFields();  | 
 | 
        fields.put("perms", permTable); | 
 | 
        s.writeFields();  | 
 | 
    }  | 
 | 
}  | 
 | 
 | 
 | 
final class PermissionsEnumerator implements Enumeration<Permission> { | 
 | 
 | 
 | 
      | 
 | 
    private Enumeration<PermissionCollection> perms;  | 
 | 
      | 
 | 
    private Enumeration<Permission> permset;  | 
 | 
 | 
 | 
    PermissionsEnumerator(Enumeration<PermissionCollection> 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;  | 
 | 
 | 
 | 
          | 
 | 
        permset = getNextEnumWithMore();  | 
 | 
 | 
 | 
          | 
 | 
        return (permset != null);  | 
 | 
    }  | 
 | 
 | 
 | 
    public synchronized Permission 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<Permission> getNextEnumWithMore() { | 
 | 
        while (perms.hasMoreElements()) { | 
 | 
            PermissionCollection pc = perms.nextElement();  | 
 | 
            Enumeration<Permission> next = pc.elements();  | 
 | 
            if (next.hasMoreElements())  | 
 | 
                return next;  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
}  |