home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / security / UnresolvedPermission.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  12.9 KB  |  432 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)UnresolvedPermission.java    1.13 98/09/15
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.io.IOException;
  18. import java.io.ByteArrayInputStream;
  19. import java.util.ArrayList;
  20. import java.util.Enumeration;
  21. import java.util.Hashtable;
  22. import java.util.Vector;
  23. import java.lang.reflect.*;
  24. import java.security.cert.*;
  25.  
  26. /**
  27.  * The UnresolvedPermission class is used to hold Permissions that
  28.  * were "unresolved" when the Policy was initialized. 
  29.  * An unresolved permission is one whose actual Permission class
  30.  * does not yet exist at the time the Policy is initialized (see below).
  31.  * 
  32.  * <p>The policy for a Java runtime (specifying 
  33.  * which permissions are available for code from various principals)
  34.  * is represented by a Policy object.
  35.  * Whenever a Policy is initialized or refreshed, Permission objects of
  36.  * appropriate classes are created for all permissions
  37.  * allowed by the Policy. 
  38.  * 
  39.  * <p>Many permission class types 
  40.  * referenced by the policy configuration are ones that exist
  41.  * locally (i.e., ones that can be found on CLASSPATH).
  42.  * Objects for such permissions can be instantiated during
  43.  * Policy initialization. For example, it is always possible
  44.  * to instantiate a java.io.FilePermission, since the
  45.  * FilePermission class is found on the CLASSPATH.
  46.  * 
  47.  * <p>Other permission classes may not yet exist during Policy
  48.  * initialization. For example, a referenced permission class may
  49.  * be in a JAR file that will later be loaded.
  50.  * For each such class, an UnresolvedPermission is instantiated.
  51.  * Thus, an UnresolvedPermission is essentially a "placeholder"
  52.  * containing information about the permission.
  53.  * 
  54.  * <p>Later, when code calls AccessController.checkPermission 
  55.  * on a permission of a type that was previously unresolved,
  56.  * but whose class has since been loaded, previously-unresolved
  57.  * permissions of that type are "resolved". That is,
  58.  * for each such UnresolvedPermission, a new object of
  59.  * the appropriate class type is instantiated, based on the
  60.  * information in the UnresolvedPermission. This new object
  61.  * replaces the UnresolvedPermission, which is removed.
  62.  *
  63.  * @see java.security.Permission
  64.  * @see java.security.Permissions
  65.  * @see java.security.PermissionCollection
  66.  * @see java.security.Policy
  67.  *
  68.  * @version 1.13 99/03/26
  69.  *
  70.  * @author Roland Schemers
  71.  */
  72.  
  73. public final class UnresolvedPermission extends Permission 
  74. implements java.io.Serializable
  75. {
  76.     /**
  77.      * The class name of the Permission class that will be
  78.      * created when this unresolved permission is resolved.
  79.      *
  80.      * @serial
  81.      */
  82.     private String type;
  83.  
  84.     /**
  85.      * The permission name.
  86.      *
  87.      * @serial
  88.      */
  89.     private String name;
  90.  
  91.     /**
  92.      * The actions of the permission.
  93.      *
  94.      * @serial
  95.      */
  96.     private String actions;
  97.  
  98.     private transient java.security.cert.Certificate certs[];
  99.  
  100.     /**
  101.      * Creates a new UnresolvedPermission containing the permission
  102.      * information needed later to actually create a Permission of the
  103.      * specified class, when the permission is resolved.
  104.      * 
  105.      * @param type the class name of the Permission class that will be
  106.      * created when this unresolved permission is resolved.
  107.      * @param name the name of the permission.
  108.      * @param actions the actions of the permission.
  109.      * @param certs the certificates the permission's class was signed with.
  110.      * This is a list of certificate chains, where each chain is composed of a
  111.      * signer certificate and optionally its supporting certificate chain.
  112.      * Each chain is ordered bottom-to-top (i.e., with the signer certificate
  113.      * first and the (root) certificate authority last).
  114.      */
  115.     public UnresolvedPermission(String type,
  116.                 String name,
  117.                 String actions,
  118.                 java.security.cert.Certificate certs[])
  119.     {
  120.     super(type);
  121.     this.type = type;
  122.     this.name = name;
  123.     this.actions = actions;
  124.     if (certs != null) {
  125.         // Extract the signer certs from the list of certificates.
  126.         for (int i=0; i<certs.length; i++) {
  127.         if (!(certs[i] instanceof X509Certificate)) {
  128.             // there is no concept of signer certs, so we store the
  129.             // entire cert array
  130.             this.certs =
  131.             (java.security.cert.Certificate[])certs.clone();
  132.             break;
  133.         }
  134.         }
  135.  
  136.         if (this.certs == null) {
  137.         // Go through the list of certs and see if all the certs are
  138.         // signer certs.
  139.         int i = 0;
  140.         int count = 0;
  141.         while (i < certs.length) {
  142.             count++;
  143.             while (((i+1) < certs.length) &&
  144.                ((X509Certificate)certs[i]).getIssuerDN().equals(
  145.                        ((X509Certificate)certs[i+1]).getSubjectDN())) {
  146.             i++;
  147.             }
  148.             i++;
  149.         }
  150.         if (count == certs.length) {
  151.             // All the certs are signer certs, so we store the entire
  152.             // array
  153.             this.certs =
  154.             (java.security.cert.Certificate[])certs.clone();
  155.         }
  156.  
  157.         if (this.certs == null) {
  158.             // extract the signer certs
  159.             ArrayList signerCerts = new ArrayList();
  160.             i = 0;
  161.             while (i < certs.length) {
  162.             signerCerts.add(certs[i]);
  163.             while (((i+1) < certs.length) &&
  164.                 ((X509Certificate)certs[i]).getIssuerDN().equals(
  165.                            ((X509Certificate)certs[i+1]).getSubjectDN())) {
  166.                 i++;
  167.             }
  168.             i++;
  169.             }
  170.             this.certs =
  171.             new java.security.cert.Certificate[signerCerts.size()];
  172.             signerCerts.toArray(this.certs);
  173.         }
  174.         }
  175.     }
  176.     }
  177.  
  178.  
  179.     private static final Class[] PARAMS = { String.class, String.class};
  180.  
  181.     /**
  182.      * try and resolve this permission using the class loader of the permission
  183.      * that was passed in.
  184.      */
  185.     Permission resolve(Permission p, java.security.cert.Certificate certs[]) {
  186.     if (this.certs != null) {
  187.         // if p wasn't signed, we don't have a match
  188.         if (certs == null) {
  189.         return null;
  190.         }
  191.  
  192.         // all certs in this.certs must be present in certs
  193.         boolean match;
  194.         for (int i = 0; i < this.certs.length; i++) {
  195.         match = false;
  196.         for (int j = 0; j < certs.length; j++) {
  197.             if (this.certs[i].equals(certs[j])) {
  198.             match = true;
  199.             break;
  200.             }
  201.         }
  202.         if (!match) return null;
  203.         }
  204.     }
  205.     try {
  206.         Class pc = p.getClass();
  207.         Constructor c = pc.getConstructor(PARAMS);
  208.         return (Permission) c.newInstance(new Object[] { name, actions });
  209.     } catch (Exception e) {
  210.         return null;
  211.     }
  212.     }
  213.  
  214.     /**
  215.      * This method always returns false for unresolved permissions.
  216.      * That is, an UnresolvedPermission is never considered to
  217.      * imply another permission.
  218.      *
  219.      * @param p the permission to check against.
  220.      * 
  221.      * @return false.
  222.      */
  223.     public boolean implies(Permission p) {
  224.     return false;
  225.     }
  226.  
  227.     /**
  228.      * Checks two UnresolvedPermission objects for equality. 
  229.      * Checks that <i>obj</i> is an UnresolvedPermission, and has 
  230.      * the same type (class) name, permission name, actions, and
  231.      * certificates as this object.
  232.      * 
  233.      * @param obj the object we are testing for equality with this object.
  234.      * 
  235.      * @return true if obj is an UnresolvedPermission, and has the same 
  236.      * type (class) name, permission name, actions, and
  237.      * certificates as this object.
  238.      */
  239.     public boolean equals(Object obj) {
  240.     if (obj == this)
  241.         return true;
  242.  
  243.     if (! (obj instanceof UnresolvedPermission))
  244.         return false;
  245.     UnresolvedPermission that = (UnresolvedPermission) obj;
  246.  
  247.     if (!(this.type.equals(that.type) &&
  248.         this.name.equals(that.name) &&
  249.         this.actions.equals(that.actions)))
  250.         return false;
  251.  
  252.     if (this.certs.length != that.certs.length)
  253.         return false;
  254.         
  255.     int i,j;
  256.     boolean match;
  257.  
  258.     for (i = 0; i < this.certs.length; i++) {
  259.         match = false;
  260.         for (j = 0; j < that.certs.length; j++) {
  261.         if (this.certs[i].equals(that.certs[j])) {
  262.             match = true;
  263.             break;
  264.         }
  265.         }
  266.         if (!match) return false;
  267.     }
  268.  
  269.     for (i = 0; i < that.certs.length; i++) {
  270.         match = false;
  271.         for (j = 0; j < this.certs.length; j++) {
  272.         if (that.certs[i].equals(this.certs[j])) {
  273.             match = true;
  274.             break;
  275.         }
  276.         }
  277.         if (!match) return false;
  278.     }
  279.     return true;
  280.     }
  281.  
  282.     /**
  283.      * Returns the hash code value for this object.
  284.      *
  285.      * @return a hash code value for this object.
  286.      */
  287.  
  288.     public int hashCode() {
  289.     int hash = type.hashCode();
  290.     if (name != null)
  291.         hash ^= name.hashCode();
  292.     if (actions != null)
  293.         hash ^= actions.hashCode();
  294.     return hash;
  295.     }
  296.  
  297.     /**
  298.      * Returns the canonical string representation of the actions,
  299.      * which currently is the empty string "", since there are no actions for 
  300.      * an UnresolvedPermission. That is, the actions for the
  301.      * permission that will be created when this UnresolvedPermission
  302.      * is resolved may be non-null, but an UnresolvedPermission
  303.      * itself is never considered to have any actions.
  304.      *
  305.      * @return the empty string "".
  306.      */
  307.     public String getActions()
  308.     {
  309.     return "";
  310.     }
  311.  
  312.     /**
  313.      * Returns a string describing this UnresolvedPermission.  The convention 
  314.      * is to specify the class name, the permission name, and the actions, in
  315.      * the following format: '(unresolved "ClassName" "name" "actions")'.
  316.      * 
  317.      * @return information about this UnresolvedPermission.
  318.      */
  319.     public String toString() {
  320.     return "(unresolved " + type + " " + name + " " + actions + ")";
  321.     }
  322.  
  323.     /**
  324.      * Returns a new PermissionCollection object for storing 
  325.      * UnresolvedPermission  objects.
  326.      * <p>
  327.      * @return a new PermissionCollection object suitable for 
  328.      * storing UnresolvedPermissions.
  329.      */
  330.  
  331.     public PermissionCollection newPermissionCollection() {
  332.     return new UnresolvedPermissionCollection();
  333.     }
  334.  
  335.     /**
  336.      * Writes this object out to a stream (i.e., serializes it).
  337.      *
  338.      * @serialData An initial <code>String</code> denoting the
  339.      * <code>type</code> is followed by a <code>String</code> denoting the
  340.      * <code>name</code> is followed by a <code>String</code> denoting the
  341.      * <code>actions</code> is followed by an <code>int</code> indicating the
  342.      * number of certificates to follow 
  343.      * (a value of "zero" denotes that there are no certificates associated
  344.      * with this object).
  345.      * Each certificate is written out starting with a <code>String</code>
  346.      * denoting the certificate type, followed by an
  347.      * <code>int</code> specifying the length of the certificate encoding,
  348.      * followed by the certificate encoding itself which is written out as an
  349.      * array of bytes.
  350.      */
  351.     private synchronized void writeObject(java.io.ObjectOutputStream oos)
  352.         throws IOException
  353.     {
  354.     oos.defaultWriteObject();
  355.  
  356.     if (certs==null || certs.length==0) {
  357.         oos.writeInt(0);
  358.     } else {
  359.         // write out the total number of certs
  360.         oos.writeInt(certs.length);
  361.         // write out each cert, including its type
  362.         for (int i=0; i < certs.length; i++) {
  363.         java.security.cert.Certificate cert = certs[i];
  364.         try {
  365.             oos.writeUTF(cert.getType());
  366.             byte[] encoded = cert.getEncoded();
  367.             oos.writeInt(encoded.length);
  368.             oos.write(encoded);
  369.         } catch (CertificateEncodingException cee) {
  370.             throw new IOException(cee.getMessage());
  371.         }
  372.         }
  373.     }
  374.     }
  375.  
  376.     /**
  377.      * Restores this object from a stream (i.e., deserializes it).
  378.      */
  379.     private synchronized void readObject(java.io.ObjectInputStream ois)
  380.     throws IOException, ClassNotFoundException
  381.     {
  382.     CertificateFactory cf;
  383.     Hashtable cfs=null;
  384.  
  385.     ois.defaultReadObject();
  386.  
  387.     // process any new-style certs in the stream (if present)
  388.     int size = ois.readInt();
  389.     if (size > 0) {
  390.         // we know of 3 different cert types: X.509, PGP, SDSI, which
  391.         // could all be present in the stream at the same time
  392.         cfs = new Hashtable(3);
  393.         this.certs = new java.security.cert.Certificate[size];
  394.     }
  395.  
  396.     for (int i=0; i<size; i++) {
  397.         // read the certificate type, and instantiate a certificate
  398.         // factory of that type (reuse existing factory if possible)
  399.         String certType = ois.readUTF();
  400.         if (cfs.containsKey(certType)) {
  401.         // reuse certificate factory
  402.         cf = (CertificateFactory)cfs.get(certType);
  403.         } else {
  404.         // create new certificate factory
  405.         try {
  406.             cf = CertificateFactory.getInstance(certType);
  407.         } catch (CertificateException ce) {
  408.             throw new ClassNotFoundException
  409.             ("Certificate factory for "+certType+" not found");
  410.         }
  411.         // store the certificate factory so we can reuse it later
  412.         cfs.put(certType, cf);
  413.         }
  414.         // parse the certificate
  415.         byte[] encoded=null;
  416.         try {
  417.         encoded = new byte[ois.readInt()];
  418.         } catch (OutOfMemoryError oome) {
  419.         throw new IOException("Certificate too big");
  420.         }
  421.         ois.readFully(encoded);
  422.         ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
  423.         try {
  424.         this.certs[i] = cf.generateCertificate(bais);
  425.         } catch (CertificateException ce) {
  426.         throw new IOException(ce.getMessage());
  427.         }
  428.         bais.close();
  429.     }
  430.     }
  431. }
  432.