Index: fedd/federation/authorizer.py
===================================================================
--- fedd/federation/authorizer.py	(revision 5c0d2446f201dcd17d5a69a6dbb76da86c297799)
+++ fedd/federation/authorizer.py	(revision 3bf0b3c74bb114d455cebc459e0b3eb3c5b45aee)
@@ -1,6 +1,9 @@
 #/usr/local/bin/python
 
+from string import join
 from tempfile import mkstemp
 from subprocess import call
+from threading import Lock
+
 from fedid import fedid
 from remote_service import service_caller
@@ -8,4 +11,5 @@
 from service_error import service_error
 
+
 import ABAC
 import pickle
@@ -13,4 +17,5 @@
 import sys
 import os
+import re
 
 class authorizer_base:
@@ -178,5 +183,5 @@
     """
 
-    def __init__(self, certs=None, me=None, key=None, from_dir=None):
+    def __init__(self, certs=None, me=None, key=None):
 	self.bad_name = authorizer_base.bad_name
 	self.attribute_error = authorizer_base.attribute_error
@@ -184,6 +189,12 @@
 	self.creddy = '/usr/local/bin/creddy'
 	self.me = me
-	self.my_key = key
+	self.key = key
 	self.context = ABAC.Context()
+	self.lock = Lock()
+
+	if me:
+	    self.fedid = fedid(file=self.me)
+	    self.context.load_id_file(self.me)
+
 	for dir in certs or []:
 	    self.context.load_directory(dir)
@@ -199,5 +210,5 @@
 		    # create temp file
 		    f, fn = mkstemp()
-		    f.close()
+		    os.close(f)
 		except EnvironmentError, e:
 		    raise self.attribute_error(
@@ -205,10 +216,13 @@
 
 		# Create the attribute certificate with creddy
-		rv = call([creddy, '--attribute', '--issuer=%s' % self.me, 
+		cmd = [self.creddy, '--attribute', '--issuer=%s' % self.me, 
 		    '--key=%s' % self.key, '--role=%s' % attr, 
-		    '--subject-id=%s' % name, '--out=%s' % fn])
+		    '--subject-id=%s' % name, '--out=%s' % fn]
+		rv = call(cmd)
 		if rv == 0:
+		    self.lock.acquire()
 		    # load it to context and remove the file
-		    self.context.load_attribute(fn)
+		    rv = self.context.load_attribute_file(fn)
+		    self.lock.release()
 		    os.unlink(fn)
 		else:
@@ -220,5 +234,7 @@
 	elif cert:
 	    # Insert this credential into the context
+	    self.lock.acquire()
 	    self.context.load_attribute_chunk(cert)
+	    self.lock.release()
 	else:
 	    raise self.attribute_error("Neither name/attr nor cert is set")
@@ -229,8 +245,16 @@
 	    raise self.bad_name("ABAC doesn't understand three-names")
 	else:
-	    proof, rv = self.context.query(attr, name)
+	    
+	    # Naked attributes are attested by this principal
+	    if attr.find('.') == -1: a = "%s.%s" % (self.fedid, attr)
+	    else: a = attr
+
+	    self.lock.acquire()
+	    proof, rv = self.context.query(a, name)
 	    # XXX delete soon
-	    if not rv and attr in self.globals: return True
-	    else: return rv
+	    if not rv and attr in self.globals: rv = True
+	    self.lock.release()
+
+	    return rv
 
     def set_global_attribute(self, attr):
@@ -239,5 +263,7 @@
 	authorizer have this attribute.
 	"""
+	self.lock.acquire()
 	self.globals.add(attr)
+	self.lock.release()
 
     def unset_global_attribute(self, attr):
@@ -246,62 +272,111 @@
 	"""
 
+	self.lock.acquire()
 	self.globals.discard(attr)
+	self.lock.release()
 
     def clone(self):
+	self.lock.acquire()
 	rv = abac_authorizer(me=self.me, key=self.key)
 	rv.globals = self.globals.copy()
 	rv.context = ABAC.Context(self.context)
+	self.lock.release()
 	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)
+	self.lock.acquire()
+	try:
+	    if not os.access(dir, os.F_OK):
+		os.mkdir(dir)
+
+	    f = open("%s/globals" % dir, "w")
+	    pickle.dump(self.globals, f)
 	    f.close()
-	    f = open("%s/key" % dir, "w")
-	    pickle.dump(self.key, f)
+
+	    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()
+	    if not os.access("%s/certs" %dir, os.F_OK):
+		os.mkdir("%s/certs" % dir)
+	    seenit = set()
+	    #remove old certs
+	    for fn in [ f for f in os.listdir("%s/certs" % dir) \
+		    if re.match('.*\.der$', f)]:
+		os.unlink('%s/certs/%s' % (dir, fn))
+	    ii = 0
+	    ai = 0
+	    for c in self.context.credentials():
+		id = c.issuer_cert()
+		attr = c.attribute_cert()
+		# NB: file naming conventions matter here.  The trailing_ID and
+		# _attr are required by ABAC.COntext.load_directory()
+		if id not in seenit:
+		    f = open("%s/certs/ID_%03d_ID.der" % (dir, ii), "w")
+		    print >>f, id
+		    f.close()
+		    ii += 1
+		    seenit.add(id)
+		if attr:
+		    f = open("%s/certs/attr_%03d_attr.der" % (dir, ai), "w")
+		    print >>f, attr
+		    f.close()
+		    ai += 1
+	except EnvironmentError, e:
+	    self.lock.release()
+	    raise e
+	except pickle.PickleError, e:
+	    self.lock.release()
+	    raise e
+	self.lock.release()
+
+    def load(self, dir):
+	self.lock.acquire()
+	try:
+	    if os.access("%s/me" % dir, os.R_OK):
+		f = open("%s/me" % dir, "r")
+		self.me = pickle.load(f)
+		f.close()
+		if self.me:
+		    self.fedid = fedid(file=self.me)
+	    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()
-	os.mkdir("%s/certs" % dir)
-	seenit = set()
-	ii = 0
-	ai = 0
+	    self.context = ABAC.Context()
+	    self.context.load_directory("%s/certs" % dir)
+	except EnvironmentError, e:
+	    self.lock.release()
+	    raise e
+	except pickle.PickleError, e:
+	    self.lock.release()
+	    raise e
+	self.lock.release()
+
+    def __str__(self):
+	def encode_role(r):
+	    if r.is_principal(): 
+		return "%s" % r.principal()
+	    elif r.is_role(): 
+		return "%s.%s" % (r.principal(), r.role_name())
+	    elif r.is_linking():
+		return "%s.%s.%s" % \
+			(r.principal(), r.linking_role(), r.role_name())
+
+	self.lock.acquire()
+	rv = "%s" % self.fedid
 	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)
-
+	    rv += '\n%s <- %s' % (encode_role(c.head()), encode_role(c.tail()))
+	self.lock.release()
+	return rv
+
