Return a nested tuple of (uid, (gids)) for a UNIX domain socket, on FreeBSD. This is useful for access control on local servers, which can limit access based on the ID of the connecting user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import struct
def getpeerid(sock):
""" Get peer credentials on a UNIX domain socket.
Returns a nested tuple: (uid, (gids)) """
LOCAL_PEERCRED = 0x001
NGROUPS = 16
#struct xucred {
# u_int cr_version; /* structure layout version */
# uid_t cr_uid; /* effective user id */
# short cr_ngroups; /* number of groups */
# gid_t cr_groups[NGROUPS]; /* groups */
# void *_cr_unused1; /* compatibility with old ucred */
#};
xucred_fmt = '2ih16iP'
res = tuple(struct.unpack(xucred_fmt, sock.getsockopt(0, LOCAL_PEERCRED, struct.calcsize(xucred_fmt))))
# Check this is the above version of the structure
if res[0] != 0:
raise OSError
return (res[1], res[3:3+res[2]])
|
UNIX domain sockets are great for communication with local servers because they are fast, and support credential passing: one end of the socket can identify the user ID and group IDs of the other party. This is useful for services that need to limit privileged access to certain users or groups.
Python does not provide an interface to this OS feature. The usual method for credential passing is to use the sendmsg/recvmsg system calls, but these are not exported by the socket module. However at least on some UNIX systems (FreeBSD, Linux, ...) there is an alternate interface using socket options. Unfortunately the interfaces are OS-specific. This is the FreeBSD interface; it would not be difficult for someone to add Linux support.