[cap-talk] introducers (cleaned up code)

John Carlson john.carlson3 at sbcglobal.net
Wed Mar 12 11:07:48 EDT 2008


import java.util.Hashtable;
import java.util.Vector;
import java.util.List;
import java.util.ArrayList;

public class Introducer {
	private Hashtable<String,RevocableSubject> users = new   
Hashtable<String,RevocableSubject>();
	public Introducer() {
	}

	/**
	 * This is called once the user has a RevocableSubject.   To get a  
RevocableSubject, you must have an Account.  To have an Account, you  
need a name, password and image match.  The user is not allowed to  
change the Account information in the RevocableSubject (yet)--but I'm  
worried about serialized objects.  Seems like a security hole.  I  
guess it's best to not keep RevocableSubjects around for very long.
	 */
	public void introduceMe(final RevocableSubject requestor, String  
recipientAccount) {
		// no changes to requestor allowed on another thread
		RevocableSubject copy = null;
		synchronized(requestor) {
			try {
				copy = (RevocableSubject)requestor.clone();
			} catch (CloneNotSupportedException e) {
				System.err.println("Cannot send");
				return;
			}
		}
		users.put(copy.getName(), copy);
		ACapabilitySendingCapability cap = new  
ACapabilitySendingCapability(copy);
		// the requestor cannot change the sender, because the Account is  
final in the RevocableSubject class, and the requestor doesn't have  
access to the capability in the first place.
		RevocableSubject s = users.get(recipientAccount);
		s.sendCapability(cap);


	}
	public boolean authenticate(final RevocableSubject s) throws  
BadAccountException {
		RevocableSubject ns = users.get(s.getName());
		if (ns == null) {
			// handle DOS and spammers by requiring they match an image to get  
an account.  See below	
			users.put(s.getName(), s);
			return true;
		}
		if  (!s.getAccount().equals(ns.getAccount())) {
				s.revoke();
				throw new BadAccountException();
		}
		return true;
	}
	public List<String> search() {
		List<String> names = new ArrayList<String>();
		for (String name : users.keySet()) {
			names.add(name);
		}
		return names;
	}
	public void revokeUserAccount(RevocableSubject s) {
			users.remove(s.getName());
	}
}

class Account {
	private final String name;
	private final int hashedPassword;
	public Account(String requestorName, char [] requestorPassword,  
String guessedImagePattern, String presentedImagePattern, Introducer  
introducer) throws BadAccountException {
		hashedPassword = requestorPassword.hashCode();
		name = requestorName;
		if (!guessedImagePattern.equals(presentedImagePattern)) {
				throw new BadAccountException();
		}
	}
	public boolean equals(Account a) {
		return name.equals(a.name) && hashedPassword == a.hashedPassword;
	}
	public String getName() {
		return name;
	}
}

class BadAccountException extends Exception {
}

class NoServiceException extends Exception {
}

final class RevocableSubject implements Cloneable {	
	final private Account account;
	private boolean revoked = false;
	private Vector<ACapabilitySendingCapability> caps = new  
Vector<ACapabilitySendingCapability>();
	final private Introducer introducer;
	private RevocableSubject() {
		account = null;
		introducer = null;
	};
	public Object clone() throws CloneNotSupportedException {
		try {
			return (Object)new RevocableSubject(account, introducer);
		} catch (Throwable t) {
			throw new CloneNotSupportedException();
		}
	}
	public RevocableSubject(final Account account, Introducer introducer)  
throws BadAccountException, NoServiceException {
		if (account == null) {
			revoke();
			throw new BadAccountException();
		}
		if (introducer == null) {
			revoke();
			throw new NoServiceException();
		}
		this.account = account;
		this.introducer = introducer;
		introducer.authenticate(this);
	}
	public Account getAccount() {
		return this.account;
	}
	public String getName() {
		return this.account.getName();
	}
	public void sendCapability(ACapabilitySendingCapability cap) {
		if (!revoked) {
			caps.add(cap);
		}
	}
	public ACapabilitySendingCapability getNextCap() {
		if (!revoked) {
			return caps.remove(0);
		}
		return null;
	}
	public void revoke() 	{
		revoked = true;
		caps.clear();
	}
}

class ACapabilitySendingCapability {
	private final RevocableSubject s;
	public ACapabilitySendingCapability(RevocableSubject s) {
		this.s = s;
	}
	public void sendBack(ACapabilitySendingCapability c) {
		s.sendCapability(c);
	}
}

//So I might define a method like

class Requestor {
	void introduce(String bob,  char [] bobsPassword) throws  
BadAccountException, NoServiceException {
		Introducer introducer = new Introducer();
		Account a = new Account(bob, bobsPassword, "23df939", "23df939",  
introducer);
		RevocableSubject s = new RevocableSubject(a, introducer);
		introducer.introduceMe(s, "Carol");
	}
}

//On the receiving side, there might be a thread like for auto accept  
introductions.

class Receive extends Thread {
	public void run() {
		try {
			Introducer introducer = new Introducer();
			Account a = new Account("Carol", new char []  
{'p','a','s','s','w','d'}, "123fdsf33", "123fdsf33", introducer);
			RevocableSubject s = new RevocableSubject(a, introducer);
			while (true) {
				ACapabilitySendingCapability cap = s.getNextCap();
				cap.sendBack(new ACapabilitySendingCapability(s));
			}
		} catch (BadAccountException e) {
			System.err.println("Cannot login");
		} catch (NoServiceException e) {
			System.err.println("Need to specify an introducer");
		}
	}
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.eros-os.org/pipermail/cap-talk/attachments/20080312/476e5d3a/attachment-0001.html 


More information about the cap-talk mailing list