def set_name(self, substitute_name, print_name): b_substitute_name = to_bytes(to_text(substitute_name), encoding='utf-16-le') b_print_name = to_bytes(to_text(print_name), encoding='utf-16-le') self['substitute_name_offset'] = 0 self['substitute_name_length'] = len(b_substitute_name) self['print_name_offset'] = len(b_substitute_name) self['print_name_length'] = len(b_print_name) self['buffer'] = b_substitute_name + b_print_name
def _get_packed_size(self): text_value = self._get_calculated_value(self.value) size = len(to_bytes(text_value, encoding=self.encoding)) if self.null_terminated: char_len = len("\x00".encode(self.encoding)) size += char_len return size
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 test_resolve_path(self, unparsed_length, sub_name, print_name, flags, link_path, expected): b_sub_name = to_bytes(sub_name, encoding='utf-16-le') b_print_name = to_bytes(print_name, encoding='utf-16-le') resp = SMB2SymbolicLinkErrorResponse() resp['unparsed_path_length'] = unparsed_length 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'] = flags resp['path_buffer'] = b_sub_name + b_print_name assert resp.get_print_name() == print_name assert resp.get_substitute_name() == sub_name actual = resp.resolve_path(link_path) assert actual == expected
def set_name(self, print_name, substitute_name): """ Set's the path_buffer and print/substitute name length of the message with the values passed in. These values should be a string and not a byte string as it is encoded in this function. :param print_name: The print name string to set :param substitute_name: The substitute name string to set """ # Ensure that the to_bytes input is an actual text string for py2 compat with native strings. print_bytes = to_bytes(to_text(print_name), encoding='utf-16-le') sub_bytes = to_bytes(to_text(substitute_name), encoding='utf-16-le') path_buffer = print_bytes + sub_bytes self['print_name_offset'].set_value(0) self['print_name_length'].set_value(len(print_bytes)) self['substitute_name_offset'].set_value(len(print_bytes)) self['substitute_name_length'].set_value(len(sub_bytes)) self['path_buffer'].set_value(path_buffer)
def test_native_to_bytes(): # Python 3 the default string type is unicode so the expected value will # be "abc" in UTF-16 form while Python 2 "abc" is the bytes representation # already if PY3: expected = b"\x61\x00\x62\x00\x63\x00" else: expected = b"\x61\x62\x63" actual = to_bytes("abc", encoding='utf-16-le') assert actual == expected
def test_create_message(self): message = SymbolicLinkReparseDataBuffer() message['substitute_name_offset'] = 8 message['substitute_name_length'] = 16 message['print_name_offset'] = 0 message['print_name_length'] = 8 message['flags'] = SymbolicLinkFlags.SYMLINK_FLAG_RELATIVE message['buffer'] = to_bytes(u"café\\??\\café", encoding='utf-16-le') actual = message.pack() assert len(message) == 36 assert actual == self.DATA
def test_parse_message(self): actual = SymbolicLinkReparseDataBuffer() data = actual.unpack(self.DATA) assert data == b"" assert len(actual) == 36 assert actual['substitute_name_offset'].get_value() == 8 assert actual['substitute_name_length'].get_value() == 16 assert actual['print_name_offset'].get_value() == 0 assert actual['print_name_length'].get_value() == 8 assert actual['flags'].get_value( ) == SymbolicLinkFlags.SYMLINK_FLAG_RELATIVE assert actual['buffer'].get_value() == to_bytes(u"café\\??\\café", encoding='utf-16-le') assert actual.get_substitute_name() == u"\\??\\café" assert actual.get_print_name() == u"café"
def resolve_path(self, link_path): """ [MS-SMB2] 2.2.2.2.1.1 Handling the Symbolic Link Error Response https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/a8da655c-8b0b-415a-b726-16dc33fa5827 Attempts to resolve the link target path. Will fail if the link is pointing to a local path or a UNC path on another host or share. :param link_path: The original path to the symbolic link to resolve relative paths from. :return: The resolved link target path. """ substitute_name = self.get_substitute_name() print_name = self.get_print_name() unparsed_path_length = self['unparsed_path_length'].get_value() b_link_path = to_bytes(to_text(link_path), encoding='utf-16-le') unparsed_idx = len(b_link_path) - unparsed_path_length base_link_path = to_text(b_link_path[:unparsed_idx], encoding='utf-16-le') unparsed_path = to_text(b_link_path[unparsed_idx:], encoding='utf-16-le') # Use the common code in SymbolicLinkReparseDataBuffer() to resolve the link target. symlink_buffer = SymbolicLinkReparseDataBuffer() symlink_buffer['flags'] = self['flags'].get_value() symlink_buffer.set_name(substitute_name, print_name) target_path = symlink_buffer.resolve_link( base_link_path) + unparsed_path if not target_path.startswith('\\\\'): raise SMBLinkRedirectionError( "Cannot resolve link targets that point to a local path", link_path, print_name) link_share = ntpath.splitdrive(link_path)[0] target_share = ntpath.splitdrive(target_path)[0] if link_share != target_share: raise SMBLinkRedirectionError( "Cannot resolve link targets that point to a different host/share", link_path, print_name) return target_path
def test_bytes_to_bytes(): expected = b"\x01\x02\x03\x04" actual = to_bytes(b"\x01\x02\x03\x04") assert actual == expected
def test_text_to_bytes_diff_encoding(): expected = b"\x61\x00\x62\x00\x63\x00" actual = to_bytes(u"abc", encoding='utf-16-le') assert actual == expected
def test_text_to_bytes_default(): expected = b"\x61\x62\x63" actual = to_bytes(u"abc") assert actual == expected
def _get_packed_size(self): text_value = self._get_calculated_value(self.value) return len(to_bytes(text_value, encoding=self.encoding))
def _pack_value(self, value): return to_bytes(value, encoding=self.encoding)
def _pack_value(self, value): if self.null_terminated: value += u"\x00" return to_bytes(value, encoding=self.encoding)