Consider the following code inspired by https://gist.github.com/jborean93/c4d8db1db14297de1c9a268084e89d36 to get DACL of file or folder:
import os
import smbclient
from smbprotocol.file_info import (
InfoType,
)
from smbprotocol.open import (
Open,
DirectoryAccessMask,
FilePipePrinterAccessMask,
SMB2QueryInfoRequest,
SMB2QueryInfoResponse,
InfoAdditionalInformation,
)
from smbprotocol.security_descriptor import (
SMB2CreateSDBuffer,
)
# Not needed when using Kerberos auth, can also be set as kwargs when calling open_file.
smbclient.ClientConfig(username=os.environ["USER"], password=os.environ["PASSWORD"])
def get_sd(fd: Open, info: int) -> SMB2CreateSDBuffer:
""" Get the Security Descriptor for the opened file. """
query_req = SMB2QueryInfoRequest()
query_req['info_type'] = InfoType.SMB2_0_INFO_SECURITY
query_req['output_buffer_length'] = 65535
query_req['additional_information'] = info
query_req['file_id'] = fd.file_id
req = fd.connection.send(query_req, sid=fd.tree_connect.session.session_id, tid=fd.tree_connect.tree_connect_id)
resp = fd.connection.receive(req)
query_resp = SMB2QueryInfoResponse()
query_resp.unpack(resp['data'].get_value())
security_descriptor = SMB2CreateSDBuffer()
security_descriptor.unpack(query_resp['buffer'].get_value())
return security_descriptor
# File example
with smbclient.open_file(
r'\\path\to\nas\file.txt',
mode='rb',
buffering=0,
file_type="file",
desired_access=FilePipePrinterAccessMask.READ_CONTROL) as file:
sd = get_sd(file.fd, InfoAdditionalInformation.OWNER_SECURTIY_INFORMATION | InfoAdditionalInformation.DACL_SECURITY_INFORMATION)
for ace in sd.get_dacl()['aces']:
print(str(ace["mask"]), ace["mask"].flag_type)
# Dir example
with smbclient.open_file(
r"\\path\to\nas\folder",
mode='br',
buffering=0,
file_type='dir',
desired_access=DirectoryAccessMask.READ_CONTROL
) as file:
sd = get_sd(file.fd, InfoAdditionalInformation.OWNER_SECURTIY_INFORMATION | InfoAdditionalInformation.DACL_SECURITY_INFORMATION)
for ace in sd.get_dacl()['aces']:
print(str(ace["mask"]), ace["mask"].flag_type)
(1179817) READ_CONTROL, SYNCHRONIZE <class 'smbprotocol.security_descriptor.AccessMask'>
(2032127) DELETE, READ_CONTROL, SYNCHRONIZE, WRITE_DACL, WRITE_OWNER, __firstlineno__ <class 'smbprotocol.security_descriptor.AccessMask'>
(2032127) DELETE, READ_CONTROL, SYNCHRONIZE, WRITE_DACL, WRITE_OWNER, __firstlineno__ <class 'smbprotocol.security_descriptor.AccessMask'>
(1179817) READ_CONTROL, SYNCHRONIZE <class 'smbprotocol.security_descriptor.AccessMask'>
(2032127) DELETE, READ_CONTROL, SYNCHRONIZE, WRITE_DACL, WRITE_OWNER, __firstlineno__ <class 'smbprotocol.security_descriptor.AccessMask'>
(1179817) READ_CONTROL, SYNCHRONIZE <class 'smbprotocol.security_descriptor.AccessMask'>
(1179817) READ_CONTROL, SYNCHRONIZE <class 'smbprotocol.security_descriptor.AccessMask'>
(2032127) DELETE, READ_CONTROL, SYNCHRONIZE, WRITE_DACL, WRITE_OWNER, __firstlineno__ <class 'smbprotocol.security_descriptor.AccessMask'>
(2032127) DELETE, READ_CONTROL, SYNCHRONIZE, WRITE_DACL, WRITE_OWNER, __firstlineno__ <class 'smbprotocol.security_descriptor.AccessMask'>
(2032127) DELETE, READ_CONTROL, SYNCHRONIZE, WRITE_DACL, WRITE_OWNER, __firstlineno__ <class 'smbprotocol.security_descriptor.AccessMask'>
I notice that ACE mask has_flag type AccessMask. Some ACE have a value with some bits undefined in AccessMask. For example, 2032127 is 0x1f01ff or 0b111110000000111111111. There is no mask defined for the right-hand side of this number in AccessMask.
The docstring of AccessMask says:
32-bit set of flags that are used to encode the user rights to an object.
This is just a generic setup of access mask flags to set an can vary
from the object being set. When setting the AccessMask on an ACE packet,
any 32-bit value can be used and this is just as a guideline.
But, I wonder if the flag_type of ace["mask"] shouldn't be instead FilePipePrinterAccessMask for a file and DirectoryAccessMask for a directory? These appear to be a subset of AccessMask but define more flags.
|
class AccessMask: |
|
""" |
|
[MS-DTYP] |
|
|
|
2.4.3 ACCESS_MASK |
|
32-bit set of flags that are used to encode the user rights to an object. |
|
This is just a generic setup of access mask flags to set an can vary |
|
from the object being set. When setting the AccessMask on an ACE packet, |
|
any 32-bit value can be used and this is just as a guideline. |
|
""" |
|
|
|
GENERIC_READ = 0x80000000 |
|
GENERIC_WRITE = 0x40000000 |
|
GENERIC_EXECUTE = 0x20000000 |
|
GENERIC_ALL = 0x10000000 |
|
MAXIMUM_ALLOWED = 0x02000000 |
|
ACCESS_SYSTEM_SECURITY = 0x01000000 |
|
SYNCHRONIZE = 0x00100000 |
|
WRITE_OWNER = 0x00080000 |
|
WRITE_DACL = 0x00040000 |
|
READ_CONTROL = 0x00020000 |
|
DELETE = 0x00010000 |
Consider the following code inspired by https://gist.github.com/jborean93/c4d8db1db14297de1c9a268084e89d36 to get DACL of file or folder:
I notice that ACE mask has_flag type
AccessMask. Some ACE have a value with some bits undefined in AccessMask. For example,2032127is0x1f01ffor0b111110000000111111111. There is no mask defined for the right-hand side of this number inAccessMask.The docstring of
AccessMasksays:But, I wonder if the flag_type of
ace["mask"]shouldn't be insteadFilePipePrinterAccessMaskfor a file andDirectoryAccessMaskfor a directory? These appear to be a subset ofAccessMaskbut define more flags.smbprotocol/src/smbprotocol/security_descriptor.py
Lines 18 to 39 in d857cbf