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 수준"임) 과는 아무런 관련이 없습니다 .