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 test_create_message_with_set_name(self): message = SymbolicLinkReparseDataBuffer() message.set_name(u"\\??\\café", u"café") message['flags'] = SymbolicLinkFlags.SYMLINK_FLAG_RELATIVE expected = b"\x00\x00" \ b"\x10\x00" \ b"\x10\x00" \ b"\x08\x00" \ b"\x01\x00\x00\x00" \ b"\x5c\x00\x3f\x00\x3f\x00\x5c\x00" \ b"\x63\x00\x61\x00\x66\x00\xe9\x00" \ b"\x63\x00\x61\x00\x66\x00\xe9\x00" actual = message.pack() assert len(message) == 36 assert actual == expected
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