我有一个程序在监听Unix域套接字。
当客户端连接到套接字时,我想找出是哪个程序连接的,然后根据用户/组设置决定是否允许连接。
在Linux下是否可能实现这一点,如果可以,如何实现?
我有一个程序在监听Unix域套接字。
当客户端连接到套接字时,我想找出是哪个程序连接的,然后根据用户/组设置决定是否允许连接。
在Linux下是否可能实现这一点,如果可以,如何实现?
在Linux下是可以实现这个的,但是这种方法不太具有可移植性。它是通过使用"ancillary data"以及sendmsg
/ recvmsg
实现的。
setsockopt
和SO_PASSCRED
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
参数将是您想要标识的客户端进程的文件描述符,而且我发现我需要从客户端进行至少一次数据读取,否则在ucred
结构中我会得到未定义的值。 - Username Obfuscation也许 getpeername 或者 getsockname 可以帮助你。我认为你的 unix socket 的权限是有用的(不太确定)。如果你的 accept
的 socket 是 12,你可以读取 /proc/self/fd/12
中的链接。
编辑
如cnicutar所建议的那样,使用辅助数据获取凭证和 sendmsg
更好。