【问题标题】:How do I check another user's file permissions in python?如何在 python 中检查另一个用户的文件权限?
【发布时间】:2021-03-04 03:49:21
【问题描述】:

在 python 中,我可以检查我自己的用户是否可以使用os.access 访问文件或目录。但是,是否可以检查其他用户是否可以这样做?

一种可能性是根据文件的权限检查用户的 uid 和组:

import os, grp, pwd, stat
def user_access(uid, path, perms=os.R_OK | os.W_OK):
    stats = os.stat(path)
    # other users
    if stats.st_mode & perms == perms:
        return True
    # owner
    if stats.st_uid == uid and (stats.st_mode >> 6) & perms == perms:
        return True
    # group
    user = pwd.getpwuid(uid).pw_name
    if (stats.st_mode >> 3) & perms == perms and user in grp.getgrgid(stats.st_gid).gr_mem:
         return True
    return False
        

但是,我想这是特定于 POSIX 系统的,我可以想象它会在某些极端情况下失败。事实上,access 上的 libc manual 专门警告反对这个解决方案:

还有另一种方法可以检查此访问,即...检查文件模式位并模拟系统自己的访问计算。这种方法是不可取的,因为许多系统都有额外的访问控制功能;您的程序无法移植地模仿它们,并且您不想尝试跟踪不同系统具有的各种功能。使用 access 很简单,并且会自动执行适合您使用的系统的任何操作。

是否有更简洁和/或更强大的解决方案来检查其他用户的访问权限?

2020 年 12 月 9 日编辑:修复了位旋转的错误。

【问题讨论】:

    标签: python cross-platform posix file-permissions


    【解决方案1】:

    我想出了一个错误的答案。基本上,你使用os.setuid切换用户,然后在文件上使用os.access。

    import multiprocessing as mp
    def user_access_mp(uid, path, perms=os.R_OK | os.W_OK):
        def disguise():
            os.setuid(uid)
            allowed = os.access(path, perms)
            exit(int(allowed))
    
        p = mp.Process(target=disguise)
        p.start()
        p.join()
        assert p.exitcode in (0, 1)  # other values indicate unexpected signals
        return bool(p.exitcode)
    

    不幸的是,这 (1) 必须以 root 身份完成,(2) 需要分叉,因为无法将 setuid 恢复为原始用户,并且 (3) 很慢。

    此外,它甚至无法在我关心的系统(使用 LDAP 的 RHEL 服务器)上始终如一地工作。在这种情况下,对于我属于该组的某些文件,我得到“假”。这很可能是因为系统对组使用 LDAP,因此某些组不会出现在用户的组列表中。可以使用 C API 绕过这个问题(就像修复 grp.getgrall() 所做的那样),但我还没有测试过。无论如何,以 root 身份运行的要求严重限制了此解决方案。

    【讨论】:

    • POSIX 在权限方面非常有限,因为不同系统实现访问控制的方式存在巨大差异。您可以使用setresuid() 避免分叉,您可以使用setresgid() 更改为用户的默认组。如果您是 root 用户,则可以以用户身份登录(类似于 su -c 'test -r myfile.txt' - otheruser 的 execve
    • @root 不错。看起来如果我在保持有效 uid 0 (setresuid(500, 0, 0)) 的同时更改真实 uid,那么 os.access 可以正常工作,但我可以改回 root。但是,LDAP 组仍然损坏。
    【解决方案2】:

    我以前从未真正尝试过,但如果它有效,请告诉我:

    import os
    import stat
    
    def isgroupreadable(filepath):
      st = os.stat(filepath)
      return bool(st.st_mode & stat.S_IRGRP)
    

    如果你想打印这个,你可以在最后添加:

    打印(组可读(文件路径))

    【讨论】:

    • 这大致相当于我的行stats.st_mode & (perms << 6) != 0。它只是从模式行中提取 group-r 位(040)。您仍然需要检查其他用户是否属于该组,并对 stat.S_IRUSR、stat.IROTH 等执行相同操作。
    猜你喜欢
    • 2015-02-10
    • 2015-06-13
    • 1970-01-01
    • 2010-12-24
    • 2015-10-09
    • 2018-02-14
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多