Index: fedd/federation/experiment_control.py
===================================================================
--- fedd/federation/experiment_control.py	(revision 62f3dd9d96f5443be02f059e213f4d3f2b67d2e0)
+++ fedd/federation/experiment_control.py	(revision 913dc7aff4a2863e0a0778a68880a0a9c3e197be)
@@ -1062,4 +1062,34 @@
 	else: e.software = s 
 
+    def append_experiment_authorization(self, expid, attrs, 
+	    need_state_lock=True):
+	"""
+	Append the authorization information to system state
+	"""
+
+	for p, a in attrs:
+	    self.auth.set_attribute(p, a)
+	self.auth.save()
+
+	if need_state_lock: self.state_lock.acquire()
+	self.state[expid]['auth'].update(attrs)
+	if self.state_filename: self.write_state()
+	if need_state_lock: self.state_lock.release()
+
+    def clear_experiment_authorizaton(self, expid, need_state_lock=True):
+	"""
+	Attrs is a set of attribute principal pairs that need to be removed
+	from the authenticator.  Remove them and save the authenticator.
+	"""
+
+	for p, a in attrs:
+	    self.auth.unset_attribute(p, a)
+	self.auth.save()
+
+	if need_state_lock: self.state_lock.acquire()
+	self.state[expid]['auth'] = set()
+	if self.state_filename: self.write_state()
+	if need_state_lock: self.state_lock.release()
+
 
     def create_experiment_state(self, fid, req, expid, expcert,
@@ -1087,7 +1117,7 @@
                 status = self.state[eid].get('experimentStatus', None)
                 if status and status == 'failed':
-                    # remove the old access attribute
-		    self.auth.unset_attribute(fid, old_expid)
-		    self.auth.save()
+                    # remove the old access attributes
+		    self.clear_experiment_authorization(self.state[eid]['auth'],
+			    need_state_lock=False)
                     overwrite = True
                     del self.state[eid]
@@ -1105,8 +1135,9 @@
                     'owner': fid,
                     'log' : [],
+		    'auth': set(),
                 }
             self.state[expid] = self.state[eid]
-            if self.state_filename: self.write_state()
-            self.state_lock.release()
+	    if self.state_filename: self.write_state()
+	    self.state_lock.release()
         else:
             eid = self.exp_stem
@@ -1126,8 +1157,15 @@
                     'owner': fid,
                     'log' : [],
+		    'auth': set(),
                 }
             self.state[expid] = self.state[eid]
-            if self.state_filename: self.write_state()
-            self.state_lock.release()
+	    if self.state_filename: self.write_state()
+	    self.state_lock.release()
+
+	# Let users touch the state.  Authorize this fid and the expid itself
+	# to touch the experiment, as well as allowing th eoverrides.
+	self.append_experiment_authorization(eid, 
+		set([(fid, expid), (expid,expid)] + \
+			[ (o, expid) for o in self.overrides]))
 
 	return eid
@@ -1362,4 +1400,5 @@
 		    "Cannot create software directory: %s" % e)
 	# The actual copying.  Everything's converted into a url for copying.
+	auth_attrs = set()
 	for pkg in pkgs:
 	    loc = pkg
@@ -1394,9 +1433,13 @@
 		    ( self.repo_url, path, dest)
 
-	    # Allow the individual segments to access the software.
-	    for tb in tbparams.keys():
-		self.auth.set_attribute(tbparams[tb]['allocID']['fedid'], 
-			"/%s/%s" % ( path, dest))
-	    self.auth.save()
+	    # Allow the individual segments to access the software by assigning
+	    # an attribute to each testbed allocation that encodes the data to
+	    # be released.  This expression collects the data for each run of
+	    # the loop.
+	    auth_attrs.update([
+		(tbparams[tb]['allocID']['fedid'], "/%s/%s" % ( path, dest)) \
+			for tb in tbparams.keys()])
+
+	self.append_experiment_authorization(expid, auth_attrs)
 
 	# Convert the software locations in the segments into the local
@@ -1467,12 +1510,4 @@
 	eid = self.create_experiment_state(fid, req, expid, expcert, 
 		state='empty')
-
-        # 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()
 
         rv = {
@@ -1700,11 +1735,11 @@
 		    "Cannot copy keyfiles: %s" % e)
 
-	# Allow the individual testbeds to access the configuration files.
-	for tb in tbparams.keys():
-	    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.save()
+	# Allow the individual testbeds to access the configuration files,
+	# again by setting an attribute for the relevant pathnames on each
+	# allocation principal.  Yeah, that's a long list comprehension.
+	self.append_experiment_authorization(expid, set([
+	    (tbparams[tb]['allocID']['fedid'], "%s/%s" % (configpath, f)) \
+		    for tb in tbparams.keys() \
+			for f in ("hosts", gw_secretkey_base, gw_pubkey_base)]))
 
 	attrs = [ 
@@ -1940,4 +1975,6 @@
 	    part.add_portals(top, topo, eid, pmasters, tbparams, ip_allocator,
 		    connInfo, expid)
+
+	    auth_attrs = set()
 	    # Now get access to the dynamic testbeds (those added above)
 	    for tb in [ t for t in topo if t not in allocated]:
@@ -1948,8 +1985,10 @@
 		# Give the testbed access to keys it exports or imports
 		if store_keys:
-		    for sk in store_keys.split(" "):
-			self.auth.set_attribute(\
-				tbparams[tb]['allocID']['fedid'], sk)
-	    self.auth.save()
+		    auth_keys.update(set([
+			(tbparams[tb]['allocID']['fedid'], sk) \
+				for sk in store_keys.split(" ")]))
+
+	    if auth_attrs:
+		self.append_experiment_authorization(expid, auth_attrs)
 
 	    # transit and disconnected testbeds may not have a connInfo entry.
@@ -1976,11 +2015,12 @@
         # here on out, the state will stick around a while.
 
+	# XXX: I think this is redundant
 	# Let users touch the state
-	self.auth.set_attribute(fid, expid)
-	self.auth.set_attribute(expid, 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()
+	# 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
@@ -2077,4 +2117,5 @@
         # Remove the owner info (should always be there, but...)
         if rv.has_key('owner'): del rv['owner']
+	if 'auth' in rv: del rv['auth']
 
         # Convert the log into the allocationLog parameter and remove the
