static int _recv_auth_req (int sd, char **pipe_name_p, char **file_dir_p) { /* Receives an authentication request from the server on the established * socket [sd], storing the path name of the authentication pipe to use for * sending an fd across in a newly-allocated string referenced by * [pipe_name_p], as well as the directory name in which to create the * authentication file [file_dir_p] corresponding to the fd to be sent. * The caller is responsible for freeing these strings. * Returns 0 on success, -1 on error. */ m_msg_t m; munge_err_t e; *pipe_name_p = NULL; *file_dir_p = NULL; if ((e = m_msg_create (&m)) != EMUNGE_SUCCESS) { goto end; } if ((e = m_msg_bind (m, sd)) != EMUNGE_SUCCESS) { goto end; } if ((e = m_msg_recv (m, MUNGE_MSG_AUTH_FD_REQ, 0)) != EMUNGE_SUCCESS) { goto end; } /* Note that error_str will be set if the received message is an error * message, whereas m_msg_recv()'s return code (e) will be set * according to how that message is received. */ if (m->error_str != NULL) { e = EMUNGE_SOCKET; goto end; } *pipe_name_p = m->auth_s_str; m->auth_s_is_copy = 1; *file_dir_p = m->auth_c_str; m->auth_c_is_copy = 1; end: if (m) { m->sd = -1; /* prevent close by m_msg_destroy() */ m_msg_destroy (m); } return (e == EMUNGE_SUCCESS ? 0 : -1); }
static int _send_auth_req (int sd, const char *pipe_name) { /* Sends an authentication request to the client on the established * socket [sd] using [pipe_name] as the authentication pipe to use * for sending an fd across. * Returns 0 on success, -1 on error. * * The authentication request message contains the authentication pipe name * for the client to send a file descriptor across, as well as the directory * name in which to create the authentication file corresponding to the file * descriptor being sent. */ m_msg_t m; munge_err_t e; if ((e = m_msg_create (&m)) != EMUNGE_SUCCESS) { goto end; } if ((e = m_msg_bind (m, sd)) != EMUNGE_SUCCESS) { goto end; } m->auth_s_str = (char *) pipe_name; m->auth_s_len = strlen (m->auth_s_str) + 1; m->auth_s_is_copy = 1; m->auth_c_str = conf->auth_client_dir; m->auth_c_len = strlen (m->auth_c_str) + 1; m->auth_c_is_copy = 1; e = m_msg_send (m, MUNGE_MSG_AUTH_FD_REQ, 0); end: if (m) { m->sd = -1; /* prevent close by m_msg_destroy() */ m_msg_destroy (m); } return (e == EMUNGE_SUCCESS ? 0 : -1); }
munge_err_t munge_decode (const char *cred, munge_ctx_t ctx, void **buf, int *len, uid_t *uid, gid_t *gid) { munge_err_t e; m_msg_t m; /* Init output parms in case of early return. */ _decode_init (ctx, buf, len, uid, gid); /* * Ensure a credential exists for decoding. */ if ((cred == NULL) || (*cred == '\0')) { return (_munge_ctx_set_err (ctx, EMUNGE_BAD_ARG, strdup ("No credential specified"))); } /* Ask the daemon to decode a credential. */ if ((e = m_msg_create (&m)) != EMUNGE_SUCCESS) ; else if ((e = _decode_req (m, ctx, cred)) != EMUNGE_SUCCESS) ; else if ((e = m_msg_client_xfer (&m, MUNGE_MSG_DEC_REQ, ctx)) != EMUNGE_SUCCESS) ; else if ((e = _decode_rsp (m, ctx, buf, len, uid, gid)) != EMUNGE_SUCCESS) ; /* Clean up and return. */ if (ctx) { _munge_ctx_set_err (ctx, e, m->error_str); m->error_is_copy = 1; } m_msg_destroy (m); return (e); }
void job_accept (conf_t conf) { work_p w; m_msg_t m; int sd; assert (conf != NULL); assert (conf->ld >= 0); if (!(w = work_init ((work_func_t) _job_exec, conf->nthreads))) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to create %d work thread%s", conf->nthreads, ((conf->nthreads > 1) ? "s" : "")); } log_msg (LOG_INFO, "Created %d work thread%s", conf->nthreads, ((conf->nthreads > 1) ? "s" : "")); while (!done) { if ((sd = accept (conf->ld, NULL, NULL)) < 0) { switch (errno) { case ECONNABORTED: case EINTR: continue; case EMFILE: case ENFILE: case ENOBUFS: case ENOMEM: log_msg (LOG_INFO, "Suspended new connections while processing backlog"); work_wait (w); continue; default: log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to accept connection"); break; } } /* With fd_timed_read_n(), a poll() is performed before any read() * in order to provide timeouts and ensure the read() won't block. * As such, it shouldn't be necessary to set the client socket as * non-blocking. However according to the Linux poll(2) and * select(2) manpages, spurious readiness notifications can occur. * poll()/select() may report a socket as ready for reading while * the subsequent read() blocks. This could happen when data has * arrived, but upon examination is discarded due to an invalid * checksum. To protect against this, the client socket is set * non-blocking and EAGAIN is handled appropriately. */ if (fd_set_nonblocking (sd) < 0) { close (sd); log_msg (LOG_WARNING, "Failed to set nonblocking client socket: %s", strerror (errno)); } else if (m_msg_create (&m) != EMUNGE_SUCCESS) { close (sd); log_msg (LOG_WARNING, "Failed to create client request"); } else if (m_msg_bind (m, sd) != EMUNGE_SUCCESS) { m_msg_destroy (m); log_msg (LOG_WARNING, "Failed to bind socket for client request"); } else if (work_queue (w, m) < 0) { m_msg_destroy (m); log_msg (LOG_WARNING, "Failed to queue client request"); } } log_msg (LOG_NOTICE, "Exiting on signal=%d", done); work_fini (w, 1); return; }
munge_err_t m_msg_client_xfer (m_msg_t *pm, m_msg_type_t mreq_type, munge_ctx_t ctx) { char *socket; int i; munge_err_t e; m_msg_t mreq, mrsp; m_msg_type_t mrsp_type; if (!pm || !*pm) { return (EMUNGE_SNAFU); } if (!ctx || !(socket = ctx->socket_str)) { socket = MUNGE_SOCKET_NAME; } mreq = *pm; mrsp = NULL; if (mreq_type == MUNGE_MSG_ENC_REQ) { mrsp_type = MUNGE_MSG_ENC_RSP; } else if (mreq_type == MUNGE_MSG_DEC_REQ) { mrsp_type = MUNGE_MSG_DEC_RSP; } else { return (EMUNGE_SNAFU); } i = 1; while (1) { if ((e = _m_msg_client_connect (mreq, socket)) != EMUNGE_SUCCESS) { break; } else if ((e = m_msg_send (mreq, mreq_type, MUNGE_MAXIMUM_REQ_LEN)) != EMUNGE_SUCCESS) { ; /* empty */ } else if (auth_send (mreq) < 0) { e = EMUNGE_SOCKET; } else if ((e = m_msg_create (&mrsp)) != EMUNGE_SUCCESS) { break; } else if ((e = m_msg_bind (mrsp, mreq->sd)) != EMUNGE_SUCCESS) { break; } else if ((e = m_msg_recv (mrsp, mrsp_type, 0)) != EMUNGE_SUCCESS) { ; /* empty */ } else if ((e = _m_msg_client_disconnect (mrsp)) != EMUNGE_SUCCESS) { break; } else if (e == EMUNGE_SUCCESS) { break; } if (i >= MUNGE_SOCKET_RETRY_ATTEMPTS) { break; } if (e == EMUNGE_BAD_LENGTH) { break; } if (mrsp != NULL) { mrsp->sd = -1; /* prevent socket close by destroy() */ m_msg_destroy (mrsp); mrsp = NULL; } if (mreq->sd >= 0) { (void) close (mreq->sd); mreq->sd = -1; } mreq->retry = i; e = _m_msg_client_millisleep (mreq, i * MUNGE_SOCKET_RETRY_MSECS); if (e != EMUNGE_SUCCESS) { break; } i++; } if (mrsp) { *pm = mrsp; mreq->sd = -1; /* prevent socket close by destroy() */ m_msg_destroy (mreq); } return (e); }