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では32ビットgid_t
でもあります)pid_t
他のシステム(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
struct passwd
これは正確なCレイアウト(「ABIレベル」ではなく「APIレベル」です)とは何の関係もありません。