Index: fedd/fedd_new.py
===================================================================
--- fedd/fedd_new.py	(revision 09b1e9dd656dd429fa8f54ee9c2a5440dd47f6ce)
+++ fedd/fedd_new.py	(revision 7206e5a9a0196d4fdf2cea8dc635d31cd1fadf2c)
@@ -3,7 +3,9 @@
 import sys
 
+from federation.fedid import fedid, generate_fedid
 from federation.remote_service import service_caller
 from federation.client_lib import client_opts, exit_with_fault, RPCException, \
-	wrangle_standard_options, do_rpc, get_experiment_names, save_certfile
+	wrangle_standard_options, do_rpc, get_experiment_names, \
+	save_certfile, get_abac_certs
 
 
@@ -15,4 +17,7 @@
         self.add_option("--experiment_name", dest="exp_name",
                 type="string", help="Suggested experiment name")
+	self.add_option('--gen-cert', action='store_true', dest='gen_cert',
+		default=False,
+		help='generate a cert to which to delegate rights')
 
 parser = new_opts()
@@ -20,4 +25,8 @@
 
 cert, fid, url = wrangle_standard_options(opts)
+try:
+    acerts = get_abac_certs(opts.abac_dir)
+except EnvironmentError, e:
+    sys.exit('%s: %s' % (e.filename, e.strerror))
 
 out_certfile = opts.out_certfile
@@ -25,6 +34,16 @@
 msg = { }
 
+if opts.gen_cert:
+    expid, expcert = generate_fedid(opts.exp_name or 'dummy')
+    print expid
+    msg['experimentAccess'] = { 'X509': expcert }
+else:
+    expcert = None
+
 if opts.exp_name:
     msg['experimentID'] = { 'localname': opts.exp_name }
+
+if acerts:
+    msg['credential'] = acerts
 
 if opts.debug > 1: print >>sys.stderr, msg
@@ -44,7 +63,11 @@
 
 try:
-    save_certfile(opts.out_certfile, resp_dict.get('experimentAccess', None))
-except EnvironmentError:
-    sys.exit('Could not write to %s' %  out_certfile)
+    save_certfile(opts.out_certfile, resp_dict.get('experimentAccess', None), 
+	    expcert)
+except EnvironmentError, e:
+    sys.exit('Could not write to %s:' %  (e.strerror, e.filename))
+except CertificateMismatchError:
+    printf >>sys.stderr, "Fedid of created experiment does not match generated"
+
 
 e_fedid, e_local = get_experiment_names(resp_dict.get('experimentID', None))
Index: fedd/federation/authorizer.py
===================================================================
--- fedd/federation/authorizer.py	(revision 09b1e9dd656dd429fa8f54ee9c2a5440dd47f6ce)
+++ fedd/federation/authorizer.py	(revision 7206e5a9a0196d4fdf2cea8dc635d31cd1fadf2c)
@@ -152,4 +152,7 @@
 	self.globals.discard(attr)
 
+    def import_credentials(self, file_list=None, data_list=None):
+	return False
+
     def __str__(self):
 	rv = ""
@@ -182,11 +185,11 @@
     """
 
-    clean_attr_re = re.compile('[^A-Za-z_]+')
+    clean_attr_re = re.compile('[^A-Za-z0-9_]+')
     cred_file_re = re.compile('.*\.der$')
     bad_name = authorizer_base.bad_name
     attribute_error = authorizer_base.attribute_error
-    ABAC.libabac_init()
-
-    def __init__(self, certs=None, me=None, key=None, loadfile=None):
+    class no_file(RuntimeError): pass
+
+    def __init__(self, certs=None, me=None, key=None, load=None):
 	self.creddy = '/usr/local/bin/creddy'
 	self.globals = set()
@@ -207,10 +210,37 @@
 	    self.context.load_directory(dir)
 
-	if loadfile:
-	    self.load(loadfile)
+	if load:
+	    self.save_dir = load
+	    self.load(load)
+	else:
+	    self.save_dir = None
 
     @staticmethod
     def clean_attr(attr):
 	return abac_authorizer.clean_attr_re.sub('_', attr)
+
+    def import_credentials(self, file_list=None, data_list=None):
+	if data_list:
+	    return any([self.import_credential(data=d) for d in data_list])
+	elif file_list:
+	    return any([self.import_credential(file=f) for f in file_list])
+	else:
+	    return False
+
+    def import_credential(self, file=None, data=None):
+	if data:
+	    if self.context.load_id_chunk(data) != ABAC.ABAC_CERT_SUCCESS:
+		return self.context.load_attribute_chunk(data) == \
+			ABAC.ABAC_CERT_SUCCESS
+	    else:
+		return True
+	elif file:
+	    if self.context.load_id_file(file) != ABAC.ABAC_CERT_SUCCESS:
+		return self.context.load_attribute_file(file) == \
+			ABAC.ABAC_CERT_SUCCESS
+	    else:
+		return True
+	else:
+	    return False
 
     def set_attribute(self, name=None, attr=None, cert=None):
@@ -219,4 +249,7 @@
 		raise abac_authorizer.bad_name(
 			"ABAC doesn't understand three-names")
+	    # Convert non-string attributes to strings
+	    if not isinstance(attr, basestring):
+		attr = "%s" % attr
 	    if self.me and self.key:
 		# Create a credential and insert it into context
@@ -261,4 +294,7 @@
 	    raise abac_authorizer.bad_name(
 		    "ABAC doesn't understand three-names")
+	# Convert non-string attributes to strings
+	if not isinstance(attr, basestring):
+	    attr = "%s" % attr
 	cattr = self.clean_attr(attr)
 	self.lock.acquire()
@@ -289,4 +325,7 @@
 		    "ABAC doesn't understand three-names")
 	else:
+	    # Convert non-string attributes to strings
+	    if not isinstance(attr, basestring):
+		attr = "%s" % attr
 	    # Naked attributes are attested by this principal
 	    if attr.find('.') == -1: 
@@ -297,5 +336,5 @@
 
 	    self.lock.acquire()
-	    proof, rv = self.context.query(a, name)
+	    rv, proof = self.context.query(a, "%s" % name)
 	    # XXX delete soon
 	    if not rv and attr in self.globals: rv = True
@@ -330,6 +369,13 @@
 	return rv
 
-    def save(self, dir):
-	self.lock.acquire()
+    def save(self, dir=None):
+	self.lock.acquire()
+	if dir:
+	    self.save_dir = dir
+	else:
+	    dir = self.save_dir
+	if dir is None:
+	    self.lock.release()
+	    raise abac_authorizer.no_file_error("No load directory specified")
 	try:
 	    if not os.access(dir, os.F_OK):
@@ -347,5 +393,6 @@
 	    if not os.access("%s/certs" %dir, os.F_OK):
 		os.mkdir("%s/certs" % dir)
-	    seenit = set()
+	    seenid = set()
+	    seenattr = set()
 
 	    #restore unpicklable state 
@@ -363,15 +410,16 @@
 		# NB: file naming conventions matter here.  The trailing_ID and
 		# _attr are required by ABAC.COntext.load_directory()
-		if id not in seenit:
+		if id and id not in seenid:
 		    f = open("%s/certs/ID_%03d_ID.der" % (dir, ii), "w")
-		    print >>f, id
+		    f.write(id)
 		    f.close()
 		    ii += 1
-		    seenit.add(id)
-		if attr:
+		    seenid.add(id)
+		if attr and attr not in seenattr:
 		    f = open("%s/certs/attr_%03d_attr.der" % (dir, ai), "w")
-		    print >>f, attr
+		    f.write(attr)
 		    f.close()
 		    ai += 1
+		    seenattr.add(attr)
 	except EnvironmentError, e:
 	    # If we've mislaid self.lock, release lock (they're the same object)
@@ -386,6 +434,13 @@
 	self.lock.release()
 
-    def load(self, dir):
-	self.lock.acquire()
+    def load(self, dir=None):
+	self.lock.acquire()
+	if dir:
+	    self.save_dir = dir
+	else:
+	    dir = self.save_dir
+	if dir is None:
+	    self.lock.release()
+	    raise abac_authorizer.no_file_error("No load directory specified")
 	try:
 	    if os.access("%s/state" % dir, os.R_OK):
@@ -402,4 +457,5 @@
 		self.context.load_id_file(self.me)
 	    self.context.load_directory("%s/certs" % dir)
+	    self.save_dir = dir
 	except EnvironmentError, e:
 	    self.lock.release()
Index: fedd/federation/client_lib.py
===================================================================
--- fedd/federation/client_lib.py	(revision 09b1e9dd656dd429fa8f54ee9c2a5440dd47f6ce)
+++ fedd/federation/client_lib.py	(revision 7206e5a9a0196d4fdf2cea8dc635d31cd1fadf2c)
@@ -80,4 +80,6 @@
 	self.errstr = errstr
 
+class CertificateMismatchError(RuntimeError): pass
+
 
 def get_user_cert():
@@ -97,5 +99,5 @@
 		if os.path.isfile("%s/%s" % (dir,p))]:
 	    f = open(fn, 'r')
-	    rv.append(join(f))
+	    rv.append(f.read())
 	    f.close()
     return rv
@@ -138,13 +140,18 @@
     return (cert, fid, url)
 
-def save_certfile(out_certfile, ea):
+def save_certfile(out_certfile, ea, check_cert=None):
     """
     if the experiment authority section in ea has a certificate and the
     out_certfile parameter has a place to put it, save the cert to the file.
-    EnvronnemtError s can come from the file operations.
+    EnvronmentError s can come from the file operations.  If check_cert is
+    given, the certificate in ea is compared with it and if they are not equal,
+    a CertificateMismatchError is raised.
     """
     if out_certfile and ea and 'X509' in ea:
+	out_cert = ea['X509']
+	if check_cert and check_cert != out_cert:
+	    raise CertificateMismatchError()
 	f = open(out_certfile, "w")
-	print >>f, ea['X509']
+	f.write(out_cert)
 	f.close()
 
Index: fedd/federation/experiment_control.py
===================================================================
--- fedd/federation/experiment_control.py	(revision 09b1e9dd656dd429fa8f54ee9c2a5440dd47f6ce)
+++ fedd/federation/experiment_control.py	(revision 7206e5a9a0196d4fdf2cea8dc635d31cd1fadf2c)
@@ -30,4 +30,5 @@
 from synch_store import synch_store
 from experiment_partition import experiment_partition
+from authorizer import abac_authorizer
 
 import topdl
@@ -282,4 +283,7 @@
                 "ssh_privkey_file")
         dt = config.get("experiment_control", "direct_transit")
+	self.auth_type = config.get('experiment_control', 'auth_type') \
+		or 'legacy'
+	self.auth_dir = config.get('experiment_control', 'auth_dir')
 	if dt: self.direct_transit = [ tb.strip() for tb in dt.split(",")]
 	else: self.direct_transit = [ ]
@@ -319,10 +323,16 @@
         self.local_access = { }
 
-        if auth:
-            self.auth = auth
-        else:
-            self.log.error(\
-                    "[access]: No authorizer initialized, creating local one.")
-            auth = authorizer()
+	if self.auth_type == 'legacy':
+	    if auth:
+		self.auth = auth
+	    else:
+		self.log.error( "[access]: No authorizer initialized, " +\
+			"creating local one.")
+		auth = authorizer()
+	elif self.auth_type == 'abac':
+	    self.auth = abac_authorizer(load=self.auth_dir)
+	else:
+	    raise service_error(service_error.internal, 
+		    "Unknown auth_type: %s" % self.auth_type)
 
 
@@ -475,15 +485,17 @@
 		eid = get_experiment_id(s)
 		if eid : 
-		    # Give the owner rights to the experiment
-                    self.auth.set_attribute(s['owner'], eid)
-		    # And holders of the eid as well
-                    self.auth.set_attribute(eid, eid)
-                    # allow overrides to control experiments as well
-                    for o in self.overrides:
-                        self.auth.set_attribute(o, eid)
-		    # Set permissions to allow reading of the software repo, if
-		    # any, as well.
-		    for a in self.get_alloc_ids(s):
-			self.auth.set_attribute(a, 'repo/%s' % eid)
+		    if self.auth_type == 'legacy':
+			# XXX: legacy
+			# Give the owner rights to the experiment
+			self.auth.set_attribute(s['owner'], eid)
+			# And holders of the eid as well
+			self.auth.set_attribute(eid, eid)
+			# allow overrides to control experiments as well
+			for o in self.overrides:
+			    self.auth.set_attribute(o, eid)
+			# Set permissions to allow reading of the software
+			# repo, if any, as well.
+			for a in self.get_alloc_ids(s):
+			    self.auth.set_attribute(a, 'repo/%s' % eid)
 		else:
 		    raise KeyError("No experiment id")
@@ -546,7 +558,9 @@
 
         # Initialize the authorization attributes
-        for fid in self.accessdb.keys():
-            self.auth.set_attribute(fid, 'create')
-            self.auth.set_attribute(fid, 'new')
+	# XXX: legacy
+	if self.auth_type == 'legacy':
+	    for fid in self.accessdb.keys():
+		self.auth.set_attribute(fid, 'create')
+		self.auth.set_attribute(fid, 'new')
 
     def read_mapdb(self, file):
@@ -589,13 +603,15 @@
 	# Set the initial permissions on data in the store.  XXX: This ad hoc
 	# authorization attribute initialization is getting out of hand.
-	for k in self.synch_store.all_keys():
-	    try:
-		if k.startswith('fedid:'):
-		    fid = fedid(hexstr=k[6:46])
-		    if self.state.has_key(fid):
-			for a in self.get_alloc_ids(self.state[fid]):
-			    self.auth.set_attribute(a, k)
-	    except ValueError, e:
-		self.log.warn("Cannot deduce permissions for %s" % k)
+	# XXX: legacy
+	if self.auth_type == 'legacy':
+	    for k in self.synch_store.all_keys():
+		try:
+		    if k.startswith('fedid:'):
+			fid = fedid(hexstr=k[6:46])
+			if self.state.has_key(fid):
+			    for a in self.get_alloc_ids(self.state[fid]):
+				self.auth.set_attribute(a, k)
+		except ValueError, e:
+		    self.log.warn("Cannot deduce permissions for %s" % k)
 
 
@@ -1300,5 +1316,6 @@
                 if status and status == 'failed':
                     # remove the old access attribute
-                    self.auth.unset_attribute(fid, old_expid)
+		    self.auth.unset_attribute(fid, old_expid)
+		    self.auth.save()
                     overwrite = True
                     del self.state[eid]
@@ -1497,4 +1514,5 @@
 		self.auth.set_attribute(tbparams[tb]['allocID']['fedid'], 
 			"/%s/%s" % ( path, dest))
+	    self.auth.save()
 
 	# Convert the software locations in the segments into the local
@@ -1518,4 +1536,12 @@
         to instantiate them and start it all up.
         """
+        req = req.get('NewRequestBody', None)
+        if not req:
+            raise service_error(service_error.req,
+                    "Bad request format (no NewRequestBody)")
+
+	if self.auth.import_credentials(data_list=req.get('credential', [])):
+	    self.auth.save()
+	
         if not self.auth.check_attribute(fid, 'new'):
             raise service_error(service_error.access, "New access denied")
@@ -1536,13 +1562,22 @@
         gid = "dummy"
 
-        req = req.get('NewRequestBody', None)
-        if not req:
-            raise service_error(service_error.req,
-                    "Bad request format (no NewRequestBody)")
-
         # Generate an ID for the experiment (slice) and a certificate that the
         # allocator can use to prove they own it.  We'll ship it back through
-        # the encrypted connection.
-        (expid, expcert) = generate_fedid("test", dir=tmpdir, log=self.log)
+        # the encrypted connection.  If the requester supplied one, use it.
+	if 'experimentAccess' in req and 'X509' in req['experimentAccess']:
+	    expcert = req['experimentAccess']['X509']
+	    tf = tempfile.NamedTemporaryFile()
+	    tf.write(expcert)
+	    tf.flush()
+	    expid = fedid(file=tf.name)
+	    tf.close()
+	    self.state_lock.acquire()
+	    if expid in self.state:
+		self.state_lock.release()
+		raise service_error(service_error.req, 
+			'fedid %s identifies an existing experiment' % expid)
+	    self.state_lock.release()
+	else:
+	    (expid, expcert) = generate_fedid("test", dir=tmpdir, log=self.log)
 
 	#now we're done with the tmpdir, and it should be empty
@@ -1557,9 +1592,10 @@
 
         # Let users touch the state
-        self.auth.set_attribute(fid, expid)
-        self.auth.set_attribute(expid, expid)
-        # Override fedids can manipulate state as well
-        for o in self.overrides:
-            self.auth.set_attribute(o, expid)
+	self.auth.set_attribute(fid, expid)
+	self.auth.set_attribute(expid, expid)
+	# Override fedids can manipulate state as well
+	for o in self.overrides:
+	    self.auth.set_attribute(o, expid)
+	self.auth.save()
 
         rv = {
@@ -1793,5 +1829,6 @@
 		asignee = tbparams[tb]['allocID']['fedid']
 		for f in ("hosts", gw_secretkey_base, gw_pubkey_base):
-		    self.auth.set_attribute(asignee, "%s/%s" % (configpath, f))
+		    self.auth.set_attribute(asignee, "%s/%s" % \
+			    (configpath, f))
 
 	    part = experiment_partition(self.auth, self.store_url, tbmap,
@@ -1809,4 +1846,5 @@
 			self.auth.set_attribute(\
 				tbparams[tb]['allocID']['fedid'], sk)
+	    self.auth.save()
 
 	    self.wrangle_software(expid, top, topo, tbparams)
@@ -1851,10 +1889,11 @@
         # here on out, the state will stick around a while.
 
-        # Let users touch the state
-        self.auth.set_attribute(fid, expid)
-        self.auth.set_attribute(expid, expid)
-        # Override fedids can manipulate state as well
-        for o in self.overrides:
-            self.auth.set_attribute(o, expid)
+	# Let users touch the state
+	self.auth.set_attribute(fid, expid)
+	self.auth.set_attribute(expid, expid)
+	# Override fedids can manipulate state as well
+	for o in self.overrides:
+	    self.auth.set_attribute(o, expid)
+	self.auth.save()
 
         # Create a logger that logs to the experiment's state object as well as
Index: fedd/federation/fedid.py
===================================================================
--- fedd/federation/fedid.py	(revision 09b1e9dd656dd429fa8f54ee9c2a5440dd47f6ce)
+++ fedd/federation/fedid.py	(revision 7206e5a9a0196d4fdf2cea8dc635d31cd1fadf2c)
@@ -158,5 +158,5 @@
 
 	    rv = subprocess.call(cmd, stdout=call_out, stderr=call_out)
-	    log.debug("rv = %d" % rv)
+	    if log: log.debug("rv = %d" % rv)
 	    if rv == 0:
 		cert = ""
