diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 75ec0f71851d45a1af6e5715d199670c81d9cbce..c07cdf70918ddaa4dbc972f27fae5c7838d3ee8a 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -15,7 +15,7 @@ noinst_LTLIBRARIES = 	\
 	libcommon.la 	\
 	libdaemonize.la \
 	libhostlist.la	\
-        libeio.la
+	libeio.la  	
 
 
 libcommon_la_SOURCES = 			\
@@ -65,7 +65,9 @@ libhostlist_la_SOURCES   = \
 	hostlist.c hostlist.h
 
 libeio_la_SOURCES = 	   \
-	eio.c eio.h
+	eio.c eio.h	   \
+	io_hdr.c io_hdr.h
+
 
 EXTRA_libcommon_la_SOURCES = \
 	qsw.c qsw.h
diff --git a/src/common/io_hdr.c b/src/common/io_hdr.c
new file mode 100644
index 0000000000000000000000000000000000000000..5bebe568d918c05385e44f8f1b95eed794de0a11
--- /dev/null
+++ b/src/common/io_hdr.c
@@ -0,0 +1,141 @@
+/*****************************************************************************\
+ * src/common/io_hdr.c - IO connection header functions
+ * $Id$
+ *****************************************************************************
+ *  Copyright (C) 2002 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Mark A. Grondona <mgrondona@llnl.gov>.
+ *  UCRL-CODE-2002-040.
+ *  
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://www.llnl.gov/linux/slurm/>.
+ *  
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *  
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *  
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+\*****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "src/common/io_hdr.h"
+#include "src/common/slurm_protocol_defs.h"
+
+#define IO_HDR_VERSION 0xa001
+
+static void
+_print_data(char *data, int datalen)
+{
+	char buf[1024];
+	size_t len = 0;
+	int i;
+
+	for (i = 0; i < datalen; i += sizeof(char))
+		len += sprintf(buf+len, "%02x", data[i]);
+
+	info("data: %s", buf);
+}
+
+
+static void
+io_hdr_pack(io_hdr_t *hdr, Buf buffer)
+{
+	pack16(hdr->version, buffer);
+	packmem(hdr->key, (uint16_t) SLURM_IO_KEY_SIZE, buffer);
+	pack32(hdr->taskid,  buffer);
+	pack16(hdr->type,    buffer);
+}
+
+static int
+io_hdr_unpack(io_hdr_t *hdr, Buf buffer)
+{
+	uint16_t val;
+
+	safe_unpack16(&hdr->version, buffer);
+
+	safe_unpackmem(hdr->key, &val, buffer);
+
+	xassert(val == SLURM_IO_KEY_SIZE);
+
+	safe_unpack32(&hdr->taskid, buffer);
+	safe_unpack16(&hdr->type, buffer);
+
+	return SLURM_SUCCESS;
+
+    unpack_error:
+	return SLURM_ERROR;
+}
+
+int 
+io_hdr_packed_size()
+{
+	return sizeof(uint32_t) + 3*sizeof(uint16_t) + SLURM_IO_KEY_SIZE;
+}
+
+int 
+io_hdr_write_cb(cbuf_t cb, io_hdr_t *hdr)
+{
+	int retval = SLURM_SUCCESS;
+
+	Buf buffer = init_buf(1024);
+	hdr->version = IO_HDR_VERSION;
+
+	io_hdr_pack(hdr, buffer);
+
+	xassert(buffer->processed == io_hdr_packed_size());
+
+	retval = cbuf_write(cb, buffer->head, buffer->processed, NULL);
+	free_buf(buffer);
+
+	return retval;
+} 
+
+int 
+io_hdr_read_cb(cbuf_t cb, io_hdr_t *hdr)
+{
+	Buf buffer = init_buf(4096);
+	int rc     = SLURM_SUCCESS;
+
+	cbuf_read(cb, buffer->head, io_hdr_packed_size());
+	
+	rc = io_hdr_unpack(hdr, buffer);
+
+	free_buf(buffer);
+	return rc; 
+}
+
+int 
+io_hdr_validate(io_hdr_t *hdr, const unsigned char *key, int len)
+{
+	
+	if (hdr->version != IO_HDR_VERSION) {
+		error("Invalid IO header version");
+		return SLURM_ERROR;
+	}
+
+	if ((hdr->type != SLURM_IO_STDOUT) && (hdr->type != SLURM_IO_STDERR)) {
+		error("Invalid IO header type: %d", hdr->type);
+		return SLURM_ERROR;
+	}
+
+	len = len < SLURM_IO_KEY_SIZE ? len : SLURM_IO_KEY_SIZE;
+
+	if (memcmp((void *) key, (void *) hdr->key, len)) {
+		error("Invalid IO header signature");
+		return SLURM_ERROR;
+	}
+
+	return SLURM_SUCCESS;
+}
+
diff --git a/src/common/io_hdr.h b/src/common/io_hdr.h
new file mode 100644
index 0000000000000000000000000000000000000000..928d33fffe1503f995056a6fd76df151f11d60db
--- /dev/null
+++ b/src/common/io_hdr.h
@@ -0,0 +1,88 @@
+/*****************************************************************************\
+ * src/common/io_hdr.h - IO connection header functions
+ * $Id$
+ *****************************************************************************
+ *  Copyright (C) 2002 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Mark A. Grondona <mgrondona@llnl.gov>.
+ *  UCRL-CODE-2002-040.
+ *  
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://www.llnl.gov/linux/slurm/>.
+ *  
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *  
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *  
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+\*****************************************************************************/
+
+#ifndef _HAVE_IO_HDR_H
+#define _HAVE_IO_HDR_H
+
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdint.h>
+
+#include "src/common/pack.h"
+#include "src/common/cbuf.h"
+
+#define SLURM_IO_KEY_SIZE 8	/* IO key is 64 bits */
+
+/* 
+ * Slurm IO stream types:
+ *
+ * STDOUT = stdout/stdin
+ * STDERR = stderr/signals
+ */
+#define SLURM_IO_STDOUT   0x00
+#define SLURM_IO_STDERR   0x01
+
+typedef struct slurm_io_header {
+	unsigned char key[SLURM_IO_KEY_SIZE]; 
+	uint32_t      taskid;
+	uint16_t      version;
+	uint16_t      type;
+} io_hdr_t;
+
+
+/*
+ * Return the packed size of an IO header in bytes;
+ */
+int io_hdr_packed_size();
+
+
+/* 
+ * Write an io header into the cbuf in packed form
+ */
+int io_hdr_write_cb(cbuf_t cb, io_hdr_t *hdr);
+
+/*
+ * Read an io header from the cbuf into hdr
+ */
+int io_hdr_read_cb(cbuf_t cb, io_hdr_t *hdr);
+
+/*
+ * Validate io header hdr against len bytes of the data in key
+ *
+ * Returns 0 on success, -1 if any of the following is not true
+ *
+ *  version          != internal version
+ *  type             != (SLURM_IO_STDOUT or SLURM_IO_STDERR)
+ *  len bytes of key != hdr->key
+ *
+ */
+int io_hdr_validate(io_hdr_t *hdr, const unsigned char *key, int len);
+
+#endif /* !_HAVE_IO_HDR_H */
diff --git a/src/common/macros.h b/src/common/macros.h
index 78122fcafc21b68484c7bf98f27ae271392dc70e..62be0810d2b05a462c6ebc775efb227ea6d62e76 100644
--- a/src/common/macros.h
+++ b/src/common/macros.h
@@ -57,6 +57,8 @@ typedef enum {false, true} bool;
 #define MAX(a,b) ((a) > (b) ? (a) : (b))	
 #endif
 
+#define SLURM_IO_KEY_SIZE 8
+
 #  define UINT64_SWAP_LE_BE(val)      ((uint64_t) (                           \
         (((uint64_t) (val) &                                                  \
           (uint64_t) (0x00000000000000ffU)) << 56) |                          \
diff --git a/src/common/slurm_cred.c b/src/common/slurm_cred.c
index 398092e8c276c44fdb982c58e74c848c42ae960e..df2cd5d501c35c057d01ff12e5449bd82821d269 100644
--- a/src/common/slurm_cred.c
+++ b/src/common/slurm_cred.c
@@ -32,6 +32,7 @@
 #include <slurm/slurm_errno.h>
 
 #include <stdarg.h>
+#include <fcntl.h>
 
 /*
  * OpenSSL includes
@@ -106,6 +107,10 @@ struct slurm_cred_context {
  *
  */
 struct slurm_job_credential {
+#ifndef NDEBUG
+#  define CRED_MAGIC 0x0b0b0b
+	int      magic;
+#endif
 	uint32_t jobid;        /* Job ID associated with this credential    */
 	uint32_t stepid;       /* Job step ID for this credential           */
 	uid_t    uid;          /* user for which this cred is valid         */
@@ -301,6 +306,9 @@ slurm_cred_create(slurm_cred_ctx_t ctx, slurm_cred_arg_t *arg)
 
 	cred = _slurm_cred_alloc();
 
+	xassert(cred != NULL);
+	xassert(cred->magic == CRED_MAGIC);
+
 	cred->jobid  = arg->jobid;
 	cred->stepid = arg->stepid;
 	cred->uid    = arg->uid;
@@ -317,6 +325,36 @@ slurm_cred_create(slurm_cred_ctx_t ctx, slurm_cred_arg_t *arg)
 	return NULL;
 }
 
+slurm_cred_t
+slurm_cred_faker(slurm_cred_arg_t *arg)
+{
+	int fd;
+	slurm_cred_t cred = NULL;
+
+	xassert(arg != NULL);
+
+	cred = _slurm_cred_alloc();
+
+	cred->jobid  = arg->jobid;
+	cred->stepid = arg->stepid;
+        cred->uid    = arg->uid;
+	cred->nodes  = xstrdup(arg->hostlist);
+	cred->ctime  = time(NULL);
+	cred->siglen = SLURM_IO_KEY_SIZE;
+
+	if ((fd = open("/dev/random", O_RDONLY)) < 0)
+		error ("unable to open /dev/random: %m");
+
+	cred->signature = xmalloc(cred->siglen * sizeof(char));
+	read(fd, cred->signature, cred->siglen);
+
+	if (close(fd) < 0)
+		error ("close(/dev/random): %m");
+
+	return cred;
+    	
+}
+
 
 int
 slurm_cred_verify(slurm_cred_ctx_t ctx, slurm_cred_t cred, 
@@ -327,8 +365,9 @@ slurm_cred_verify(slurm_cred_ctx_t ctx, slurm_cred_t cred,
 	xassert(ctx  != NULL);
 	xassert(cred != NULL);
 	xassert(arg  != NULL);
-	xassert(ctx->magic == CRED_CTX_MAGIC);
-	xassert(ctx->type  == SLURM_CRED_VERIFIER);
+	xassert(ctx->magic  == CRED_CTX_MAGIC);
+	xassert(ctx->type   == SLURM_CRED_VERIFIER);
+	xassert(cred->magic == CRED_MAGIC);
 
 	if (_slurm_cred_verify_signature(ctx, cred) < 0)
 		slurm_seterrno_ret(ESLURMD_INVALID_JOB_CREDENTIAL);
@@ -360,6 +399,8 @@ slurm_cred_destroy(slurm_cred_t cred)
 	if (cred == NULL)
 		return;
 
+	xassert(cred->magic == CRED_MAGIC);
+
 	if (cred->nodes)
 		xfree(cred->nodes);
 	if (cred->signature)
@@ -418,9 +459,12 @@ slurm_cred_revoke(slurm_cred_ctx_t ctx, uint32_t jobid)
 }
 
 int
-slurm_cred_get_signature(slurm_cred_t cred, char *data, int *datalen)
+slurm_cred_get_signature(slurm_cred_t cred, char **datap, int *datalen)
 {
-	data     = cred->signature;
+	xassert(datap != NULL);
+	xassert(datalen != NULL);
+
+	*datap   = cred->signature;
 	*datalen = cred->siglen;
 	return SLURM_SUCCESS;
 }
@@ -428,7 +472,11 @@ slurm_cred_get_signature(slurm_cred_t cred, char *data, int *datalen)
 void
 slurm_cred_pack(slurm_cred_t cred, Buf buffer)
 {
+	xassert(cred != NULL);
+	xassert(cred->magic == CRED_MAGIC);
+
 	_pack_cred(cred, buffer);
+	xassert(cred->siglen > 0);
 	packmem(cred->signature, (uint16_t) cred->siglen, buffer);
 	return;
 }
@@ -453,6 +501,8 @@ slurm_cred_unpack(Buf buffer)
 	safe_unpack_time(       &cred->ctime,        buffer);
 	safe_unpackmem_xmalloc( sigp,         &len,  buffer);
 
+	xassert(len > 0);
+
 	cred->siglen = len;
 
 	return cred;
@@ -494,6 +544,8 @@ slurm_cred_print(slurm_cred_t cred)
 	if (cred == NULL)
 		return;
 
+	xassert(cred->magic == CRED_MAGIC);
+
 	info("Cred: Jobid   %u",  cred->jobid         );
 	info("Cred: Stepid  %u",  cred->jobid         );
 	info("Cred: UID     %lu", cred->uid           );
@@ -659,6 +711,8 @@ _slurm_cred_alloc(void)
 	cred->signature = NULL;
 	cred->siglen    = 0;
 
+	xassert(cred->magic = CRED_MAGIC);
+
 	return cred;
 }
 
@@ -721,6 +775,8 @@ _slurm_cred_verify_signature(slurm_cred_ctx_t ctx, slurm_cred_t cred)
 	buffer = init_buf(4096);
 	_pack_cred(cred, buffer);
 
+	debug("Checking credential with %d bytes of sig data", siglen);
+
 	EVP_VerifyInit(&ectx, EVP_sha1());
 	EVP_VerifyUpdate(&ectx, get_buf_data(buffer), get_buf_offset(buffer));
 
@@ -734,7 +790,7 @@ _slurm_cred_verify_signature(slurm_cred_ctx_t ctx, slurm_cred_t cred)
 
 	if (!rc) {
 		ERR_load_crypto_strings();
-		error("EVP_VerifyFinal: %s", _ssl_error());
+		error("Credential signature check error: %s", _ssl_error());
 		ERR_free_strings();
 		rc = SLURM_ERROR;
 	} else
@@ -940,7 +996,6 @@ _job_state_pack_one(job_state_t *j, Buf buffer)
 	pack_time(j->ctime, buffer);
 	pack_time(j->expiration, buffer);
 
-	_print_data(buffer->head, buffer->processed);
 }
 
 
diff --git a/src/common/slurm_cred.h b/src/common/slurm_cred.h
index 284f7106974374cab2027a72fac0f864ecd46c08..75615eb314f75c845e89e2344d6c028957cd9459 100644
--- a/src/common/slurm_cred.h
+++ b/src/common/slurm_cred.h
@@ -133,6 +133,15 @@ typedef struct {
  */
 slurm_cred_t slurm_cred_create(slurm_cred_ctx_t ctx, slurm_cred_arg_t *arg);
 
+
+/*
+ * Create a "fake" credential with bogus data in the signature.
+ * This function can be used for testing, or when srun would like
+ * to talk to slurmd directly, bypassing the controller
+ * (which normally signs creds)
+ */
+slurm_cred_t slurm_cred_faker(slurm_cred_arg_t *arg);
+
 /*
  * Verify the signed credential `cred,' and return cred contents in
  * the cred_arg structure. The credential is cached and cannot be reused.
@@ -179,7 +188,7 @@ slurm_cred_t slurm_cred_unpack(Buf buffer);
  * Get a pointer to the slurm credential signature
  * (used by slurm IO connections to verify connecting agent)
  */
-int slurm_cred_get_signature(slurm_cred_t cred, char *data, int *len);
+int slurm_cred_get_signature(slurm_cred_t cred, char **datap, int *len);
 
 
 /*
diff --git a/src/common/slurm_protocol_defs.h b/src/common/slurm_protocol_defs.h
index a84c062797fd47bab55224070647cff8c8a68c24..dda9db06ee47a7abea872e0638bbb155415daa1c 100644
--- a/src/common/slurm_protocol_defs.h
+++ b/src/common/slurm_protocol_defs.h
@@ -49,12 +49,6 @@
 #include "src/common/slurm_protocol_common.h"
 #include "src/common/xassert.h"
 
-/* used to define the type of the io_stream_header_t.type
- */
-enum io_stream_types {
-	SLURM_IO_STREAM_INOUT = 0,
-	SLURM_IO_STREAM_SIGERR = 1
-};
 
 /* used to define flags of the launch_tasks_request_msg_t.task_flags
  */
@@ -164,13 +158,6 @@ typedef struct slurm_protocol_header {
 	uint32_t body_length;
 } header_t;
 
-typedef struct slurm_io_stream_header {
-	uint16_t version;	/*version/magic number */
-	char key[SLURM_SSL_SIGNATURE_LENGTH];
-	uint32_t task_id;
-	uint16_t type;
-} slurm_io_stream_header_t;
-
 typedef struct slurm_msg {
 	slurm_msg_type_t msg_type;
 	slurm_addr address;
@@ -294,15 +281,15 @@ typedef struct job_time_msg {
 } job_time_msg_t;
 
 typedef struct reattach_tasks_request_msg {
-	uint32_t  job_id;
-	uint32_t  job_step_id;
-	uint32_t  srun_node_id;
-	uint16_t  resp_port;
-	uint16_t  io_port;
-	char     *ofname;
-	char     *efname;
-	char     *ifname;
-	char      key[SLURM_SSL_SIGNATURE_LENGTH];
+	uint32_t     job_id;
+	uint32_t     job_step_id;
+	uint32_t     srun_node_id;
+	uint16_t     resp_port;
+	uint16_t     io_port;
+	char        *ofname;
+	char        *efname;
+	char        *ifname;
+	slurm_cred_t cred;
 } reattach_tasks_request_msg_t;
 
 typedef struct reattach_tasks_response_msg {
diff --git a/src/common/slurm_protocol_pack.c b/src/common/slurm_protocol_pack.c
index 0d358a0dd9da1334be9a4ce8ffe2d87d0434b1a3..5e65b58d263700af36c9e858dce9e66195f532d0 100644
--- a/src/common/slurm_protocol_pack.c
+++ b/src/common/slurm_protocol_pack.c
@@ -235,58 +235,6 @@ unpack_header(header_t * header, Buf buffer)
 	return SLURM_ERROR;
 }
 
-/* size_io_stream_header - get the size of an I/O stream header
- * RET number of bytes in an I/O steam header
- */
-int
-size_io_stream_header(void)
-{
-	/* must match un/pack_io_stream_header and size_io_stream_header */
-	return (SLURM_SSL_SIGNATURE_LENGTH +
-		2 * sizeof(uint16_t) + sizeof(uint32_t));
-}
-
-/* pack_io_stream_header
- * packs an i/o stream protocol header used for stdin/out/err
- * IN header - the header structure to pack
- * IN/OUT buffer - destination of the pack, contains pointers that are
- *			automatically updated
- */
-void
-pack_io_stream_header(slurm_io_stream_header_t * header, Buf buffer)
-{				/* must match un/pack_io_stream_header and size_io_stream_header */
-
-	assert(header != NULL);
-
-	pack16(header->version, buffer);
-	packmem_array(header->key, (uint32_t) SLURM_SSL_SIGNATURE_LENGTH,
-		      buffer);
-	pack32(header->task_id, buffer);
-	pack16(header->type, buffer);
-}
-
-/* unpack_io_stream_header
- * unpacks an i/o stream protocol header used for stdin/out/err
- * OUT header - the header structure to unpack
- * IN/OUT buffer - source of the unpack data, contains pointers that are
- *			automatically updated
- * RET 0 or error code
- */
-int
-unpack_io_stream_header(slurm_io_stream_header_t * header, Buf buffer)
-{
-	/* must match un/pack_io_stream_header and size_io_stream_header */
-	safe_unpack16(&header->version, buffer);
-	safe_unpackmem_array(header->key,
-			     (uint32_t) SLURM_SSL_SIGNATURE_LENGTH, buffer);
-	safe_unpack32(&header->task_id, buffer);
-	safe_unpack16(&header->type, buffer);
-	return SLURM_SUCCESS;
-
-      unpack_error:
-	return SLURM_ERROR;
-}
-
 
 /* pack_msg
  * packs a generic slurm protocol message body
@@ -1849,8 +1797,7 @@ _pack_reattach_tasks_request_msg(reattach_tasks_request_msg_t * msg,
 	packstr(msg->ofname, buffer);
 	packstr(msg->efname, buffer);
 	packstr(msg->ifname, buffer);
-	packmem_array(msg->key,
-		      (uint32_t) SLURM_SSL_SIGNATURE_LENGTH, buffer);
+	slurm_cred_pack(msg->cred, buffer);
 }
 
 static int
@@ -1871,8 +1818,9 @@ _unpack_reattach_tasks_request_msg(reattach_tasks_request_msg_t ** msg_ptr,
 	safe_unpackstr_xmalloc(&msg->ofname, &uint16_tmp, buffer);
 	safe_unpackstr_xmalloc(&msg->efname, &uint16_tmp, buffer);
 	safe_unpackstr_xmalloc(&msg->ifname, &uint16_tmp, buffer);
-	safe_unpackmem_array(msg->key,
-			     (uint32_t) SLURM_SSL_SIGNATURE_LENGTH, buffer);
+
+	if (!(msg->cred = slurm_cred_unpack(buffer)))
+		goto unpack_error;
 
 	return SLURM_SUCCESS;
 
diff --git a/src/common/slurm_protocol_pack.h b/src/common/slurm_protocol_pack.h
index d8d7f9ccd77359e0aa60fb5271b45e5941da6634..3d5cfe58cb061a0a8e7ee1cd583a4ae9fc383b56 100644
--- a/src/common/slurm_protocol_pack.h
+++ b/src/common/slurm_protocol_pack.h
@@ -65,34 +65,6 @@ extern void pack_header ( header_t  * header , Buf buffer );
 extern int unpack_header ( header_t * header , Buf buffer );
 
 
-/****************************/
-/* Stream header functions  */
-/****************************/
-
-/* size_io_stream_header - get the size of an I/O stream header
- * RET number of bytes in an I/O steam header
- */
-extern int size_io_stream_header ( void );
-
-/* pack_io_stream_header
- * packs an i/o stream protocol header used for stdin/out/err
- * IN header - the header structure to pack
- * IN/OUT buffer - destination of the pack, contains pointers that are
- *			automatically updated
- */
-extern void pack_io_stream_header ( slurm_io_stream_header_t * header , 
-                                    Buf buffer ) ;
-
-/* unpack_io_stream_header
- * unpacks an i/o stream protocol header used for stdin/out/err
- * OUT header - the header structure to unpack
- * IN/OUT buffer - source of the unpack data, contains pointers that are
- *			automatically updated
- * RET 0 or error code
- */
-extern int unpack_io_stream_header ( slurm_io_stream_header_t * header , 
-                                     Buf buffer ) ;
-
 /**************************************************************************/
 /* generic case statement Pack / Unpack methods for slurm protocol bodies */
 /**************************************************************************/
diff --git a/src/common/slurm_protocol_util.c b/src/common/slurm_protocol_util.c
index c6a4040c2a8a9d58aa30616df6fe6dd5bca311dc..2727dce5e22dc4cb06a6ffd0ffadc2ba7e9c5d63 100644
--- a/src/common/slurm_protocol_util.c
+++ b/src/common/slurm_protocol_util.c
@@ -74,171 +74,6 @@ void update_header(header_t * header, uint32_t msg_length)
 	header->body_length = msg_length;
 }
 
-/*
- * check_io_stream_header_version checks to see that the specified header 
- *	was sent from a node running the same version of the protocol as 
- *	the current node
- * IN header - the message recevied
- * RET - SLURM error code
- */
-uint32_t check_io_stream_header_version(slurm_io_stream_header_t * header)
-{
-	if (header->version != SLURM_PROTOCOL_VERSION) {
-		debug("Invalid IO Stream Protocol Version %d ",
-		      header->version);
-		slurm_seterrno_ret(SLURM_PROTOCOL_IO_STREAM_VERSION_ERROR);
-	}
-	return SLURM_PROTOCOL_SUCCESS;
-}
-
-/*
- * init_io_stream_header - simple function to create a header, always 
- *	insuring that an accurate version string is inserted
- * OUT header - the message header to be sent
- * IN key - authentication signature
- * IN task_id - message's task_id
- * IN type - message type
- */
-void init_io_stream_header(slurm_io_stream_header_t * header, char *key,
-			   uint32_t task_id, uint16_t type)
-{
-	assert(key != NULL);
-	header->version = SLURM_PROTOCOL_VERSION;
-	memcpy(header->key, key, SLURM_SSL_SIGNATURE_LENGTH);
-	header->task_id = task_id;
-	header->type = type;
-}
-
-/*
- * read an i/o stream header from the supplied slurm stream
- *	data is copied in a block
- * IN fd - the file descriptor to read from
- * OUT header - the header read
- * RET number of bytes read
- */
-int read_io_stream_header(slurm_io_stream_header_t * header, slurm_fd fd)
-{
-	char *data;
-	int  buf_size, rsize;
-	Buf my_buf;
-
-	buf_size = sizeof(slurm_io_stream_header_t);
-	data = xmalloc(buf_size);
-	rsize = slurm_read_stream(fd, data, buf_size);
-	my_buf = create_buf (data, buf_size);
-	if ((rsize == buf_size) &&
-	    (unpack_io_stream_header(header, my_buf) != SLURM_SUCCESS)) {
-		error ("Malformed stream header");
-		rsize = 0;
-	}
-	free_buf(my_buf);
-	return rsize;
-}
-
-/*
- * write an i/o stream header to the supplied slurm stream
- *	data is copied in a block
- * IN fd - the file descriptor to read from
- * IN header - the header read
- * RET number of bytes written
- */
-int write_io_stream_header(slurm_io_stream_header_t * header, slurm_fd fd)
-{
-	int  buf_size, wsize;
-	Buf my_buf;
-
-	buf_size = sizeof(slurm_io_stream_header_t);
-	my_buf = init_buf(buf_size);
-	pack_io_stream_header(header, my_buf);
-	wsize = slurm_write_stream(fd, get_buf_data(my_buf), 
-	                           get_buf_offset(my_buf));
-	free_buf(my_buf);
-	return wsize;
-}
-
-/*
- * read an i/o stream header from the supplied slurm stream
- *	data is unpacked field by field
- * IN fd - the file descriptor to read from
- * OUT header - the header read
- * RET number of bytes read
- */
-int read_io_stream_header2(slurm_io_stream_header_t * header, slurm_fd fd)
-{
-	int rsize;
-
-	rsize = slurm_read_stream(fd, (char *)&header->version, 
-			          sizeof(header->version));
-	if (rsize != sizeof(header->version)) 
-		return rsize;
-	header->version = ntohs(header->version);
-
-	rsize = slurm_read_stream(fd, (char *) &header->key,
-	                          sizeof(header->key));
-	if (rsize != sizeof(header->key)) 
-		return rsize;
-
-	rsize = slurm_read_stream(fd, (char *) &header->task_id, 
-			          sizeof(header->task_id));
-	if (rsize != sizeof(header->task_id)) 
-		return rsize;
-	header->task_id = ntohl(header->task_id);
-
-	rsize = slurm_read_stream(fd, (char *) &header->type, 
-	                          sizeof(header->type));
-	if (rsize != sizeof(header->type))
-		return rsize;
-	header->type = ntohs(header->type);
-
-	return SLURM_SUCCESS;
-}
-
-/*
- * write an i/o stream header to the supplied slurm stream
- *	data is packed field by field
- * IN fd - the file descriptor to read from
- * IN header - the header read
- * RET number of bytes written
- */
-int write_io_stream_header2(slurm_io_stream_header_t * header, slurm_fd fd)
-{
-	int write_size;
-	slurm_io_stream_header_t header2 = *header;
-
-	header->version = htons(header2.version);
-	if ((write_size =
-	     slurm_write_stream(fd, (char *) &header2.version,
-				sizeof(header2.version))) !=
-	    sizeof(header2.version)) {
-		return write_size;
-	}
-
-	if ((write_size =
-	     slurm_write_stream(fd, header2.key,
-				sizeof(header2.key))) !=
-	    sizeof(header2.key)) {
-		return write_size;
-	}
-
-	header->task_id = htonl(header2.task_id);
-	if ((write_size =
-	     slurm_write_stream(fd, (char *) &header2.version,
-				sizeof(header2.task_id))) !=
-	    sizeof(header2.task_id)) {
-		return write_size;
-	}
-
-	header->type = htons(header2.type);
-	if ((write_size =
-	     slurm_write_stream(fd, (char *) &header2.version,
-				sizeof(header2.type))) !=
-	    sizeof(header2.type)) {
-		return write_size;
-	}
-
-	return SLURM_SUCCESS;
-}
-
 
 /* log the supplied slurm task launch message as debug3() level */
 void slurm_print_launch_task_msg(launch_tasks_request_msg_t * msg)
diff --git a/src/common/slurm_protocol_util.h b/src/common/slurm_protocol_util.h
index 2b22c10520c20778173079538303d7f305525169..35070bc5b00a41bc48671d486ad6bc9402b87e7f 100644
--- a/src/common/slurm_protocol_util.h
+++ b/src/common/slurm_protocol_util.h
@@ -64,27 +64,6 @@ extern uint32_t check_header_version(header_t * header);
 extern void 
 init_header(header_t * header, slurm_msg_type_t msg_type, uint16_t flags);
 
-/*
- * check_io_stream_header_version checks to see that the specified header 
- *	was sent from a node running the same version of the protocol as 
- *	the current node
- * IN header - the message recevied
- * RET - SLURM error code
- */
-extern uint32_t 
-check_io_stream_header_version(slurm_io_stream_header_t * header);
-
-/*
- * init_io_stream_header - simple function to create a header, always 
- *	insuring that an accurate version string is inserted
- * OUT header - the message header to be sent
- * IN key - authentication signature
- * IN task_id - message's task_id
- * IN type - message type
- */
-extern void 
-init_io_stream_header(slurm_io_stream_header_t * header, char *key,
-                      uint32_t task_id, uint16_t type);
 
 /*
  * update_header - update a message header with the message len
@@ -94,44 +73,6 @@ init_io_stream_header(slurm_io_stream_header_t * header, char *key,
 extern void 
 update_header(header_t * header, uint32_t msg_length);
 
-/*
- * read an i/o stream header from the supplied slurm stream
- *	data is copied in a block
- * IN fd - the file descriptor to read from
- * OUT header - the header read
- * RET number of bytes read
- */
-extern int read_io_stream_header(slurm_io_stream_header_t * header, slurm_fd fd);
-
-/*
- * read an i/o stream header from the supplied slurm stream
- *	data is unpacked field by field
- * IN fd - the file descriptor to read from
- * OUT header - the header read
- * RET number of bytes read
- */
-extern int read_io_stream_header2(slurm_io_stream_header_t * header, slurm_fd fd);
-
-/*
- * write an i/o stream header to the supplied slurm stream
- *	data is copied in a block
- * IN fd - the file descriptor to read from
- * IN header - the header read
- * RET number of bytes written
- */
-extern int write_io_stream_header(slurm_io_stream_header_t * header, slurm_fd fd);
-
-/* log the supplied slurm credential as debug3() level */
-/* extern void slurm_print_job_credential(slurm_job_credential_t * credential);*/
-
-/*
- * write an i/o stream header to the supplied slurm stream
- *	data is packed field by field
- * IN fd - the file descriptor to read from
- * IN header - the header read
- * RET number of bytes written
- */
-extern int write_io_stream_header2(slurm_io_stream_header_t * header, slurm_fd fd);
 
 /* log the supplied slurm task launch message as debug3() level */
 extern void slurm_print_launch_task_msg(launch_tasks_request_msg_t * msg);
diff --git a/src/plugins/auth/auth_munge.c b/src/plugins/auth/auth_munge.c
index bc7ba70d9354150c93a26b9b5106b73498ed4b60..c0cc9f336b3e9bd6e462e9361d1455f967df1e7f 100644
--- a/src/plugins/auth/auth_munge.c
+++ b/src/plugins/auth/auth_munge.c
@@ -111,13 +111,14 @@ _decode_cred(char *m, slurm_auth_credential_t *c)
 }
 
 
-void init ( void )
+int init ( void )
 {
 	/* 
 	 * Perhaps we could init a global context here? 
 	 * Do nothing for now.
 	 *
 	 */
+	return 0;
 }
 
 
diff --git a/src/slurmctld/Makefile.am b/src/slurmctld/Makefile.am
index 1b2a6a99d82a3dcae98510afcda63574592852b9..2c6dada5335db9c9b5d946949a7bbe963c6bdca3 100644
--- a/src/slurmctld/Makefile.am
+++ b/src/slurmctld/Makefile.am
@@ -11,7 +11,6 @@ sbin_PROGRAMS = slurmctld
 
 slurmctld_LDADD = 					\
 	$(top_builddir)/src/common/libcommon.la    	\
-	$(top_builddir)/src/common/libcred.la      	\
 	$(top_builddir)/src/common/libhostlist.la      	\
 	$(top_builddir)/src/common/libdaemonize.la 
 
diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c
index 3aaf32d1b363ccd8435ffef5d622f617b3db7889..9532c098d56cdc943b511fae774a91ad9c9bbb84 100644
--- a/src/slurmctld/controller.c
+++ b/src/slurmctld/controller.c
@@ -115,7 +115,7 @@ static void *       _background_rpc_mgr(void *no_data);
 static void *       _background_signal_hand(void *no_data);
 static void         _fill_ctld_conf(slurm_ctl_conf_t * build_ptr);
 static int          _make_step_cred(struct step_record *step_rec, 
-				    slurm_cred_t slurm_cred);
+				    slurm_cred_t *slurm_cred);
 static void         _parse_commandline(int argc, char *argv[], 
                                        slurm_ctl_conf_t *);
 static int          _ping_controller(void);
@@ -225,7 +225,11 @@ int main(int argc, char *argv[])
 						 job_credential_private_key);
 	if (!cred_ctx)
 		fatal("slurm_cred_creator_ctx_create: %m");
-	slurm_cred_ctx_set(cred_ctx, SLURM_CRED_OPT_EXPIRY_WINDOW, CRED_LIFE);
+	/* Not used in creator
+	 *
+	 * slurm_cred_ctx_set(cred_ctx, 
+	 *                    SLURM_CRED_OPT_EXPIRY_WINDOW, CRED_LIFE);
+	 */
 
 	/* Block SIGALRM everyone not explicitly enabled */
 	if (sigemptyset(&set))
@@ -1516,7 +1520,7 @@ static void _slurm_rpc_allocate_and_run(slurm_msg_t * msg)
 	req_step_msg.task_dist  = job_desc_msg->task_dist;
 	error_code = step_create(&req_step_msg, &step_rec, true);
 	if (error_code == SLURM_SUCCESS)
-		error_code = _make_step_cred(step_rec, slurm_cred);
+		error_code = _make_step_cred(step_rec, &slurm_cred);
 
 	/* note: no need to free step_rec, pointer to global job step record */
 	if (error_code) {
@@ -1872,7 +1876,7 @@ static void _slurm_rpc_job_step_create(slurm_msg_t * msg)
 		error_code = step_create(req_step_msg, &step_rec, false);
 	}
 	if (error_code == SLURM_SUCCESS)
-		error_code = _make_step_cred(step_rec, slurm_cred);
+		error_code = _make_step_cred(step_rec, &slurm_cred);
 
 	/* return result */
 	if (error_code) {
@@ -1910,7 +1914,7 @@ static void _slurm_rpc_job_step_create(slurm_msg_t * msg)
 
 /* create a credential for a given job step, return error code */
 static int _make_step_cred(struct step_record *step_rec, 
-			   slurm_cred_t slurm_cred)
+			   slurm_cred_t *slurm_cred)
 {
 	slurm_cred_arg_t cred_arg;
 
@@ -1918,10 +1922,12 @@ static int _make_step_cred(struct step_record *step_rec,
 	cred_arg.stepid   = step_rec->step_id;
 	cred_arg.uid      = step_rec->job_ptr->user_id;
 	cred_arg.hostlist = step_rec->step_node_list;
-	if ((slurm_cred = slurm_cred_create(cred_ctx, &cred_arg)) == NULL) {
+
+	if ((*slurm_cred = slurm_cred_create(cred_ctx, &cred_arg)) == NULL) {
 		error("slurm_cred_create error");
 		return ESLURM_INVALID_JOB_CREDENTIAL;
 	}
+
 	return SLURM_SUCCESS;
 }
 
diff --git a/src/slurmd/Makefile.am b/src/slurmd/Makefile.am
index 8f48ad9b8782f3d9eb3e10ea2d688008888c2435..f84f534fe182e871251e71491c458e26148abab6 100644
--- a/src/slurmd/Makefile.am
+++ b/src/slurmd/Makefile.am
@@ -17,7 +17,6 @@ endif
 slurmd_LDADD = 					   \
         $(top_builddir)/src/common/libcommon.la    \
 	$(top_builddir)/src/common/libdaemonize.la \
-	$(top_builddir)/src/common/libcred.la      \
 	$(top_builddir)/src/common/libhostlist.la  \
 	$(top_builddir)/src/common/libeio.la       \
 	$(SSL_LIBS) 
diff --git a/src/slurmd/io.c b/src/slurmd/io.c
index a6c2c4a4616d2f267290ee65c85c8f18b4baead6..59efdcac9db5689d4a4770e0c8ec4913f4b817e7 100644
--- a/src/slurmd/io.c
+++ b/src/slurmd/io.c
@@ -49,6 +49,7 @@
 #include <errno.h>
 
 #include "src/common/eio.h"
+#include "src/common/io_hdr.h"
 #include "src/common/cbuf.h"
 #include "src/common/log.h"
 #include "src/common/fd.h"
@@ -1028,31 +1029,22 @@ io_init_pipes(slurmd_job_t *job)
 static int
 _io_write_header(struct io_info *client, srun_info_t *srun)
 {
-	slurm_io_stream_header_t hdr;
-	char *buf;
-	int retval;
-	int size   = sizeof(hdr);
-	Buf buffer = init_buf(size);
+	io_hdr_t hdr;
 
-	hdr.version = SLURM_PROTOCOL_VERSION;
-	memcpy(hdr.key, srun->key->data, SLURM_SSL_SIGNATURE_LENGTH);
-	hdr.task_id = client->id;
+	memcpy(hdr.key, srun->key->data, SLURM_IO_KEY_SIZE);
+	hdr.taskid = client->id;
 
 	if ((client->type == CLIENT_STDOUT) || (client->type == CLIENT_STDIN)) 
-		hdr.type = SLURM_IO_STREAM_INOUT; 
+		hdr.type = SLURM_IO_STDOUT; 
 	else
-		hdr.type = SLURM_IO_STREAM_SIGERR;
+		hdr.type = SLURM_IO_STDERR;
 
-	pack_io_stream_header(&hdr, buffer);
+	if (io_hdr_write_cb(client->buf, &hdr) < 0) {
+		error ("Unable to write io header: %m");
+		return SLURM_ERROR;
+	}
 
-	/* XXX Shouldn't have to jump through these hoops to 
-	 * support slurm Buf type. Need a better way to do this
-	 */
-	size   = buffer->processed;
-	buf    = xfer_buf_data(buffer);
-	retval = cbuf_write(client->buf, buf, size, NULL);
-	xfree(buf);
-	return retval;
+	return SLURM_SUCCESS;
 }
 
 static int
diff --git a/src/slurmd/job.c b/src/slurmd/job.c
index 8129e3042b59a258cf4640429de09ff202a561b4..c948c1b44c8419cf11f6f3f003f63ca26e6ef176 100644
--- a/src/slurmd/job.c
+++ b/src/slurmd/job.c
@@ -336,16 +336,16 @@ srun_info_create(slurm_cred_t cred, slurm_addr *resp_addr, slurm_addr *ioaddr)
 	struct srun_info *srun = xmalloc(sizeof(*srun));
 	srun_key_t       *key  = xmalloc(sizeof(*key ));
 
-	slurm_cred_get_signature(cred, data, &len);
+	slurm_cred_get_signature(cred, &data, &len);
 
-	len = len > SLURM_KEY_SIZE ? SLURM_KEY_SIZE : len;
+	len = len > SLURM_IO_KEY_SIZE ? SLURM_IO_KEY_SIZE : len;
 
 	if (data != NULL) {
 		memcpy((void *) key->data, data, len);
 
-		if (len < SLURM_KEY_SIZE)
+		if (len < SLURM_IO_KEY_SIZE)
 			memset( (void *) (key->data + len), 0, 
-			        SLURM_KEY_SIZE - len           );
+			        SLURM_IO_KEY_SIZE - len        );
 	}
 
 	srun->key = key;
diff --git a/src/slurmd/job.h b/src/slurmd/job.h
index 1a4c5463e7fde18c5a3e60139b2626d2878ef921..735f9d5eb9be1e3d74f49046befb68ba370493ab 100644
--- a/src/slurmd/job.h
+++ b/src/slurmd/job.h
@@ -43,9 +43,8 @@
 #define MAXHOSTNAMELEN	64
 #endif
 
-#define SLURM_KEY_SIZE	64
 typedef struct srun_key {
-	unsigned char data[SLURM_KEY_SIZE];
+	unsigned char data[SLURM_IO_KEY_SIZE];
 } srun_key_t;
 
 typedef enum task_state {
diff --git a/src/slurmd/req.c b/src/slurmd/req.c
index de612c3c392b37e9f85385e769807f1ae4d7da89..9bb037c7644194e088939daa3b6321b55765de99 100644
--- a/src/slurmd/req.c
+++ b/src/slurmd/req.c
@@ -507,6 +507,8 @@ _rpc_reattach_tasks(slurm_msg_t *msg, slurm_addr *cli)
 	uid_t       req_uid;
 	gid_t       req_gid;
 	slurm_addr  ioaddr;
+	char       *key;
+	int         len;
 	slurm_msg_t                    resp_msg;
 	reattach_tasks_request_msg_t  *req = msg->data;
 	reattach_tasks_response_msg_t  resp;
@@ -547,10 +549,13 @@ _rpc_reattach_tasks(slurm_msg_t *msg, slurm_addr *cli)
 
 	debug3("reattach: srun ioaddr: %s:%d", host, port);
 
+
+	slurm_cred_get_signature(req->cred, &key, &len);
+
 	while (1) {
 		rc = shm_update_step_addrs( req->job_id, req->job_step_id,
 				            &ioaddr, &resp_msg.address,
-				            req->key ); 
+				            key ); 
 		if ((rc == 0) || (errno != EAGAIN))
 			break;
 		sched_yield();	/* relinquish processor */
diff --git a/src/slurmd/shm.c b/src/slurmd/shm.c
index dedd5090f98f638d1233d060ff2db3a3b7707152..99b8968f111ca463dd58670bdf698dcd71337a16 100644
--- a/src/slurmd/shm.c
+++ b/src/slurmd/shm.c
@@ -605,7 +605,7 @@ shm_update_step_addrs(uint32_t jobid, uint32_t stepid,
 		if (!s->io_update) {
 			s->ioaddr    = *ioaddr;
 			s->respaddr  = *respaddr;
-			memcpy(s->key.data, keydata, SLURM_KEY_SIZE);
+			memcpy(s->key.data, keydata, SLURM_IO_KEY_SIZE);
 			s->io_update = true;
 
 			debug3("Going to send shm update signal to %ld", 
@@ -646,7 +646,7 @@ shm_step_addrs(uint32_t jobid, uint32_t stepid,
 		job_step_t *s = &slurmd_shm->step[i];
 		*ioaddr   = s->ioaddr;
 		*respaddr = s->respaddr;
-		memcpy(key->data, s->key.data, SLURM_KEY_SIZE);
+		memcpy(key->data, s->key.data, SLURM_IO_KEY_SIZE);
 		s->io_update = false;
 	} else {
 		slurm_seterrno(ESRCH);
diff --git a/src/slurmd/slurmd.c b/src/slurmd/slurmd.c
index 1962e619e73805b8371da62ad2bc4690f02ad9a3..2d01a101e5b7c0f1cabf7b09eb3d5970430ffe3a 100644
--- a/src/slurmd/slurmd.c
+++ b/src/slurmd/slurmd.c
@@ -732,7 +732,7 @@ _set_slurmd_spooldir(void)
 	if ((mkdir(conf->spooldir, 0755) < 0) && (errno != EEXIST))
 		error("mkdir(%s): %m", conf->spooldir);
 
-	if (chdir(conf->spooldir) < 0)
+	if (conf->daemonize && chdir(conf->spooldir) < 0)
 		fatal("chdir(%s): %m", conf->spooldir);
 }
 
diff --git a/src/srun/Makefile.am b/src/srun/Makefile.am
index 36fdfbd5d3b8a692dc4f6fa9bdb73b4cc5c43211..52a9c9c8a8bd7fb4c901a2a6de9c93893c2f959f 100644
--- a/src/srun/Makefile.am
+++ b/src/srun/Makefile.am
@@ -20,6 +20,7 @@ srun_SOURCES = srun.c opt.c env.c opt.h env.h job.c job.h net.c net.h \
 
 srun_LDADD = $(top_builddir)/src/common/libcommon.la   \
              $(top_builddir)/src/common/libhostlist.la \
+             $(top_builddir)/src/common/libeio.la      \
 	     $(top_builddir)/src/api/libslurm.la       \
 	     $(POPT_LIBS) 
 
diff --git a/src/srun/allocate.c b/src/srun/allocate.c
index c372dd1e186718f3387098dc569dd2eafebf117e..9937471657642d6469561eb44d7755c61bb30b11 100644
--- a/src/srun/allocate.c
+++ b/src/srun/allocate.c
@@ -313,7 +313,7 @@ create_job_step(job_t *job)
 		job_fatal (job, "Unable to create job step: %m");
 
 	job->stepid  = resp->job_step_id;
-	job->cred    = resp->credentials;
+	job->cred    = resp->cred;
 #ifdef HAVE_LIBELAN3
 	job->qsw_job = resp->qsw_job;
 #endif
diff --git a/src/srun/io.c b/src/srun/io.c
index de64f06ac2baab52bddf1a08e14f1c8747462d0e..6cb3dfdcb0137411e016efc56d0d8f8934b5887e 100644
--- a/src/srun/io.c
+++ b/src/srun/io.c
@@ -44,9 +44,11 @@
 #include "src/common/pack.h"
 #include "src/common/slurm_protocol_defs.h"
 #include "src/common/slurm_protocol_pack.h"
+#include "src/common/slurm_cred.h"
 #include "src/common/xassert.h"
 #include "src/common/xmalloc.h"
 #include "src/common/xsignal.h"
+#include "src/common/io_hdr.h"
 
 #include "src/srun/io.h"
 #include "src/srun/job.h"
@@ -81,9 +83,8 @@ static int      _do_task_input(job_t *job, int taskid);
 static int 	_do_task_input_poll(job_t *job, fd_info_t *info);
 static inline bool _io_thr_done(job_t *job);
 static int	_handle_pollerr(fd_info_t *info);
-static ssize_t	_readn(int fd, void *buf, size_t nbytes);
 static ssize_t	_readx(int fd, char *buf, size_t maxbytes);
-static int	_validate_header(slurm_io_stream_header_t *hdr, job_t *job);
+static int      _read_io_header(int fd, job_t *job, char *host);
 
 #define _poll_set_rd(_pfd, _fd) do { 	\
 	(_pfd).fd = _fd;		\
@@ -566,22 +567,71 @@ _is_fd_ready(int fd)
 }
 
 
+static int
+_read_io_header(int fd, job_t *job, char *host)
+{
+	int      size = io_hdr_packed_size();
+	cbuf_t   cb   = cbuf_create(size, size);
+	char    *key  = NULL;
+	int      len  = 0;
+	io_hdr_t hdr;
+
+	if (cbuf_write_from_fd(cb, fd, size, NULL) < 0) {
+		error ("Bad stream header read: %m");
+		goto fail;
+	}
+
+	if (io_hdr_read_cb(cb, &hdr) < 0) {
+		error ("Unable to unpack io header: %m");
+		goto fail;
+	}
+
+	if (slurm_cred_get_signature(job->cred, &key, &len) < 0) {
+		error ("Couldn't get existing cred signature");
+		goto fail;
+	}
+
+	if (io_hdr_validate(&hdr, key, len) < 0)  /* check key */
+		goto fail;
+
+	/* 
+	 * validate reality of hdr.taskid
+	 */
+	if ((hdr.taskid < 0) || (hdr.taskid >= opt.nprocs)) {
+		error ("Invalid taskid %d from %s", hdr.taskid, host);
+		goto fail;
+	}
+
+	if (hdr.type == SLURM_IO_STDOUT)
+		job->out[hdr.taskid] = fd;
+	else
+		job->err[hdr.taskid] = fd;
+
+	debug2("accepted %s connection from %s task %ld, sd=%d", 
+	       (hdr.type == SLURM_IO_STDERR ? "stderr" : "stdout"), 
+		host, hdr.taskid, fd                               );
+
+	return SLURM_SUCCESS;
+
+    fail:
+	close(fd);
+	return SLURM_ERROR;
+}
+
+
 static void
 _accept_io_stream(job_t *job, int i)
 {
-	int len = size_io_stream_header();
 	int j;
 	int fd = job->iofd[i];
 	debug2("Activity on IO server port %d fd %d", i, fd);
 
 	for (j = 0; j < 15; i++) {
-		int sd, size_read;
+		int sd;
 		struct sockaddr addr;
 		struct sockaddr_in *sin;
 		int size = sizeof(addr);
 		char buf[INET_ADDRSTRLEN];
-		slurm_io_stream_header_t hdr;
-		Buf buffer;
 
 		/* 
 		 * Return early if fd is not now ready
@@ -612,55 +662,13 @@ _accept_io_stream(job_t *job, int i)
 
 		debug3("Accepted IO connection: ip=%s sd=%d", buf, sd); 
 
-		buffer = init_buf(len);
-		size_read = _readn(sd, buffer->head, len); 
-		if (size_read != len) {
-			/* A fatal error for this stream */
-			error("Incomplete stream header read");
-			free_buf(buffer);
-			return;
-		}
-
-		if (unpack_io_stream_header(&hdr, buffer)) {
-			/* A fatal error for this stream */
-			error ("Bad stream header read");
-			free_buf(buffer); /* NOTE: this frees msgbuf */
-			return;
-		}
-		free_buf(buffer); /* NOTE: this frees msgbuf */
-		if (_validate_header(&hdr, job))	/* check key */
-			return;
-
-
-		/* Assign new fds arbitrarily for now, until slurmd
-		 * sends along some control information
-		 */
-		if ((hdr.task_id < 0) || (hdr.task_id >= opt.nprocs)) {
-			error ("Invalid task_id %d from %s", hdr.task_id, buf);
-			continue;
-		}
-
 		/*
-		 * IO connection from task may come after task exits,
-		 * in which case, state should be waiting for IO.
-		 * 
-		 * Update to RUNNING now handled in msg.c
-		 *
-		 * slurm_mutex_lock(&job->task_mutex);
-		 * job->task_state[hdr.task_id] = SRUN_TASK_RUNNING;
-		 * slurm_mutex_unlock(&job->task_mutex);
+		 * Read IO header and update job structure appropriately
 		 */
+		if (_read_io_header(sd, job, buf) < 0)
+			continue;
 
 		fd_set_nonblocking(sd);
-
-		if (hdr.type == SLURM_IO_STREAM_INOUT)
-			job->out[hdr.task_id] = sd;
-		else
-			job->err[hdr.task_id] = sd;
-
-		debug2("accepted %s connection from %s task %ld, sd=%d", 
-				(hdr.type ? "stderr" : "stdout"), 
-				buf, hdr.task_id, sd                   );
 	}
 
 }
@@ -739,31 +747,6 @@ _readx(int fd, char *buf, size_t maxbytes)
 }	
 
 
-ssize_t
-_readn(int fd, void *buf, size_t nbytes) 
-{
-	int n = 0;
-	char *pbuf = (char *)buf;
-	size_t nleft = nbytes;
-
-	while (nleft > 0) {
-		n = read(fd, (void *)pbuf, nleft);
-		if (n > 0) {
-			pbuf+=n;
-			nleft-=n;
-		} else if (n == 0) 	/* EOF */
-			break;
-		else if (errno == EINTR)
-			continue;
-		else {
-			error("read error: %m");
-			break;
-		}
-	}
-
-	return(n);
-}
-
 static void
 _write_all(job_t *job, cbuf_t cb, char *buf, size_t len, int taskid)
 {
@@ -838,31 +821,3 @@ _bcast_stdin(int fd, job_t *job)
 	return;
 }
 
-static 
-int _validate_header(slurm_io_stream_header_t *hdr, job_t *job)
-{
-	if (hdr->version != SLURM_PROTOCOL_VERSION) {
-		error("Invalid header version, notify administrators");
-		return SLURM_ERROR;
-	}
-
-	if ((hdr->task_id < 0) && (hdr->task_id >= opt.nprocs)) {
-		error("Invalid header client task_id, notify administrators");
-		return SLURM_ERROR;
-	}
-
-	if ((hdr->type != SLURM_IO_STREAM_INOUT) && 
-	    (hdr->type != SLURM_IO_STREAM_SIGERR)) {
-		error("Invalid header client type, notify administrators");
-		return SLURM_ERROR;
-	}
-
-	if (memcmp((void *)job->cred->signature,
-	           (void *)hdr->key, SLURM_SSL_SIGNATURE_LENGTH)) {
-		error("Invalid header signature, notify administrators");
-		return SLURM_ERROR;
-	}
-
-	return SLURM_SUCCESS;
-}
-
diff --git a/src/srun/job.c b/src/srun/job.c
index 86b7a66b2d8ba599ca6ee56ed8dca2a8906eb047..4353fd3580b2d051bd62164e1ec348403b7c7223 100644
--- a/src/srun/job.c
+++ b/src/srun/job.c
@@ -37,6 +37,7 @@
 #include "src/common/hostlist.h"
 #include "src/common/log.h"
 #include "src/common/slurm_protocol_api.h"
+#include "src/common/slurm_cred.h"
 #include "src/common/xmalloc.h"
 #include "src/common/xstring.h"
 #include "src/common/cbuf.h"
@@ -433,18 +434,12 @@ _job_create_internal(allocation_info_t *info)
 static void
 _job_fake_cred(job_t *job)
 {
-	int fd;
-	if ((fd = open("/dev/random", O_RDONLY)) < 0)
-		error ("unable to open /dev/random: %m");
-
-	job->cred          = xmalloc(sizeof(*job->cred));
-	job->cred->job_id  = job->jobid;
-	job->cred->user_id = opt.uid;
-	job->cred->expiration_time = 0x7fffffff;
-	read(fd, job->cred->signature, SLURM_SSL_SIGNATURE_LENGTH);
-
-	if (close(fd) < 0)
-		error ("close(/dev/random): %m");
+	slurm_cred_arg_t arg;
+	arg.jobid    = job->jobid;
+	arg.stepid   = job->stepid;
+	arg.uid      = opt.uid;
+	arg.hostlist = job->nodelist;
+	job->cred = slurm_cred_faker(&arg);
 }
 
 
diff --git a/src/srun/job.h b/src/srun/job.h
index 101e54e92ab86661d2ebdbd911caae3bdfd3d3da..62492a13ed18ad644de8f14f755b9286ac43d234 100644
--- a/src/srun/job.h
+++ b/src/srun/job.h
@@ -80,7 +80,7 @@ typedef struct srun_job {
 	pthread_mutex_t state_mutex; 
 	pthread_cond_t  state_cond;
 
-	slurm_job_credential_t *cred;
+	slurm_cred_t  cred;     /* Slurm job credential    */
 	char *nodelist;		/* nodelist in string form */
 	int nhosts;
 	char **host;		/* hostname vector */
diff --git a/src/srun/launch.c b/src/srun/launch.c
index e42539534370d203559dbb2529da1d9558b7ddb1..25fdea878e4e57bf9329d2fb81a240ad28b62d93 100644
--- a/src/srun/launch.c
+++ b/src/srun/launch.c
@@ -163,7 +163,7 @@ launch(void *arg)
 		r->uid             = opt.uid;
 		r->argc            = remote_argc;
 		r->argv            = remote_argv;
-		r->credential      = job->cred;
+		r->cred            = job->cred;
 		r->job_step_id     = job->stepid;
 		r->envc            = my_envc;
 		r->env             = environ;
diff --git a/src/srun/reattach.c b/src/srun/reattach.c
index 7088138735c34ace38d05383194d32eb72fa09dd..db575ba7da21a67469138f643eb2dd23d8efaac9 100644
--- a/src/srun/reattach.c
+++ b/src/srun/reattach.c
@@ -308,10 +308,8 @@ _attach_to_job(job_t *job)
 		r->srun_node_id    = (uint32_t) i;
 		r->io_port         = ntohs(job->ioport[i%job->niofds]);
 		r->resp_port       = ntohs(job->jaddr[i%job->njfds].sin_port);
+		r->cred            = job->cred;
 
-		/* XXX: Get random key */
-		memcpy(r->key, job->cred->signature, 
-		       SLURM_SSL_SIGNATURE_LENGTH);
 
 		/* XXX: redirecting output to files not yet
 		 * supported