def test_create_message(self): share = u'\\\\server\\shares\\%s' % UNICODE_TEXT message = DFSReferralRequestEx() message['max_referral_level'] = 4 message['request_flags'] = DFSReferralRequestFlags.SITE_NAME message['request_file_name'] = share message['site_name'] = UNICODE_TEXT expected = b"\x04\x00" \ b"\x01\x00" \ b"\x44\x00\x00\x00" \ b"\x30\x00" \ b"\x5C\x00\x5C\x00\x73\x00\x65\x00" \ b"\x72\x00\x76\x00\x65\x00\x72\x00" \ b"\x5C\x00\x73\x00\x68\x00\x61\x00" \ b"\x72\x00\x65\x00\x73\x00\x5C\x00" \ b"\x55\x00\x08\x03\x73\x00\x65\x00" \ b"\xDC\x04\x34\xD8\x1E\xDD\x00\x00" \ b"\x10\x00" \ b"\x55\x00\x08\x03\x73\x00\x65\x00" \ b"\xDC\x04\x34\xD8\x1E\xDD\x00\x00" actual = message.pack() assert len(message) == 76 assert actual == expected assert str(message['request_file_name']) == to_native(share) assert str(message['site_name']) == to_native(UNICODE_TEXT)
def __str__(self): struct_name = self.__class__.__name__ raw_hex = _bytes_to_hex(self.pack(), True, hex_per_line=0) field_strings = [] for name, field in self.fields.items(): # the field header is slightly different for a StructureField # remove the leading space and put the value on the next line if isinstance(field, StructureField): field_header = "%s =\n%s" else: field_header = "%s = %s" field_string = field_header % (field.name, str(field)) field_strings.append(_indent_lines(field_string, TAB)) field_strings.append("") field_strings.append(_indent_lines("Raw Hex:", TAB)) hex_wrapper = textwrap.TextWrapper( width=33, # set to show 8 hex values per line, 33 for 8, 56 for 16 initial_indent=TAB + TAB, subsequent_indent=TAB + TAB) field_strings.append(hex_wrapper.fill(raw_hex)) string = "%s:\n%s" % (to_native(struct_name), '\n'.join( [to_native(s) for s in field_strings])) return string
def __init__(self, ntstatus, filename, filename2=None): self.ntstatus = ntstatus self.filename2 = to_native(filename2) if filename2 else None ntstatus_name = 'STATUS_UNKNOWN' for name, val in vars(NtStatus).items(): if ntstatus == val: ntstatus_name = name break error_details = { NtStatus.STATUS_OBJECT_NAME_NOT_FOUND: errno.ENOENT, NtStatus.STATUS_OBJECT_PATH_NOT_FOUND: errno.ENOENT, NtStatus.STATUS_OBJECT_NAME_COLLISION: errno.EEXIST, NtStatus.STATUS_PRIVILEGE_NOT_HELD: (errno.EACCES, "Required privilege not held"), NtStatus.STATUS_SHARING_VIOLATION: (errno.EPERM, "The process cannot access the file because it is being " "used by another process"), NtStatus.STATUS_NOT_A_REPARSE_POINT: (errno.EINVAL, "The file or directory is not a reparse point"), NtStatus.STATUS_FILE_IS_A_DIRECTORY: errno.EISDIR, NtStatus.STATUS_NOT_A_DIRECTORY: errno.ENOTDIR, NtStatus.STATUS_DIRECTORY_NOT_EMPTY: errno.ENOTEMPTY, NtStatus.STATUS_END_OF_FILE: getattr(errno, 'ENODATA', 120), # Not present on py2 for Windows. }.get(ntstatus, (0, "Unknown NtStatus error returned '%s'" % ntstatus_name)) if not isinstance(error_details, tuple): error_details = (error_details, os.strerror(error_details)) super(SMBOSError, self).__init__(error_details[0], error_details[1], to_native(filename))
def message(self): # type: () -> str error_details = [] for detail in self.error_details: if isinstance(detail, SMB2SymbolicLinkErrorResponse): flag = str(detail['flags']) print_name = detail.get_print_name() sub_name = detail.get_substitute_name() error_details.append("Flag: %s, Print Name: %s, Substitute Name: %s" % (flag, print_name, sub_name)) elif isinstance(detail, SMB2ShareRedirectErrorContext): ip_addresses = [] for ip_addr in detail['ip_addr_move_list'].get_value(): ip_addresses.append(ip_addr.get_ipaddress()) resource_name = to_text(detail['resource_name'].get_value(), encoding='utf-16-le') error_details.append("IP Addresses: '%s', Resource Name: %s" % ("', '".join(ip_addresses), resource_name)) else: # unknown error details in response, output raw bytes error_details.append("Raw: %s" % to_text(binascii.hexlify(detail))) error_msg = '%s %s: 0x%s' % (self._BASE_MESSAGE, str(self.header['status']), format(self.status, 'x').zfill(8)) if error_details: error_msg += " - %s" % ", ".join(error_details) return to_native("Received unexpected status from the server: %s" % error_msg)
def test_create_message(self): message = FileNotifyInformation() message['action'] = 1 message['file_name'] = u"café" actual = message.pack() assert len(message) == 20 assert actual == self.DATA assert str(message['file_name']) == to_native(u"café")
def test_resolve_path_different_host(self): b_sub_name = to_bytes(u'\\??\\UNC\\sérver\\sharé2\\foldér', encoding='utf-16-le') b_print_name = to_bytes(u'\\\\sérver\\sharé2\\foldér', encoding='utf-16-le') resp = SMB2SymbolicLinkErrorResponse() resp['unparsed_path_length'] = 0 resp['substitute_name_offset'] = 0 resp['substitute_name_length'] = len(b_sub_name) resp['print_name_offset'] = len(b_sub_name) resp['print_name_length'] = len(b_print_name) resp['flags'] = SymbolicLinkErrorFlags.SYMLINK_FLAG_ABSOLUTE resp['path_buffer'] = b_sub_name + b_print_name link_path = u'\\\\sérver\\sharé\\foldér' expected = u"Encountered symlink at '%s' that points to '\\\\sérver\\sharé2\\foldér' which cannot be " \ u"redirected: Cannot resolve link targets that point to a different host/share" % link_path with pytest.raises(SMBLinkRedirectionError, match=re.escape(to_native(expected))): resp.resolve_path(link_path)
def message(self): msg = "Encountered symlink at '%s' that points to '%s' which cannot be redirected: %s" \ % (to_native(self.path), to_native(self.target), to_native(self.args[0])) return msg
def copyfile(src, dst, follow_symlinks=True, **kwargs): """ Copy the contents (no metadata) of the file names src to a file named dst and return dst in the most efficient way possible. If the src and dst reside on the same UNC share then a more efficient remote side copy is used. If the src and dst reside on the same local path then the proper shutil.copyfile() method is called, otherwise the content is copied using copyfileobj() in chunks. dst must be the complete target file name; look at copy() for a copy that accepts a target directory path. If src dst specify the same file, ValueError is raised. The destination location must be writable; otherwise, an OSError exception will be raised. If dst already exists, it will be replaced. Special files such as character or block devices and pipes cannot be copied with this function. If follow_symlinks is 'False' and src is a symbolic link, a new symbolic link will be created instead of copying the file src points to. This will fail if the symbolic link at src is a different root as dst. :param src: The src filepath to copy. :param dst: The destinoation filepath to copy to. :param follow_symlinks: Whether to copy the symlink target of source or the symlink itself. :param kwargs: Common arguments used to build the SMB Session for any UNC paths. :return: The dst path. """ def wrap_not_implemented(function_name): def raise_not_implemented(*args, **kwargs): raise NotImplementedError( "%s is unavailable on this platform as a local operation" % function_name) return raise_not_implemented norm_src = ntpath.normpath(src) if norm_src.startswith('\\\\'): src_root = ntpath.splitdrive(norm_src)[0] islink_func = islink readlink_func = readlink symlink_func = symlink src_open = open_file src_kwargs = kwargs else: src_root = None islink_func = os.path.islink # readlink and symlink are not available on Windows on Python 2. readlink_func = getattr(os, 'readlink', wrap_not_implemented('readlink')) symlink_func = getattr(os, 'symlink', wrap_not_implemented('symlink')) src_open = open src_kwargs = {} norm_dst = ntpath.normpath(dst) if norm_dst.startswith('\\\\'): dst_root = ntpath.splitdrive(norm_dst)[0] dst_open = open_file dst_kwargs = kwargs else: dst_root = None dst_open = open dst_kwargs = {} if not follow_symlinks and islink_func(src, **src_kwargs): if src_root != dst_root: raise ValueError("Cannot copy a symlink on different roots.") symlink_func(readlink_func(src), dst, **src_kwargs) return dst if src_root is None and dst_root is None: # The files are local and follow_symlinks is True, rely on the builtin copyfile mechanism. shutil.copyfile(src, dst) return dst if src_root == dst_root: # The files are located on the same share and follow_symlinks is True, rely on smbclient.copyfile for an # efficient server side copy. try: is_same = samefile(src, dst, **kwargs) except OSError as err: if err.errno == errno.ENOENT: is_same = False else: raise if is_same: raise shutil.Error( to_native("'%s' and '%s' are the same file, cannot copy" % (src, dst))) smbclient_copyfile(src, dst, **kwargs) return dst # Finally we are copying across different roots so we just chunk the data using copyfileobj with src_open(src, mode='rb', **src_kwargs) as src_fd, dst_open(dst, mode='wb', **dst_kwargs) as dst_fd: copyfileobj(src_fd, dst_fd, MAX_PAYLOAD_SIZE) return dst