async def create( self, path: Union[str, PureWindowsPath], session: SMBv2Session, tree_id: int, requested_oplock_level: OplockLevel = OplockLevel. SMB2_OPLOCK_LEVEL_BATCH, impersonation_level: ImpersonationLevel = ImpersonationLevel. IMPERSONATION, desired_access: Union[FilePipePrinterAccessMask, DirectoryAccessMask] = FilePipePrinterAccessMask( file_read_data=True, file_read_attributes=True), file_attributes: FileAttributes = FileAttributes(normal=True), share_access: ShareAccess = ShareAccess(read=True), create_disposition: CreateDisposition = CreateDisposition.FILE_OPEN, create_options: CreateOptions = CreateOptions(non_directory_file=True), create_context_list: CreateContextList = None ) -> AsyncContextManager[CreateResponse]: """ Create/open a file or directory in an SMB share and close it once finished with it. The default parameters reflect read only access to an existing file. :param path: The share relative path of the file or directory which to operate on. :param session: An SMB session with to access the file or directory. :param tree_id: The tree ID of the SMB share where the specified file or directory will be or is located. :param requested_oplock_level: :param impersonation_level: :param desired_access: :param file_attributes: :param share_access: :param create_disposition: :param create_options: :param create_context_list: :return: """ create_response: CreateResponse = (await self._create( path=path, session=session, tree_id=tree_id, requested_oplock_level=requested_oplock_level, impersonation_level=impersonation_level, desired_access=desired_access, file_attributes=file_attributes, share_access=share_access, create_disposition=create_disposition, create_options=create_options, create_context_list=create_context_list)) yield create_response await self.close(session=session, tree_id=tree_id, file_id=create_response.file_id)
async def create_dir( self, path: Union[str, PureWindowsPath], session: SMBv2Session, tree_id: int, requested_oplock_level: OplockLevel = OplockLevel. SMB2_OPLOCK_LEVEL_NONE, impersonation_level: ImpersonationLevel = ImpersonationLevel. IMPERSONATION, desired_access: DirectoryAccessMask = DirectoryAccessMask( file_list_directory=True, file_read_attributes=True), file_attributes: FileAttributes = FileAttributes(directory=True), share_access: ShareAccess = ShareAccess(read=True), create_disposition: CreateDisposition = CreateDisposition. FILE_OPEN, create_options: CreateOptions = CreateOptions(directory_file=True), create_context_list: CreateContextList = None): """ :param path: :param session: :param tree_id: :param requested_oplock_level: :param impersonation_level: :param desired_access: :param file_attributes: :param share_access: :param create_disposition: :param create_options: :param create_context_list: :return: """ create_response: CreateResponse = (await self._create( path=path, session=session, tree_id=tree_id, requested_oplock_level=requested_oplock_level, impersonation_level=impersonation_level, desired_access=desired_access, file_attributes=file_attributes, share_access=share_access, create_disposition=create_disposition, create_options=create_options, create_context_list=create_context_list)) yield create_response await self.close(session=session, tree_id=tree_id, file_id=create_response.file_id)
async def _create( self, path: Union[str, PureWindowsPath], tree_id: int, requested_oplock_level: OplockLevel = OplockLevel. SMB2_OPLOCK_LEVEL_BATCH, impersonation_level: ImpersonationLevel = ImpersonationLevel. IMPERSONATION, desired_access: Union[ FilePipePrinterAccessMask, DirectoryAccessMask] = FilePipePrinterAccessMask( file_read_data=True, file_read_ea=True, file_read_attributes=True), file_attributes: FileAttributes = FileAttributes(normal=True), share_access: ShareAccess = ShareAccess(read=True), create_disposition: CreateDisposition = CreateDisposition. FILE_OPEN, create_options: CreateOptions = CreateOptions( non_directory_file=True), create_context_list: CreateContextList = None) -> CreateResponse: create_context_list = create_context_list if create_context_list is not None else CreateContextList( ) if self.connection.negotiated_details.dialect is not Dialect.SMB_2_1: raise NotImplementedError create_response: CreateResponse = await self.connection._obtain_response( request_message=CreateRequest( header=SMB210SyncRequestHeader( command=SMBv2Command.SMB2_CREATE, session_id=self.session_id, tree_id=tree_id, ), requested_oplock_level=requested_oplock_level, impersonation_level=impersonation_level, desired_access=desired_access, file_attributes=file_attributes, share_access=share_access, create_disposition=create_disposition, create_options=create_options, name=str(path), create_context_list=create_context_list), sign_key=self.session_key) # TODO: I need to add stuff to some connection table, don't I? # TODO: Consider what to return from this function. There is a lot of information in the response. return create_response
async def make_smbv2_transport( self, session: SMBv2Session, # TODO: Is this the correct name? pipe: str, # TODO: This argument does not make much sense to me... server_address: Optional[Union[str, IPv4Address, IPv6Address]] = None, ): async with self.tree_connect( share_name='IPC$', session=session, server_address=server_address) as (tree_id, share_type): if share_type is not ShareType.SMB2_SHARE_TYPE_PIPE: # TODO: Use proper exception. raise ValueError create_options: Dict[str, Any] = dict( path=pipe, session=session, tree_id=tree_id, requested_oplock_level=OplockLevel.SMB2_OPLOCK_LEVEL_NONE, desired_access=FilePipePrinterAccessMask(file_read_data=True, file_write_data=True), file_attributes=FileAttributes(normal=True), share_access=ShareAccess(), create_disposition=CreateDisposition.FILE_OPEN, create_options=CreateOptions(non_directory_file=True)) async with self.create(**create_options) as create_response: yield ( partial( self.read, file_id=create_response.file_id, # TODO: Not sure about this value. file_size=self.negotiated_details.max_read_size, session=session, tree_id=tree_id, use_generator=False), partial(self.write, file_id=create_response.file_id, session=session, tree_id=tree_id, offset=0, remaining_bytes=0, flags=WriteFlag()))
async def dump_reg( rpc_connection: RPCConnection, smb_session: SMBv2Session, root_key_handle: bytes, tree_id: int, sub_key_name: str, save_path: Optional[PureWindowsPath] = None, sam_desired: Regsam = Regsam(maximum_allowed=True), delete_file_on_close: bool = True ) -> bytes: save_path = save_path or PureWindowsPath(f'C:\\Windows\\Temp\\{uuid4()}') base_reg_open_key_options = dict( rpc_connection=rpc_connection, request=BaseRegOpenKeyRequest(key_handle=root_key_handle, sub_key_name=sub_key_name, sam_desired=sam_desired) ) async with base_reg_open_key(**base_reg_open_key_options) as lsa_key_handle: await base_reg_save_key( rpc_connection=rpc_connection, request=BaseRegSaveKeyRequest( key_handle=lsa_key_handle, save_path=save_path ) ) create_kwargs = dict( path=PureWindowsPath(*save_path.parts[1:]), tree_id=tree_id, create_options=CreateOptions(non_directory_file=True, delete_on_close=delete_file_on_close), desired_access=FilePipePrinterAccessMask(file_read_data=True, delete=delete_file_on_close) ) async with smb_session.create(**create_kwargs) as create_response: return await smb_session.read( file_id=create_response.file_id, file_size=create_response.endof_file, tree_id=tree_id )