我需要打开一个系统文件并从中读取内容。这个文件通常只有root(超级用户)才能读取。我有一种方法可以要求用户输入超级用户密码。我想使用这些凭据打开文件并从中读取内容,而不必将整个程序运行为超级用户进程。是否有一种跨平台的方法实现这个功能?
我需要打开一个系统文件并从中读取内容。这个文件通常只有root(超级用户)才能读取。我有一种方法可以要求用户输入超级用户密码。我想使用这些凭据打开文件并从中读取内容,而不必将整个程序运行为超级用户进程。是否有一种跨平台的方法实现这个功能?
sudo
读取文件的内容。由于特权在类Unix系统和Windows上的工作方式完全不同,因此您需要具有特定于平台的代码。无论如何,您都需要将程序分为两个单独的程序,其中一个以提升的权限运行,另一个以标准/降低的权限运行。
在类Unix系统(包括Linux和Mac OS X)中,以提升权限运行的可执行文件应该执行以下操作:
setreuid(2)
和setregid(2)
将用户ID和组ID设置回非特权用户。exec(3)
函数来执行非特权可执行文件。sudo
即可运行,则将其所有者设置为root,并使用chown root the-program; chmod +s the-program
将其设置为设置用户ID可执行文件。非特权程序现在将以普通权限运行,但是当它启动时,它将具有一个可以用于从您的特殊文件中读取的打开文件描述符(文件描述符#3)。
对于Windows来说,它类似但略有不同:CreateFile
打开文件进行读取。不要使用默认安全属性 - 创建一个SECURITY_ATTRIBUTES
结构,将bInheritHandle
设置为TRUE
,以便句柄将被子进程继承。如果打开文件失败,请打印错误消息并退出。CreateProcess
启动子进程。在命令行上传递上面的句柄(例如,作为数字值打印);您也可以使用共享内存区域,但这比解决此问题更麻烦。requireAdministrator
设置为true
。完成后,运行程序时,您将收到一个UAC提示,询问您是否允许该程序进行更改。read(2)
,Windows上的ReadFile
)从中读取--您不能使用更高级别的函数,如C的fread(3)
或C ++的iostream
(好吧,Unix有fdopen(3)
,但据我所知,Windows上没有相应的函数)。正如您现在已经注意到的那样,以上所有内容都是用C编写的。在Unix中,这很容易转换为Python,因为os
模块拥有许多好东西,如setreuid
、exec*
和fdopen
。在Windows上,您可能可以使用ctypes
模块和/或Pywin32来完成其中一些工作,但最好还是使用C。在Linux上,这非常简单,就像@ViktorKerkez展示的那样。这是我如何流式传输我的WiFi密码文件(仅限root/sudo读取):
import subprocess
import sys
# substitute your Windoze/DOS/PowerlessShell command here:
cat_wifi_pws = 'sudo cat /etc/NetworkManager/system-connections/*'
process = subprocess.Popen(cat_wifi_pws, stdout=subprocess.PIPE, shell=True)
# read one line at a time, as it becomes available
for line in iter(process.stdout.readline, ''):
sys.stdout.write(line)
当然,这将提示您输入sudo密码。如果您的系统有gksudo并且您喜欢对话框,则可以使用它。作为奖励,如果在/etc/sudoers
中有一个合适的timeout_default
,并且您最近在启动Python解释器的同一Shell中运行了sudo,则根本不需要输入密码。