コード例 #1
0
    def testToElement(self):
        """
        Tests the to_etree method of the OneLogin_Saml2_XML
        """
        xml = '<test>test1</test>'
        elem = etree.fromstring(xml)
        xml_expected = etree.tostring(elem)

        res = OneLogin_Saml2_XML.to_etree(xml)
        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        res = OneLogin_Saml2_XML.to_etree(xml.encode('utf8'))
        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        res = OneLogin_Saml2_XML.to_etree(elem)
        self.assertIs(res, elem)

        with self.assertRaises(ValueError) as context:
            OneLogin_Saml2_XML.to_etree(1)
            exception = context.exception
            self.assertIn("unsupported type", str(exception))
コード例 #2
0
    def testValidateXML(self):
        """
        Tests the validate_xml method of the OneLogin_Saml2_XML
        """
        metadata_unloaded = '<xml><EntityDescriptor>'
        res = OneLogin_Saml2_XML.validate_xml(metadata_unloaded,
                                              'saml-schema-metadata-2.0.xsd')
        self.assertIsInstance(res, str)
        self.assertIn('unloaded_xml', res)

        metadata_invalid = self.file_contents(
            join(self.data_path, 'metadata',
                 'noentity_metadata_settings1.xml'))

        res = OneLogin_Saml2_XML.validate_xml(metadata_invalid,
                                              'saml-schema-metadata-2.0.xsd')
        self.assertIsInstance(res, str)
        self.assertIn('invalid_xml', res)

        metadata_expired = self.file_contents(
            join(self.data_path, 'metadata', 'expired_metadata_settings1.xml'))
        res = OneLogin_Saml2_XML.validate_xml(metadata_expired,
                                              'saml-schema-metadata-2.0.xsd')
        self.assertIsInstance(res, OneLogin_Saml2_XML._element_class)

        metadata_ok = self.file_contents(
            join(self.data_path, 'metadata', 'metadata_settings1.xml'))
        res = OneLogin_Saml2_XML.validate_xml(metadata_ok,
                                              'saml-schema-metadata-2.0.xsd')
        self.assertIsInstance(res, OneLogin_Saml2_XML._element_class)
コード例 #3
0
    def testToElement(self):
        """
        Tests the to_etree method of the OneLogin_Saml2_XML
        """
        xml = '<test>test1</test>'
        elem = etree.fromstring(xml)
        xml_expected = etree.tostring(elem)

        res = OneLogin_Saml2_XML.to_etree(xml)
        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        res = OneLogin_Saml2_XML.to_etree(xml.encode('utf8'))
        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        res = OneLogin_Saml2_XML.to_etree(elem)
        self.assertIs(res, elem)

        self.assertRaisesRegexp(ValueError,
                                'unsupported type',
                                OneLogin_Saml2_XML.to_etree, 1)
コード例 #4
0
    def testToElement(self):
        """
        Tests the to_etree method of the OneLogin_Saml2_XML
        """
        xml = '<test>test1</test>'
        elem = etree.fromstring(xml)
        xml_expected = etree.tostring(elem)

        res = OneLogin_Saml2_XML.to_etree(xml)
        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        res = OneLogin_Saml2_XML.to_etree(xml.encode('utf8'))
        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        res = OneLogin_Saml2_XML.to_etree(elem)
        self.assertIs(res, elem)

        with self.assertRaises(ValueError) as context:
            OneLogin_Saml2_XML.to_etree(1)
            exception = context.exception
            self.assertIn("unsupported type", str(exception))
コード例 #5
0
    def test_start_authentication(self, _, service_provider,
                                  identity_providers):
        configuration = create_autospec(spec=SAMLConfiguration)
        configuration.service_provider_debug_mode = MagicMock(
            return_value=False)
        configuration.service_provider_strict_mode = MagicMock(
            return_value=False)
        configuration.get_service_provider = MagicMock(
            return_value=service_provider)
        configuration.get_identity_providers = MagicMock(
            return_value=identity_providers)
        onelogin_configuration = SAMLOneLoginConfiguration(configuration)
        subject_parser = SAMLSubjectParser()
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)
        subject_filter = SAMLSubjectFilter(evaluator)
        authentication_manager = SAMLAuthenticationManager(
            onelogin_configuration, subject_parser, subject_filter)

        with self.app.test_request_context("/"):
            result = authentication_manager.start_authentication(
                self._db, fixtures.IDP_1_ENTITY_ID, "")

            query_items = parse_qs(urlsplit(result).query)
            saml_request = query_items["SAMLRequest"][0]
            decoded_saml_request = OneLogin_Saml2_Utils.decode_base64_and_inflate(
                saml_request)

            validation_result = OneLogin_Saml2_XML.validate_xml(
                decoded_saml_request, "saml-schema-protocol-2.0.xsd", False)
            assert isinstance(validation_result,
                              OneLogin_Saml2_XML._element_class)

            saml_request_dom = fromstring(decoded_saml_request)

            acs_url = saml_request_dom.get("AssertionConsumerServiceURL")
            assert acs_url == SERVICE_PROVIDER_WITH_UNSIGNED_REQUESTS.acs_service.url

            acs_binding = saml_request_dom.get("ProtocolBinding")
            assert (acs_binding == SERVICE_PROVIDER_WITH_UNSIGNED_REQUESTS.
                    acs_service.binding.value)

            sso_url = saml_request_dom.get("Destination")
            assert sso_url == IDENTITY_PROVIDERS[0].sso_service.url

            name_id_policy_nodes = OneLogin_Saml2_XML.query(
                saml_request_dom, "./samlp:NameIDPolicy")

            assert name_id_policy_nodes is not None
            assert len(name_id_policy_nodes) == 1

            name_id_policy_node = name_id_policy_nodes[0]
            name_id_format = name_id_policy_node.get("Format")

            assert (name_id_format ==
                    SERVICE_PROVIDER_WITH_UNSIGNED_REQUESTS.name_id_format)
コード例 #6
0
    def testQuery(self):
        """
        Tests the query method of the OneLogin_Saml2_Utils
        """
        xml = self.file_contents(
            join(self.data_path, 'responses', 'valid_response.xml.base64'))
        xml = b64decode(xml)
        dom = etree.fromstring(xml)

        assertion_nodes = OneLogin_Saml2_XML.query(
            dom, '/samlp:Response/saml:Assertion')
        self.assertEqual(1, len(assertion_nodes))
        assertion = assertion_nodes[0]
        self.assertIn('Assertion', assertion.tag)

        attribute_statement_nodes = OneLogin_Saml2_XML.query(
            dom, '/samlp:Response/saml:Assertion/saml:AttributeStatement')
        self.assertEqual(1, len(assertion_nodes))
        attribute_statement = attribute_statement_nodes[0]
        self.assertIn('AttributeStatement', attribute_statement.tag)

        attribute_statement_nodes_2 = OneLogin_Saml2_XML.query(
            dom, './saml:AttributeStatement', assertion)
        self.assertEqual(1, len(attribute_statement_nodes_2))
        attribute_statement_2 = attribute_statement_nodes_2[0]
        self.assertEqual(attribute_statement, attribute_statement_2)

        signature_res_nodes = OneLogin_Saml2_XML.query(
            dom, '/samlp:Response/ds:Signature')
        self.assertEqual(1, len(signature_res_nodes))
        signature_res = signature_res_nodes[0]
        self.assertIn('Signature', signature_res.tag)

        signature_nodes = OneLogin_Saml2_XML.query(
            dom, '/samlp:Response/saml:Assertion/ds:Signature')
        self.assertEqual(1, len(signature_nodes))
        signature = signature_nodes[0]
        self.assertIn('Signature', signature.tag)

        signature_nodes_2 = OneLogin_Saml2_XML.query(dom, './ds:Signature',
                                                     assertion)
        self.assertEqual(1, len(signature_nodes_2))
        signature2 = signature_nodes_2[0]
        self.assertNotEqual(signature_res, signature2)
        self.assertEqual(signature, signature2)

        signature_nodes_3 = OneLogin_Saml2_XML.query(dom,
                                                     './ds:SignatureValue',
                                                     assertion)
        self.assertEqual(0, len(signature_nodes_3))

        signature_nodes_4 = OneLogin_Saml2_XML.query(
            dom, './ds:Signature/ds:SignatureValue', assertion)
        self.assertEqual(1, len(signature_nodes_4))

        signature_nodes_5 = OneLogin_Saml2_XML.query(dom,
                                                     './/ds:SignatureValue',
                                                     assertion)
        self.assertEqual(1, len(signature_nodes_5))
コード例 #7
0
    def testToString(self):
        """
        Tests the to_string method of the OneLogin_Saml2_XML
        """
        xml = '<test>test1</test>'
        elem = etree.fromstring(xml)
        bxml = xml.encode('utf8')

        self.assertIs(xml, OneLogin_Saml2_XML.to_string(xml))
        self.assertIs(bxml, OneLogin_Saml2_XML.to_string(bxml))
        self.assertEqual(etree.tostring(elem), OneLogin_Saml2_XML.to_string(elem))
        self.assertRaisesRegexp(ValueError,
                                'unsupported type',
                                OneLogin_Saml2_XML.to_string, 1)
コード例 #8
0
    def testToString(self):
        """
        Tests the to_string method of the OneLogin_Saml2_XML
        """
        xml = '<test>test1</test>'
        elem = etree.fromstring(xml)
        bxml = xml.encode('utf8')

        self.assertIs(xml, OneLogin_Saml2_XML.to_string(xml))
        self.assertIs(bxml, OneLogin_Saml2_XML.to_string(bxml))
        self.assertEqual(etree.tostring(elem),
                         OneLogin_Saml2_XML.to_string(elem))
        self.assertRaisesRegexp(ValueError, 'unsupported type',
                                OneLogin_Saml2_XML.to_string, 1)
コード例 #9
0
    def testToString(self):
        """
        Tests the to_string method of the OneLogin_Saml2_XML
        """
        xml = '<test>test1</test>'
        elem = etree.fromstring(xml)
        bxml = xml.encode('utf8')

        self.assertIs(xml, OneLogin_Saml2_XML.to_string(xml))
        self.assertIs(bxml, OneLogin_Saml2_XML.to_string(bxml))
        self.assertEqual(etree.tostring(elem), OneLogin_Saml2_XML.to_string(elem))
        with self.assertRaises(ValueError) as context:
            OneLogin_Saml2_XML.to_string(1)
            exception = context.exception
            self.assertIn("unsupported type", str(exception))
コード例 #10
0
    def testToString(self):
        """
        Tests the to_string method of the OneLogin_Saml2_XML
        """
        xml = '<test>test1</test>'
        elem = etree.fromstring(xml)
        bxml = xml.encode('utf8')

        self.assertIs(xml, OneLogin_Saml2_XML.to_string(xml))
        self.assertIs(bxml, OneLogin_Saml2_XML.to_string(bxml))
        self.assertEqual(etree.tostring(elem), OneLogin_Saml2_XML.to_string(elem))
        with self.assertRaises(ValueError) as context:
            OneLogin_Saml2_XML.to_string(1)
            exception = context.exception
            self.assertIn("unsupported type", str(exception))
コード例 #11
0
 def testConstructor(self):
     """
     Tests the OneLogin_Saml2_LogoutResponse Constructor.
     """
     settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
     message = self.file_contents(join(self.data_path, 'logout_responses', 'logout_response_deflated.xml.base64'))
     response = OneLogin_Saml2_Logout_Response(settings, message)
     self.assertRegex(compat.to_string(OneLogin_Saml2_XML.to_string(response.document)), '<samlp:LogoutResponse')
コード例 #12
0
    def testQuery(self):
        """
        Tests the query method of the OneLogin_Saml2_Utils
        """
        xml = self.file_contents(join(self.data_path, 'responses', 'valid_response.xml.base64'))
        xml = b64decode(xml)
        dom = etree.fromstring(xml)

        assertion_nodes = OneLogin_Saml2_XML.query(dom, '/samlp:Response/saml:Assertion')
        self.assertEqual(1, len(assertion_nodes))
        assertion = assertion_nodes[0]
        self.assertIn('Assertion', assertion.tag)

        attribute_statement_nodes = OneLogin_Saml2_XML.query(dom, '/samlp:Response/saml:Assertion/saml:AttributeStatement')
        self.assertEqual(1, len(assertion_nodes))
        attribute_statement = attribute_statement_nodes[0]
        self.assertIn('AttributeStatement', attribute_statement.tag)

        attribute_statement_nodes_2 = OneLogin_Saml2_XML.query(dom, './saml:AttributeStatement', assertion)
        self.assertEqual(1, len(attribute_statement_nodes_2))
        attribute_statement_2 = attribute_statement_nodes_2[0]
        self.assertEqual(attribute_statement, attribute_statement_2)

        signature_res_nodes = OneLogin_Saml2_XML.query(dom, '/samlp:Response/ds:Signature')
        self.assertEqual(1, len(signature_res_nodes))
        signature_res = signature_res_nodes[0]
        self.assertIn('Signature', signature_res.tag)

        signature_nodes = OneLogin_Saml2_XML.query(dom, '/samlp:Response/saml:Assertion/ds:Signature')
        self.assertEqual(1, len(signature_nodes))
        signature = signature_nodes[0]
        self.assertIn('Signature', signature.tag)

        signature_nodes_2 = OneLogin_Saml2_XML.query(dom, './ds:Signature', assertion)
        self.assertEqual(1, len(signature_nodes_2))
        signature2 = signature_nodes_2[0]
        self.assertNotEqual(signature_res, signature2)
        self.assertEqual(signature, signature2)

        signature_nodes_3 = OneLogin_Saml2_XML.query(dom, './ds:SignatureValue', assertion)
        self.assertEqual(0, len(signature_nodes_3))

        signature_nodes_4 = OneLogin_Saml2_XML.query(dom, './ds:Signature/ds:SignatureValue', assertion)
        self.assertEqual(1, len(signature_nodes_4))

        signature_nodes_5 = OneLogin_Saml2_XML.query(dom, './/ds:SignatureValue', assertion)
        self.assertEqual(1, len(signature_nodes_5))
コード例 #13
0
 def testConstructor(self):
     """
     Tests the OneLogin_Saml2_LogoutResponse Constructor.
     """
     settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
     message = self.file_contents(
         join(self.data_path, 'logout_responses',
              'logout_response_deflated.xml.base64'))
     response = OneLogin_Saml2_Logout_Response(settings, message)
     self.assertRegex(
         compat.to_string(OneLogin_Saml2_XML.to_string(response.document)),
         '<samlp:LogoutResponse')
コード例 #14
0
    def testValidateXML(self):
        """
        Tests the validate_xml method of the OneLogin_Saml2_XML
        """
        metadata_unloaded = '<xml><EntityDescriptor>'
        res = OneLogin_Saml2_XML.validate_xml(metadata_unloaded, 'saml-schema-metadata-2.0.xsd')
        self.assertIsInstance(res, str)
        self.assertIn('unloaded_xml', res)

        metadata_invalid = self.file_contents(join(self.data_path, 'metadata', 'noentity_metadata_settings1.xml'))

        res = OneLogin_Saml2_XML.validate_xml(metadata_invalid, 'saml-schema-metadata-2.0.xsd')
        self.assertIsInstance(res, str)
        self.assertIn('invalid_xml', res)

        metadata_expired = self.file_contents(join(self.data_path, 'metadata', 'expired_metadata_settings1.xml'))
        res = OneLogin_Saml2_XML.validate_xml(metadata_expired, 'saml-schema-metadata-2.0.xsd')
        self.assertIsInstance(res, OneLogin_Saml2_XML._element_class)

        metadata_ok = self.file_contents(join(self.data_path, 'metadata', 'metadata_settings1.xml'))
        res = OneLogin_Saml2_XML.validate_xml(metadata_ok, 'saml-schema-metadata-2.0.xsd')
        self.assertIsInstance(res, OneLogin_Saml2_XML._element_class)
コード例 #15
0
    def testToElement(self):
        """
        Tests the to_etree method of the OneLogin_Saml2_XML
        """
        xml = '<test>test1</test>'
        elem = etree.fromstring(xml)
        xml_expected = etree.tostring(elem)

        res = OneLogin_Saml2_XML.to_etree(xml)
        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        res = OneLogin_Saml2_XML.to_etree(xml.encode('utf8'))
        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        self.assertIsInstance(res, etree._Element)
        self.assertEqual(xml_expected, etree.tostring(res))

        res = OneLogin_Saml2_XML.to_etree(elem)
        self.assertIs(res, elem)

        self.assertRaisesRegexp(ValueError, 'unsupported type',
                                OneLogin_Saml2_XML.to_etree, 1)
コード例 #16
0
def validateAssertion(xml, fingerprint=None, fingerprintalg=None):

    result = {
        'schemaValidate': False,
        'signCheck': False,
        'certValidity': False,
        'certAllowed': True,
        'error': 0,
        'msg': '',
        'assertionName': None,
        'chkTime': None,
        'chkStatus': None,
        'serviceAttributes': None
    }

    assert isinstance(xml, compat.text_types)

    if len(xml) == 0:
        result['error'] = 1
        result['msg'] = 'Empty string supplied as input'
        return result

    OneLoginResponse = OneLogin_Saml2_Response({}, Saml2_Utils.b64encode(xml))
    xml = xmlRemoveDeclaration(xml)
    parsedassertion = etree.fromstring(xml)

    # assertion name path
    assertionNameXpath = "local-name(/*)"
    assertionName = parsedassertion.xpath(assertionNameXpath)
    assertionName = str(assertionName)

    # find assertion schema
    if assertionName == 'EntityDescriptor':
        asscertionShema = 'saml-schema-metadata-2.0.xsd'
    elif assertionName == 'Response':
        asscertionShema = 'saml-schema-protocol-2.0.xsd'
    elif assertionName == 'AuthnRequest':
        asscertionShema = 'saml-schema-protocol-2.0.xsd'
    else:
        result['error'] = 2
        result['msg'] = 'Assertion unknown'
        return result

    # siganture node path
    signatureNodeXpath = ".//*[local-name()='Signature']"

    if assertionName == 'Response':
        signatureNodeXpath = "*[local-name(/*)='Response']//*[local-name()='Signature']"

    result['assertionName'] = assertionName
    # get certificate signing
    try:
        signingcert = easyspid.lib.easyspid.get_signature_cert(xml)

    except Exception as error:
        signingcert = False

    # validate xml against its schema
    schemaCheck = OneLogin_Saml2_XML.validate_xml(xml, asscertionShema, False)
    if isinstance(schemaCheck, str):
        result['msg'] = schemaCheck
        result['schemaValidate'] = False
        result['error'] = 3
    else:
        result['schemaValidate'] = True

    # check signature
    if signingcert:
        signingfingerprintalg = 'sha1'
        if fingerprintalg is not None:
            signingfingerprintalg = fingerprintalg

        signingfingerprint = (easyspid.lib.easyspid.calcCertFingerprint(
            signingcert, signingfingerprintalg))['result']

        if assertionName == 'EntityDescriptor' and fingerprint is None:
            allowedCert = easyspid.lib.easyspid.get_metadata_allowed_cert(xml)
            allowedfingerprint = (easyspid.lib.easyspid.calcCertFingerprint(
                allowedCert, signingfingerprintalg))['result']

        elif assertionName != 'EntityDescriptor' and fingerprint is None:
            allowedfingerprint = signingfingerprint

        if fingerprint is not None:
            allowedfingerprint = fingerprint

        signCheck = Saml2_Utils.validate_sign(
            xml,
            cert=signingcert,
            fingerprint=signingfingerprint,
            fingerprintalg=signingfingerprintalg,
            validatecert=False,
            debug=False,
            xpath=signatureNodeXpath,
            multicerts=None)

        if signCheck:
            result['signCheck'] = True
        else:
            result['error'] = 3

        # check expired certificate
        certTimeValdity = easyspid.lib.easyspid.timeValidateCert(signingcert)
        if certTimeValdity:
            result['certValidity'] = True

        # checktime certificate allow
        if allowedfingerprint != signingfingerprint:
            result['certAllowed'] = False
            result['error'] = 3

    elif not signingcert and assertionName == 'AuthnRequest':
        result['signCheck'] = None
        result['certValidity'] = None
        result['certAllowed'] = None

    if assertionName == 'Response':
        try:
            OneLoginResponse.validate_timestamps(raise_exceptions=True)
            result['chkTime'] = True

        except OneLogin_Saml2_ValidationError as error:
            result['chkTime'] = False
            result['error'] = 3

        try:
            OneLoginResponse.check_status()
            result['chkStatus'] = True

        except OneLogin_Saml2_ValidationError as error:
            result['chkStatus'] = False
            result['error'] = 3

    try:
        result['serviceAttributes'] = OneLoginResponse.get_attributes()
    except:
        pass

    return result
コード例 #17
0
def AddSign(xml,
            key,
            cert,
            debug=False,
            sign_algorithm=OneLogin_Saml2_Constants.RSA_SHA1,
            digest_algorithm=OneLogin_Saml2_Constants.SHA1,
            addKeyValue=False):
    """
        Adds signature key and senders certificate to an element (Message or
        Assertion).

        :param xml: The element we should sign
        :type: string | Document

        :param key: The private key
        :type: string

        :param cert: The public
        :type: string

        :param debug: Activate the xmlsec debug
        :type: bool

        :param sign_algorithm: Signature algorithm method
        :type sign_algorithm: string

        :param digest_algorithm: Digest algorithm method
        :type digest_algorithm: string

        :returns: Signed XML
        :rtype: string
        """
    if xml is None or xml == '':
        raise Exception('Empty string supplied as input')

    elem = OneLogin_Saml2_XML.to_etree(xml)
    xmlsec.enable_debug_trace(debug)
    xmlsec.tree.add_ids(elem, ["ID"])
    # Sign the metadata with our private key.
    sign_algorithm_transform_map = {
        OneLogin_Saml2_Constants.DSA_SHA1: xmlsec.Transform.DSA_SHA1,
        OneLogin_Saml2_Constants.RSA_SHA1: xmlsec.Transform.RSA_SHA1,
        OneLogin_Saml2_Constants.RSA_SHA256: xmlsec.Transform.RSA_SHA256,
        OneLogin_Saml2_Constants.RSA_SHA384: xmlsec.Transform.RSA_SHA384,
        OneLogin_Saml2_Constants.RSA_SHA512: xmlsec.Transform.RSA_SHA512
    }
    sign_algorithm_transform = sign_algorithm_transform_map.get(
        sign_algorithm, xmlsec.Transform.RSA_SHA1)

    signature = xmlsec.template.create(elem,
                                       xmlsec.Transform.EXCL_C14N,
                                       sign_algorithm_transform,
                                       ns='ds')

    issuer = OneLogin_Saml2_XML.query(elem, '//saml:Issuer')
    if len(issuer) > 0:
        issuer = issuer[0]
        issuer.addnext(signature)
    else:
        elem.insert(0, signature)

    elem_id = elem.get('ID', None)
    if elem_id:
        elem_id = '#' + elem_id
    #else:
    #    elem_id = ""

    digest_algorithm_transform_map = {
        OneLogin_Saml2_Constants.SHA1: xmlsec.Transform.SHA1,
        OneLogin_Saml2_Constants.SHA256: xmlsec.Transform.SHA256,
        OneLogin_Saml2_Constants.SHA384: xmlsec.Transform.SHA384,
        OneLogin_Saml2_Constants.SHA512: xmlsec.Transform.SHA512
    }
    digest_algorithm_transform = digest_algorithm_transform_map.get(
        digest_algorithm, xmlsec.Transform.SHA1)

    ref = xmlsec.template.add_reference(signature,
                                        digest_algorithm_transform,
                                        uri=elem_id)
    xmlsec.template.add_transform(ref, xmlsec.Transform.ENVELOPED)
    xmlsec.template.add_transform(ref, xmlsec.Transform.EXCL_C14N)
    key_info = xmlsec.template.ensure_key_info(signature)
    if addKeyValue:
        xmlsec.template.add_key_value(key_info)
    xmlsec.template.add_x509_data(key_info)

    dsig_ctx = xmlsec.SignatureContext()
    sign_key = xmlsec.Key.from_memory(key, xmlsec.KeyFormat.PEM, None)
    sign_key.load_cert_from_memory(cert, xmlsec.KeyFormat.PEM)

    dsig_ctx.key = sign_key
    dsig_ctx.sign(signature)

    return OneLogin_Saml2_XML.to_string(elem)
コード例 #18
0
    def validate_metadata_sign(xml,
                               cert=None,
                               fingerprint=None,
                               fingerprintalg='sha1',
                               validatecert=False,
                               debug=False):
        """
        Validates a signature of a EntityDescriptor.

        :param xml: The element we should validate
        :type: string | Document

        :param cert: The public cert
        :type: string

        :param fingerprint: The fingerprint of the public cert
        :type: string

        :param fingerprintalg: The algorithm used to build the fingerprint
        :type: string

        :param validatecert: If true, will verify the signature and if the cert is valid.
        :type: bool

        :param debug: Activate the xmlsec debug
        :type: bool

        :param raise_exceptions: Whether to return false on failure or raise an exception
        :type raise_exceptions: Boolean
        """
        if xml is None or xml == '':
            raise Exception('Empty string supplied as input')

        elem = OneLogin_Saml2_XML.to_etree(xml)
        xmlsec.enable_debug_trace(debug)
        xmlsec.tree.add_ids(elem, ["ID"])

        signature_nodes = OneLogin_Saml2_XML.query(
            elem, '/md:EntitiesDescriptor/ds:Signature')

        if len(signature_nodes) == 0:
            signature_nodes += OneLogin_Saml2_XML.query(
                elem, '/md:EntityDescriptor/ds:Signature')

            if len(signature_nodes) == 0:
                signature_nodes += OneLogin_Saml2_XML.query(
                    elem,
                    '/md:EntityDescriptor/md:SPSSODescriptor/ds:Signature')
                signature_nodes += OneLogin_Saml2_XML.query(
                    elem,
                    '/md:EntityDescriptor/md:IDPSSODescriptor/ds:Signature')

        if len(signature_nodes) > 0:
            for signature_node in signature_nodes:
                # Raises expection if invalid
                Saml2_Utils.validate_node_sign(signature_node,
                                               elem,
                                               cert,
                                               fingerprint,
                                               fingerprintalg,
                                               validatecert,
                                               debug,
                                               raise_exceptions=True)
            return True
        else:
            raise Exception(
                'Could not validate metadata signature: No signature nodes found.'
            )
コード例 #19
0
    def validate_node_sign(signature_node,
                           elem,
                           cert=None,
                           fingerprint=None,
                           fingerprintalg='sha1',
                           validatecert=False,
                           debug=False):
        """
        Validates a signature node.

        :param signature_node: The signature node
        :type: Node

        :param xml: The element we should validate
        :type: Document

        :param cert: The public cert
        :type: string

        :param fingerprint: The fingerprint of the public cert
        :type: string

        :param fingerprintalg: The algorithm used to build the fingerprint
        :type: string

        :param validatecert: If true, will verify the signature and if the cert is valid.
        :type: bool

        :param debug: Activate the xmlsec debug
        :type: bool

        :param raise_exceptions: Whether to return false on failure or raise an exception
        :type raise_exceptions: Boolean
        """
        if (cert is None or cert == '') and fingerprint:
            x509_certificate_nodes = OneLogin_Saml2_XML.query(
                signature_node,
                '//ds:Signature/ds:KeyInfo/ds:X509Data/ds:X509Certificate')
            if len(x509_certificate_nodes) > 0:
                x509_certificate_node = x509_certificate_nodes[0]
                x509_cert_value = OneLogin_Saml2_XML.element_text(
                    x509_certificate_node)
                x509_cert_value_formatted = Saml2_Utils.format_cert(
                    x509_cert_value)
                x509_fingerprint_value = Saml2_Utils.calculate_x509_fingerprint(
                    x509_cert_value_formatted, fingerprintalg)
                if fingerprint == x509_fingerprint_value:
                    cert = x509_cert_value_formatted

        if cert is None or cert == '':
            raise OneLogin_Saml2_Error(
                'Could not validate node signature: No certificate provided.',
                OneLogin_Saml2_Error.CERT_NOT_FOUND)

        # Check if Reference URI is empty
        #reference_elem = OneLogin_Saml2_XML.query(signature_node, '//ds:Reference')
        #if len(reference_elem) > 0:
        #    if reference_elem[0].get('URI') == '':
        #        reference_elem[0].set('URI', '#%s' % signature_node.getparent().get('ID'))

        if validatecert:
            manager = xmlsec.KeysManager()
            manager.load_cert_from_memory(cert, xmlsec.KeyFormat.CERT_PEM,
                                          xmlsec.KeyDataType.TRUSTED)
            dsig_ctx = xmlsec.SignatureContext(manager)
        else:
            dsig_ctx = xmlsec.SignatureContext()
            dsig_ctx.key = xmlsec.Key.from_memory(cert,
                                                  xmlsec.KeyFormat.CERT_PEM,
                                                  None)

        dsig_ctx.set_enabled_key_data([xmlsec.KeyData.X509])

        try:
            dsig_ctx.verify(signature_node)
        except Exception as err:
            raise OneLogin_Saml2_ValidationError(
                'Signature validation failed. SAML Response rejected. %s',
                OneLogin_Saml2_ValidationError.INVALID_SIGNATURE, str(err))

        return True
コード例 #20
0
    def validate_metadata(self,
                          xml,
                          fingerprint=None,
                          fingerprintalg='sha1',
                          validatecert=False):
        """
        Validates an XML SP Metadata.

        :param xml: Metadata's XML that will be validate
        :type xml: string

        :param fingerprint: The fingerprint of the public cert
        :type: string

        :param fingerprintalg: The algorithm used to build the fingerprint
        :type: string

        :param validatecert: If true, will verify the signature and if the cert is valid.
        :type: bool

        :returns: a dictionary with the list of found validation errors and signature check
        :rtype: dict
        """
        result = {
            'schemaValidate': True,
            'signCheck': False,
            'error': 0,
            'msg': ''
        }

        assert isinstance(xml, compat.text_types)

        if len(xml) == 0:
            raise Exception('Empty string supplied as input')

        #errors = {'validate':[], 'signCheck':0}
        root = OneLogin_Saml2_XML.validate_xml(
            xml, 'saml-schema-metadata-2.0.xsd',
            self._OneLogin_Saml2_Settings__debug)
        if isinstance(root, str):
            result['msg'] = root
            result['schemaValidate'] = False
        else:
            if root.tag != '{%s}EntityDescriptor' % OneLogin_Saml2_Constants.NS_MD:
                result['msg'] = 'noEntityDescriptor_xml'
                result['error'] = 1
                result['schemaValidate'] = False
                #errors.append('noEntityDescriptor_xml')
            else:
                if (len(
                        root.findall(
                            './/md:SPSSODescriptor',
                            namespaces=OneLogin_Saml2_Constants.NSMAP))) != 1:
                    #errors.append('onlySPSSODescriptor_allowed_xml')
                    result['msg'] = 'onlySPSSODescriptor_allowed_xml'
                    result['error'] = 2
                    result['schemaValidate'] = False
                else:
                    valid_until, cache_duration = root.get(
                        'validUntil'), root.get('cacheDuration')

                    if valid_until:
                        valid_until = Saml2_Utils.parse_SAML_to_time(
                            valid_until)
                    expire_time = Saml2_Utils.get_expire_time(
                        cache_duration, valid_until)
                    if expire_time is not None and int(
                            time()) > int(expire_time):
                        #errors.append('expired_xml')
                        result['msg'] = 'expired_xml'
                        result['error'] = 3
                        result['schemaValidate'] = False

        # Validate Sign
        signCheck = Saml2_Utils.validate_metadata_sign(
            xml,
            fingerprint=fingerprint,
            fingerprintalg=fingerprintalg,
            validatecert=validatecert)
        if signCheck:
            result['signCheck'] = True

        return result