| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package javax.security.auth.kerberos;  | 
 | 
 | 
 | 
import java.util.*;  | 
 | 
import java.security.Permission;  | 
 | 
import java.security.BasicPermission;  | 
 | 
import java.security.PermissionCollection;  | 
 | 
import java.io.ObjectStreamField;  | 
 | 
import java.io.ObjectOutputStream;  | 
 | 
import java.io.ObjectInputStream;  | 
 | 
import java.io.IOException;  | 
 | 
 | 
 | 
/**  | 
 | 
 * This class is used to restrict the usage of the Kerberos  | 
 | 
 * delegation model, ie: forwardable and proxiable tickets.  | 
 | 
 * <p>  | 
 | 
 * The target name of this {@code Permission} specifies a pair of | 
 | 
 * kerberos service principals. The first is the subordinate service principal  | 
 | 
 * being entrusted to use the TGT. The second service principal designates  | 
 | 
 * the target service the subordinate service principal is to  | 
 | 
 * interact with on behalf of the initiating KerberosPrincipal. This  | 
 | 
 * latter service principal is specified to restrict the use of a  | 
 | 
 * proxiable ticket.  | 
 | 
 * <p>  | 
 | 
 * For example, to specify the "host" service use of a forwardable TGT the  | 
 | 
 * target permission is specified as follows:  | 
 | 
 *  | 
 | 
 * <pre>  | 
 | 
 *  DelegationPermission("\"host/foo.example.com@EXAMPLE.COM\" \"krbtgt/EXAMPLE.COM@EXAMPLE.COM\""); | 
 | 
 * </pre>  | 
 | 
 * <p>  | 
 | 
 * To give the "backup" service a proxiable nfs service ticket the target permission  | 
 | 
 * might be specified:  | 
 | 
 *  | 
 | 
 * <pre>  | 
 | 
 *  DelegationPermission("\"backup/bar.example.com@EXAMPLE.COM\" \"nfs/home.EXAMPLE.COM@EXAMPLE.COM\""); | 
 | 
 * </pre>  | 
 | 
 *  | 
 | 
 * @since 1.4  | 
 | 
 */  | 
 | 
 | 
 | 
public final class DelegationPermission extends BasicPermission  | 
 | 
    implements java.io.Serializable { | 
 | 
 | 
 | 
    private static final long serialVersionUID = 883133252142523922L;  | 
 | 
 | 
 | 
    private transient String subordinate, service;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public DelegationPermission(String principals) { | 
 | 
        super(principals);  | 
 | 
        init(principals);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public DelegationPermission(String principals, String actions) { | 
 | 
        super(principals, actions);  | 
 | 
        init(principals);  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private void init(String target) { | 
 | 
 | 
 | 
        StringTokenizer t = null;  | 
 | 
        if (!target.startsWith("\"")) { | 
 | 
            throw new IllegalArgumentException  | 
 | 
                ("service principal [" + target + | 
 | 
                 "] syntax invalid: " +  | 
 | 
                 "improperly quoted");  | 
 | 
        } else { | 
 | 
            t = new StringTokenizer(target, "\"", false);  | 
 | 
            subordinate = t.nextToken();  | 
 | 
            if (t.countTokens() == 2) { | 
 | 
                t.nextToken();    | 
 | 
                service = t.nextToken();  | 
 | 
            } else if (t.countTokens() > 0) { | 
 | 
                throw new IllegalArgumentException  | 
 | 
                    ("service principal [" + t.nextToken() + | 
 | 
                     "] syntax invalid: " +  | 
 | 
                     "improperly quoted");  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public boolean implies(Permission p) { | 
 | 
        if (!(p instanceof DelegationPermission))  | 
 | 
            return false;  | 
 | 
 | 
 | 
        DelegationPermission that = (DelegationPermission) p;  | 
 | 
        if (this.subordinate.equals(that.subordinate) &&  | 
 | 
            this.service.equals(that.service))  | 
 | 
            return true;  | 
 | 
 | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public boolean equals(Object obj) { | 
 | 
        if (obj == this)  | 
 | 
            return true;  | 
 | 
 | 
 | 
        if (! (obj instanceof DelegationPermission))  | 
 | 
            return false;  | 
 | 
 | 
 | 
        DelegationPermission that = (DelegationPermission) obj;  | 
 | 
        return implies(that);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public int hashCode() { | 
 | 
        return getName().hashCode();  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    /**  | 
 | 
     * Returns a PermissionCollection object for storing  | 
 | 
     * DelegationPermission objects.  | 
 | 
     * <br>  | 
 | 
     * DelegationPermission objects must be stored in a manner that  | 
 | 
     * allows them to be inserted into the collection in any order, but  | 
 | 
     * that also enables the PermissionCollection implies method to  | 
 | 
     * be implemented in an efficient (and consistent) manner.  | 
 | 
     *  | 
 | 
     * @return a new PermissionCollection object suitable for storing  | 
 | 
     * DelegationPermissions.  | 
 | 
     */  | 
 | 
 | 
 | 
    public PermissionCollection newPermissionCollection() { | 
 | 
        return new KrbDelegationPermissionCollection();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private synchronized void writeObject(java.io.ObjectOutputStream s)  | 
 | 
        throws IOException  | 
 | 
    { | 
 | 
        s.defaultWriteObject();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private synchronized void readObject(java.io.ObjectInputStream s)  | 
 | 
         throws IOException, ClassNotFoundException  | 
 | 
    { | 
 | 
          | 
 | 
        s.defaultReadObject();  | 
 | 
        init(getName());  | 
 | 
    }  | 
 | 
 | 
 | 
    /*  | 
 | 
      public static void main(String args[]) throws Exception { | 
 | 
      DelegationPermission this_ =  | 
 | 
      new DelegationPermission(args[0]);  | 
 | 
      DelegationPermission that_ =  | 
 | 
      new DelegationPermission(args[1]);  | 
 | 
      System.out.println("-----\n"); | 
 | 
      System.out.println("this.implies(that) = " + this_.implies(that_)); | 
 | 
      System.out.println("-----\n"); | 
 | 
      System.out.println("this = "+this_); | 
 | 
      System.out.println("-----\n"); | 
 | 
      System.out.println("that = "+that_); | 
 | 
      System.out.println("-----\n"); | 
 | 
 | 
 | 
      KrbDelegationPermissionCollection nps =  | 
 | 
      new KrbDelegationPermissionCollection();  | 
 | 
      nps.add(this_);  | 
 | 
      nps.add(new DelegationPermission("\"host/foo.example.com@EXAMPLE.COM\" \"CN=Gary Ellison/OU=JSN/O=SUNW/L=Palo Alto/ST=CA/C=US\"")); | 
 | 
      try { | 
 | 
      nps.add(new DelegationPermission("host/foo.example.com@EXAMPLE.COM \"CN=Gary Ellison/OU=JSN/O=SUNW/L=Palo Alto/ST=CA/C=US\"")); | 
 | 
      } catch (Exception e) { | 
 | 
      System.err.println(e);  | 
 | 
      }  | 
 | 
 | 
 | 
      System.out.println("nps.implies(that) = " + nps.implies(that_)); | 
 | 
      System.out.println("-----\n"); | 
 | 
 | 
 | 
      Enumeration e = nps.elements();  | 
 | 
 | 
 | 
      while (e.hasMoreElements()) { | 
 | 
      DelegationPermission x =  | 
 | 
      (DelegationPermission) e.nextElement();  | 
 | 
      System.out.println("nps.e = " + x); | 
 | 
      }  | 
 | 
      }  | 
 | 
    */  | 
 | 
}  | 
 | 
 | 
 | 
 | 
 | 
final class KrbDelegationPermissionCollection extends PermissionCollection  | 
 | 
    implements java.io.Serializable { | 
 | 
 | 
 | 
      | 
 | 
    private transient List<Permission> perms;  | 
 | 
 | 
 | 
    public KrbDelegationPermissionCollection() { | 
 | 
        perms = new ArrayList<Permission>();  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public boolean implies(Permission permission) { | 
 | 
        if (! (permission instanceof DelegationPermission))  | 
 | 
                return false;  | 
 | 
 | 
 | 
        synchronized (this) { | 
 | 
            for (Permission x : perms) { | 
 | 
                if (x.implies(permission))  | 
 | 
                    return true;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return false;  | 
 | 
 | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void add(Permission permission) { | 
 | 
        if (! (permission instanceof DelegationPermission))  | 
 | 
            throw new IllegalArgumentException("invalid permission: "+ | 
 | 
                                               permission);  | 
 | 
        if (isReadOnly())  | 
 | 
            throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection"); | 
 | 
 | 
 | 
        synchronized (this) { | 
 | 
            perms.add(0, permission);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Enumeration<Permission> elements() { | 
 | 
          | 
 | 
        synchronized (this) { | 
 | 
            return Collections.enumeration(perms);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private static final long serialVersionUID = -3383936936589966948L;  | 
 | 
 | 
 | 
    // Need to maintain serialization interoperability with earlier releases,  | 
 | 
    // which had the serializable field:  | 
 | 
    //    private Vector permissions;  | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final ObjectStreamField[] serialPersistentFields = { | 
 | 
        new ObjectStreamField("permissions", Vector.class), | 
 | 
    };  | 
 | 
 | 
 | 
    /**  | 
 | 
     * @serialData "permissions" field (a Vector containing the DelegationPermissions).  | 
 | 
     */  | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void writeObject(ObjectOutputStream out) throws IOException { | 
 | 
        // Don't call out.defaultWriteObject()  | 
 | 
 | 
 | 
          | 
 | 
        Vector<Permission> permissions = new Vector<>(perms.size());  | 
 | 
 | 
 | 
        synchronized (this) { | 
 | 
            permissions.addAll(perms);  | 
 | 
        }  | 
 | 
 | 
 | 
        ObjectOutputStream.PutField pfields = out.putFields();  | 
 | 
        pfields.put("permissions", permissions); | 
 | 
        out.writeFields();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    @SuppressWarnings("unchecked") | 
 | 
    private void readObject(ObjectInputStream in)  | 
 | 
        throws IOException, ClassNotFoundException  | 
 | 
    { | 
 | 
        // Don't call defaultReadObject()  | 
 | 
 | 
 | 
          | 
 | 
        ObjectInputStream.GetField gfields = in.readFields();  | 
 | 
 | 
 | 
          | 
 | 
        Vector<Permission> permissions =  | 
 | 
                (Vector<Permission>)gfields.get("permissions", null); | 
 | 
        perms = new ArrayList<Permission>(permissions.size());  | 
 | 
        perms.addAll(permissions);  | 
 | 
    }  | 
 | 
}  |