예제 #1
0
파일: m_msg_client.c 프로젝트: dun/munge
static munge_err_t
_m_msg_client_millisleep (m_msg_t m, unsigned long msecs)
{
/*  Sleeps for 'msecs' milliseconds.
 *  Returns EMUNGE_SUCCESS on success,
 *    or EMUNGE_SNAFU on error (with additional info if 'm' is not NULL).
 */
    struct timespec ts;
    int rv;

    ts.tv_sec = msecs / 1000;
    ts.tv_nsec = (msecs % 1000) * 1000 * 1000;

    while (1) {
        rv = nanosleep (&ts, &ts);
        if (rv == 0) {
            break;
        }
        else if (errno == EINTR) {
            continue;
        }
        else if (m != NULL) {
            m_msg_set_err (m, EMUNGE_SNAFU,
                strdupf ("Failed nanosleep: %s", strerror (errno)));
        }
        return (EMUNGE_SNAFU);
    }
    return (EMUNGE_SUCCESS);
}
예제 #2
0
파일: job.c 프로젝트: dun/munge
static void
_job_exec (m_msg_t m)
{
/*  Receives and responds to the message request [m].
 */
    munge_err_t  e;
    const char  *p;

    assert (m != NULL);

    e = m_msg_recv (m, MUNGE_MSG_UNDEF, MUNGE_MAXIMUM_REQ_LEN);
    if (e == EMUNGE_SUCCESS) {
        switch (m->type) {
            case MUNGE_MSG_ENC_REQ:
                enc_process_msg (m);
                break;
            case MUNGE_MSG_DEC_REQ:
                dec_process_msg (m);
                break;
            default:
                m_msg_set_err (m, EMUNGE_SNAFU,
                    strdupf ("Invalid message type %d", m->type));
                break;
        }
    }
    /*  For certain MUNGE "cred" errors, the credential has been successfully
     *    decoded but is deemed invalid for other reasons.  In these cases,
     *    the origin IP address is added to the logged error message to aid
     *    in troubleshooting.
     */
    if (m->error_num != EMUNGE_SUCCESS) {
        p = (m->error_str != NULL)
            ? m->error_str
            : munge_strerror (m->error_num);
        switch (m->error_num) {
            case EMUNGE_CRED_EXPIRED:
            case EMUNGE_CRED_REWOUND:
            case EMUNGE_CRED_REPLAYED:
                if (m->addr_len == 4) {
                    char ip_addr_buf [INET_ADDRSTRLEN];
                    if (inet_ntop (AF_INET, &m->addr, ip_addr_buf,
                                   sizeof (ip_addr_buf)) != NULL) {
                        log_msg (LOG_INFO, "%s from %s", p, ip_addr_buf);
                        break;
                    }
                }
                /* fall-through */
            default:
                log_msg (LOG_INFO, "%s", p);
                break;
        }
    }
    m_msg_destroy (m);
    return;
}
예제 #3
0
파일: decode.c 프로젝트: JakeMick/munge
static munge_err_t
_decode_rsp (m_msg_t m, munge_ctx_t ctx,
               void **buf, int *len, uid_t *uid, gid_t *gid)
{
/*  Extracts a Decode Response message received from the local munge daemon.
 *  The outputs from this message are as follows:
 *    cipher, mac, zip, realm, ttl, addr, time0, time1, cred_uid, cred_gid,
 *    auth_uid, auth_gid, data_len, data, error_num, error_len, error_str.
 *  Note that error_num and error_str are set by _munge_ctx_set_err()
 *    called from munge_decode() (ie, the parent of this stack frame).
 */
    assert (m != NULL);

    /*  Perform sanity checks.
     */
    if (m->type != MUNGE_MSG_DEC_RSP) {
        m_msg_set_err (m, EMUNGE_SNAFU,
            strdupf ("Client received invalid message type %d", m->type));
        return (EMUNGE_SNAFU);
    }
    /*  Return the result.
     */
    if (ctx) {
        ctx->cipher = m->cipher;
        ctx->mac = m->mac;
        ctx->zip = m->zip;
        if ((ctx->realm_str = m->realm_str) != NULL) {
            m->realm_is_copy = 1;
        }
        ctx->ttl = m->ttl;
        ctx->addr.s_addr = m->addr.s_addr;;
        ctx->time0 = m->time0;
        ctx->time1 = m->time1;
        ctx->auth_uid = m->auth_uid;
        ctx->auth_gid = m->auth_gid;
    }
    if (buf && len && (m->data_len > 0)) {
        assert (* ((unsigned char *) m->data + m->data_len) == '\0');
        *buf = m->data;
        m->data_is_copy = 1;
    }
    if (len) {
        *len = m->data_len;
    }
    if (uid) {
        *uid = m->cred_uid;
    }
    if (gid) {
        *gid = m->cred_gid;
    }
    return (m->error_num);
}
예제 #4
0
파일: m_msg_client.c 프로젝트: dun/munge
static munge_err_t
_m_msg_client_disconnect (m_msg_t m) {
    munge_err_t e;

    assert (m != NULL);
    assert (m->sd >= 0);

    if (close (m->sd) < 0) {
        m_msg_set_err (m, EMUNGE_SOCKET,
            strdupf ("Failed to close socket: %s", strerror (errno)));
        e = EMUNGE_SOCKET;
    }
    else {
        e = EMUNGE_SUCCESS;
    }
    m->sd = -1;
    return (e);
}
예제 #5
0
파일: m_msg_client.c 프로젝트: dun/munge
static munge_err_t
_m_msg_client_connect (m_msg_t m, char *path)
{
    struct stat         st;
    struct sockaddr_un  addr;
    int                 sd;
    int                 n;
    int                 i;
    unsigned long       delay_msecs;

    assert (m != NULL);
    assert (m->sd < 0);

    if ((path == NULL) || (*path == '\0')) {
        m_msg_set_err (m, EMUNGE_SOCKET,
            strdup ("MUNGE socket name is undefined"));
        return (EMUNGE_SOCKET);
    }
    if (stat (path, &st) < 0) {
        m_msg_set_err (m, EMUNGE_SOCKET,
            strdupf ("Failed to access \"%s\": %s", path, strerror (errno)));
        return (EMUNGE_SOCKET);
    }
    if (!S_ISSOCK (st.st_mode)) {
        m_msg_set_err (m, EMUNGE_SOCKET,
            strdupf ("Invalid file type for socket \"%s\"", path));
        return (EMUNGE_SOCKET);
    }
    if ((sd = socket (PF_UNIX, SOCK_STREAM, 0)) < 0) {
        m_msg_set_err (m, EMUNGE_SOCKET,
            strdupf ("Failed to create socket: %s", strerror (errno)));
        return (EMUNGE_SOCKET);
    }
    if (fd_set_nonblocking (sd) < 0) {
        close (sd);
        m_msg_set_err (m, EMUNGE_SOCKET,
            strdupf ("Failed to set nonblocking socket: %s",
            strerror (errno)));
        return (EMUNGE_SOCKET);
    }
    memset (&addr, 0, sizeof (addr));
    addr.sun_family = AF_UNIX;
    addr.sun_path[ sizeof (addr.sun_path) - 1 ] = '\0';
    strncpy (addr.sun_path, path, sizeof (addr.sun_path));
    if (addr.sun_path[ sizeof (addr.sun_path) - 1 ] != '\0') {
        close (sd);
        m_msg_set_err (m, EMUNGE_OVERFLOW,
            strdup ("Exceeded maximum length of socket pathname"));
        return (EMUNGE_OVERFLOW);
    }
    i = 1;
    while (1) {
        /*
         * If a call to connect() for a Unix domain stream socket finds that
         *   the listening socket's queue is full, ECONNREFUSED is returned
         *   immediately.  (cf, Stevens UNPv1, s14.4, p378)
         * If ECONNREFUSED, try again up to MUNGE_SOCKET_CONNECT_ATTEMPTS.
         */
        n = connect (sd, (struct sockaddr *) &addr, sizeof (addr));

        if (n == 0) {
            break;
        }
        if (errno == EINTR) {
            continue;
        }
        if (errno != ECONNREFUSED) {
            break;
        }
        if (i >= MUNGE_SOCKET_CONNECT_ATTEMPTS) {
            break;
        }
        delay_msecs = i * MUNGE_SOCKET_CONNECT_RETRY_MSECS;
        if (_m_msg_client_millisleep (m, delay_msecs) != EMUNGE_SUCCESS) {
            break;
        }
        i++;
    }
    if (n < 0) {
        close (sd);
        m_msg_set_err (m, EMUNGE_SOCKET,
            strdupf ("Failed to connect to \"%s\": %s", path,
            strerror (errno)));
        return (EMUNGE_SOCKET);
    }
    m->sd = sd;
    return (EMUNGE_SUCCESS);
}
예제 #6
0
파일: auth_send.c 프로젝트: dun/munge
int
auth_send (m_msg_t m)
{
    char *pipe_name = NULL;
    char *file_dir = NULL;
    char *file_name = NULL;
    int   file_fd = -1;
    int   pipe_fd = -1;
    char *estr;

    if (_recv_auth_req (m->sd, &pipe_name, &file_dir) < 0) {
        estr = strdup ("Failed to receive auth request");
        goto err;
    }
    assert (pipe_name != NULL);
    if (_name_auth_file (pipe_name, file_dir, &file_name) < 0) {
        estr = strdup ("Failed to name auth file");
        goto err;
    }
    assert (file_name != NULL);
    unlink (file_name);                 /* in case it already exists */

    if ((file_fd= open (file_name, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR)) <0) {
        estr = strdupf ("Failed to open auth file \"%s\": %s",
            file_name, strerror (errno));
        goto err;
    }
    if (unlink (file_name) < 0) {
        estr = strdupf ("Failed to remove auth file \"%s\": %s",
            file_name, strerror (errno));
        goto err;
    }
    if ((pipe_fd = open (pipe_name, O_WRONLY)) < 0) {
        estr = strdupf ("Failed to open auth pipe \"%s\": %s",
            pipe_name, strerror (errno));
        goto err;
    }
    if (ioctl (pipe_fd, I_SENDFD, file_fd) < 0) {
        estr = strdupf ("Failed to send client identity: %s",
            strerror (errno));
        goto err;
    }
    if (close (pipe_fd) < 0) {
        estr = strdupf ("Failed to close auth pipe \"%s\": %s",
            pipe_name, strerror (errno));
        goto err;
    }
    if (close (file_fd) < 0) {
        estr = strdupf ("Failed to close auth file \"%s\": %s",
            file_name, strerror (errno));
        goto err;
    }
    free (pipe_name);
    free (file_dir);
    free (file_name);
    return (0);

err:
    if (pipe_fd >= 0) {
        (void) close (pipe_fd);
    }
    if (pipe_name != NULL) {
        free (pipe_name);
    }
    if (file_fd >= 0) {
        (void) close (file_fd);
    }
    if (file_name != NULL) {
        (void) unlink (file_name);
        free (file_name);
    }
    if (file_dir != NULL) {
        free (file_dir);
    }
    return (m_msg_set_err (m, EMUNGE_SNAFU, estr));
}