[python-win32] python-win32 Digest, Vol 162, Issue 4

eryk sun eryksun at gmail.com
Fri Sep 23 10:12:03 EDT 2016


On Fri, Sep 23, 2016 at 10:39 AM, Goku Balu <tfa.signup.test1 at gmail.com> wrote:
> On Tue, Sep 20, 2016 at 9:30 PM, <python-win32-request at python.org> wrote:
>> >
>> > That doesn't seem like a bug to me. GENERIC_WRITE represents several
>> > permissions mashed together, including FILE_WRITE and read control.
>> >
>> > Perhaps try with just FILE_WRITE on its own?
>>
>> For a file or directory, GENERIC_WRITE (0x80000000) gets mapped to
>> FILE_GENERIC_WRITE, which includes the following standard rights
>> (upper 16 bits):
>>
>>     SYNCHRONIZE  = 0x00100000
>>     READ_CONTROL = 0x00020000
>>
>> and File-object specific rights (lower 16 bits):
>>
>>     FILE_WRITE_ATTRIBUTES = 0x00000100
>>     FILE_WRITE_EA         = 0x00000010
>>     FILE_APPEND_DATA      = 0x00000004
>>     FILE_WRITE_DATA       = 0x00000002
>>
>> The relevant access right that's being denied in this case is SYNCHRONIZE.
>
> So if we deny WRITE then SYNCHRONIZE will be denied which will in-turn
> affect READ. Is there a way to deny WRITE alone without affecting
> file/folder read?

Each kernel object type has a GENERIC_MAPPING that maps generic rights
to sets of standard and object-specific rights. Before doing an
AccessCheck, generic rights have to be mapped to specific rights via
MapGenericMask.

For the File type this generic mapping consists of the following values:

        FILE_GENERIC_READ
        FILE_GENERIC_WRITE
        FILE_GENERIC_EXECUTE
        FILE_ALL_ACCESS

If you deny GENERIC_WRITE for a File, that's the same as denying the 6
rights in FILE_GENERIC_WRITE, which includes the standard SYNCHRONIZE
and READ_CONTROL rights. You need to mask the value to filter out
rights that shouldn't be denied. Use the constant SPECIFIC_RIGHTS_ALL,
which is defined as 0xFFFF (i.e. the lower 16 bits of an access mask
are reserved for object-specific rights). For example:

    import win32security
    import ntsecuritycon

    WORLD = win32security.CreateWellKnownSid(win32security.WinWorldSid)

    FILE_WRITE = (ntsecuritycon.FILE_GENERIC_WRITE &
                  ntsecuritycon.SPECIFIC_RIGHTS_ALL)

    def deny_write(filename, account=None, ace_flags=0):
        sd = win32security.GetFileSecurity(
            filename, win32security.DACL_SECURITY_INFORMATION)
        sid = WORLD if account is None else (
                win32security.LookupAccountName(None, account)[0])
        dacl = sd.GetSecurityDescriptorDacl()
        dacl.AddAccessDeniedAceEx(
            win32security.ACL_REVISION_DS, ace_flags, FILE_WRITE, sid)
        sd.SetSecurityDescriptorDacl(1, dacl, 0)
        win32security.SetFileSecurity(
            filename, win32security.DACL_SECURITY_INFORMATION, sd)

For a directory, generic write access entails the ability to write
attributes and add files and subdirectories. Note that file delete
rights are separately controlled by standard DELETE access and the
specific directory right FILE_DELETE_CHILD, which is the right to
delete files or subdirectories of a directory, even if the user is
otherwise denied or not granted DELETE access.

The ace_flags parameter allows controlling whether the ACE is
inherited by subdirectories and files (CONTAINER_INHERIT_ACE,
OBJECT_INHERIT_ACE) , whether the inheritance flags get propagated
(NO_PROPAGATE_INHERIT_ACE), and whether the ACE applies only for
inheritance (INHERIT_ONLY_ACE).


More information about the python-win32 mailing list