Beispiel #1
0
    def deserialize(self, element, metadata=None, clear=True):
        if clear:
            self._clear()

        if isinstance(element, string_types):
            element_string = element
            try:
                element = ET.fromstring(element)
            except ET.ParseError as err:
                log.warning("Failed to parse data '%s' as XML, return raw "
                            "xml: %s" % (element_string, str(err)))
                return element_string
        else:
            xml_string = ET.tostring(element, encoding='utf-8', method='xml')
            element_string = to_string(xml_string)

        metadata = metadata or ObjectMeta()
        if metadata.tag == "*":
            metadata.tag = element.tag

        # get the object types so we store the TN Ref ids for later use
        obj_types = self._get_types_from_obj(element)

        # check if it is a primitive object
        unpack_function = {
            # Primitive types
            'S': lambda d: self._deserialize_string(d.text),
            'ToString': lambda d: self._deserialize_string(d.text),
            'C': lambda d: chr(int(d.text)),
            'B': lambda d: d.text.lower() == "true",
            'DT': lambda d: d.text,
            'TS': lambda d: d.text,
            'By': lambda d: int(d.text),
            'SB': lambda d: int(d.text),
            'U16': lambda d: int(d.text),
            'I16': lambda d: int(d.text),
            'U32': lambda d: int(d.text),
            'I32': lambda d: int(d.text),
            'U64': lambda d: int(d.text),
            'I64': lambda d: int(d.text),
            'Sg': lambda d: float(d.text),
            'Db': lambda d: float(d.text),
            'D': lambda d: d.text,  # TODO: deserialize this
            'BA': lambda d: base64.b64decode(d.text),
            'G': lambda d: uuid.UUID(d.text),
            'URI': lambda d: self._deserialize_string(d.text),
            'Nil': lambda d: None,
            'Version': lambda d: d.text,
            'XD': lambda d: self._deserialize_string(d.text),
            'SBK': lambda d: self._deserialize_string(d.text),
            'SS': lambda d: self._deserialize_secure_string(d),

            # references an object already deserialized
            'Ref': lambda d: self.obj[d.attrib['RefId']],
        }.get(element.tag)

        if unpack_function is not None:
            return unpack_function(element)

        # not a primitive object, so try and decode the complex object
        if type(metadata) == ObjectMeta and metadata.object is None:
            structures = {
                "Selected.Microsoft.PowerShell.Commands.GenericMeasureInfo":
                ObjectMeta("Obj", object=CommandMetadataCount),
                "System.Array":
                ListMeta(),
                "System.Collections.ArrayList":
                ListMeta(),
                "System.Collections.Hashtable":
                DictionaryMeta(),
                "System.Collections.Generic.List":
                ListMeta(),
                "System.Collections.Queue":
                QueueMeta(),
                "System.Collections.Stack":
                StackMeta(),
                "System.ConsoleColor":
                ObjectMeta("Obj", object=Color),
                "System.Management.Automation.CommandOrigin":
                ObjectMeta("Obj", object=CommandOrigin),
                "System.Management.Automation.DebugRecord":
                ObjectMeta("Obj", object=DebugRecord),
                "System.Management.Automation.ErrorRecord":
                ObjectMeta("Obj", object=ErrorRecord),
                "System.Management.Automation.Host.Coordinates":
                ObjectMeta("Obj", object=Coordinates),
                "System.Management.Automation.Host.KeyInfo":
                ObjectMeta("Obj", object=KeyInfoDotNet),
                "System.Management.Automation.Host.Size":
                ObjectMeta("Obj", object=Size),
                "System.Management.Automation.InformationalRecord":
                ObjectMeta("Obj", object=InformationalRecord),
                "System.Management.Automation.InformationRecord":
                ObjectMeta("Obj", object=InformationRecord),
                "System.Management.Automation.ParameterMetadata":
                ObjectMeta("Obj", object=ParameterMetadata),
                "System.Management.Automation.ProgressRecordType":
                ObjectMeta("Obj", object=ProgressRecordType),
                "System.Management.Automation.PSBoundParametersDictionary":
                DictionaryMeta(),
                "System.Management.Automation.PSCredential":
                ObjectMeta("Obj", object=PSCredential),
                "System.Management.Automation.PSObject":
                ObjectMeta("ObjDynamic", object=GenericComplexObject),
                "System.Management.Automation.PSPrimitiveDictionary":
                DictionaryMeta(),
                "System.Management.Automation.PSTypeName":
                ObjectMeta("S"),
                "System.Management.Automation.Remoting.RemoteHostMethodId":
                ObjectMeta("Obj", object=HostMethodIdentifier),
                "System.Management.Automation.Runspaces.ApartmentState":
                ObjectMeta("Obj", object=ApartmentState),
                "System.Management.Automation.Runspaces.PipelineResultTypes":
                ObjectMeta("Obj", object=PipelineResultTypes),
                "System.Management.Automation.Runspaces.PSThreadOptions":
                ObjectMeta("Obj", object=PSThreadOptions),
                "System.Management.Automation.Runspaces.RemoteStreamOptions":
                ObjectMeta("Obj", object=RemoteStreamOptions),
                "System.Management.Automation.SessionStateEntryVisibility":
                ObjectMeta("Obj", object=SessionStateEntryVisibility),
                "System.Management.Automation.VerboseRecord":
                ObjectMeta("Obj", object=VerboseRecord),
                "System.Management.Automation.WarningRecord":
                ObjectMeta("Obj", object=WarningRecord),
                "System.Globalization.CultureInfo":
                ObjectMeta("Obj", object=CultureInfo),

                # Fallback to the GenericComplexObject
                "System.Object":
                ObjectMeta("ObjDynamic", object=GenericComplexObject),

                # Primitive types
                "System.String":
                ObjectMeta("S"),
                "System.Char":
                ObjectMeta("C"),
                "System.Boolean":
                ObjectMeta("B"),
                "System.DateTime":
                ObjectMeta("DT"),
                # None: ObjectMeta("TS"), # duration timespan
                "System.Byte":
                ObjectMeta("By"),
                "System.SByte":
                ObjectMeta("SB"),
                "System.UInt16":
                ObjectMeta("U16"),
                "System.Int16":
                ObjectMeta("I16"),
                "System.UInt32":
                ObjectMeta("U32"),
                "System.Int32":
                ObjectMeta("I32"),
                "System.UInt64":
                ObjectMeta("U64"),
                "System.Int64":
                ObjectMeta("I64"),
                "System.Single":
                ObjectMeta("Sg"),
                "System.Double":
                ObjectMeta("Db"),
                "System.Decimal":
                ObjectMeta("D"),
                # None: ObjectMeta("BA"), # Byte array base64 encoded
                "System.Guid":
                ObjectMeta("G"),
                "System.Uri":
                ObjectMeta("URI"),
                "System.Version":
                ObjectMeta("Version"),
                "System.Xml.XmlDocument":
                ObjectMeta("XD"),
                "System.Management.Automation.ScriptBlock":
                ObjectMeta("SBK"),
                "System.Security.SecureString":
                ObjectMeta("SS"),
            }

            # fallback to GenericComplexObject if no types were defined
            if metadata.tag == "Obj" and len(obj_types) == 0:
                obj_types = ["System.Object"]

            metadata = None
            for obj_type in obj_types:
                if obj_type.startswith("Deserialized.System."):
                    obj_type = obj_type[13:]

                is_list = False
                if obj_type.endswith("[]"):
                    obj_type = obj_type[0:-2]
                    is_list = True
                elif obj_type.startswith("System.Collections."
                                         "Generic.List`1[["):
                    list_info = obj_type[35:-1]
                    obj_type = list_info.split(",")[0]
                    is_list = True
                elif obj_type.startswith("System.Collections.ObjectModel."
                                         "Collection`1[["):
                    list_info = obj_type[45:-1]
                    obj_type = list_info.split(",")[0]
                    is_list = True
                elif obj_type.startswith("System.Collections.ObjectModel."
                                         "ReadOnlyCollection`1[["):
                    list_info = obj_type[53:-1]
                    obj_type = list_info.split(",")[0]
                    is_list = True
                elif obj_type.startswith("System.Collections.Generic."
                                         "Dictionary`2[["):
                    dict_meta = obj_type[41:-2].split("],[")
                    key_type = structures.get(dict_meta[0].split(",")[0],
                                              ObjectMeta())
                    value_type = structures.get(dict_meta[1].split(",")[0],
                                                ObjectMeta())
                    metadata = DictionaryMeta(dict_key_meta=key_type,
                                              dict_value_meta=value_type)
                    break

                obj_meta = structures.get(obj_type)
                if obj_meta is not None:
                    metadata = obj_meta
                    if is_list:
                        metadata = ListMeta(list_value_meta=metadata)
                    break

        # we were unable to find the complex object type so just return the
        # element
        if metadata is None:
            obj = element_string
        elif metadata.tag == "Obj":
            obj = self._deserialize_obj(element, metadata)
        elif metadata.tag == "ObjDynamic":
            obj = self._deserialize_dynamic_obj(element, metadata)
        elif metadata.tag == "LST":
            obj = self._deserialize_lst(element, metadata)
        elif metadata.tag == "QUE":
            obj = self._deserialize_que(element)
        elif metadata.tag == "STK":
            obj = self._deserialize_stk(element)
        elif metadata.tag == "DCT":
            obj = self._deserialize_dct(element)
        else:
            log.warning("Unknown metadata tag type '%s', failed to "
                        "deserialize object" % metadata.tag)
            obj = element_string

        if element.tag == "Obj":
            self.obj[element.attrib['RefId']] = obj

        if isinstance(obj, ComplexObject):
            obj._xml = element_string

        return obj
Beispiel #2
0
    def serialize(self, value, metadata=None, parent=None, clear=True):
        """
        Serializes a raw value or class into an XML Element that can be sent
        over to the remote host.

        :param value: The value to serialize
        :param metadata: Any extra metadata to control how to serialize the
            value, if None then the value will be inferred by the type
        :param parent: Whether to append the element onto a parent element
        :param clear: Whether to clear the Obj and TN reference map, this
            should only be True when initially calling serialize
        :return: The XML Element from the serializied value
        """
        if clear:
            self._clear()

        if isinstance(value, element_type):
            if metadata is not None and metadata.name is not None:
                value.attrib['N'] = metadata.name

            if parent is not None:
                parent.append(value)

            return value

        metadata = metadata or ObjectMeta()
        if metadata.tag == "*":
            metadata.tag = self._get_tag_from_value(value)

        pack_function = {
            # primitive types
            'S': lambda m, d: self._serialize_string(d),
            'ToString': lambda d: self._serialize_string(d),
            'C': lambda m, d: str(ord(d)),
            'B': lambda m, d: str(d).lower(),
            'DT': lambda m, d: None,
            'TS': lambda m, d: str(d),
            'By': lambda m, d: str(d),
            'SB': lambda m, d: str(d),
            'U16': lambda m, d: str(d),
            'I16': lambda m, d: str(d),
            'U32': lambda m, d: str(d),
            'I32': lambda m, d: str(d),
            'U64': lambda m, d: str(d),
            'I64': lambda m, d: str(d),
            'Sg': lambda m, d: str(d),
            'Db': lambda m, d: str(d),
            'D': lambda m, d: str(d),
            'BA': lambda m, d: to_string(base64.b64encode(d)),
            'G': lambda m, d: str(d),
            'URI': lambda m, d: self._serialize_string(d),
            'Version': lambda m, d: str(d),
            'XD': lambda m, d: self._serialize_string(d),
            'SBK': lambda m, d: self._serialize_string(d),
            'SS': lambda m, d: self._serialize_secure_string(d),
            'Obj': self._serialize_obj,
            "ObjDynamic": self._serialize_dynamic_obj,
            'LST': self._serialize_lst,
            'IE': self._serialize_ie,
            'QUE': self._serialize_que,
            'STK': self._serialize_stk,
            'DCT': self._serialize_dct
        }[metadata.tag]

        if value is None:
            if metadata.optional:
                return
            element = ET.Element("Nil")
        else:
            element_value = pack_function(metadata, value)
            if isinstance(element_value, string_types):
                element = ET.Element(metadata.tag)
                element.text = element_value
            else:
                element = element_value

        if metadata.name is not None:
            element.attrib['N'] = metadata.name

        if parent is not None:
            parent.append(element)

        return element
Beispiel #3
0
    def copy(self, src, dest):
        """
        Copies a single file from the current host to the remote Windows host.
        This can be quite slow when it comes to large files due to the
        limitations of WinRM but it is designed to be as fast as it can be.
        During the copy process, the bytes will be stored in a temporary file
        before being copied.

        When copying it will replace the file at dest if one already exists. It
        also will verify the checksum of the copied file is the same as the
        actual file locally before copying the file to the path at dest.

        :param src: The path to the local file
        :param dest: The path to the destionation file on the Windows host
        :return: The absolute path of the file on the Windows host
        """
        def read_buffer(b_path, buffer_size):
            offset = 0
            sha1 = hashlib.sha1()

            with open(b_path, 'rb') as src_file:
                for data in iter((lambda: src_file.read(buffer_size)), b""):
                    log.debug("Reading data of file at offset=%d with size=%d"
                              % (offset, buffer_size))
                    offset += len(data)
                    sha1.update(data)
                    b64_data = base64.b64encode(data) + b"\r\n"

                    yield b64_data, False

                # the file was empty, return empty buffer
                if offset == 0:
                    yield b"", False

            # the last input is the actual file hash used to verify the
            # transfer was ok
            actual_hash = b"\x00\xffHash: " + to_bytes(sha1.hexdigest())
            yield base64.b64encode(actual_hash), True

        src = os.path.expanduser(os.path.expandvars(src))
        b_src = to_bytes(src)
        src_size = os.path.getsize(b_src)
        log.info("Copying '%s' to '%s' with a total size of %d"
                 % (src, dest, src_size))

        # check if the src size is twice as large as the max payload and fetch
        # the max size from the server, we only check in this case to save on a
        # round trip if the file is small enough to fit in 2 msg's, otherwise
        # we want to get the largest size possible
        buffer_size = int(self.wsman.max_payload_size / 4 * 3)
        if src_size > (buffer_size * 2) and \
                self.wsman.max_envelope_size == 153600:
            log.debug("Updating the max WSMan envelope size")
            self.wsman.update_max_payload_size()
            buffer_size = int(self.wsman.max_payload_size / 4 * 3)
        log.info("Creating file reader with a buffer size of %d" % buffer_size)
        read_gen = read_buffer(b_src, buffer_size)

        command = u'''begin {
    $ErrorActionPreference = "Stop"
    $path = [System.IO.Path]::GetTempFileName()
    $fd = [System.IO.File]::Create($path)
    $algo = [System.Security.Cryptography.SHA1CryptoServiceProvider]::Create()
    $bytes = @()
    $expected_hash = ""
} process {
    $base64_string = $input

    $bytes = [System.Convert]::FromBase64String($base64_string)
    if ($bytes.Count -eq 48 -and $bytes[0] -eq 0 -and $bytes[1] -eq 255) {
        $hash_bytes = $bytes[-40..-1]
        $expected_hash = [System.Text.Encoding]::UTF8.GetString($hash_bytes)
    } else {
        $algo.TransformBlock($bytes, 0, $bytes.Length, $bytes, 0) > $null
        $fd.Write($bytes, 0, $bytes.Length)
    }
} end {
    $output_path = "%s"
    $dest = New-Object -TypeName System.IO.FileInfo -ArgumentList $output_path
    $fd.Close()

    try {
        $algo.TransformFinalBlock($bytes, 0, 0) > $null
        $actual_hash = [System.BitConverter]::ToString($algo.Hash)
        $actual_hash = $actual_hash.Replace("-", "").ToLowerInvariant()

        if ($actual_hash -ne $expected_hash) {
            $msg = "Transport failure, hash mistmatch"
            $msg += "`r`nActual: $actual_hash"
            $msg += "`r`nExpected: $expected_hash"
            throw $msg
        }
        [System.IO.File]::Copy($path, $output_path, $true)
        $dest.FullName
    } finally {
        [System.IO.File]::Delete($path)
    }
}''' % to_unicode(dest)
        encoded_command = to_string(base64.b64encode(to_bytes(command,
                                                              'utf-16-le')))

        with WinRS(self.wsman) as shell:
            process = Process(shell, "powershell.exe",
                              ["-NoProfile", "-NonInteractive",
                               "-EncodedCommand", encoded_command])
            process.begin_invoke()
            log.info("Starting to send file data to remote process")
            for input_data, end in read_gen:
                process.send(input_data, end)
            log.info("Finished sending file data to remote process")
            process.end_invoke()

        stderr = self.sanitise_clixml(process.stderr)
        if process.rc != 0:
            raise WinRMError("Failed to copy file: %s" % stderr)
        output_file = to_unicode(process.stdout).strip()
        log.info("Completed file transfer of '%s' to '%s'"
                 % (src, output_file))
        return output_file
Beispiel #4
0
    def _normalise_xml(self,
                       xml,
                       generify=True,
                       overrides=None,
                       psrp_fragment_type=None):
        if not xml:
            return xml

        overrides = overrides if overrides is not None else []

        if generify:
            # convert all UUID values to the blank UUID
            xml = re.sub(self._uuid_pattern,
                         "00000000-0000-0000-0000-000000000000", xml)

            xml_obj = ET.fromstring(to_bytes(xml))

            # convert the To hostname in the headers to the generic one
            to_field = xml_obj.find("s:Header/wsa:To", NAMESPACES)
            if to_field is not None:
                to_field.text = self.endpoint

            for override in overrides:
                override_element = xml_obj.find(override["path"], NAMESPACES)
                if override.get("text"):
                    override_element.text = override["text"]
                attributes = override.get("attributes", {})
                for attr_key, attr_value in attributes.items():
                    override_element.attrib[attr_key] = attr_value
        else:
            xml_obj = ET.fromstring(to_bytes(xml))

        # PSRP message contain another set of XML messages that have been
        # base64 encoded. We need to strip these out and compare them
        # separately once all the fragments have been received.
        if psrp_fragment_type:
            creation_xml = xml_obj.find(
                "s:Body/rsp:Shell/{http://schemas.microsoft.com/powershell}creationXml",
                NAMESPACES)
            if creation_xml is not None:
                creation_xml.text = self._generify_fragment(
                    creation_xml.text, psrp_fragment_type)

            connect_xml = xml_obj.find("s:Body/rsp:Connect/pwsh:connectXml",
                                       NAMESPACES)
            if connect_xml is not None:
                connect_xml.text = self._generify_fragment(
                    connect_xml.text, psrp_fragment_type)

            # when resource uri is PowerShell we know the Send/Command messages
            # contain PSRP fragments and we need to generify them
            exp_res_uri = "http://schemas.microsoft.com/powershell/"
            res_uri = xml_obj.find("s:Header/wsman:ResourceURI", NAMESPACES)
            if res_uri is not None:
                res_uri = res_uri.text

            streams = xml_obj.findall("s:Body/rsp:Send/rsp:Stream", NAMESPACES)
            if res_uri is not None and res_uri.startswith(
                    exp_res_uri) and len(streams) > 0:
                for stream in streams:
                    stream.text = self._generify_fragment(
                        stream.text, psrp_fragment_type)

            command = xml_obj.find("s:Body/rsp:CommandLine/rsp:Arguments",
                                   NAMESPACES)
            if res_uri is not None and res_uri.startswith(
                    exp_res_uri) and command is not None:
                command.text = self._generify_fragment(command.text,
                                                       psrp_fragment_type)

        return to_string(ET.tostring(xml_obj, encoding="utf-8"))
Beispiel #5
0
    def serialize(
        self,
        value: typing.Any,
        metadata: typing.Optional[ObjectMeta] = None,
        parent: typing.Optional[ET.Element] = None,
        clear: bool = True,
    ) -> typing.Optional[ET.Element]:
        """
        Serializes a raw value or class into an XML Element that can be sent
        over to the remote host.

        :param value: The value to serialize
        :param metadata: Any extra metadata to control how to serialize the
            value, if None then the value will be inferred by the type
        :param parent: Whether to append the element onto a parent element
        :param clear: Whether to clear the Obj and TN reference map, this
            should only be True when initially calling serialize
        :return: The XML Element from the serializied value
        """
        if clear:
            self._clear()

        if isinstance(value, ET.Element):
            if metadata is not None and metadata.name is not None:
                value.attrib["N"] = metadata.name

            if parent is not None:
                parent.append(value)

            return value

        metadata = metadata or ObjectMeta()
        if metadata.tag == "*":
            if isinstance(value, TaggedValue):
                metadata.tag = value.tag
                value = value.value
            else:
                metadata.tag = self._get_tag_from_value(value)

        pack_function: typing.Callable[[ObjectMeta, typing.Any], ET.Element] = {  # type: ignore[assignment] # Not sure why
            # primitive types
            "S": lambda m, d: self._serialize_string(d),
            "ToString": lambda d: self._serialize_string(d),
            "C": lambda m, d: str(ord(d)),
            "B": lambda m, d: str(d).lower(),
            "DT": lambda m, d: None,
            "TS": lambda m, d: str(d),
            "By": lambda m, d: str(d),
            "SB": lambda m, d: str(d),
            "U16": lambda m, d: str(d),
            "I16": lambda m, d: str(d),
            "U32": lambda m, d: str(d),
            "I32": lambda m, d: str(d),
            "U64": lambda m, d: str(d),
            "I64": lambda m, d: str(d),
            "Sg": lambda m, d: str(d),
            "Db": lambda m, d: str(d),
            "D": lambda m, d: str(d),
            "BA": lambda m, d: to_string(base64.b64encode(d)),
            "G": lambda m, d: str(d),
            "URI": lambda m, d: self._serialize_string(d),
            "Version": lambda m, d: str(d),
            "XD": lambda m, d: self._serialize_string(d),
            "SBK": lambda m, d: self._serialize_string(d),
            "SS": lambda m, d: self._serialize_secure_string(d),
            "Obj": self._serialize_obj,
            "ObjDynamic": self._serialize_dynamic_obj,
            "LST": self._serialize_lst,
            "IE": self._serialize_ie,
            "QUE": self._serialize_que,
            "STK": self._serialize_stk,
            "DCT": self._serialize_dct,
        }[
            metadata.tag
        ]

        if value is None:
            if metadata.optional:
                return None
            element = ET.Element("Nil")
        else:
            element_value = pack_function(metadata, value)
            if isinstance(element_value, str):
                element = ET.Element(metadata.tag)
                element.text = element_value
            else:
                element = element_value

        if metadata.name is not None:
            element.attrib["N"] = metadata.name

        if parent is not None:
            parent.append(element)

        return element
Beispiel #6
0
    def _normalise_xml(self, xml, generify=True, overrides=None):
        overrides = overrides if overrides is not None else []

        if generify:
            # convert all UUID values to the blank UUID
            xml = re.sub(self._uuid_pattern,
                         "00000000-0000-0000-0000-000000000000", xml)

            xml_obj = ET.fromstring(to_bytes(xml))

            # convert the To hostname in the headers to the generic one
            to_field = xml_obj.find("s:Header/wsa:To", NAMESPACES)
            if to_field is not None:
                to_field.text = self.endpoint

            for override in overrides:
                override_element = xml_obj.find(override['path'], NAMESPACES)
                if override.get('text'):
                    override_element.text = override['text']
                attributes = override.get('attributes', {})
                for attr_key, attr_value in attributes.items():
                    override_element.attrib[attr_key] = attr_value

            # PSRP messages contain the runspace and pipeline ID that is
            # base64 encoded, this needs to be converted back to \x00 * 16
            # for mock test
            creation_xml = xml_obj.find(
                "s:Body/rsp:Shell/{http://schemas."
                "microsoft.com/powershell}creationXml", NAMESPACES)
            if creation_xml is not None:
                self._generify_fragment(creation_xml)

            connect_xml = xml_obj.find("s:Body/rsp:Connect/pwsh:connectXml",
                                       NAMESPACES)
            if connect_xml is not None:
                self._generify_fragment(connect_xml)

            # when resource uri is PowerShell we know the Send/Command messages
            # contain PSRP fragments and we need to generify them
            exp_res_uri = "http://schemas.microsoft.com/powershell/"
            res_uri = \
                xml_obj.find("s:Header/wsman:ResourceURI", NAMESPACES)
            if res_uri is not None:
                res_uri = res_uri.text

            streams = xml_obj.findall("s:Body/rsp:Send/rsp:Stream", NAMESPACES)
            if res_uri is not None and res_uri.startswith(exp_res_uri) and \
                    len(streams) > 0:
                for stream in streams:
                    self._generify_fragment(stream)

            command = xml_obj.find("s:Body/rsp:CommandLine/rsp:Arguments",
                                   NAMESPACES)
            if res_uri is not None and res_uri.startswith(exp_res_uri) and \
                    command is not None:
                self._generify_fragment(command)
        else:
            xml_obj = ET.fromstring(to_bytes(xml))

        # convert the string to an XML object, for Python 2.6 (lxml) we need
        # to change the namespace handling to mimic the ElementTree way of
        # working so the string compare works
        if sys.version_info[0] == 2 and sys.version_info[1] < 7:
            namespaces = {}
            new_xml_obj = self._simplify_namespaces(namespaces, xml_obj)
            for key, value in namespaces.items():
                new_xml_obj.attrib["xmlns:%s" % key] = value

            xml_obj = new_xml_obj

        return to_string(ETNew.tostring(xml_obj, encoding='utf-8'))
Beispiel #7
0
    def unpack(data, serializer):
        destination = struct.unpack("<I", data[0:4])[0]
        message_type = struct.unpack("<I", data[4:8])[0]
        rpid = str(uuid.UUID(bytes_le=data[8:24]))
        pid = str(uuid.UUID(bytes_le=data[24:40]))

        if data[40:43] == b"\xEF\xBB\xBF":
            # 40-43 is the UTF-8 BOM which we don't care about
            message_data = to_string(data[43:])
        else:
            message_data = to_string(data[40:])

        log.debug("Unpacking PSRP message of type %d: %s" %
                  (message_type, message_data))

        message_obj = {
            MessageType.SESSION_CAPABILITY: SessionCapability,
            MessageType.INIT_RUNSPACEPOOL: InitRunspacePool,
            MessageType.PUBLIC_KEY: PublicKey,
            MessageType.ENCRYPTED_SESSION_KEY: EncryptedSessionKey,
            MessageType.PUBLIC_KEY_REQUEST: PublicKeyRequest,
            MessageType.SET_MAX_RUNSPACES: SetMaxRunspaces,
            MessageType.SET_MIN_RUNSPACES: SetMinRunspaces,
            MessageType.RUNSPACE_AVAILABILITY: RunspaceAvailability,
            MessageType.RUNSPACEPOOL_STATE: RunspacePoolStateMessage,
            MessageType.CREATE_PIPELINE: CreatePipeline,
            MessageType.GET_AVAILABLE_RUNSPACES: GetAvailableRunspaces,
            MessageType.USER_EVENT: UserEvent,
            MessageType.APPLICATION_PRIVATE_DATA: ApplicationPrivateData,
            MessageType.GET_COMMAND_METADATA: GetCommandMetadata,
            MessageType.RUNSPACEPOOL_HOST_CALL: RunspacePoolHostCall,
            MessageType.RUNSPACEPOOL_HOST_RESPONSE: RunspacePoolHostResponse,
            MessageType.PIPELINE_INPUT: PipelineInput,
            MessageType.END_OF_PIPELINE_INPUT: EndOfPipelineInput,
            MessageType.PIPELINE_OUTPUT: PipelineOutput,
            MessageType.ERROR_RECORD: ErrorRecordMessage,
            MessageType.PIPELINE_STATE: PipelineState,
            MessageType.DEBUG_RECORD: DebugRecord,
            MessageType.VERBOSE_RECORD: VerboseRecord,
            MessageType.WARNING_RECORD: WarningRecord,
            MessageType.PROGRESS_RECORD: ProgressRecord,
            MessageType.INFORMATION_RECORD: InformationRecord,
            MessageType.PIPELINE_HOST_CALL: PipelineHostCall,
            MessageType.PIPELINE_HOST_RESPONSE: PipelineHostResponse,
            MessageType.CONNECT_RUNSPACEPOOL: ConnectRunspacePool,
            MessageType.RUNSPACEPOOL_INIT_DATA: RunspacePoolInitData,
            MessageType.RESET_RUNSPACE_STATE: ResetRunspaceState
        }[message_type]

        # PIPELINE_OUTPUT is a weird one, it contains the actual output objects
        # not encapsulated so we set it to a dynamic object and the serializer
        # will work out what is best
        if message_type == MessageType.PIPELINE_OUTPUT:
            # try to deserialize using our known objects, if that fails then
            # we want to get a generic object at least but raise a warning
            try:
                message_data = serializer.deserialize(message_data)
            except SerializationError as err:
                warnings.warn("Failed to deserialize msg, trying to "
                              "deserialize as generic complex object: %s" %
                              str(err))
                meta = ObjectMeta("ObjDynamic", object=GenericComplexObject)
                message_data = serializer.deserialize(message_data, meta)
            message = PipelineOutput()
            message.data = message_data
        elif message_type == MessageType.PIPELINE_INPUT:
            message_data = serializer.deserialize(message_data)
            message = PipelineInput()
            message.data = message_data
        elif message_type == MessageType.PUBLIC_KEY_REQUEST:
            message = PublicKeyRequest()
        else:
            message_meta = ObjectMeta("Obj", object=message_obj)
            message = serializer.deserialize(message_data, message_meta)

        return Message(destination, rpid, pid, message, serializer)