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); }
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; }
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); }
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); }
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); }
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)); }