Index: fedd/federation/experiment_control.py
===================================================================
--- fedd/federation/experiment_control.py	(revision 2627eb377cd2380a86775e63b5cf1637ffe01c8f)
+++ fedd/federation/experiment_control.py	(revision e83f2f2a321f4a61b9dc5a7671bb03b4a6267b72)
@@ -801,4 +801,5 @@
 	    self.response = None
 	    self.node = { }
+	    self.proof = None
 
 	def make_map(self, resp):
@@ -850,4 +851,5 @@
 			    self.log_collector.write(line)
 		    self.make_map(r['StartSegmentResponseBody'])
+		    if 'proof' in r: self.proof = r['proof']
 		    self.response = r
 		else:
@@ -1021,4 +1023,5 @@
 	    # mapping.
 	    embedding = [ ]
+	    proofs = { }
 	    for s in starters:
 		for k, v in s.node.items():
@@ -1028,4 +1031,6 @@
 			'testbed': s.testbed
 			})
+		if s.proof:
+		    proofs[s.testbed] = s.proof
             log.info("[start_segment]: Experiment %s active" % eid)
 
@@ -1044,4 +1049,10 @@
 		top.to_dict()
 	self.state[eid]['embedding'] = embedding
+	# Append startup proofs
+	for f in self.state[eid]['federant']:
+	    if 'name' in f and 'localname' in f['name']:
+		if f['name']['localname'] in proofs:
+		    f['proof'].append(proofs[f['name']['localname']])
+
         if self.state_filename: self.write_state()
         self.state_lock.release()
@@ -1326,8 +1337,12 @@
 	    raise service_error(service_error.protocol,
                         "Bad proxy response")
+	if 'proof' not in r:
+	    raise service_error(service_error.protocol,
+                        "Bad access response (no access proof)")
         
 	tbparam[tb] = { 
 		"allocID" : r['allocID'],
 		"uri": uri,
+		"proof": [ r['proof'] ],
 		}
 
@@ -1498,6 +1513,10 @@
 	    self.auth.save()
 
-        if not self.auth.check_attribute(fid, 'new'):
-            raise service_error(service_error.access, "New access denied")
+	access_ok, proof = self.auth.check_attribute(fid, 'new', 
+		with_proof=True)
+
+        if not access_ok:
+            raise service_error(service_error.access, "New access denied",
+		    proof=[proof])
 
         try:
@@ -1543,5 +1562,6 @@
                 ],
                 'experimentStatus': 'empty',
-                'experimentAccess': { 'X509' : expcert }
+                'experimentAccess': { 'X509' : expcert },
+		'proof': proof.to_dict(),
             }
 
@@ -1814,11 +1834,12 @@
             raise service_error(service_error.req, "No request?")
 
-        self.check_experiment_access(fid, key)
+        proof = self.check_experiment_access(fid, key)
 
         self.state_lock.acquire()
         if self.state.has_key(key):
             if self.state[key].has_key('vtopo'):
-                rv = { 'experiment' : {keytype: key },\
-                        'vtopo': self.state[key]['vtopo'],\
+                rv = { 'experiment' : {keytype: key },
+                        'vtopo': self.state[key]['vtopo'],
+			'proof': proof.to_dict(), 
                     }
             else:
@@ -1858,11 +1879,12 @@
             raise service_error(service_error.req, "No request?")
 
-        self.check_experiment_access(fid, key)
+        proof = self.check_experiment_access(fid, key)
 
         self.state_lock.acquire()
         if self.state.has_key(key):
             if self.state[key].has_key('vis'):
-                rv =  { 'experiment' : {keytype: key },\
-                        'vis': self.state[key]['vis'],\
+                rv =  { 'experiment' : {keytype: key },
+                        'vis': self.state[key]['vis'],
+			'proof': proof.to_dict(), 
                         }
             else:
@@ -1885,5 +1907,7 @@
 	between when it was started and the beginning of resource allocation.
 	This is basically the information about each local allocation.  This
-	fills in the values of the placeholder allocation in the state.
+	fills in the values of the placeholder allocation in the state.  It
+	also collects the access proofs and returns them as dicts for a
+	response message.
 	"""
 	# save federant information
@@ -1893,4 +1917,5 @@
 		    'allocID' : tbparams[k]['allocID'],
 		    'uri': tbparams[k]['uri'],
+		    'proof': tbparams[k]['proof'],
 		}
 
@@ -1903,7 +1928,11 @@
 		[ tbparams[tb]['federant'] for tb in tbparams.keys() \
 		    if tbparams[tb].has_key('federant') ]
+	# Access proofs for the response message
+	proofs = [copy.deepcopy(p) for k in tbparams.keys()\
+		    for p in tbparams[k]['federant']['proof']]
 	if self.state_filename: 
 	    self.write_state()
 	self.state_lock.release()
+	return proofs
 
     def clear_placeholder(self, eid, expid, tmpdir):
@@ -1945,5 +1974,5 @@
 
 	# Make sure that the caller can talk to us
-        self.check_experiment_access(fid, key)
+        proof = self.check_experiment_access(fid, key)
 
 	# Install the testbed map entries supplied with the request into a copy
@@ -2030,6 +2059,6 @@
 	    vtopo = topdl.topology_to_vtopo(top)
 	    vis = self.genviz(vtopo)
-	    self.save_federant_information(allocated, tbparams, eid, vtopo, 
-		    vis, top)
+	    proofs = self.save_federant_information(allocated, tbparams, 
+		    eid, vtopo, vis, top)
         except service_error, e:
             # If something goes wrong in the parse (usually an access error)
@@ -2042,13 +2071,4 @@
         # Start the background swapper and return the starting state.  From
         # 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)
-	# 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
@@ -2076,4 +2096,5 @@
                 ],
                 'experimentStatus': 'starting',
+		'proof': [ proof.to_dict() ] + proofs,
             }
 
@@ -2121,8 +2142,11 @@
             key = self.get_experiment_fedid(key)
 
-        if self.auth.check_attribute(fid, key):
-            return True
+	access_ok, proof = self.auth.check_attribute(fid, key, with_proof=True)
+
+        if access_ok:
+            return proof
         else:
-            raise service_error(service_error.access, "Access Denied")
+            raise service_error(service_error.access, "Access Denied",
+		proof)
 
 
@@ -2133,4 +2157,5 @@
 	"""
 	self.log.info("Get handler %s %s" % (path, fid))
+	# XXX: log proofs?
 	if self.auth.check_attribute(fid, path):
 	    return ("%s/%s" % (self.repodir, path), "application/binary")
@@ -2138,5 +2163,5 @@
 	    return (None, None)
 
-    def clean_info_response(self, rv):
+    def clean_info_response(self, rv, proof):
         """
         Remove the information in the experiment's state object that is not in
@@ -2162,4 +2187,5 @@
                 if f.has_key('allocID'): del f['allocID']
 		if f.has_key('uri'): del f['uri']
+	rv['proof'] = proof.to_dict()
 
         return rv
@@ -2188,5 +2214,5 @@
             raise service_error(service_error.req, "No request?")
 
-        self.check_experiment_access(fid, key)
+        proof = self.check_experiment_access(fid, key)
 
         # The state may be massaged by the service function that called
@@ -2199,5 +2225,5 @@
 
         if rv:
-            return self.clean_info_response(rv)
+            return self.clean_info_response(rv, proof)
         else:
             raise service_error(service_error.req, "No such experiment")
@@ -2207,10 +2233,10 @@
         Return all the stored info that this fedid can access
         """
-        rv = { 'info': [ ] }
+	rv = { 'info': [ ], 'proof': [ ] }
 
         self.state_lock.acquire()
         for key in [ k for k in self.state.keys() if isinstance(k, fedid)]:
 	    try:
-		self.check_experiment_access(fid, key)
+		proof = self.check_experiment_access(fid, key)
 	    except service_error, e:
 		if e.code == service_error.access:
@@ -2222,6 +2248,7 @@
             if self.state.has_key(key):
                 e = copy.deepcopy(self.state[key])
-                e = self.clean_info_response(e)
+                e = self.clean_info_response(e, proof)
                 rv['info'].append(e)
+		rv['proof'].append(proof.to_dict())
         self.state_lock.release()
         return rv
@@ -2351,5 +2378,4 @@
 	    if tmpdir: self.remove_dirs(tmpdir)
 
-
     def terminate_experiment(self, req, fid):
         """
@@ -2364,5 +2390,5 @@
 
 	key = self.get_experiment_key(req, 'experiment')
-        self.check_experiment_access(fid, key)
+        proof = self.check_experiment_access(fid, key)
         exp = req.get('experiment', False)
         force = req.get('force', False)
@@ -2416,8 +2442,9 @@
 	    if repo:
 		self.remove_dirs("%s/%s" % (self.repodir, repo))
-		
+	
             return { 
                     'experiment': exp , 
                     'deallocationLog': string.join(dealloc_list, ''),
+		    'proof': [proof.to_dict()],
                     }
         else:
@@ -2438,5 +2465,10 @@
 	rv = { 'name': name }
 
-        if name and self.auth.check_attribute(fid, name):
+	if not name:
+	    raise service_error(service_error.req, "No name?")
+
+	access_ok, proof = self.auth.check_attribute(fid, name, with_proof=True)
+
+        if access_ok:
 	    self.log.debug("[GetValue] asking for %s " % name)
 	    try:
@@ -2448,8 +2480,10 @@
 	    if v is not None:
 		rv['value'] = v
+	    rv['proof'] = proof.to_dict()
 	    self.log.debug("[GetValue] got %s from %s" % (v, name))
 	    return rv
         else:
-            raise service_error(service_error.access, "Access Denied")
+            raise service_error(service_error.access, "Access Denied",
+		    proof=proof)
 	
 
@@ -2466,5 +2500,10 @@
 	v = req.get('value', '')
 
-        if name and self.auth.check_attribute(fid, name):
+	if not name:
+	    raise service_error(service_error.req, "No name?")
+
+	access_ok, proof = self.auth.check_attribute(fid, name, with_proof=True)
+
+        if access_ok:
 	    try:
 		self.synch_store.set_value(name, v)
@@ -2479,5 +2518,6 @@
 		raise service_error(service_error.federant, 
 			"Synch key %s revoked" % name)
-	    return { 'name': name, 'value': v }
+		return { 'name': name, 'value': v, 'proof': proof.to_dict() }
         else:
-            raise service_error(service_error.access, "Access Denied")
+            raise service_error(service_error.access, "Access Denied",
+		    proof=proof)
