Python中的Unix套接字凭证传递

12 投票
2 回答
4244 浏览
提问于 2025-04-17 05:30

在Python中,如何实现Unix套接字的凭证传递?

2 个回答

2

这里是一个Python 3版本的Rakis的server.py,它不再使用固定的ID,并且可以显示客户端的用户和组名:

#!/usr/bin/env python
import os
import atexit
import grp
import pwd
import struct
from socket import socket, AF_UNIX, SOCK_STREAM, SOL_SOCKET, SO_PEERCRED

def remove_sock():
    try:
        os.unlink('/tmp/pass_cred')
    except FileNotFoundError:
        pass

remove_sock()
atexit.register(remove_sock)

s = socket(AF_UNIX, SOCK_STREAM)
s.bind('/tmp/pass_cred')
s.listen(1)

conn, addr = s.accept()

creds = conn.getsockopt(SOL_SOCKET, SO_PEERCRED, struct.calcsize('3i'))

pid, uid, gid = struct.unpack('3i',creds)

user_name = pwd.getpwuid(uid)[0]
group_name = grp.getgrgid(gid)[0]

print(f'pid={pid}, uid={uid}({user_name}), gid={gid}({group_name})')

此外,这个版本也进行了更新,使其可以重复使用(因为你不能把套接字绑定到一个已经存在的文件名,所以我们在绑定之前和正常退出后都会清理这个套接字)

23

关于这个话题,我在网上搜索时发现结果非常少。于是我决定在这里发布这个问题和答案,方便其他对这个话题感兴趣的人。

下面的客户端和服务器应用程序展示了如何在Linux上使用标准的python解释器来实现这个功能。你不需要任何额外的扩展,但由于使用了嵌入的常量,这段代码是特定于Linux的。

服务器:

#!/usr/bin/env python

import struct
from socket import socket, AF_UNIX, SOCK_STREAM, SOL_SOCKET

SO_PEERCRED = 17 # Pulled from /usr/include/asm-generic/socket.h

s = socket(AF_UNIX, SOCK_STREAM)

s.bind('/tmp/pass_cred')
s.listen(1)

conn, addr = s.accept()

creds = conn.getsockopt(SOL_SOCKET, SO_PEERCRED, struct.calcsize('3i'))

pid, uid, gid = struct.unpack('3i',creds)

print 'pid: %d, uid: %d, gid %d' % (pid, uid, gid)

客户端:

#!/usr/bin/env python

from socket import socket, AF_UNIX, SOCK_STREAM, SOL_SOCKET

SO_PASSCRED = 16 # Pulled from /usr/include/asm-generic/socket.h

s = socket(AF_UNIX, SOCK_STREAM)

s.setsockopt(SOL_SOCKET, SO_PASSCRED, 1)

s.connect('/tmp/pass_cred')

s.close()

不幸的是,python的socket模块没有导出SO_PEERCRED和SO_PASSCRED这两个常量,所以你需要手动输入它们。虽然这些值不太可能会改变,但也有这种可能性。任何使用这种方法的应用程序都应该考虑到这一点。

撰写回答