Index: fedd/federation/authorizer.py
===================================================================
--- fedd/federation/authorizer.py	(revision 49e66b48acb47e18c8e0a8f8d256da6b2bdaff8b)
+++ fedd/federation/authorizer.py	(revision 5c0d2446f201dcd17d5a69a6dbb76da86c297799)
@@ -1,4 +1,6 @@
 #/usr/local/bin/python
 
+from tempfile import mkstemp
+from subprocess import call
 from fedid import fedid
 from remote_service import service_caller
@@ -6,5 +8,9 @@
 from service_error import service_error
 
+import ABAC
+import pickle
+
 import sys
+import os
 
 class authorizer_base:
@@ -17,4 +23,6 @@
     # general error exception for badly formed names.  
     class bad_name(RuntimeError): pass
+    # difficulty creating an attribute
+    class attribute_error(RuntimeError): pass
 
     @staticmethod
@@ -146,4 +154,23 @@
 	return rv
 
+    def clone(self):
+	rv = authorizer()
+	rv.attrs = self.attrs.copy()
+	rv.globals = self.globals.copy()
+	return rv
+
+    def save(self, fn):
+	f = open(fn, "w")
+	pickle.dump(self, f)
+	f.close()
+
+    def load(self, fn):
+	f = open(fn, "r")
+	a = pickle.load(f)
+	f.close()
+	self.attrs = a.attrs
+	self.globals = a.globals
+	
+
 class abac_authorizer(authorizer_base):
     """
@@ -151,79 +178,59 @@
     """
 
-    def __init__(self, url=None, cert_file=None, cert_pwd=None,
-	    trusted_certs=None, me=None):
-	self.call_CreateContext = abac_service_caller('CreateContext')
-	self.call_CredentialUpdate = abac_service_caller('CredentialUpdate')
-	self.call_Access = abac_service_caller('Access')
+    def __init__(self, certs=None, me=None, key=None, from_dir=None):
+	self.bad_name = authorizer_base.bad_name
+	self.attribute_error = authorizer_base.attribute_error
 	self.globals = set()
-
-	self.url = url
-	self.cert_file = cert_file
-	self.cert_pwd = cert_pwd
-	self.trusted_certs = trusted_certs
+	self.creddy = '/usr/local/bin/creddy'
 	self.me = me
-	req = { 'context': { 'self': me.get_hexstr()} }
-	# May throw a service error
-	resp = self.call_CreateContext(self.url, req, self.cert_file,
-		self.cert_pwd, self.trusted_certs, tracefile=sys.stderr)
-
-	if resp.has_key('CreateContextResponseBody'):
-	    resp =  resp['CreateContextResponseBody']
-	    if resp.has_key('contextID'):
-		self.contextID = resp['contextID']
+	self.my_key = key
+	self.context = ABAC.Context()
+	for dir in certs or []:
+	    self.context.load_directory(dir)
+
+    def set_attribute(self, name=None, attr=None, cert=None):
+	if name and attr:
+	    if isinstance(name, tuple):
+		raise self.bad_name("ABAC doesn't understand three-names")
+	    if self.me and self.key:
+		# Create a credential and insert it into context
+		# This will simplify when we have libcreddy
+		try:
+		    # create temp file
+		    f, fn = mkstemp()
+		    f.close()
+		except EnvironmentError, e:
+		    raise self.attribute_error(
+			    "Cannot create temp file: %s" %e)
+
+		# Create the attribute certificate with creddy
+		rv = call([creddy, '--attribute', '--issuer=%s' % self.me, 
+		    '--key=%s' % self.key, '--role=%s' % attr, 
+		    '--subject-id=%s' % name, '--out=%s' % fn])
+		if rv == 0:
+		    # load it to context and remove the file
+		    self.context.load_attribute(fn)
+		    os.unlink(fn)
+		else:
+		    os.unlink(fn)
+		    raise self.attribute_error("creddy returned %s" % rv)
 	    else:
-		raise service_error(service_error.internal, 
-			"No context ID for the new authorization context")
-	else:
-	    raise service_error(service_error.internal, 
-		    "Bad response to creating service context")
-
-    def set_attribute(self, name, attr):
-	self.valid_name(name)
+		raise self.attribute_error(
+			"Identity and key not specified on creation")
+	elif cert:
+	    # Insert this credential into the context
+	    self.context.load_attribute_chunk(cert)
+	else:
+	    raise self.attribute_error("Neither name/attr nor cert is set")
+
+    def check_attribute(self, name, attr):
+	# XXX proof soon
 	if isinstance(name, tuple):
-	    if not isinstance(name[0], fedid):
-		raise service_error(service_error.internal, 
-			"Triple not anchored in testbed")
-	    if not name[1] and not name[2]:
-		raise service_error(service_error.internal,
-			"Anonymous access not yet permitted")
-
-	    preconditions = "^".join(
-		    [ "%s.%s" % (name[0], self.auth_name(n)) \
-			    for n in name[1:3] if n ])
-
-	    req = { 
-		    'credential': [ '%s.%s<--%s' % \
-			    ( self.me, attr, preconditions) ],
-		    'context': { 'contextID': self.contextID  }
-		}
-	else:
-	    req = { 
-		    'credential': [ '%s.%s<--%s' % \
-			    ( self.me, attr, self.auth_name(name)) ],
-		    'context': { 'contextID': self.contextID }
-		}
-	print req
-	self.call_CredentialUpdate(self.url, req, self.cert_file, 
-		self.cert_pwd, self.trusted_certs, tracefile=sys.stderr)
-
-    def check_attribute(self, name, attr):
-	self.valid_name(name)
-	if attr in self.globals: return True
-
-	if isinstance(name, tuple):
-	    raise service_error(service_error.internal, 
-		    "Only fedids permitted here")
-	req = {
-		'goal': '%s:%s<<---%s' % (self.me, attr, name),
-		'context': { 'contextID': self.contextID }
-	    }
-	resp = self.call_Access(self.url, req, self.cert_file, self.cert_pwd, 
-		self.trusted_certs)
-	if resp.has_key('AccessResponseBody'):
-	    resp = resp['AccessResponseBody']
-
-	result = resp.get('result', None)
-	return (result and result.lower() == 'true')
+	    raise self.bad_name("ABAC doesn't understand three-names")
+	else:
+	    proof, rv = self.context.query(attr, name)
+	    # XXX delete soon
+	    if not rv and attr in self.globals: return True
+	    else: return rv
 
     def set_global_attribute(self, attr):
@@ -241,2 +248,60 @@
 	self.globals.discard(attr)
 
+    def clone(self):
+	rv = abac_authorizer(me=self.me, key=self.key)
+	rv.globals = self.globals.copy()
+	rv.context = ABAC.Context(self.context)
+	return rv
+
+    def save(self, dir):
+	os.mkdir(dir)
+
+	f = open("%s/globals" % dir, "w")
+	pickle.dump(self.globals, f)
+	f.close()
+
+	if self.me and self.key:
+	    f = open("%s/me" % dir, "w")
+	    pickle.dump(self.me, f)
+	    f.close()
+	    f = open("%s/key" % dir, "w")
+	    pickle.dump(self.key, f)
+	    f.close()
+	os.mkdir("%s/certs" % dir)
+	seenit = set()
+	ii = 0
+	ai = 0
+	for c in self.context.credentials():
+	    id = c.issuer_cert()
+	    attr = c.attribute_cert()
+	    if id not in seenit:
+		f = open("%s/certs/%03d_ID.der" % (dir, ii), "w")
+		print >>f, id
+		f.close()
+		ii += 1
+		seenit.add(id)
+	    if attr:
+		f = open("%s/certs/%03d_attr.der" % (dir, ai), "w")
+		print >>f, attr
+		f.close()
+		ai += 1
+
+    def load(self, dir):
+	if os.access("%s/me" % dir, os.R_OK):
+	    f = open("%s/me" % dir, "r")
+	    self.me = pickle.load(f)
+	    f.close()
+	else:
+	    self.me = None
+	if os.access("%s/key" % dir, os.R_OK):
+	    f = open("%s/key" % dir, "r")
+	    self.key = pickle.load(f)
+	    f.close()
+	else:
+	    self.key = None
+	f = open("%s/globals" % dir, "r")
+	self.globals = pickle.load(f)
+	f.close()
+	self.context = ABAC.context()
+	self.context.load_directory("%s/certs" % dir)
+
