我正在尝试在 python 中获取 Unix 套接字对等凭据。
我正在使用这段代码:
peercred = conn.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, struct.calcsize("3i"))
pid, uid, gid = struct.unpack("3i", peercred)
这在 Linux 中工作正常,但在 OpenBSD 中顺序不同。在 OpenBsd 中,顺序是[uid, gid, pid]
相反的。
是什么造成了这种差异?我如何知道何时使用哪个订单?
我尝试的linux系统运行在x86_64架构上,而openbsd系统运行在amd64架构上。
答案1
我不是 python 程序员,但我想你应该对基于sys.platform
.
SO_PEERCRED
不是标准化接口,实际结构/二进制接口在系统之间是不同的。
在 Linux 上,定义如下/usr/include/bits/socket.h
:
struct ucred {
__u32 pid;
__u32 uid;
__u32 gid;
};
在 OpenBSD 上,定义如下/usr/include/sys/socket.h
:
struct sockpeercred {
uid_t uid; /* effective user id */
gid_t gid; /* effective group id */
pid_t pid;
};
(uid_t
,在 OpenBSD 上gid_t
也是pid_t
32 位)
其他系统(例如,solaris、FreeBSD)具有完全不同的界面 - 对于某些以“系统独立”方式获取对等凭据的代码,您可以查看update_client_creds()来自heimdal源代码的函数(使用getpeereid(3)
OpenBSD和FreeBSD上的库函数而不是直接SO_PEERCRED
或LOCAL_PEERCRED
)。
无论如何,通过这种方式获得的凭据将是调用套接字的进程(可能不再存在的进程)的凭据connect(2)
,listen(2)
而不一定是通过写入或读取套接字实际使用套接字的进程的凭据。
答案2
您可以使用cffi
“API 级别”方法。这需要 C 编译器,尽管可以在兼容系统上进行编译,然后重新使用结果。
https://cffi.readthedocs.io/en/latest/overview.html#api-mode-calling-the-c-standard-library
请注意,这与确切的 C 布局无关
struct passwd
(它是“API 级别”,而不是“ABI 级别”)。