From 67e860903e1a785a29a12484dc50c2efbfe62ce1 Mon Sep 17 00:00:00 2001
From: Mark Grondona <mgrondona@llnl.gov>
Date: Wed, 26 Mar 2003 23:02:48 +0000
Subject: [PATCH]  o src/common/slurm_cred.c : add mutexes to cred and ctx
 types "just    to be sure"  o src/slurmd/slurmd.c (_reconfigure) :
 reinitialize job credential key

---
 src/common/slurm_cred.c | 181 ++++++++++++++++++++++++++++++++++------
 src/slurmd/slurmd.c     |  12 ++-
 2 files changed, 164 insertions(+), 29 deletions(-)

diff --git a/src/common/slurm_cred.c b/src/common/slurm_cred.c
index d484afacc92..80ede171b67 100644
--- a/src/common/slurm_cred.c
+++ b/src/common/slurm_cred.c
@@ -41,6 +41,10 @@
 #include <openssl/pem.h>
 #include <openssl/err.h>
 
+#if WITH_PTHREADS
+#  include <pthread.h>
+#endif /* WITH_PTHREADS */
+
 #include "src/common/macros.h"
 #include "src/common/list.h"
 #include "src/common/log.h"
@@ -90,6 +94,9 @@ struct slurm_cred_context {
 #ifndef NDEBUG
 #  define CRED_CTX_MAGIC 0x0c0c0c
 	int magic;
+#endif
+#if WITH_PTHREADS
+	pthread_mutex_t mutex;
 #endif
 	enum ctx_type  type;       /* type of context (creator or verifier) */
 	EVP_PKEY      *key;        /* private or public key                 */
@@ -102,6 +109,7 @@ struct slurm_cred_context {
 	time_t         exkey_exp;  /* Old key expiration time               */
 };
 
+
 /*
  * Completion of slurm job credential type:
  *
@@ -110,6 +118,9 @@ struct slurm_job_credential {
 #ifndef NDEBUG
 #  define CRED_MAGIC 0x0b0b0b
 	int      magic;
+#endif
+#ifdef  WITH_PTHREADS
+	pthread_mutex_t mutex;
 #endif
 	uint32_t jobid;        /* Job ID associated with this credential    */
 	uint32_t stepid;       /* Job step ID for this credential           */
@@ -177,16 +188,19 @@ slurm_cred_creator_ctx_create(const char *path)
 	xassert(path != NULL);
 
 	ctx = _slurm_cred_ctx_alloc();
+	slurm_mutex_lock(&ctx->mutex);
 
 	ctx->type = SLURM_CRED_CREATOR;
 
 	if (!(ctx->key = _read_private_key(path))) 
 		goto fail;
 
+	slurm_mutex_unlock(&ctx->mutex);
 	return ctx;
 
     fail:
-	xfree(ctx);
+	slurm_mutex_unlock(&ctx->mutex);
+	slurm_cred_ctx_destroy(ctx);
 	return NULL;
 }
 
@@ -199,16 +213,21 @@ slurm_cred_verifier_ctx_create(const char *path)
 	xassert(path != NULL);
 
 	ctx = _slurm_cred_ctx_alloc();
+	slurm_mutex_lock(&ctx->mutex);
+
 	ctx->type = SLURM_CRED_VERIFIER;
 
 	if (!(ctx->key = _read_public_key(path)))
 		goto fail;
 
 	_verifier_ctx_init(ctx);
+
+	slurm_mutex_unlock(&ctx->mutex);
 	return ctx;
 
     fail:
-	xfree(ctx);
+	slurm_mutex_unlock(&ctx->mutex);
+	slurm_cred_ctx_destroy(ctx);
 	return NULL;
 }
 
@@ -219,6 +238,7 @@ slurm_cred_ctx_destroy(slurm_cred_ctx_t ctx)
 	if (ctx == NULL)
 		return;
 
+	slurm_mutex_lock(&ctx->mutex);
 	xassert(ctx->magic == CRED_CTX_MAGIC);
 
 	if (ctx->key)
@@ -230,6 +250,9 @@ slurm_cred_ctx_destroy(slurm_cred_ctx_t ctx)
 
 	xassert(ctx->magic = ~CRED_CTX_MAGIC);
 
+	slurm_mutex_unlock(&ctx->mutex);
+	slurm_mutex_destroy(&ctx->mutex);
+
 	xfree(ctx);
 
 	return;
@@ -241,8 +264,13 @@ slurm_cred_ctx_set(slurm_cred_ctx_t ctx, slurm_cred_opt_t opt, ...)
 	int     rc  = SLURM_SUCCESS;
 	va_list ap;
 
+	xassert(ctx != NULL);
+
 	va_start(ap, opt);
 
+	slurm_mutex_lock(&ctx->mutex);
+	xassert(ctx->magic == CRED_CTX_MAGIC);
+
 	switch (opt) {
 	case SLURM_CRED_OPT_EXPIRY_WINDOW: 
 		ctx->expiry_window = va_arg(ap, int);
@@ -253,6 +281,8 @@ slurm_cred_ctx_set(slurm_cred_ctx_t ctx, slurm_cred_opt_t opt, ...)
 		break;
 	}
 
+	slurm_mutex_unlock(&ctx->mutex);
+
 	va_end(ap);
 
 	return rc;
@@ -265,8 +295,13 @@ slurm_cred_ctx_get(slurm_cred_ctx_t ctx, slurm_cred_opt_t opt, ...)
 	va_list ap;
 	int *intp;
 
+	xassert(ctx != NULL);
+
 	va_start(ap, opt);
 
+	slurm_mutex_lock(&ctx->mutex);
+	xassert(ctx->magic == CRED_CTX_MAGIC);
+
 	switch (opt) {
 	case SLURM_CRED_OPT_EXPIRY_WINDOW: 
 		intp  = va_arg(ap, int *);
@@ -278,6 +313,8 @@ slurm_cred_ctx_get(slurm_cred_ctx_t ctx, slurm_cred_opt_t opt, ...)
 		break;
 	}
 
+	slurm_mutex_unlock(&ctx->mutex);
+
 	va_end(ap);
 
 	return rc;
@@ -290,7 +327,6 @@ slurm_cred_ctx_key_update(slurm_cred_ctx_t ctx, const char *path)
 		return _ctx_update_private_key(ctx, path);
 	else
 		return _ctx_update_public_key(ctx, path);
-
 }
 
 
@@ -301,12 +337,18 @@ slurm_cred_create(slurm_cred_ctx_t ctx, slurm_cred_arg_t *arg)
 
 	xassert(ctx != NULL);
 	xassert(arg != NULL);
+
+	slurm_mutex_lock(&ctx->mutex);
+
 	xassert(ctx->magic == CRED_CTX_MAGIC);
 	xassert(ctx->type == SLURM_CRED_CREATOR);
 
 	cred = _slurm_cred_alloc();
 
 	xassert(cred != NULL);
+
+	slurm_mutex_lock(&cred->mutex);
+
 	xassert(cred->magic == CRED_MAGIC);
 
 	cred->jobid  = arg->jobid;
@@ -318,9 +360,14 @@ slurm_cred_create(slurm_cred_ctx_t ctx, slurm_cred_arg_t *arg)
 	if (_slurm_cred_sign(ctx, cred) < 0) 
 		goto fail;
 
+	slurm_mutex_unlock(&ctx->mutex);
+	slurm_mutex_unlock(&cred->mutex);
+
 	return cred;
 
     fail:
+	slurm_mutex_unlock(&ctx->mutex);
+	slurm_mutex_unlock(&cred->mutex);
 	slurm_cred_destroy(cred);
 	return NULL;
 }
@@ -335,6 +382,8 @@ slurm_cred_faker(slurm_cred_arg_t *arg)
 
 	cred = _slurm_cred_alloc();
 
+	slurm_mutex_lock(&cred->mutex);
+
 	cred->jobid  = arg->jobid;
 	cred->stepid = arg->stepid;
         cred->uid    = arg->uid;
@@ -351,6 +400,7 @@ slurm_cred_faker(slurm_cred_arg_t *arg)
 	if (close(fd) < 0)
 		error ("close(/dev/random): %m");
 
+	slurm_mutex_unlock(&cred->mutex);
 	return cred;
     	
 }
@@ -365,21 +415,35 @@ slurm_cred_verify(slurm_cred_ctx_t ctx, slurm_cred_t cred,
 	xassert(ctx  != NULL);
 	xassert(cred != NULL);
 	xassert(arg  != NULL);
+
+	slurm_mutex_lock(&ctx->mutex);
+	slurm_mutex_lock(&cred->mutex);
+
 	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);
+	if (_slurm_cred_verify_signature(ctx, cred) < 0) {
+		slurm_seterrno(ESLURMD_INVALID_JOB_CREDENTIAL);
+		goto error;
+	}
 
-	if (now > (cred->ctime + ctx->expiry_window)) 
-		slurm_seterrno_ret(ESLURMD_CREDENTIAL_EXPIRED);
+	if (now > (cred->ctime + ctx->expiry_window)) {
+		slurm_seterrno(ESLURMD_CREDENTIAL_EXPIRED);
+		goto error;
+	}
 
-	if (_credential_revoked(ctx, cred))
-		slurm_seterrno_ret(ESLURMD_CREDENTIAL_REVOKED);
+	if (_credential_revoked(ctx, cred)) {
+		slurm_seterrno(ESLURMD_CREDENTIAL_REVOKED);
+		goto error;
+	}
 
-	if (_credential_replayed(ctx, cred))
-		slurm_seterrno_ret(ESLURMD_CREDENTIAL_REPLAYED);
+	if (_credential_replayed(ctx, cred)) {
+		slurm_seterrno(ESLURMD_CREDENTIAL_REPLAYED);
+		goto error;
+	}
+
+	slurm_mutex_unlock(&ctx->mutex);
 
 	/*
 	 * set arguments to cred contents
@@ -389,7 +453,14 @@ slurm_cred_verify(slurm_cred_ctx_t ctx, slurm_cred_t cred,
 	arg->uid      = cred->uid;
 	arg->hostlist = xstrdup(cred->nodes);
 
+	slurm_mutex_unlock(&cred->mutex);
+
 	return SLURM_SUCCESS;
+
+    error:
+	slurm_mutex_unlock(&ctx->mutex);
+	slurm_mutex_unlock(&cred->mutex);
+	return SLURM_ERROR;
 }
 
 
@@ -401,10 +472,16 @@ slurm_cred_destroy(slurm_cred_t cred)
 
 	xassert(cred->magic == CRED_MAGIC);
 
+	slurm_mutex_lock(&cred->mutex);
 	if (cred->nodes)
 		xfree(cred->nodes);
 	if (cred->signature)
 		xfree(cred->signature);
+	xassert(cred->magic = ~CRED_MAGIC);
+
+	slurm_mutex_unlock(&cred->mutex);
+	slurm_mutex_destroy(&cred->mutex);
+
 	xfree(cred);
 }
 
@@ -412,16 +489,24 @@ slurm_cred_destroy(slurm_cred_t cred)
 bool
 slurm_cred_jobid_cached(slurm_cred_ctx_t ctx, uint32_t jobid)
 {
+	bool retval = false; 
+
 	xassert(ctx != NULL);
 	xassert(ctx->magic == CRED_CTX_MAGIC);
 	xassert(ctx->type  == SLURM_CRED_VERIFIER);
 
+	slurm_mutex_lock(&ctx->mutex);
+
 	_clear_expired_job_states(ctx);
 
 	/*
 	 * Return true if we find a cached job state for job id `jobid'
 	 */
-	return (_find_job_state(ctx, jobid) != NULL);
+	retval = (_find_job_state(ctx, jobid) != NULL);
+
+	slurm_mutex_unlock(&ctx->mutex);
+
+	return retval;
 }
 
 int
@@ -431,10 +516,13 @@ slurm_cred_insert_jobid(slurm_cred_ctx_t ctx, uint32_t jobid)
 	xassert(ctx->magic == CRED_CTX_MAGIC);
 	xassert(ctx->type  == SLURM_CRED_VERIFIER);
 
-	_clear_expired_job_states(ctx);
+	slurm_mutex_lock(&ctx->mutex);
 
+	_clear_expired_job_states(ctx);
 	_insert_job_state(ctx, jobid);
 
+	slurm_mutex_unlock(&ctx->mutex);
+
 	return SLURM_SUCCESS;
 }
 
@@ -447,15 +535,24 @@ slurm_cred_revoke(slurm_cred_ctx_t ctx, uint32_t jobid)
 	xassert(ctx->magic == CRED_CTX_MAGIC);
 	xassert(ctx->type  == SLURM_CRED_VERIFIER);
 
+	slurm_mutex_lock(&ctx->mutex);
+
 	_clear_expired_job_states(ctx);
 
-	if (!(j = _find_job_state(ctx, jobid))) 
-		slurm_seterrno_ret(ESRCH);
+	if (!(j = _find_job_state(ctx, jobid))) {
+		slurm_seterrno(ESRCH);
+		goto error;
+	}
 
 	j->revoked     = true;
 	j->expiration  = time(NULL) + ctx->expiry_window;
 
+	slurm_mutex_unlock(&ctx->mutex);
 	return SLURM_SUCCESS;
+
+    error:
+	slurm_mutex_unlock(&ctx->mutex);
+	return SLURM_FAILURE;
 }
 
 int
@@ -465,9 +562,13 @@ slurm_cred_get_signature(slurm_cred_t cred, char **datap, int *datalen)
 	xassert(datap   != NULL);
 	xassert(datalen != NULL);
 
+	slurm_mutex_lock(&cred->mutex);
+
 	*datap   = cred->signature;
 	*datalen = cred->siglen;
 
+	slurm_mutex_unlock(&cred->mutex);
+
 	return SLURM_SUCCESS;
 }
 
@@ -477,9 +578,14 @@ slurm_cred_pack(slurm_cred_t cred, Buf buffer)
 	xassert(cred != NULL);
 	xassert(cred->magic == CRED_MAGIC);
 
+	slurm_mutex_lock(&cred->mutex);
+
 	_pack_cred(cred, buffer);
 	xassert(cred->siglen > 0);
 	packmem(cred->signature, (uint16_t) cred->siglen, buffer);
+
+	slurm_mutex_unlock(&cred->mutex);
+
 	return;
 }
 
@@ -493,6 +599,7 @@ slurm_cred_unpack(Buf buffer)
 	xassert(buffer != NULL);
 
 	cred = _slurm_cred_alloc();
+	slurm_mutex_lock(&cred->mutex);
 
 	sigp = (char **) &cred->signature;
 
@@ -507,9 +614,11 @@ slurm_cred_unpack(Buf buffer)
 
 	cred->siglen = len;
 
+	slurm_mutex_unlock(&cred->mutex);
 	return cred;
 
     unpack_error:
+	slurm_mutex_unlock(&cred->mutex);
 	slurm_cred_destroy(cred);
 	return NULL;
 }
@@ -517,8 +626,10 @@ slurm_cred_unpack(Buf buffer)
 int
 slurm_cred_ctx_pack(slurm_cred_ctx_t ctx, Buf buffer)
 {
+	slurm_mutex_lock(&ctx->mutex);
 	_job_state_pack(ctx, buffer);
 	_cred_state_pack(ctx, buffer);
+	slurm_mutex_unlock(&ctx->mutex);
 
 	return SLURM_SUCCESS;
 }
@@ -530,6 +641,8 @@ slurm_cred_ctx_unpack(slurm_cred_ctx_t ctx, Buf buffer)
 	xassert(ctx->magic == CRED_CTX_MAGIC);
 	xassert(ctx->type  == SLURM_CRED_VERIFIER);
 
+	slurm_mutex_lock(&ctx->mutex);
+
 	/* 
 	 * Unpack job state list and cred state list from buffer
 	 * appening them onto ctx->state_list and ctx->job_list.
@@ -537,6 +650,8 @@ slurm_cred_ctx_unpack(slurm_cred_ctx_t ctx, Buf buffer)
 	_job_state_unpack(ctx, buffer);
 	_cred_state_unpack(ctx, buffer);
 
+	slurm_mutex_unlock(&ctx->mutex);
+
 	return SLURM_SUCCESS;
 }
 
@@ -546,6 +661,8 @@ slurm_cred_print(slurm_cred_t cred)
 	if (cred == NULL)
 		return;
 
+	slurm_mutex_lock(&cred->mutex);
+
 	xassert(cred->magic == CRED_MAGIC);
 
 	info("Cred: Jobid   %u",  cred->jobid         );
@@ -554,6 +671,7 @@ slurm_cred_print(slurm_cred_t cred)
 	info("Cred: Nodes   %s",  cred->nodes         );
 	info("Cred: ctime   %s",  ctime(&cred->ctime) );
 	info("Cred: siglen  %d",  cred->siglen        );
+	slurm_mutex_unlock(&cred->mutex);
 
 }
 
@@ -623,15 +741,20 @@ _ctx_update_private_key(slurm_cred_ctx_t ctx, const char *path)
 	EVP_PKEY *tmpk = NULL;
 
 	xassert(ctx != NULL);
-	xassert(ctx->magic == CRED_CTX_MAGIC);
-	xassert(ctx->type  == SLURM_CRED_CREATOR);
 
 	if (!(pk = _read_private_key(path)))
 		return SLURM_ERROR;
 
+	slurm_mutex_lock(&ctx->mutex);
+
+	xassert(ctx->magic == CRED_CTX_MAGIC);
+	xassert(ctx->type  == SLURM_CRED_CREATOR);
+
 	tmpk = ctx->key;
 	ctx->key = pk;
 
+	slurm_mutex_unlock(&ctx->mutex);
+
 	EVP_PKEY_free(tmpk);
 
 	return SLURM_SUCCESS;
@@ -644,12 +767,15 @@ _ctx_update_public_key(slurm_cred_ctx_t ctx, const char *path)
 	EVP_PKEY *pk   = NULL;
 
 	xassert(ctx != NULL);
-	xassert(ctx->magic == CRED_CTX_MAGIC);
-	xassert(ctx->type  == SLURM_CRED_VERIFIER);
 
 	if (!(pk = _read_public_key(path)))
 		return SLURM_ERROR;
 
+	slurm_mutex_lock(&ctx->mutex);
+
+	xassert(ctx->magic == CRED_CTX_MAGIC);
+	xassert(ctx->type  == SLURM_CRED_VERIFIER);
+
 	if (ctx->exkey) 
 		EVP_PKEY_free(ctx->exkey);
 
@@ -657,11 +783,12 @@ _ctx_update_public_key(slurm_cred_ctx_t ctx, const char *path)
 	ctx->key   = pk;
 
 	/*
-	 * exkey expires in expiry_window seconds.
+	 * exkey expires in expiry_window seconds plus one minute.
 	 * This should be long enough to capture any keys in-flight.
 	 */
-	ctx->exkey_exp = time(NULL) + ctx->expiry_window;
+	ctx->exkey_exp = time(NULL) + ctx->expiry_window + 60;
 
+	slurm_mutex_unlock(&ctx->mutex);
 	return SLURM_SUCCESS;
 }
 
@@ -669,11 +796,10 @@ _ctx_update_public_key(slurm_cred_ctx_t ctx, const char *path)
 static bool
 _exkey_is_valid(slurm_cred_ctx_t ctx)
 {
-	time_t now = time(NULL);
-
 	if (!ctx->exkey) return false;
 	
-	if (now > ctx->exkey_exp) {
+	if (time(NULL) > ctx->exkey_exp) {
+		debug2("old job credential key slurmd expired");
 		EVP_PKEY_free(ctx->exkey);
 		ctx->exkey = NULL;
 		return false;
@@ -688,6 +814,9 @@ _slurm_cred_ctx_alloc(void)
 {
 	slurm_cred_ctx_t ctx = xmalloc(sizeof(*ctx));
 
+	slurm_mutex_init(&ctx->mutex);
+	slurm_mutex_lock(&ctx->mutex);
+
 	ctx->key           = NULL;
 	ctx->job_list      = NULL;
 	ctx->state_list    = NULL;
@@ -698,6 +827,7 @@ _slurm_cred_ctx_alloc(void)
 
 	xassert(ctx->magic = CRED_CTX_MAGIC);
 
+	slurm_mutex_unlock(&ctx->mutex);
 	return ctx;
 }
 
@@ -706,6 +836,8 @@ _slurm_cred_alloc(void)
 {
 	slurm_cred_t cred = xmalloc(sizeof(*cred));
 
+	slurm_mutex_init(&cred->mutex);
+
 	cred->jobid     = 0;
 	cred->stepid    = 0;
 	cred->uid       = (uid_t) -1;
@@ -793,7 +925,6 @@ _slurm_cred_verify_signature(slurm_cred_ctx_t ctx, slurm_cred_t cred)
 	if (!rc) {
 		ERR_load_crypto_strings();
 		error("Credential signature check error: %s", _ssl_error());
-		ERR_free_strings();
 		rc = SLURM_ERROR;
 	} else
 		rc = SLURM_SUCCESS;
diff --git a/src/slurmd/slurmd.c b/src/slurmd/slurmd.c
index e49017028f4..3a2eb7b9c64 100644
--- a/src/slurmd/slurmd.c
+++ b/src/slurmd/slurmd.c
@@ -452,12 +452,12 @@ _read_config()
 static void
 _reconfigure(void)
 {
+	slurm_mutex_lock(&conf->config_mutex);
+
 	read_slurm_conf_ctl(&conf->cf);
 	_update_logging();
 	_print_conf();
 
-	slurm_mutex_lock(&conf->config_mutex);
-
 	if (conf->conffile == NULL)
 		_free_and_set(&conf->conffile, conf->cf.slurm_conf);
 
@@ -465,13 +465,18 @@ _reconfigure(void)
 	_free_and_set(&conf->epilog, xstrdup(conf->cf.epilog));
 	_free_and_set(&conf->prolog, xstrdup(conf->cf.prolog));
 
+	/*
+	 * Make best effort at changing to new public key
+	 */
+	slurm_cred_ctx_key_update( conf->vctx, 
+                                   conf->cf.job_credential_public_certificate);
+
 	slurm_mutex_unlock(&conf->config_mutex);
 }
 
 static void
 _print_conf()
 {
-	slurm_mutex_lock(&conf->config_mutex);
 	debug3("Confile     = `%s'",     conf->conffile);
 	debug3("Debug       = %d",       conf->cf.slurmd_debug);
 	debug3("Epilog      = `%s'",     conf->epilog);
@@ -483,7 +488,6 @@ _print_conf()
 	debug3("Spool Dir   = `%s'",     conf->spooldir);
 	debug3("Pid File    = `%s'",     conf->pidfile);
 	debug3("Slurm UID   = %u",       conf->slurm_user_id);
-	slurm_mutex_unlock(&conf->config_mutex);
 }
 
 static void 
-- 
GitLab