예제 #1
0
 def to_binary(self):
     security = struct_to_binary(self.SecurityHeader)
     encrypted_part = struct_to_binary(self.SequenceHeader) + self.Body
     encrypted_part += self.security_policy.padding(len(encrypted_part))
     self.MessageHeader.body_size = len(security) + self.encrypted_size(len(encrypted_part))
     header = header_to_binary(self.MessageHeader)
     encrypted_part += self.security_policy.signature(header + security + encrypted_part)
     return header + security + self.security_policy.encrypt(encrypted_part)
예제 #2
0
 def to_binary(self):
     security = struct_to_binary(self.SecurityHeader)
     encrypted_part = struct_to_binary(self.SequenceHeader) + self.Body
     encrypted_part += self.security_policy.padding(len(encrypted_part))
     self.MessageHeader.body_size = len(security) + self.encrypted_size(len(encrypted_part))
     header = header_to_binary(self.MessageHeader)
     encrypted_part += self.security_policy.signature(header + security + encrypted_part)
     return header + security + self.security_policy.encrypt(encrypted_part)
예제 #3
0
    def test_custom_structs_array(self):
        xmlpath = "tests/example.bsd"
        c = StructGenerator()
        c.make_model_from_file(xmlpath)
        c.save_to_file("tests/structures.py")
        import structures as s

        # test with default values
        v = s.ArrayValueDataType()
        data = struct_to_binary(v)
        v2 = struct_from_binary(s.ArrayValueDataType, ua.utils.Buffer(data))

        # set some values
        v = s.ArrayValueDataType()
        v.SbyteValue = [1]
        v.ByteValue = [2]
        v.Int16Value = [3]
        v.UInt16Value = [4]
        v.Int32Value = [5]
        v.UInt32Value = [6]
        v.Int64Value = [7]
        v.UInt64Value = [8]
        v.FloatValue = [9.0]
        v.DoubleValue = [10.0]
        v.StringValue = ["elleven"]
        v.DateTimeValue = [datetime.utcnow()]
        #self.GuidValue = uuid.uudib"14"
        v.ByteStringValue = [b"fifteen", b"sixteen"]
        v.XmlElementValue = [ua.XmlElement("<toto>titi</toto>")]
        v.NodeIdValue = [
            ua.NodeId.from_string("ns=4;i=9999"),
            ua.NodeId.from_string("i=6")
        ]
        #self.ExpandedNodeIdValue =
        #self.QualifiedNameValue =
        #self.LocalizedTextValue =
        #self.StatusCodeValue =
        #self.VariantValue =
        #self.EnumerationValue =
        #self.StructureValue =
        #self.Number =
        #self.Integer =
        #self.UInteger =

        data = struct_to_binary(v)
        v2 = struct_from_binary(s.ArrayValueDataType, ua.utils.Buffer(data))
        self.assertEqual(v.NodeIdValue, v2.NodeIdValue)
        print(v2.NodeIdValue)
예제 #4
0
    def send_response(self, requesthandle, algohdr, seqhdr, response, msgtype=ua.MessageType.SecureMessage):
        with self._socketlock:
            response.ResponseHeader.RequestHandle = requesthandle
            data = self._connection.message_to_binary(
                struct_to_binary(response), message_type=msgtype, request_id=seqhdr.RequestId, algohdr=algohdr)

            self.socket.write(data)
예제 #5
0
 def from_header_and_body(security_policy, header, buf):
     assert len(buf) >= header.body_size, 'Full body expected here'
     data = buf.copy(header.body_size)
     buf.skip(header.body_size)
     if header.MessageType in (ua.MessageType.SecureMessage,
                               ua.MessageType.SecureClose):
         security_header = struct_from_binary(ua.SymmetricAlgorithmHeader,
                                              data)
         crypto = security_policy.symmetric_cryptography
     elif header.MessageType == ua.MessageType.SecureOpen:
         security_header = struct_from_binary(ua.AsymmetricAlgorithmHeader,
                                              data)
         crypto = security_policy.asymmetric_cryptography
     else:
         raise ua.UaError("Unsupported message type: {0}".format(
             header.MessageType))
     obj = MessageChunk(crypto)
     obj.MessageHeader = header
     obj.SecurityHeader = security_header
     decrypted = crypto.decrypt(data.read(len(data)))
     signature_size = crypto.vsignature_size()
     if signature_size > 0:
         signature = decrypted[-signature_size:]
         decrypted = decrypted[:-signature_size]
         crypto.verify(
             header_to_binary(obj.MessageHeader) +
             struct_to_binary(obj.SecurityHeader) + decrypted, signature)
     data = ua.utils.Buffer(crypto.remove_padding(decrypted))
     obj.SequenceHeader = struct_from_binary(ua.SequenceHeader, data)
     obj.Body = data.read(len(data))
     return obj
예제 #6
0
 def from_header_and_body(security_policy, header, buf):
     assert len(buf) >= header.body_size, 'Full body expected here'
     data = buf.copy(header.body_size)
     buf.skip(header.body_size)
     if header.MessageType in (ua.MessageType.SecureMessage, ua.MessageType.SecureClose):
         security_header = struct_from_binary(ua.SymmetricAlgorithmHeader, data)
         crypto = security_policy.symmetric_cryptography
     elif header.MessageType == ua.MessageType.SecureOpen:
         security_header = struct_from_binary(ua.AsymmetricAlgorithmHeader, data)
         crypto = security_policy.asymmetric_cryptography
     else:
         raise ua.UaError("Unsupported message type: {0}".format(header.MessageType))
     obj = MessageChunk(crypto)
     obj.MessageHeader = header
     obj.SecurityHeader = security_header
     decrypted = crypto.decrypt(data.read(len(data)))
     signature_size = crypto.vsignature_size()
     if signature_size > 0:
         signature = decrypted[-signature_size:]
         decrypted = decrypted[:-signature_size]
         crypto.verify(header_to_binary(obj.MessageHeader) + struct_to_binary(obj.SecurityHeader) + decrypted, signature)
     data = ua.utils.Buffer(crypto.remove_padding(decrypted))
     obj.SequenceHeader = struct_from_binary(ua.SequenceHeader, data)
     obj.Body = data.read(len(data))
     return obj
예제 #7
0
def get_request(client):
    """ Assemble an OpenSecureChannelRequest for the specified client

    :param client: client object containing the channel parameters
    :return: binary OpenSecureChannelRequest
    """
    params = ua.OpenSecureChannelParameters()
    params.ClientProtocolVersion = 0
    params.RequestType = ua.SecurityTokenRequestType.Issue
    params.SecurityMode = client.security_policy.Mode
    params.RequestedLifetime = client.secure_channel_timeout

    nonce = utils.create_nonce(client.security_policy.symmetric_key_size)
    params.ClientNonce = nonce

    request = ua.OpenSecureChannelRequest()
    request.Parameters = params
    request.RequestHeader = client.uaclient._uasocket._create_request_header()

    try:
        binreq = struct_to_binary(request)
    except Exception:
        # reset request handle if any error
        # see self._create_request_header
        client.uaclient._uasocket._request_handle -= 1
        raise

    return binreq
예제 #8
0
    def send_response(self, requesthandle, algohdr, seqhdr, response, msgtype=ua.MessageType.SecureMessage):
        with self._socketlock:
            response.ResponseHeader.RequestHandle = requesthandle
            data = self._connection.message_to_binary(
                struct_to_binary(response), message_type=msgtype, request_id=seqhdr.RequestId, algohdr=algohdr)

            self.socket.write(data)
예제 #9
0
    def _send_request(self,
                      request,
                      callback=None,
                      timeout=1000,
                      message_type=ua.MessageType.SecureMessage):
        """
        send request to server, lower-level method
        timeout is the timeout written in ua header
        returns future
        """
        with self._lock:
            request.RequestHeader = self._create_request_header(timeout)
            self.logger.debug("Sending: %s", request)
            try:
                binreq = struct_to_binary(request)
            except Exception:
                # reset reqeust handle if any error
                # see self._create_request_header
                self._request_handle -= 1
                raise
            self._request_id += 1
            future = Future()
            if callback:
                future.add_done_callback(callback)
            self._callbackmap[self._request_id] = future

            # Change to the new security token if the connection has been renewed.
            if self._connection.next_security_token.TokenId != 0:
                self._connection.revolve_tokens()

            msg = self._connection.message_to_binary(
                binreq, message_type=message_type, request_id=self._request_id)
            self._socket.write(msg)
        return future
예제 #10
0
    def test_custom_structs_array(self):
        xmlpath = "tests/example.bsd"
        c = StructGenerator()
        c.make_model_from_file(xmlpath)
        c.save_to_file("tests/structures.py")
        import structures as s

        # test with default values
        v = s.ArrayValueDataType()
        data = struct_to_binary(v)
        v2 = struct_from_binary(s.ArrayValueDataType, ua.utils.Buffer(data))


        # set some values
        v = s.ArrayValueDataType()
        v.SbyteValue = [1]
        v.ByteValue = [2]
        v.Int16Value = [3]
        v.UInt16Value = [4]
        v.Int32Value = [5]
        v.UInt32Value = [6]
        v.Int64Value = [7]
        v.UInt64Value = [8]
        v.FloatValue = [9.0]
        v.DoubleValue = [10.0]
        v.StringValue = ["elleven"]
        v.DateTimeValue = [datetime.utcnow()]
        #self.GuidValue = uuid.uudib"14"
        v.ByteStringValue = [b"fifteen", b"sixteen"]
        v.XmlElementValue = [ua.XmlElement("<toto>titi</toto>")]
        v.NodeIdValue = [ua.NodeId.from_string("ns=4;i=9999"), ua.NodeId.from_string("i=6")]
        #self.ExpandedNodeIdValue =
        #self.QualifiedNameValue =
        #self.LocalizedTextValue =
        #self.StatusCodeValue =
        #self.VariantValue =
        #self.EnumerationValue =
        #self.StructureValue =
        #self.Number =
        #self.Integer =
        #self.UInteger =


        data = struct_to_binary(v)
        v2 = struct_from_binary(s.ArrayValueDataType, ua.utils.Buffer(data))
        self.assertEqual(v.NodeIdValue, v2.NodeIdValue)
        print(v2.NodeIdValue)
예제 #11
0
 def test_text(self):
     t1 = ua.LocalizedText('Root')
     t2 = ua.LocalizedText('Root')
     t3 = ua.LocalizedText('root')
     self.assertEqual(t1, t2)
     self.assertNotEqual(t1, t3)
     t4 = struct_from_binary(ua.LocalizedText, ua.utils.Buffer(struct_to_binary(t1)))
     self.assertEqual(t1, t4)
예제 #12
0
    def test_custom_structs(self):
        xmlpath = "tests/example.bsd"
        c = StructGenerator()
        c.make_model_from_file(xmlpath)
        c.save_to_file("tests/structures.py")
        import structures as s

        # test with default values
        v = s.ScalarValueDataType()
        data = struct_to_binary(v)
        v2 = struct_from_binary(s.ScalarValueDataType, ua.utils.Buffer(data))


        # set some values
        v = s.ScalarValueDataType()
        v.SbyteValue = 1
        v.ByteValue = 2
        v.Int16Value = 3
        v.UInt16Value = 4
        v.Int32Value = 5
        v.UInt32Value = 6
        v.Int64Value = 7
        v.UInt64Value = 8
        v.FloatValue = 9.0
        v.DoubleValue = 10.0
        v.StringValue = "elleven"
        v.DateTimeValue = datetime.utcnow()
        #self.GuidValue = uuid.uudib"14"
        v.ByteStringValue = b"fifteen"
        v.XmlElementValue = ua.XmlElement("<toto>titi</toto>")
        v.NodeIdValue = ua.NodeId.from_string("ns=4;i=9999")
        #self.ExpandedNodeIdValue =
        #self.QualifiedNameValue =
        #self.LocalizedTextValue =
        #self.StatusCodeValue =
        #self.VariantValue =
        #self.EnumerationValue =
        #self.StructureValue =
        #self.Number =
        #self.Integer =
        #self.UInteger =


        data = struct_to_binary(v)
        v2 = struct_from_binary(s.ScalarValueDataType, ua.utils.Buffer(data))
        self.assertEqual(v.NodeIdValue, v2.NodeIdValue)
예제 #13
0
 def test_text(self):
     t1 = ua.LocalizedText('Root')
     t2 = ua.LocalizedText('Root')
     t3 = ua.LocalizedText('root')
     self.assertEqual(t1, t2)
     self.assertNotEqual(t1, t3)
     t4 = struct_from_binary(ua.LocalizedText, ua.utils.Buffer(struct_to_binary(t1)))
     self.assertEqual(t1, t4)
예제 #14
0
    def test_custom_structs(self):
        xmlpath = "tests/example.bsd"
        c = StructGenerator()
        c.make_model_from_file(xmlpath)
        c.save_to_file("tests/structures.py")
        import structures as s

        # test with default values
        v = s.ScalarValueDataType()
        data = struct_to_binary(v)
        v2 = struct_from_binary(s.ScalarValueDataType, ua.utils.Buffer(data))


        # set some values
        v = s.ScalarValueDataType()
        v.SbyteValue = 1
        v.ByteValue = 2
        v.Int16Value = 3
        v.UInt16Value = 4
        v.Int32Value = 5
        v.UInt32Value = 6
        v.Int64Value = 7
        v.UInt64Value = 8
        v.FloatValue = 9.0
        v.DoubleValue = 10.0
        v.StringValue = "elleven"
        v.DateTimeValue = datetime.utcnow()
        #self.GuidValue = uuid.uudib"14"
        v.ByteStringValue = b"fifteen"
        v.XmlElementValue = ua.XmlElement("<toto>titi</toto>")
        v.NodeIdValue = ua.NodeId.from_string("ns=4;i=9999")
        #self.ExpandedNodeIdValue =
        #self.QualifiedNameValue =
        #self.LocalizedTextValue =
        #self.StatusCodeValue =
        #self.VariantValue =
        #self.EnumerationValue =
        #self.StructureValue =
        #self.Number =
        #self.Integer =
        #self.UInteger =


        data = struct_to_binary(v)
        v2 = struct_from_binary(s.ScalarValueDataType, ua.utils.Buffer(data))
        self.assertEqual(v.NodeIdValue, v2.NodeIdValue)
예제 #15
0
    def test_string_to_val_xml_element(self):
        string = "<p> titi toto </p>"
        obj = ua.XmlElement(string)

        self.assertEqual(string_to_val(string, ua.VariantType.XmlElement), obj)
        self.assertEqual(val_to_string(obj), string)

        b = struct_to_binary(obj)
        obj2 = struct_from_binary(ua.XmlElement, ua.utils.Buffer(b))
        self.assertEqual(obj, obj2)
예제 #16
0
 def test_binary_struct_example(self):
     # Example test so that we can manually control the object that gets
     # generated and see how it gets serialized/deserialized
     original = ObjectWithOptionalFields()
     serialized = struct_to_binary(original)
     deserialized = struct_from_binary(ObjectWithOptionalFields, ua.utils.Buffer(serialized))
     self.assertEqual(len(original.ua_switches), len(deserialized.ua_switches))
     self.assertEqual(len(original.ua_types), len(deserialized.ua_types))
     for field, _ in original.ua_types:
         self.assertEqual(getattr(original, field), getattr(deserialized, field))
예제 #17
0
    def test_string_to_val_xml_element(self):
        string = "<p> titi toto </p>"
        obj = ua.XmlElement(string)

        self.assertEqual(string_to_val(string, ua.VariantType.XmlElement), obj)
        self.assertEqual(val_to_string(obj), string)

        b = struct_to_binary(obj)
        obj2 = struct_from_binary(ua.XmlElement, ua.utils.Buffer(b))
        self.assertEqual(obj, obj2)
예제 #18
0
    def test_status_code_to_string(self):
        # serialize a status code and deserialize it, name and doc resolution should work just fine
        statuscode = ua.StatusCode(ua.StatusCodes.BadNotConnected)
        statuscode2 = struct_from_binary(ua.StatusCode, io.BytesIO(struct_to_binary(ua.StatusCode(ua.StatusCodes.BadNotConnected))))

        self.assertEqual(statuscode, statuscode2)
        self.assertEqual(statuscode.value, statuscode2.value)

        # properties that are not serialized should still translate properly
        self.assertEqual(statuscode.name, statuscode2.name)
        self.assertEqual(statuscode.doc, statuscode2.doc)
예제 #19
0
def to_binary(chunk, cert, padding=None, ciphertext_manipulator=None):
    """ Convert chunk to binary

    :param chunk: chunk to convert
    :param cert: server certificate to use for ciphertext manipulation
    :param padding: padding function
    :param ciphertext_manipulator: manipulation function for the ciphertext
    :return: bytes to send to the server
    """
    security = struct_to_binary(chunk.SecurityHeader)
    encrypted_part = struct_to_binary(chunk.SequenceHeader) + chunk.Body
    encrypted_part += chunk.security_policy.padding(len(encrypted_part))

    chunk.MessageHeader.body_size = len(security) + chunk.encrypted_size(
        len(encrypted_part))
    header = header_to_binary(chunk.MessageHeader)
    signature = chunk.security_policy.signature(header + security +
                                                encrypted_part)
    encrypted_part += signature

    # if no padding is given, use the default PKCS #1 v1.5 padding
    if not padding:
        plaintext = paddings.pad_pkcs1v15(encrypted_part)
    else:
        plaintext = padding(encrypted_part)

    # extract modulus and exponent from the server certificate
    N = cert.public_key().public_numbers().n
    e = cert.public_key().public_numbers().e

    modulus_bits = int(math.ceil(math.log(N, 2)))
    modulus_bytes = (modulus_bits + 7) // 8

    plaintext_bytes = int.from_bytes(plaintext, byteorder='big')
    ciphertext = int(gmpy2.powmod(plaintext_bytes, e,
                                  N)).to_bytes(modulus_bytes, byteorder="big")
    if ciphertext_manipulator:
        ciphertext = ciphertext_manipulator(ciphertext)

    return header + security + ciphertext
예제 #20
0
 def test_custom_struct_with_optional_fields(self):
     xmlpath = "custom_extension_with_optional_fields.xml"
     c = StructGenerator()
     c.make_model_from_file(xmlpath)
     for m in c.model:
         if type(m) in (Struct, EnumType):
             m.typeid = self._generate_node_id()
     c.save_to_file("custom_extension_with_optional_fields.py", register=True)
     import como_structures as s
     for name, obj in inspect.getmembers(sys.modules[s.__name__], predicate=inspect.isclass):
         if name.startswith('__') or obj in (datetime,) or isinstance(obj, EnumMeta):
             continue
         with self.subTest(name=name):
             original = obj()
             serialized = struct_to_binary(original)
             deserialized = struct_from_binary(obj, ua.utils.Buffer(serialized))
             self.assertCustomStructEqual(original, deserialized)
예제 #21
0
 def _send_request(self, request, callback=None, timeout=1000, message_type=ua.MessageType.SecureMessage):
     """
     send request to server, lower-level method
     timeout is the timeout written in ua header
     returns future
     """
     with self._lock:
         request.RequestHeader = self._create_request_header(timeout)
         self.logger.debug("Sending: %s", request)
         try:
             binreq = struct_to_binary(request)
         except Exception:
             # reset reqeust handle if any error
             # see self._create_request_header
             self._request_handle -= 1
             raise
         self._request_id += 1
         future = Future()
         if callback:
             future.add_done_callback(callback)
         self._callbackmap[self._request_id] = future
         msg = self._connection.message_to_binary(binreq, message_type=message_type, request_id=self._request_id)
         self._socket.write(msg)
     return future
예제 #22
0
def error_message_to_binary(message):
    header = ua.Header(ua.MessageType.Error, ua.ChunkType.Single)
    body = struct_to_binary(message)
    header.body_size = len(body)
    return header_to_binary(header) + body