【发布时间】:2011-12-27 15:23:38
【问题描述】:
我有一个程序正在侦听 Unix 域套接字。
当客户端连接到套接字时,我想找出连接的程序,然后决定是否允许连接(基于用户/组设置)。
这在 Linux 下是否可行,如果可以,如何实现?
【问题讨论】:
标签: linux unix-socket
我有一个程序正在侦听 Unix 域套接字。
当客户端连接到套接字时,我想找出连接的程序,然后决定是否允许连接(基于用户/组设置)。
这在 Linux 下是否可行,如果可以,如何实现?
【问题讨论】:
标签: linux unix-socket
是的,这在 Linux 上是可能的,但它的可移植性不是很好。它是通过sendmsg / recvmsg 使用所谓的“辅助数据”来实现的。
SO_PASSCRED 和setsockopt
SCM_CREDENTIALS 和struct ucred 结构这个结构是在Linux中定义的:
struct ucred {
pid_t pid; /* process ID of the sending process */
uid_t uid; /* user ID of the sending process */
gid_t gid; /* group ID of the sending process */
};
请注意,您必须在msghdr.control 中填写这些内容,内核将检查它们是否正确。
主要的可移植性障碍是这种结构在其他 Unix 上有所不同 - 例如在 FreeBSD 上:
struct cmsgcred {
pid_t cmcred_pid; /* PID of sending process */
uid_t cmcred_uid; /* real UID of sending process */
uid_t cmcred_euid; /* effective UID of sending process */
gid_t cmcred_gid; /* real GID of sending process */
short cmcred_ngroups; /* number or groups */
gid_t cmcred_groups[CMGROUP_MAX]; /* groups */
};
【讨论】:
我对此进行了相当多的搜索,因此我将向您展示如何在套接字sock 上使用 SO_PEERCRED 来获取套接字对等方的 pid/uid/gid:
int len;
struct ucred ucred;
len = sizeof(struct ucred);
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) {
//getsockopt failed
}
printf("Credentials from SO_PEERCRED: pid=%ld, euid=%ld, egid=%ld\n",
(long) ucred.pid, (long) ucred.uid, (long) ucred.gid);
【讨论】:
sendmsg 和recvmsg,而这根本不属实。我将补充一点,给出的示例中的sock 参数将是您要识别的客户端进程的文件描述符,并且我发现我需要从客户端执行至少一个read() 的数据,否则我得到ucred 结构中的未定义值。
_GNU_SOURCE。临时来源:github.com/apple/cups/issues/2860
也许getpeername 或getsockname 会有所帮助。而且我认为您的unix socket 的许可很有用(不确定)。如果您的 accept-ed 套接字是 12,您可能会阅读 /proc/self/fd/12 中的链接。
编辑
使用辅助数据作为凭据和sendmsg 会更好,如下cnicutar 所建议。
【讨论】: