ATF_TC_BODY(getpeereid, tc) { int sv[2]; int s; uid_t real_euid, euid; gid_t real_egid, egid; real_euid = geteuid(); real_egid = getegid(); s = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv); ATF_CHECK_EQ(0, s); ATF_CHECK(sv[0] >= 0); ATF_CHECK(sv[1] >= 0); ATF_CHECK(sv[0] != sv[1]); ATF_REQUIRE_EQ(0, getpeereid(sv[0], &euid, &egid)); ATF_CHECK_EQ(real_euid, euid); ATF_CHECK_EQ(real_egid, egid); ATF_REQUIRE_EQ(0, getpeereid(sv[1], &euid, &egid)); ATF_CHECK_EQ(real_euid, euid); ATF_CHECK_EQ(real_egid, egid); close(sv[0]); close(sv[1]); }
int clients_set_fh (int id, int fh) { struct roar_client * c; #ifdef SO_PEERCRED struct ucred cred; socklen_t cred_len = sizeof(cred); #endif _CHECK_CID(id); if ( (c = ROAR_CLIENT(g_clients[id])) == NULL ) return -1; c->fh = fh; #ifdef SO_PEERCRED if (getsockopt(fh, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) != -1) { if ( cred.pid != 0 ) { c->pid = cred.pid; c->uid = cred.uid; c->gid = cred.gid; } } else { ROAR_DBG("req_on_identify(): Can't get creds via SO_PEERCRED: %s", strerror(errno)); } #elif defined(ROAR_HAVE_GETPEEREID) if (getpeereid(fh, &(c->uid), &(c->gid)) == -1) { ROAR_DBG("req_on_identify(): Can't get creds via getpeereid(): %s", strerror(errno)); } #endif return 0; }
int32_t SystemNative_GetPeerID(intptr_t socket, uid_t* euid) { int fd = ToFileDescriptor(socket); // ucred causes Emscripten to fail even though it's defined, // but getting peer credentials won't work for WebAssembly anyway #if defined(SO_PEERCRED) && !defined(_WASM_) struct ucred creds; socklen_t len = sizeof(creds); if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) == 0) { *euid = creds.uid; return 0; } return -1; #elif HAVE_GETPEEREID uid_t egid; return getpeereid(fd, euid, &egid); #else (void)fd; (void)*euid; errno = ENOTSUP; return -1; #endif }
_PUBLIC_ int sys_getpeereid( int s, uid_t *uid) { #if defined(HAVE_PEERCRED) struct ucred cred; socklen_t cred_len = sizeof(struct ucred); int ret; ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len); if (ret != 0) { return -1; } if (cred_len != sizeof(struct ucred)) { errno = EINVAL; return -1; } *uid = cred.uid; return 0; #else #if defined(HAVE_GETPEEREID) gid_t gid; return getpeereid(s, uid, &gid); #endif errno = ENOSYS; return -1; #endif }
/* * Set local connection credentials into given hash structure */ int __pmServerSetLocalCreds(int fd, __pmHashCtl *attrs) { #if defined(HAVE_STRUCT_UCRED) /* Linux */ struct ucred ucred; __pmSockLen length = sizeof(ucred); if (__pmGetSockOpt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &length) < 0) return -oserror(); return SetCredentialAttrs(attrs, ucred.pid, ucred.uid, ucred.gid); #elif defined(HAVE_GETPEEREID) /* MacOSX */ uid_t uid; gid_t gid; if (getpeereid(__pmFD(fd), &uid, &gid) < 0) return -oserror(); return SetCredentialAttrs(attrs, 0, uid, gid); #elif defined(HAVE_GETPEERUCRED) /* Solaris */ unsigned int uid, gid, pid; ucred_t *ucred = NULL; if (getpeerucred(__pmFD(fd), &ucred) < 0) return -oserror(); pid = ucred_getpid(ucred); uid = ucred_geteuid(ucred); gid = ucred_getegid(ucred); ucred_free(ucred); return SetCredentialAttrs(attrs, pid, uid, gid); #else return -EOPNOTSUPP; #endif }
/** * pfl_socket_getpeercred - Retrieve credentials of process on other end * of a UNIX domain socket. * @s: socket file descriptor. * @uid: value-result user ID. * @gid: value-result group ID. */ int pfl_socket_getpeercred(int s, uid_t *uid, gid_t *gid) { #ifdef HAVE_GETPEEREID if (getpeereid(s, uid, gid) == -1) return (errno); #elif defined(HAVE_GETPEERUCRED) ucred_t *ucr; if (getpeerucred(s, &ucr) == -1) return (errno); *uid = ucred_geteuid(ucr); *gid = ucred_getegid(ucr); ucred_free(ucr); #else struct ucred ucr; socklen_t len; len = sizeof(ucr); if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &ucr, &len)) return (errno); *uid = ucr.uid; *gid = ucr.gid; #endif return (0); }
char * check_id(int fd) { uid_t sockuid, myuid; gid_t sockgid, mygid; static char problem[1024]; if (getpeereid(fd, &sockuid, &sockgid) == -1) { snprintf(problem, sizeof problem, "getpeereid: %s", strerror(errno)); return problem; } myuid = geteuid(); mygid = getgid(); if (myuid != sockuid) { snprintf(problem, sizeof problem, "uid discrepancy %ld vs %ld", (long)myuid, (long)sockuid); return problem; } if (mygid != sockgid) { snprintf(problem, sizeof problem, "gid discrepancy %ld vs %ld", (long)mygid, (long)sockgid); return problem; } return NULL; }
/* * call-seq: * basicsocket.getpeereid => [euid, egid] * * Returns the user and group on the peer of the UNIX socket. * The result is a two element array which contains the effective uid and the effective gid. * * Socket.unix_server_loop("/tmp/sock") {|s| * begin * euid, egid = s.getpeereid * * # Check the connected client is myself or not. * next if euid != Process.uid * * # do something about my resource. * * ensure * s.close * end * } * */ static VALUE bsock_getpeereid(VALUE self) { UNRUBBY_SOCKET_HACK; #if defined(HAVE_GETPEEREID) rb_io_t *fptr; uid_t euid; gid_t egid; GetOpenFile(self, fptr); if (getpeereid(fptr->fd, &euid, &egid) == -1) rb_sys_fail("getpeereid"); return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid)); #elif defined(SO_PEERCRED) /* GNU/Linux */ rb_io_t *fptr; struct ucred cred; socklen_t len = sizeof(cred); GetOpenFile(self, fptr); if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1) rb_sys_fail("getsockopt(SO_PEERCRED)"); return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid)); #elif defined(HAVE_GETPEERUCRED) /* Solaris */ rb_io_t *fptr; ucred_t *uc = NULL; VALUE ret; GetOpenFile(self, fptr); if (getpeerucred(fptr->fd, &uc) == -1) rb_sys_fail("getpeerucred"); ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc))); ucred_free(uc); return ret; #endif }
int main (void) { int uid ; int gid ; int s = 0 ; return getpeereid(s, &uid, &gid) ; }
int auth_recv (m_msg_t m, uid_t *uid, gid_t *gid) { if (getpeereid (m->sd, uid, gid) < 0) { log_msg (LOG_ERR, "Failed to get peer identity: %s", strerror (errno)); return (-1); } return (0); }
int ipc_eid (int s, unsigned int *u, unsigned int *g) { uid_t dummyu ; gid_t dummyg ; if (getpeereid(s, &dummyu, &dummyg) < 0) return -1 ; *u = (unsigned int)dummyu ; *g = (unsigned int)dummyg ; return 0 ; }
/* Retrieve the credentials from the peer using the connect file descriptor FD. Returns 0 on success or -1 on error. */ int credentials_from_socket (int fd, pid_t *r_pid, uid_t *r_uid, gid_t *r_gid) { int rc = -1; #ifdef HAVE_SO_PEERCRED { struct ucred cr; socklen_t cl = sizeof cr; if (!getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)) { *r_pid = cr.pid; *r_uid = cr.uid; *r_gid = cr.gid; rc = 0; } } #elif defined (HAVE_GETPEERUCRED) { ucred_t *ucred = NULL; if (getpeerucred (fd, &ucred) != -1) { *r_pid = ucred_getpid (ucred); *r_uid = ucred_geteuid (ucred); *r_gid = ucred_getegid (ucred); rc = 0; ucred_free (ucred); } } #elif defined (HAVE_LOCAL_PEEREID) { struct unpcbid unp; socklen_t unpl = sizeof unp; if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1) { *r_pid = unp.unp_pid; *r_uid = unp.unp_euid; *r_gid = unp.unp_egid; rc = 0; } } #elif defined(HAVE_GETPEEREID) { if (getpeereid (fd, r_uid, r_gid) != -1) { r_pid = (pid_t)(-1); rc = 0; } } #endif return rc; }
static int agent_socket_get_cred(int fd, struct ucred *cred) { if (getpeereid(fd, &cred->uid, &cred->gid) < 0) return -1; if (read(fd, &cred->pid, sizeof(cred->pid)) != sizeof(cred->pid)) return -1; return 0; }
static uim_lisp c_getpeereid(uim_lisp s_) { uid_t euid; gid_t egid; if (getpeereid(C_INT(s_), &euid, &egid) == -1) return uim_scm_f(); return CONS(MAKE_INT(euid), MAKE_INT(egid)); }
static int ctrls_get_creds_peereid(int sockfd, uid_t *uid, gid_t *gid) { if (getpeereid(sockfd, uid, gid) < 0) { int xerrno = errno; pr_trace_msg(trace_channel, 7, "error obtaining credentials using " "getpeereid(2) on fd %d: %s", sockfd, strerror(xerrno)); errno = xerrno; return -1; } return 0; }
bool check_unix_peer_name(int fd, const char *username) { int res; uid_t peer_uid = -1; gid_t peer_gid = -1; struct passwd *pw; res = getpeereid(fd, &peer_uid, &peer_gid); if (res < 0) return false; pw = getpwuid(peer_uid); if (!pw) return false; return strcmp(pw->pw_name, username) == 0; }
/* * Get the effective UID of the sending process. Used by rpcbind, keyserv * and rpc.yppasswdd on AF_LOCAL. */ int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) { int sock, ret; gid_t egid; uid_t euid; struct sockaddr *sa; sock = transp->xp_fd; sa = (struct sockaddr *)transp->xp_rtaddr; if (sa->sa_family == AF_LOCAL) { ret = getpeereid(sock, &euid, &egid); if (ret == 0) *uid = euid; return (ret); } else return (-1); }
scon_status_t scon_util_getid(int sd, uid_t *uid, gid_t *gid) { #if defined(SO_PEERCRED) #ifdef HAVE_STRUCT_SOCKPEERCRED_UID #define HAVE_STRUCT_UCRED_UID struct sockpeercred ucred; #else struct ucred ucred; #endif socklen_t crlen = sizeof (ucred); #endif #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID)) /* Ignore received 'cred' and validate ucred for socket instead. */ scon_output_verbose(2, scon_globals.debug_output, "getid: checking getsockopt for peer credentials"); if (getsockopt(sd, SOL_SOCKET, SO_PEERCRED, &ucred, &crlen) < 0) { scon_output_verbose(2, scon_globals.debug_output, "getid: getsockopt SO_PEERCRED failed: %s", strerror (scon_socket_errno)); return SCON_ERR_INVALID_CRED; } #if defined(HAVE_STRUCT_UCRED_UID) *uid = ucred.uid; *gid = ucred.gid; #else *uid = ucred.cr_uid; *gid = ucred.cr_gid; #endif #elif defined(HAVE_GETPEEREID) scon_output_verbose(2, scon_globals.debug_output, "getid: checking getpeereid for peer credentials"); if (0 != getpeereid(sd, uid, gid)) { scon_output_verbose(2, scon_globals.debug_output, "getid: getsockopt getpeereid failed: %s", strerror (scon_socket_errno)); return SCON_ERR_INVALID_CRED; } #else return SCON_ERR_NOT_SUPPORTED; #endif return SCON_SUCCESS; }
/** * Get credentials from socket file. * * Supports: * AIX - pid, euid, egid * LINUX - pid, uid, gid * FREEBSD - uid, gid; pid is unavailable and set to -1 * * @param sd socket descriptor * @param creds credentials object in which to put infomation * @return 0 on success; -1 on error */ int russ_get_creds(int sd, struct russ_creds *creds) { socklen_t _cred_len; #ifdef AIX struct peercred_struct _cred; _cred_len = sizeof(struct peercred_struct); if (getsockopt(sd, SOL_SOCKET, SO_PEERID, &_cred, &_cred_len) < 0) { /*printf("errno (%d)\n", errno);*/ return -1; } creds->pid = (long)_cred.pid; creds->uid = (long)_cred.euid; creds->gid = (long)_cred.egid; #elif LINUX struct ucred _cred; _cred_len = sizeof(struct ucred); if (getsockopt(sd, SOL_SOCKET, SO_PEERCRED, &_cred, &_cred_len) < 0) { return -1; } creds->pid = (long)_cred.pid; creds->uid = (long)_cred.uid; creds->gid = (long)_cred.gid; #elif FREEBSD if (getpeereid(sd, (uid_t *)&(creds->uid), (gid_t *)&(creds->gid)) < 0) { return -1; } creds->pid = -1; #elif FREEBSD_ALT struct xucred _cred; _cred_len = sizeof(struct xucred); if (getsockopt(sd, SOL_SOCKET, LOCAL_PEERCRED, &_cred, &_cred_len) < 0) { return -1; } creds->pid = (long)-1; creds->uid = (long)_cred.cr_uid; creds->gid = (long)_cred.cr_groups[0]; #endif return 0; }
/* ARGSUSED */ static void control_accept(int listenfd, short event, void *arg) { int connfd; socklen_t len; struct sockaddr_un sun; struct ctl_conn *c; if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE) goto pause; len = sizeof(sun); if ((connfd = accept(listenfd, (struct sockaddr *)&sun, &len)) == -1) { if (errno == ENFILE || errno == EMFILE) goto pause; if (errno == EINTR || errno == EWOULDBLOCK || errno == ECONNABORTED) return; fatal("control_accept: accept"); } session_socket_blockmode(connfd, BM_NONBLOCK); c = xcalloc(1, sizeof(*c), "control_accept"); if (getpeereid(connfd, &c->euid, &c->egid) == -1) fatal("getpeereid"); c->id = ++connid; c->mproc.proc = PROC_CLIENT; c->mproc.handler = control_dispatch_ext; c->mproc.data = c; mproc_init(&c->mproc, connfd); mproc_enable(&c->mproc); tree_xset(&ctl_conns, c->id, c); stat_backend->increment("control.session", 1); return; pause: log_warnx("warn: ctl client limit hit, disabling new connections"); event_del(&control_state.ev); }
static mrb_value mrb_basicsocket_getpeereid(mrb_state *mrb, mrb_value self) { #ifdef HAVE_GETPEEREID mrb_value ary; gid_t egid; uid_t euid; int s; s = socket_fd(mrb, self); if (getpeereid(s, &euid, &egid) != 0) mrb_sys_fail(mrb, "getpeereid"); ary = mrb_ary_new_capa(mrb, 2); mrb_ary_push(mrb, ary, mrb_fixnum_value((mrb_int)euid)); mrb_ary_push(mrb, ary, mrb_fixnum_value((mrb_int)egid)); return ary; #else mrb_raise(mrb, E_RUNTIME_ERROR, "getpeereid is not avaialble on this system"); return mrb_nil_value(); #endif }
extern "C" int32_t SystemNative_GetPeerID(intptr_t socket, uid_t* euid) { int fd = ToFileDescriptor(socket); #ifdef SO_PEERCRED struct ucred creds; socklen_t len = sizeof(creds); if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) == 0) { *euid = creds.uid; return 0; } return -1; #elif HAVE_GETPEEREID uid_t egid; return getpeereid(fd, euid, &egid); #else (void)fd; (void)*euid; errno = ENOTSUP; return -1; #endif }
int uim_helper_check_connection_fd(int fd) { uid_t euid; gid_t egid; if (getpeereid(fd, &euid, &egid) < 0) { #if USE_UIM_NOTIFY && !UIM_NON_LIBUIM_PROG uim_notify_fatal("uim_helper: %s", strerror(errno)); #else perror("getpeereid failed"); #endif return -1; } if ((euid != 0) && (euid != getuid())) { #if USE_UIM_NOTIFY && !UIM_NON_LIBUIM_PROG uim_notify_fatal("uim_helper: uid mismatch"); #else fprintf(stderr, "uid mismatch\n"); #endif return -1; } return 0; }
static int get_remote_uid(int fd) { #ifdef HAVE_STRUCT_UCRED struct ucred cred; socklen_t len = sizeof (cred); if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0) return 0; return cred.uid; #else #ifdef HAVE_GETPEEREID uid_t euid; gid_t egid; if (getpeereid(fd, &euid, &egid) == 0) return euid; #else (void)fd; #endif return -1; #endif }
static void suidaccept_cb (suidservcb cb, int fd) { if (fd < 0) { (*cb) (NULL, NULL); return; } suidaccept *sa = New suidaccept; #ifdef HAVE_GETPEEREID if (getpeereid (fd, &sa->uid, &sa->gid) < 0) { warn ("getpeereid: %m\n"); close (fd); delete sa; return; } #endif /* HAVE_GETPEEREID */ sa->cb = cb; sa->ax = axprt_unix::alloc (fd); assert (!sa->ax->ateof ()); sa->ax->allow_recvfd = false; sa->as = asrv::alloc (sa->ax, setuid_prog_1, wrap (sa, &suidaccept::dispatch)); }
static bool check_client_uid(struct winbindd_cli_state *state, uid_t uid) { int ret; uid_t ret_uid; gid_t ret_gid; ret_uid = (uid_t)-1; ret = getpeereid(state->sock, &ret_uid, &ret_gid); if (ret != 0) { DEBUG(1, ("check_client_uid: Could not get socket peer uid: %s; " "denying access\n", strerror(errno))); return False; } if (uid != ret_uid && ret_uid != sec_initial_uid()) { DEBUG(1, ("check_client_uid: Client lied about its uid: said %u, " "actually was %u; denying access\n", (unsigned int)uid, (unsigned int)ret_uid)); return False; } return True; }
/** * Create a connection handle by accepting on a listen socket. This * function may block if the listen socket has no connection ready. * * @param access function to use to check if access is allowed * @param access_cls closure for access * @param lsock listen socket * @return the connection handle, NULL on error */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, void *access_cls, struct GNUNET_NETWORK_Handle *lsock) { struct GNUNET_CONNECTION_Handle *connection; char addr[128]; socklen_t addrlen; struct GNUNET_NETWORK_Handle *sock; int aret; struct sockaddr_in *v4; struct sockaddr_in6 *v6; struct sockaddr *sa; void *uaddr; struct GNUNET_CONNECTION_Credentials *gcp; struct GNUNET_CONNECTION_Credentials gc; #ifdef SO_PEERCRED struct ucred uc; socklen_t olen; #endif addrlen = sizeof (addr); sock = GNUNET_NETWORK_socket_accept (lsock, (struct sockaddr *) &addr, &addrlen); if (NULL == sock) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept"); return NULL; } if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t))) { GNUNET_break (0); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); return NULL; } sa = (struct sockaddr *) addr; v6 = (struct sockaddr_in6 *) addr; if ((AF_INET6 == sa->sa_family) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr))) { /* convert to V4 address */ v4 = GNUNET_malloc (sizeof (struct sockaddr_in)); memset (v4, 0, sizeof (struct sockaddr_in)); v4->sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4->sin_len = (u_char) sizeof (struct sockaddr_in); #endif memcpy (&v4->sin_addr, &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) - sizeof (struct in_addr)], sizeof (struct in_addr)); v4->sin_port = v6->sin6_port; uaddr = v4; addrlen = sizeof (struct sockaddr_in); } else { uaddr = GNUNET_malloc (addrlen); memcpy (uaddr, addr, addrlen); } gcp = NULL; gc.uid = 0; gc.gid = 0; if (AF_UNIX == sa->sa_family) { #if HAVE_GETPEEREID /* most BSDs */ if (0 == getpeereid (GNUNET_NETWORK_get_fd (sock), &gc.uid, &gc.gid)) gcp = &gc; #else #ifdef SO_PEERCRED /* largely traditional GNU/Linux */ olen = sizeof (uc); if ((0 == getsockopt (GNUNET_NETWORK_get_fd (sock), SOL_SOCKET, SO_PEERCRED, &uc, &olen)) && (olen == sizeof (uc))) { gc.uid = uc.uid; gc.gid = uc.gid; gcp = &gc; } #else #if HAVE_GETPEERUCRED /* this is for Solaris 10 */ ucred_t *uc; uc = NULL; if (0 == getpeerucred (GNUNET_NETWORK_get_fd (sock), &uc)) { gc.uid = ucred_geteuid (uc); gc.gid = ucred_getegid (uc); gcp = &gc; } ucred_free (uc); #endif #endif #endif } if ((NULL != access) && (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen)))) { if (GNUNET_NO == aret) LOG (GNUNET_ERROR_TYPE_INFO, _("Access denied to `%s'\n"), GNUNET_a2s (uaddr, addrlen)); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_shutdown (sock, SHUT_RDWR)); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); GNUNET_free (uaddr); return NULL; } connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle)); connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE; connection->write_buffer = GNUNET_malloc (connection->write_buffer_size); connection->addr = uaddr; connection->addrlen = addrlen; connection->sock = sock; LOG (GNUNET_ERROR_TYPE_INFO, _("Accepting connection from `%s': %p\n"), GNUNET_a2s (uaddr, addrlen), connection); return connection; }
value netsys_get_peer_credentials(value fd) { CAMLparam1(fd); CAMLlocal1(result); #if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED) uid_t uid; gid_t gid; #else int uid; int gid; #endif #if defined(HAVE_GETPEEREID) /* BSD, AIX, Cygwin */ /* http://cr.yp.to/docs/secureipc.html */ if (getpeereid(Int_val(fd), &uid, &gid) != 0) { uerror("getpeereid", Nothing); } #elif defined(SO_PEERCRED) /* Linux */ { socklen_t len; struct ucred credentials; len = sizeof(struct ucred); if (getsockopt(Int_val(fd), SOL_SOCKET, SO_PEERCRED, &credentials, &len) == -1) { uerror("getsockopt",Nothing); }; uid = credentials.uid; /* Effective user ID */ gid = credentials.gid; /* Effective group ID */ } #elif defined(HAVE_GETPEERUCRED) /* Solaris */ { ucred_t *ucred; ucred = NULL; /* must be initialized to NULL */ if (getpeerucred(Int_val(fd), &ucred) == -1) { uerror("getpeerucred",Nothing); }; if ((uid = ucred_geteuid(ucred)) == -1) { uerror("ucred_geteuid",Nothing); ucred_free(ucred); }; if ((gid = ucred_getegid(ucred)) == -1) { uerror("ucred_getegid",Nothing); ucred_free(ucred); }; ucred_free(ucred); } #else invalid_argument("get_peer_credentials"); #endif /* Allocate a pair, and put the result into it: */ result = alloc_tuple(2); Store_field(result, 0, Val_int(uid)); Store_field(result, 1, Val_int(gid)); CAMLreturn(result); }
static pmix_status_t validate_cred(struct pmix_peer_t *peer, const pmix_info_t directives[], size_t ndirs, pmix_info_t **info, size_t *ninfo, const pmix_byte_object_t *cred) { pmix_peer_t *pr = (pmix_peer_t*)peer; #if defined(SO_PEERCRED) #ifdef HAVE_STRUCT_SOCKPEERCRED_UID #define HAVE_STRUCT_UCRED_UID struct sockpeercred ucred; #else struct ucred ucred; #endif socklen_t crlen = sizeof (ucred); #endif uid_t euid = -1; gid_t egid = -1; char *ptr; size_t ln; bool takeus; char **types; size_t n, m; uint32_t u32; pmix_output_verbose(2, pmix_globals.debug_output, "psec: native validate_cred %s", (NULL == cred) ? "NULL" : "NON-NULL"); if (PMIX_PROTOCOL_V1 == pr->protocol) { /* usock protocol - get the remote side's uid/gid */ #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID)) /* Ignore received 'cred' and validate ucred for socket instead. */ pmix_output_verbose(2, pmix_globals.debug_output, "psec:native checking getsockopt on socket %d for peer credentials", pr->sd); if (getsockopt(pr->sd, SOL_SOCKET, SO_PEERCRED, &ucred, &crlen) < 0) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: getsockopt SO_PEERCRED failed: %s", strerror (pmix_socket_errno)); return PMIX_ERR_INVALID_CRED; } #if defined(HAVE_STRUCT_UCRED_UID) euid = ucred.uid; egid = ucred.gid; #else euid = ucred.cr_uid; egid = ucred.cr_gid; #endif #elif defined(HAVE_GETPEEREID) pmix_output_verbose(2, pmix_globals.debug_output, "psec:native checking getpeereid on socket %d for peer credentials", pr->sd); if (0 != getpeereid(pr->sd, &euid, &egid)) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: getsockopt getpeereid failed: %s", strerror (pmix_socket_errno)); return PMIX_ERR_INVALID_CRED; } #else return PMIX_ERR_NOT_SUPPORTED; #endif } else if (PMIX_PROTOCOL_V2 == pr->protocol) { /* this is a tcp protocol, so the cred is actually the uid/gid * passed upwards from the client */ if (NULL == cred) { /* not allowed */ return PMIX_ERR_INVALID_CRED; } ln = cred->size; euid = 0; egid = 0; if (sizeof(uid_t) <= ln) { memcpy(&euid, cred->bytes, sizeof(uid_t)); ln -= sizeof(uid_t); ptr = cred->bytes + sizeof(uid_t); } else { return PMIX_ERR_INVALID_CRED; } if (sizeof(gid_t) <= ln) { memcpy(&egid, ptr, sizeof(gid_t)); } else { return PMIX_ERR_INVALID_CRED; } } else if (PMIX_PROTOCOL_UNDEF != pr->protocol) { /* don't recognize the protocol */ return PMIX_ERR_NOT_SUPPORTED; } /* if we are responding to a local request to validate a credential, * then see if they specified a mechanism */ if (NULL != directives && 0 < ndirs) { for (n=0; n < ndirs; n++) { if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) { /* split the specified string */ types = pmix_argv_split(directives[n].value.data.string, ','); takeus = false; for (m=0; NULL != types[m]; m++) { if (0 == strcmp(types[m], "native")) { /* it's us! */ takeus = true; break; } } pmix_argv_free(types); if (!takeus) { return PMIX_ERR_NOT_SUPPORTED; } } } } /* check uid */ if (euid != pr->info->uid) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: socket cred contains invalid uid %u", euid); return PMIX_ERR_INVALID_CRED; } /* check gid */ if (egid != pr->info->gid) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: socket cred contains invalid gid %u", egid); return PMIX_ERR_INVALID_CRED; } /* validated - mark that we did it */ if (NULL != info) { PMIX_INFO_CREATE(*info, 3); if (NULL == *info) { return PMIX_ERR_NOMEM; } *ninfo = 3; /* mark that this came from us */ PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "munge", PMIX_STRING); /* provide the uid it contained */ u32 = euid; PMIX_INFO_LOAD(info[1], PMIX_USERID, &u32, PMIX_UINT32); /* provide the gid it contained */ u32 = egid; PMIX_INFO_LOAD(info[2], PMIX_GRPID, &u32, PMIX_UINT32); } return PMIX_SUCCESS; }
static int32_t qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len, struct ipc_auth_ugp *ugp) { int32_t res = 0; struct msghdr msg_recv; struct iovec iov_recv; #ifdef SO_PASSCRED char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))]; int off = 0; int on = 1; #endif msg_recv.msg_iov = &iov_recv; msg_recv.msg_iovlen = 1; msg_recv.msg_name = 0; msg_recv.msg_namelen = 0; #ifdef SO_PASSCRED msg_recv.msg_control = (void *)cmsg_cred; msg_recv.msg_controllen = sizeof(cmsg_cred); #endif #ifdef QB_SOLARIS msg_recv.msg_accrights = 0; msg_recv.msg_accrightslen = 0; #else msg_recv.msg_flags = 0; #endif /* QB_SOLARIS */ iov_recv.iov_base = msg; iov_recv.iov_len = len; #ifdef SO_PASSCRED setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); #endif res = qb_ipc_us_recv_msghdr(sock, &msg_recv, msg, len); if (res < 0) { goto cleanup_and_return; } if (res != len) { res = -EIO; goto cleanup_and_return; } /* * currently support getpeerucred, getpeereid, and SO_PASSCRED credential * retrieval mechanisms for various Platforms */ #ifdef HAVE_GETPEERUCRED /* * Solaris and some BSD systems */ { ucred_t *uc = NULL; if (getpeerucred(sock, &uc) == 0) { res = 0; ugp->uid = ucred_geteuid(uc); ugp->gid = ucred_getegid(uc); ugp->pid = ucred_getpid(uc); ucred_free(uc); } else { res = -errno; } } #elif HAVE_GETPEEREID /* * Usually MacOSX systems */ { /* * TODO get the peer's pid. * c->pid = ?; */ if (getpeereid(sock, &ugp->uid, &ugp->gid) == 0) { res = 0; } else { res = -errno; } } #elif SO_PASSCRED /* * Usually Linux systems */ { struct ucred cred; struct cmsghdr *cmsg; res = -EINVAL; for (cmsg = CMSG_FIRSTHDR(&msg_recv); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg_recv, cmsg)) { if (cmsg->cmsg_type != SCM_CREDENTIALS) continue; memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred)); res = 0; ugp->pid = cred.pid; ugp->uid = cred.uid; ugp->gid = cred.gid; break; } } #else /* no credentials */ ugp->pid = 0; ugp->uid = 0; ugp->gid = 0; res = -ENOTSUP; #endif /* no credentials */ cleanup_and_return: #ifdef SO_PASSCRED setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off)); #endif return res; }