Linux 和 OpenBSD 中 getsockopt SO_PEERCRED 的不同顺序

Linux 和 OpenBSD 中 getsockopt SO_PEERCRED 的不同顺序

我正在尝试在 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_t32 位)

其他系统(例如,solaris、FreeBSD)具有完全不同的界面 - 对于某些以“系统独立”方式获取对等凭据的代码,您可以查看update_client_creds()来自heimdal源代码的函数(使用getpeereid(3)OpenBSD和FreeBSD上的库函数而不是直接SO_PEERCREDLOCAL_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 级别”)。

相关内容