[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