extern int crypto_verify_sign(void * key, char *buffer, unsigned int buf_size, char *signature, unsigned int sig_size) { int retry = RETRY_COUNT; uid_t uid; gid_t gid; void *buf_out = NULL; int buf_out_size; int rc = 0; munge_err_t err; munge_ctx_t ctx = (munge_ctx_t) key; again: err = munge_decode(signature, ctx, &buf_out, &buf_out_size, &uid, &gid); if (err != EMUNGE_SUCCESS) { if ((err == EMUNGE_SOCKET) && retry--) { debug("Munge decode failed: %s (retrying ...)", munge_ctx_strerror(ctx)); usleep(RETRY_USEC); /* Likely munged too busy */ goto again; } if (err == EMUNGE_SOCKET) error("If munged is up, restart with --num-threads=10"); #ifdef MULTIPLE_SLURMD if (err != EMUNGE_CRED_REPLAYED) { rc = err; goto end_it; } else { debug2("We had a replayed crypto, but this " "is expected in multiple slurmd mode."); } #else if (err == EMUNGE_CRED_REPLAYED) rc = ESIG_CRED_REPLAYED; else rc = err; goto end_it; #endif } if ((uid != slurm_user) && (uid != 0)) { error("crypto/munge: Unexpected uid (%d) != SLURM uid (%d)", (int) uid, (int) slurm_user); rc = ESIG_BAD_USERID; } else if (buf_size != buf_out_size) rc = ESIG_BUF_SIZE_MISMATCH; else if (memcmp(buffer, buf_out, buf_size)) rc = ESIG_BUF_DATA_MISMATCH; end_it: if (buf_out) free(buf_out); return rc; }
static char *_decrypt(char *msg, uid_t *uid) { void *buf_out = NULL; int buf_out_size = 0, err; gid_t gid; err = munge_decode(msg, ctx, &buf_out, &buf_out_size, uid, &gid); if (err != EMUNGE_SUCCESS) { info("slurmctld/nonstop: munge_decode error: %s", munge_strerror(err)); xfree(buf_out); } return (char *) buf_out; }
/* Checkauth is called in the handling of a TATTACH request with valid afid. * Validate the credential that should now be dangling off afid. * Returns 1=success (auth is good, send RATTACH) * 0=failure (send RLERROR with np_rerror ()) */ static int checkauth(Npfid *fid, Npfid *afid, char *aname) { da_t da; int ret = 0; char a[128]; if (!fid || !afid || !afid->aux) { np_uerror (EIO); err ("checkauth: invalid arguments"); goto done; } da = afid->aux; assert (da->magic == DIOD_AUTH_MAGIC); snprintf (a, sizeof(a), "checkauth(%s@%s:%s)", fid->user->uname, np_conn_get_client_id (fid->conn), aname ? aname : "<NULL>"); #if HAVE_LIBMUNGE if (!da->datastr) { msg ("%s: munge cred missing", a); goto done; } da->mungerr = munge_decode (da->datastr, da->mungectx, NULL, 0, &da->mungeuid, NULL); if (da->mungerr != EMUNGE_SUCCESS) { np_uerror (EPERM); err ("%s: munge cred decode: %s", a, munge_strerror (da->mungerr)); goto done; } assert (afid->user->uid == fid->user->uid); /* enforced in np_attach */ if (afid->user->uid != da->mungeuid) { np_uerror (EPERM); err ("%s: munge cred uid mismatch: %d", a, da->mungeuid); goto done; } ret = 1; #else np_uerror (EPERM); err ("%s: diod was not built with support for auth services", a); #endif done: return ret; }
static int authenticate(opal_sec_cred_t *cred) { munge_err_t rc; opal_output_verbose(2, opal_sec_base_framework.framework_output, "sec: munge validate_cred %s", cred->credential); /* parse the inbound string */ if (EMUNGE_SUCCESS != (rc = munge_decode(cred->credential, NULL, NULL, NULL, NULL, NULL))) { opal_output_verbose(2, opal_sec_base_framework.framework_output, "sec: munge failed to decode credential: %s", munge_strerror(rc)); return OPAL_ERR_AUTHENTICATION_FAILED; } opal_output_verbose(2, opal_sec_base_framework.framework_output, "sec: munge credential valid"); return OPAL_SUCCESS; }
/* * Decode the munge encoded credential `m_str' placing results, if validated, * into slurm credential `c' */ static int _decode_cred(slurm_auth_credential_t *c, char *socket) { int retry = 2; munge_err_t e; munge_ctx_t ctx; if (c == NULL) return SLURM_ERROR; xassert(c->magic == MUNGE_MAGIC); if (c->verified) return SLURM_SUCCESS; if ((ctx = munge_ctx_create()) == NULL) { error("munge_ctx_create failure"); return SLURM_ERROR; } if (socket && (munge_ctx_set(ctx, MUNGE_OPT_SOCKET, socket) != EMUNGE_SUCCESS)) { error("munge_ctx_set failure"); munge_ctx_destroy(ctx); return SLURM_ERROR; } again: c->buf = NULL; e = munge_decode(c->m_str, ctx, &c->buf, &c->len, &c->uid, &c->gid); if (e != EMUNGE_SUCCESS) { if (c->buf) { free(c->buf); c->buf = NULL; } if ((e == EMUNGE_SOCKET) && retry--) { error ("Munge decode failed: %s (retrying ...)", munge_ctx_strerror(ctx)); #ifdef MULTIPLE_SLURMD sleep(1); #endif goto again; } #ifdef MULTIPLE_SLURMD /* In multple slurmd mode this will happen all the * time since we are authenticating with the same * munged. */ if (e != EMUNGE_CRED_REPLAYED) { #endif /* * Print any valid credential data */ error ("Munge decode failed: %s", munge_ctx_strerror(ctx)); _print_cred(ctx); if (e == EMUNGE_CRED_REWOUND) error("Check for out of sync clocks"); c->cr_errno = e + MUNGE_ERRNO_OFFSET; #ifdef MULTIPLE_SLURMD } else { debug2("We had a replayed cred, " "but this is expected in multiple " "slurmd mode."); e = 0; } #endif goto done; } c->verified = true; done: munge_ctx_destroy(ctx); return e ? SLURM_ERROR : SLURM_SUCCESS; }
int main(int argc, char *argv[]) { int rc = 1; int ret; signal(SIGINT, signal_handler); int c; char ep[28]; const char *host = "0.0.0.0"; char *ohost = NULL; int port = 48005; void *ctx = NULL; void *fe = NULL; void *be = NULL; while ((c = getopt (argc, argv, "h:p:")) != -1) switch (c) { case 'h': ohost = strdup(optarg); break; case 'p': port = atoi(optarg); } pid_t pid = spawn_worker(); printf("Spawned worker w/ pid %d\n", pid); if (ohost != NULL) host = ohost; snprintf(ep, 28, "tcp://%s:%d", host, port); if (ohost != NULL) free(ohost); ctx = zmq_ctx_new(); if (ctx == NULL) goto finished; fe = zmq_socket(ctx, ZMQ_ROUTER); if (fe == NULL) goto finished; be = zmq_socket(ctx, ZMQ_DEALER); if (be == NULL) goto finished; ret = zmq_bind(fe, ep); if (ret < 0) { fprintf(stderr, "Unable to bind socket\n"); goto finished; } zmq_bind(be, WORKER_IPC); zmq_pollitem_t items [] = { { fe, 0, ZMQ_POLLIN, 0 }, { be, 0, ZMQ_POLLIN, 0 } }; printf("Waiting for messages...\n"); void *cred; void *buf; int len; while (1) { zmq_msg_t message; zmq_msg_t out; ret = zmq_poll(items, 2, -1); if (ret < 0) if (errno == EINTR) { break; } if (items[0].revents & ZMQ_POLLIN) { while (1) { zmq_msg_init(&message); zmq_msg_recv(&message, fe, 0); int more = zmq_msg_more(&message); if (!more) { cred = zmq_msg_data(&message); munge_err_t err = munge_decode(cred, NULL, &buf, &len, NULL, NULL); if (err != EMUNGE_SUCCESS) fprintf(stderr, "Munge failed to decode\n"); zmq_msg_init_data(&out, buf, len, free_buf, NULL); zmq_msg_send(&out, be, 0); zmq_msg_close(&out); } else { zmq_msg_send(&message, be, more? ZMQ_SNDMORE: 0); } zmq_msg_close(&message); if (!more) break; } } if (items[1].revents & ZMQ_POLLIN) { while (1) { zmq_msg_init(&message); zmq_msg_recv(&message, be, 0); int more = zmq_msg_more(&message); zmq_msg_send(&message, fe, more? ZMQ_SNDMORE: 0); zmq_msg_close(&message); if (!more) break; } } } rc = 0; printf("Shutting down\n"); finished: printf("Stopping workers...\n"); pid_t w; int status; do { w = waitpid(pid, &status, 0); if (w == -1) { fprintf(stderr, "Unable to wait\n"); break; } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); printf("Finishing cleanup\n"); ret = zmq_close(fe); if (ret < 0) fprintf(stderr, "Failed to close frontend socket\n"); ret = zmq_close(be); if (ret < 0) fprintf(stderr, "Failed to close backend socket\n"); ret = zmq_ctx_destroy(ctx); if(ret < 0) fprintf(stderr, "Failed to stop ZMQ\n"); return rc; }
void * remunge (conf_t conf) { /* Worker thread responsible for encoding/decoding/validating credentials. */ tdata_t tdata; int cancel_state; unsigned long n; unsigned long got_encode_err; unsigned long got_decode_err; struct timeval t_start; struct timeval t_stop; double delta; munge_err_t e; char *cred; void *data; int dlen; uid_t uid; gid_t gid; tdata = create_tdata (conf); pthread_cleanup_push ((thread_cleanup_f) remunge_cleanup, tdata); if ((errno = pthread_mutex_lock (&conf->mutex)) != 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to lock mutex"); } while (conf->num_creds - conf->shared.num_creds_done > 0) { pthread_testcancel (); if ((errno = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &cancel_state)) != 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to disable thread cancellation"); } n = ++conf->shared.num_creds_done; if ((errno = pthread_mutex_unlock (&conf->mutex)) != 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to unlock mutex"); } got_encode_err = 0; got_decode_err = 0; data = NULL; GET_TIMEVAL (t_start); e = munge_encode(&cred, tdata->ectx, conf->payload, conf->num_payload); GET_TIMEVAL (t_stop); delta = DIFF_TIMEVAL (t_stop, t_start); if (delta > conf->warn_time) { output_msg ("Credential #%lu encoding took %0.3f seconds", n, delta); } if (e != EMUNGE_SUCCESS) { output_msg ("Credential #%lu encoding failed: %s (err=%d)", n, munge_ctx_strerror (tdata->ectx), e); ++got_encode_err; } else if (conf->do_decode) { GET_TIMEVAL (t_start); e = munge_decode (cred, tdata->dctx, &data, &dlen, &uid, &gid); GET_TIMEVAL (t_stop); delta = DIFF_TIMEVAL (t_stop, t_start); if (delta > conf->warn_time) { output_msg ("Credential #%lu decoding took %0.3f seconds", n, delta); } if (e != EMUNGE_SUCCESS) { output_msg ("Credential #%lu decoding failed: %s (err=%d)", n, munge_ctx_strerror (tdata->dctx), e); ++got_decode_err; } /* FIXME: * The following block does some validating of the decoded credential. * It should have a cmdline option to enable this validation check. * The decode ctx should also be checked against the encode ctx. * This becomes slightly more difficult in that it must also take * into account the default field settings. * * This block should be moved into a separate function (or more). * The [cred], [data], [dlen], [uid], and [gid] vars could be placed * into the tdata struct to facilitate parameter passing. */ #if 0 else if (conf->do_validate) { if (getuid () != uid) { output_msg ( "Credential #%lu UID %d does not match process UID %d", n, uid, getuid ()); } if (getgid () != gid) { output_msg ( "Credential #%lu GID %d does not match process GID %d", n, gid, getgid ()); } if (conf->num_payload != dlen) { output_msg ( "Credential #%lu payload length mismatch (%d/%d)", n, conf->num_payload, dlen); } else if (data && memcmp (conf->payload, data, dlen) != 0) { output_msg ("Credential #%lu payload mismatch", n); } } #endif /* 0 */ /* The 'data' parm can still be set on certain munge errors. */ if (data != NULL) { free (data); } } if (cred != NULL) { free (cred); } if ((errno = pthread_setcancelstate (cancel_state, &cancel_state)) != 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to enable thread cancellation"); } if ((errno = pthread_mutex_lock (&conf->mutex)) != 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to lock mutex"); } conf->shared.num_encode_errs += got_encode_err; conf->shared.num_decode_errs += got_decode_err; } pthread_cleanup_pop (1); return (NULL); }