Search code examples
pythonwinapipermissionsaclntfs

Checking folder/file ntfs permissions using python


As the question title might suggest, I would very much like to know of the way to check the ntfs permissions of the given file or folder (hint: those are the ones you see in the "security" tab). Basically, what I need is to take a path to a file or directory (on a local machine, or, preferrably, on a share on a remote machine) and get the list of users/groups and the corresponding permissions for this file/folder. Ultimately, the application is going to traverse a directory tree, reading permissions for each object and processing them accordingly.

Now, I can think of a number of ways to do that:

  • parse cacls.exe output -- easily done, BUT, unless im missing something, cacls.exe only gives the permissions in the form of R|W|C|F (read/write/change/full), which is insufficient (I need to get the permissions like "List folder contents", extended permissions too)
  • xcacls.exe or xcacls.vbs output -- yes, they give me all the permissions I need, but they work dreadfully slow, it takes xcacls.vbs about ONE SECOND to get permissions on a local system file. Such speed is unacceptable
  • win32security (it wraps around winapi, right?) -- I am sure it can be handled like this, but I'd rather not reinvent the wheel

Is there anything else I am missing here?


Solution

  • Unless you fancy rolling your own, win32security is the way to go. There's the beginnings of an example here:

    http://timgolden.me.uk/python/win32_how_do_i/get-the-owner-of-a-file.html

    If you want to live slightly dangerously (!) my in-progress winsys package is designed to do exactly what you're after. It is available on pip:

    pip install winsys

    or you can just checkout the git repository:

    git clone https://github.com/tjguk/winsys.git winsys

    To do what you describe (guessing slightly at the exact requirements) you could do this:

    import codecs
    from winsys import fs
    
    base = "c:\\temp"
    with codecs.open("permissions.log", "wb", encoding="utf8") as log:
        for f in fs.flat(base):
            log.write("\n" + f.relative_to(base) + "\n")
        for ace in f.security().dacl:
            access_flags = fs.FILE_ACCESS.names_from_value(ace.access)
            log.write("  %s => %s\n" % (ace.trustee, ", ".join(access_flags)))
    

    TJG