Index: fedd/federation/emulab_access.py
===================================================================
--- fedd/federation/emulab_access.py	(revision b6a6206de72822cb63f7b26373273586f5b891a5)
+++ fedd/federation/emulab_access.py	(revision 3df9b3328fe95742ccd22d24bab5295e599588dd)
@@ -925,5 +925,6 @@
 	allocation log bound to the state log variable as well. 
 	"""
-	configs = set(('hosts', 'ssh_pubkey', 'ssh_secretkey'))
+	configs = ('hosts', 'ssh_pubkey', 'ssh_secretkey', 
+		'seer_ca_pem', 'seer_node_pem')
 	ename = None
 	pubkey_base = None
Index: fedd/federation/experiment_control.py
===================================================================
--- fedd/federation/experiment_control.py	(revision b6a6206de72822cb63f7b26373273586f5b891a5)
+++ fedd/federation/experiment_control.py	(revision 3df9b3328fe95742ccd22d24bab5295e599588dd)
@@ -13,4 +13,6 @@
 import signal
 import time
+
+import os.path
 
 import traceback
@@ -551,4 +553,73 @@
                     "Cannot generate nonce ssh keys.  %s return code %d" \
                             % (self.ssh_keygen, rv))
+
+    def generate_seer_certs(self, destdir):
+	'''
+	Create a SEER ca cert and a node cert in destdir/ca.pem and
+	destdir/node.pem respectively.  These will be distributed throughout
+	the federated experiment.  This routine reports errors via
+	service_errors.
+	'''
+	openssl = '/usr/bin/openssl'
+	# All the filenames and parameters we need for openssl calls below
+	ca_serial =os.path.join(destdir, 'ca.serial') 
+	ca_key =os.path.join(destdir, 'ca.key') 
+	ca_pem = os.path.join(destdir, 'ca.pem')
+	node_key =os.path.join(destdir, 'node.key') 
+	node_pem = os.path.join(destdir, 'node.pem')
+	node_req = os.path.join(destdir, 'node.req')
+	node_signed = os.path.join(destdir, 'node.signed')
+	days = '%s' % (3600 * 24 * 365 * 10)
+
+        try:
+	    # init a serial number for the openssl calls
+	    f = open(ca_serial, 'w')
+	    print >>f, '%s' % random.randint(0, 0xffffffff)
+	    f.close()
+
+	    # Sequence of calls to create a CA key, create a ca cert, create a
+	    # node key, node signing request, and finally a signed node
+	    # certificate.
+	    sequence = (
+		    (openssl, 'genrsa', '-out', ca_key, '1024'),
+		    (openssl, 'req', '-new', '-x509', '-key', ca_key, '-out', 
+			ca_pem, '-days', days, '-subj', 
+			'/C=US/ST=CA/O=DETER/OU=fedd/CN=CA' ),
+		    (openssl, 'genrsa', '-out', node_key, '1024'),
+		    (openssl, 'req', '-new', '-key', node_key, '-out', 
+			node_req, '-days', days, '-subj', 
+			'/C=US/ST=CA/O=DETER/OU=fedd/CN=node' ),
+		    (openssl, 'x509', '-CA', ca_pem, '-CAkey', ca_key, 
+			'-CAserial', ca_serial, '-req', '-in', node_req, 
+			'-out', node_signed, '-days', days),
+		)
+	    # Do all that stuff; bail if there's an error, and push all the
+	    # output to dev/null.
+	    for cmd in sequence:
+		trace = open("/dev/null", "w")
+		rv = call(cmd, stdout=trace, stderr=trace, close_fds=True)
+		if rv != 0:
+		    raise service_error(service_error.internal, 
+			    "Cannot generate SEER certs.  %s return code %d" \
+				    % (' '.join(cmd), rv))
+	    # Concatinate the node key and signed certificate into node.pem
+	    f = open(node_pem, 'w')
+	    for comp in (node_signed, node_key):
+		g = open(comp, 'r')
+		f.write(g.read))
+		g.close()
+	    f.close()
+
+	    # Throw out intermediaries.
+	    for fn in (ca_serial, ca_key, node_key, node_req, node_signed):
+		os.unlink(fn)
+
+        except EnvironmentError, e:
+	    # Any difficulties with the file system wind up here
+            raise service_error(service_error.internal,
+		    "File error on  %s while creating SEER certs: %s" % \
+			    (e.filename, e.strerror))
+
+
 
     def gentopo(self, str):
@@ -1692,5 +1763,5 @@
 	testbed to lists of federated_service objects.  The first lists all
 	exporters of services, and the second all exporters of services that
-	need control portals int the experiment.
+	need control portals in the experiment.
 	"""
 	masters = { }
@@ -1733,15 +1804,16 @@
     def generate_keys_and_hosts(self, tmpdir, expid, hosts, tbparams):
 	"""
-	Create the ssh keys necessary for interconnecting the potral nodes and
+	Create the ssh keys necessary for interconnecting the portal nodes and
 	the global hosts file for letting each segment know about the IP
 	addresses in play.  Save these into the repo.  Add attributes to the
 	autorizer allowing access controllers to download them and return a set
-	of attributes that inform the segments where to find this stuff.  Mau
+	of attributes that inform the segments where to find this stuff.  May
 	raise service_errors in if there are problems.
 	"""
         gw_pubkey_base = "fed.%s.pub" % self.ssh_type
         gw_secretkey_base = "fed.%s" % self.ssh_type
-        gw_pubkey = tmpdir + "/keys/" + gw_pubkey_base
-        gw_secretkey = tmpdir + "/keys/" + gw_secretkey_base
+        keydir = os.path.join(tmpdir, 'keys')
+        gw_pubkey = os.path.join(keydir, gw_pubkey_base)
+        gw_secretkey = os.path.join(keydir, gw_secretkey_base)
 
 	try:
@@ -1751,4 +1823,5 @@
 		    "Bad key type (%s)" % self.ssh_type)
 
+	self.generate_seer_certs(keydir)
 
 	# Copy configuration files into the remote file store
@@ -1770,8 +1843,10 @@
 		    "Cannot write hosts file: %s" % e)
 	try:
-	    copy_file("%s" % gw_pubkey, "%s/%s" % \
-		    (configdir, gw_pubkey_base))
-	    copy_file("%s" % gw_secretkey, "%s/%s" % \
-		    (configdir, gw_secretkey_base))
+	    copy_file(gw_pubkey, os.path.join(configdir, gw_pubkey_base))
+	    copy_file(gw_secretkey, os.path.join(configdir, gw_secretkey_base))
+	    copy_file(os.path.join(keydir, 'ca.pem'), 
+		    os.path.join(configdir, 'ca.pem'))
+	    copy_file(os.path.join(keydir, 'node.pem'), 
+		    os.path.join(configdir, 'node.pem'))
 	except EnvironmentError, e:
 	    raise service_error(service_error.internal, 
@@ -1784,5 +1859,6 @@
 	    (tbparams[tb]['allocID']['fedid'], "%s/%s" % (configpath, f)) \
 		    for tb in tbparams.keys() \
-			for f in ("hosts", gw_secretkey_base, gw_pubkey_base)]))
+			for f in ("hosts", 'ca.pem', 'node.pem', 
+			    gw_secretkey_base, gw_pubkey_base)]))
 
 	attrs = [ 
@@ -1801,4 +1877,14 @@
 		    'value': '%s/%s/config/hosts' % \
 			    (self.repo_url, expid)
+		},
+		{
+		    'attribute': 'seer_ca_pem', 
+		    'value': '%s/%s/config/%s' % \
+			    (self.repo_url, expid, 'ca.pem')
+		},
+		{
+		    'attribute': 'seer_node_pem', 
+		    'value': '%s/%s/config/%s' % \
+			    (self.repo_url, expid, 'node.pem')
 		},
 	    ]
