ssize_t send_unix_creds(int sd) { struct iovec vec; struct msghdr msg; struct cmsghdr *cmsg; char dummy = 'm'; char buf[CMSG_SPACE(sizeof(struct ucred))]; struct ucred *uptr; memset(&msg, 0, sizeof(msg)); vec.iov_base = &dummy; vec.iov_len = 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_control = buf; msg.msg_controllen = sizeof(buf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_CREDS; cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); uptr = (struct ucred *)CMSG_DATA(cmsg); SPC_PEER_UID(uptr) = getuid(); SPC_PEER_GID(uptr) = getgid(); #ifdef linux uptr->pid = getpid(); #endif msg.msg_controllen = cmsg->cmsg_len; return (sendmsg(sd, &msg, 0) != -1); }
int get_creds( int sd, char *username, char *hostname) { int nb/*, sync*/; char ctrl[CMSG_SPACE(sizeof(struct ucred))]; size_t size; struct iovec iov[1]; struct msghdr msg; struct cmsghdr *cmptr; ucreds *credentials; struct passwd *cpwd; char dummy; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = ctrl; msg.msg_controllen = sizeof(ctrl); msg.msg_flags = 0; #ifdef LOCAL_CREDS nb = 1; if (setsockopt(sd, 0, LOCAL_CREDS, &nb, sizeof(nb)) == -1) return 0; #else #ifdef SO_PASSCRED nb = 1; if (setsockopt(sd, SOL_SOCKET, SO_PASSCRED, &nb, sizeof(nb)) == -1) return 0; #endif dummy = '\0'; do { msg.msg_iov->iov_base = (void *) & dummy; msg.msg_iov->iov_len = sizeof(dummy); nb = recvmsg(sd, &msg, 0); } while (nb == -1 && (errno == EINTR || errno == EAGAIN)); if (nb == -1) return 0; if ((unsigned)msg.msg_controllen < sizeof(struct cmsghdr)) return 0; cmptr = CMSG_FIRSTHDR(&msg); #ifndef __NetBSD__ size = sizeof(ucreds); #else if (cmptr->cmsg_len < SOCKCREDSIZE(0)) return(0); size = SOCKCREDSIZE(((cred *)CMSG_DATA(cmptr))->sc_ngroups); #endif if ((unsigned)cmptr->cmsg_len != CMSG_LEN(size)) return(0); if (cmptr->cmsg_level != SOL_SOCKET) return 0; if (cmptr->cmsg_type != SCM_CREDS) return 0; if (!(credentials = (ucreds *)calloc(1, size))) return 0; *credentials = *(ucreds *)CMSG_DATA(cmptr); cpwd = getpwuid(SPC_PEER_UID(credentials)); if (cpwd) strcpy(username, cpwd->pw_name); strcpy(hostname, server_name); free(credentials); return 0; }