Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
File: job.c Progetto: dun/munge
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;
}
Esempio n. 4
0
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);
}