Milán Major

netscape-revival

1 branch
Code

sun-java/classsrc/netscape/security/CapTarget.java

//
// CapTarget.java -- Copyright 1996, Netscape Communications Corp.
// Dan Wallach <dwallach@netscape.com>
// 16 July 1996
//

// $Id: CapTarget.java,v 1.5 1996/07/31 05:39:50 dwallach Exp $

package netscape.security;

import java.lang.*;
import java.util.*;

/**
 * This class represents a system target -- either a primitive device or
 * a macro ("typical game privileges").
 * <p>
 * Related documentation here:
 * <ul>
 * <a href="http://iapp15/java/signing/authorsigning.html">http://iapp15/java/signing/authorsigning.html</a>
 * </ul>
 *
 * @version 	$Id: CapTarget.java,v 1.5 1996/07/31 05:39:50 dwallach Exp $
 * @author	Dan Wallach
 */
public
class CapTarget {
    private String itsName;
    private CapPrincipal itsPrincipal;
    private boolean isRegistered;
    static private Hashtable theTargetRegistry = new Hashtable();

    private void registerCapTarget(String name, CapPrincipal p) {
	CapTarget t;

	itsName = name;
	itsPrincipal = p;
	isRegistered = false;

	//
	// security concern: Hashtable currently calls the equals() method
	// on objects already stored in the hash table.  This is good, because
	// it means an intruder can't hack a subclass of CapTarget with its
	// own equals function and get it registered.
	//
	// it's extremely important that Hashtable continues to work this way.
	//
	t = (CapTarget) theTargetRegistry.get(this);

	//
	// if the target is already registered, just return this one
	// without registering it.
	//
	if(t != null) return;

	//
	// otherwise, add the target to the registry
	//
	// TODO: make sure the caller has the given principal -- you
	// shouldn't be allowed to register a target under a principal
	// you don't own.
	//
	theTargetRegistry.put(this, this);
	isRegistered = true;
    }

    /**
     * Create a new target with the given name and principal and, if
     * it hasn't been registered, add it to the registry.  The calling
     * method must have the principal it's using to register the target.
     * If not, the target you get back will *not* be registered, but you
     * can still play with it yourself.
     *
     * Normally, applets won't create their own targets, but will instead
     * reference system targets.  However, a sufficiently complex applet
     * could use the capability system to manage security within itself.
     *
     * @param name Name of the target (e.g.: "system microphone")
     * @param p Principal who owns the target (e.g.: CapManager.getSystemPrincipal())
     *
     * @see CapManager#getSystemPrincipal
     */
    public CapTarget(String name, CapPrincipal p) {
	registerCapTarget(name, p);
    }

    /**
     * create a new target without a principal.  Any applet could
     * potentially create one of these, and maybe even (uggh) use it
     * as a method of inter-applet communication by subclassing
     * CapTarget.
     */
    public CapTarget(String name) {
	registerCapTarget(name, null);
    }

    /**
     * these methods attempt to find a pre-existing instance of
     * the desired target.  Eventually, principals will be able to
     * register their own targets (using the capability system
     * to manage their own resources), so the principal is an optional
     * second argument, used for disambiguation.  By default, only
     * the "system" principal is searched.
     */
    public static CapTarget getTarget(String name) {
	return getTarget(name, null);
    }

    public static CapTarget getTarget(String name, CapPrincipal p) {
	CapTarget t = (CapTarget)
	    theTargetRegistry.get(new CapTarget(name, p));
	return t;
    }

    /**
     * for "simple" targets, these will always return "blank"
     * (and the principal will store the "allowed" bit, if necessary),
     * but "smart" targets may do more interesting things.  In
     * particular, smart targets will subclass this class and
     * add more arguments to these functions.
     */
    public CapPermission checkScopePermission(CapPrincipal p) {
	return new CapPermission(CapPermission.BLANK, CapPermission.PERMANENT);
    }

    public CapPermission checkPrincipalPermission(CapPrincipal p) {
	return new CapPermission(CapPermission.BLANK, CapPermission.PERMANENT);
    }


    /**
     * generic utility functions
     */
    public boolean equals(Object obj) {
        boolean bSameName, bSamePrin;

	if(obj == this) return true;
	if(obj == null || this == null) return false;
        if(!(obj instanceof CapTarget)) return false;

        CapTarget t = (CapTarget) obj;

        //
        // this is deliberately inefficient so I can debug it
        //
        bSameName = (itsName.equals(t.itsName));

	//
	// this extra garbage is necessary because you can't
	// invoke a method on a null instance of a class, even
	// if that methods tries to check this == null first.
	// *sigh*
	//
	if(itsPrincipal == null)
	    bSamePrin = (t.itsPrincipal == null);
	else
	    bSamePrin = (itsPrincipal.equals(t.itsPrincipal));

        return bSameName && bSamePrin;
    }

    public String toString() {
	if(itsPrincipal != null)
	    return "Target: " + itsName + " Prin: " + itsPrincipal.toString();
	else
	    return "Target: " + itsName + " Prin: <none>";
    }

    public int hashCode() {
	return hashCode(itsName, itsPrincipal);
    }

    public int hashCode(String name, CapPrincipal prin) {
	return name.hashCode() +
	    ((prin != null) ?prin.hashCode() :0);
    }
}