Ejemplo n.º 1
0
    def __decrypt_assertion(self, dom):
        """
        Decrypts the Assertion

        :raises: Exception if no private key available
        :param dom: Encrypted Assertion
        :type dom: Element
        :returns: Decrypted Assertion
        :rtype: Element
        """
        key = self.__settings.get_sp_key()

        if not key:
            raise Exception('No private key available, check settings')

        encrypted_assertion_nodes = OneLogin_Saml2_Utils.query(
            dom, '//saml:EncryptedAssertion')
        if encrypted_assertion_nodes:
            encrypted_data_nodes = OneLogin_Saml2_Utils.query(
                encrypted_assertion_nodes[0],
                '//saml:EncryptedAssertion/xenc:EncryptedData')
            if encrypted_data_nodes:
                encrypted_data = encrypted_data_nodes[0]
                OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        return dom
Ejemplo n.º 2
0
    def testDecryptElementInplace(self):
        """
        Tests the decrypt_element method of the OneLogin_Saml2_Utils with inplace=True
        """
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())

        key = settings.get_sp_key()

        xml_nameid_enc = b64decode(self.file_contents(join(self.data_path, 'responses', 'response_encrypted_nameid.xml.base64')))
        dom = fromstring(xml_nameid_enc)
        encrypted_node = dom.xpath('//saml:EncryptedID/xenc:EncryptedData', namespaces=OneLogin_Saml2_Constants.NSMAP)[0]

        # can be decrypted twice when copy the node first
        for _ in range(2):
            decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=False)
            self.assertIn('NameID', decrypted_nameid.tag)
            self.assertEqual('2de11defd199f8d5bb63f9b7deb265ba5c675c10', decrypted_nameid.text)

        # can only be decrypted once in place
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=True)
        self.assertIn('NameID', decrypted_nameid.tag)
        self.assertEqual('2de11defd199f8d5bb63f9b7deb265ba5c675c10', decrypted_nameid.text)

        # can't be decrypted twice since it has been decrypted inplace
        with self.assertRaisesRegex(Exception, "(1, 'failed to decrypt')"):
            OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=True)
Ejemplo n.º 3
0
    def testDecryptElement(self):
        """
        Tests the decrypt_element method of the OneLogin_Saml2_Utils
        """
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())

        key = settings.get_sp_key()

        xml_nameid_enc = b64decode(self.file_contents(join(self.data_path, 'responses', 'response_encrypted_nameid.xml.base64')))
        dom_nameid_enc = etree.fromstring(xml_nameid_enc)
        encrypted_nameid_nodes = dom_nameid_enc.find('.//saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data = encrypted_nameid_nodes[0]
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        self.assertEqual('{%s}NameID' % OneLogin_Saml2_Constants.NS_SAML, decrypted_nameid.tag)
        self.assertEqual('2de11defd199f8d5bb63f9b7deb265ba5c675c10', decrypted_nameid.text)

        xml_assertion_enc = b64decode(self.file_contents(join(self.data_path, 'responses', 'valid_encrypted_assertion_encrypted_nameid.xml.base64')))
        dom_assertion_enc = etree.fromstring(xml_assertion_enc)
        encrypted_assertion_enc_nodes = dom_assertion_enc.find('.//saml:EncryptedAssertion', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data_assert = encrypted_assertion_enc_nodes[0]

        decrypted_assertion = OneLogin_Saml2_Utils.decrypt_element(encrypted_data_assert, key)
        self.assertEqual('{%s}Assertion' % OneLogin_Saml2_Constants.NS_SAML, decrypted_assertion.tag)
        self.assertEqual('_6fe189b1c241827773902f2b1d3a843418206a5c97', decrypted_assertion.get('ID'))

        encrypted_nameid_nodes = decrypted_assertion.xpath('./saml:Subject/saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data = encrypted_nameid_nodes[0][0]
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        self.assertEqual('{%s}NameID' % OneLogin_Saml2_Constants.NS_SAML, decrypted_nameid.tag)
        self.assertEqual('457bdb600de717891c77647b0806ce59c089d5b8', decrypted_nameid.text)

        key_2_file_name = join(self.data_path, 'misc', 'sp2.key')
        f = open(key_2_file_name, 'r')
        key2 = f.read()
        f.close()

        self.assertRaises(Exception, OneLogin_Saml2_Utils.decrypt_element, encrypted_data, key2)

        key_3_file_name = join(self.data_path, 'misc', 'sp2.key')
        f = open(key_3_file_name, 'r')
        key3 = f.read()
        f.close()
        self.assertRaises(Exception, OneLogin_Saml2_Utils.decrypt_element, encrypted_data, key3)
        xml_nameid_enc_2 = b64decode(self.file_contents(join(self.data_path, 'responses', 'invalids', 'encrypted_nameID_without_EncMethod.xml.base64')))
        dom_nameid_enc_2 = etree.fromstring(xml_nameid_enc_2)
        encrypted_nameid_nodes_2 = dom_nameid_enc_2.find('.//saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data_2 = encrypted_nameid_nodes_2[0]
        self.assertRaises(Exception, OneLogin_Saml2_Utils.decrypt_element, encrypted_data_2, key)

        xml_nameid_enc_3 = b64decode(self.file_contents(join(self.data_path, 'responses', 'invalids', 'encrypted_nameID_without_keyinfo.xml.base64')))
        dom_nameid_enc_3 = etree.fromstring(xml_nameid_enc_3)
        encrypted_nameid_nodes_3 = dom_nameid_enc_3.find('.//saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data_3 = encrypted_nameid_nodes_3[0]
        self.assertRaises(Exception, OneLogin_Saml2_Utils.decrypt_element, encrypted_data_3, key)
Ejemplo n.º 4
0
    def testDecryptElement(self):
        """
        Tests the decrypt_element method of the OneLogin_Saml2_Utils
        """
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())

        key = settings.get_sp_key()

        xml_nameid_enc = b64decode(self.file_contents(join(self.data_path, 'responses', 'response_encrypted_nameid.xml.base64')))
        dom_nameid_enc = etree.fromstring(xml_nameid_enc)
        encrypted_nameid_nodes = dom_nameid_enc.find('.//saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data = encrypted_nameid_nodes[0]
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        self.assertEqual('{%s}NameID' % OneLogin_Saml2_Constants.NS_SAML, decrypted_nameid.tag)
        self.assertEqual('2de11defd199f8d5bb63f9b7deb265ba5c675c10', decrypted_nameid.text)

        xml_assertion_enc = b64decode(self.file_contents(join(self.data_path, 'responses', 'valid_encrypted_assertion_encrypted_nameid.xml.base64')))
        dom_assertion_enc = etree.fromstring(xml_assertion_enc)
        encrypted_assertion_enc_nodes = dom_assertion_enc.find('.//saml:EncryptedAssertion', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data_assert = encrypted_assertion_enc_nodes[0]

        decrypted_assertion = OneLogin_Saml2_Utils.decrypt_element(encrypted_data_assert, key)
        self.assertEqual('{%s}Assertion' % OneLogin_Saml2_Constants.NS_SAML, decrypted_assertion.tag)
        self.assertEqual('_6fe189b1c241827773902f2b1d3a843418206a5c97', decrypted_assertion.get('ID'))

        encrypted_nameid_nodes = decrypted_assertion.xpath('./saml:Subject/saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data = encrypted_nameid_nodes[0][0]
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        self.assertEqual('{%s}NameID' % OneLogin_Saml2_Constants.NS_SAML, decrypted_nameid.tag)
        self.assertEqual('457bdb600de717891c77647b0806ce59c089d5b8', decrypted_nameid.text)

        key_2_file_name = join(self.data_path, 'misc', 'sp2.key')
        f = open(key_2_file_name, 'r')
        key2 = f.read()
        f.close()

        self.assertRaises(Exception, OneLogin_Saml2_Utils.decrypt_element, encrypted_data, key2)

        key_3_file_name = join(self.data_path, 'misc', 'sp2.key')
        f = open(key_3_file_name, 'r')
        key3 = f.read()
        f.close()
        self.assertRaises(Exception, OneLogin_Saml2_Utils.decrypt_element, encrypted_data, key3)
        xml_nameid_enc_2 = b64decode(self.file_contents(join(self.data_path, 'responses', 'invalids', 'encrypted_nameID_without_EncMethod.xml.base64')))
        dom_nameid_enc_2 = etree.fromstring(xml_nameid_enc_2)
        encrypted_nameid_nodes_2 = dom_nameid_enc_2.find('.//saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data_2 = encrypted_nameid_nodes_2[0]
        self.assertRaises(Exception, OneLogin_Saml2_Utils.decrypt_element, encrypted_data_2, key)

        xml_nameid_enc_3 = b64decode(self.file_contents(join(self.data_path, 'responses', 'invalids', 'encrypted_nameID_without_keyinfo.xml.base64')))
        dom_nameid_enc_3 = etree.fromstring(xml_nameid_enc_3)
        encrypted_nameid_nodes_3 = dom_nameid_enc_3.find('.//saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data_3 = encrypted_nameid_nodes_3[0]
        self.assertRaises(Exception, OneLogin_Saml2_Utils.decrypt_element, encrypted_data_3, key)
Ejemplo n.º 5
0
    def __decrypt_assertion(self, dom):
        """
        Decrypts the Assertion

        :raises: Exception if no private key available
        :param dom: Encrypted Assertion
        :type dom: Element
        :returns: Decrypted Assertion
        :rtype: Element
        """
        key = self.__settings.get_sp_key()
        debug = self.__settings.is_debug_active()

        if not key:
            raise Exception('No private key available, check settings')

        encrypted_assertion_nodes = OneLogin_Saml2_Utils.query(
            dom, '/samlp:Response/saml:EncryptedAssertion')
        if encrypted_assertion_nodes:
            encrypted_data_nodes = OneLogin_Saml2_Utils.query(
                encrypted_assertion_nodes[0],
                '//saml:EncryptedAssertion/xenc:EncryptedData')
            if encrypted_data_nodes:
                keyinfo = OneLogin_Saml2_Utils.query(
                    encrypted_assertion_nodes[0],
                    '//saml:EncryptedAssertion/xenc:EncryptedData/ds:KeyInfo')
                if not keyinfo:
                    raise Exception('No KeyInfo present, invalid Assertion')
                keyinfo = keyinfo[0]
                children = keyinfo.getchildren()
                if not children:
                    raise Exception('No child to KeyInfo, invalid Assertion')
                for child in children:
                    if 'RetrievalMethod' in child.tag:
                        if child.attrib[
                                'Type'] != 'http://www.w3.org/2001/04/xmlenc#EncryptedKey':
                            raise Exception(
                                'Unsupported Retrieval Method found')
                        uri = child.attrib['URI']
                        if not uri.startswith('#'):
                            break
                        uri = uri.split('#')[1]
                        encrypted_key = OneLogin_Saml2_Utils.query(
                            encrypted_assertion_nodes[0],
                            './xenc:EncryptedKey[@Id="' + uri + '"]')
                        if encrypted_key:
                            keyinfo.append(encrypted_key[0])

                encrypted_data = encrypted_data_nodes[0]
                OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key,
                                                     debug)
        return dom
Ejemplo n.º 6
0
    def get_nameid_data(self):
        """
        Gets the NameID Data provided by the SAML Response from the IdP

        :returns: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        nameid = None
        nameid_data = {}

        encrypted_id_data_nodes = self.__query_assertion('/saml:Subject/saml:EncryptedID/xenc:EncryptedData')
        if encrypted_id_data_nodes:
            encrypted_data = encrypted_id_data_nodes[0]
            key = self.__settings.get_sp_key()
            nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        else:
            nameid_nodes = self.__query_assertion('/saml:Subject/saml:NameID')
            if nameid_nodes:
                nameid = nameid_nodes[0]
        if nameid is None:
            security = self.__settings.get_security_data()

            if security.get('wantNameId', True):
                raise Exception('Not NameID found in the assertion of the Response')
        else:
            nameid_data = {'Value': nameid.text}
            for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
                value = nameid.get(attr, None)
                if value:
                    nameid_data[attr] = value
        return nameid_data
Ejemplo n.º 7
0
    def get_nameid_data(self):
        """
        Gets the NameID Data provided by the SAML Response from the IdP

        :returns: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        nameid = None
        encrypted_id_data_nodes = self.__query_assertion(
            '/saml:Subject/saml:EncryptedID/xenc:EncryptedData')
        if encrypted_id_data_nodes:
            encrypted_data = encrypted_id_data_nodes[0]
            key = self.__settings.get_sp_key()
            nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        else:
            nameid_nodes = self.__query_assertion('/saml:Subject/saml:NameID')
            if nameid_nodes:
                nameid = nameid_nodes[0]
        if nameid is None:
            raise Exception(
                'Not NameID found in the assertion of the Response')

        nameid_data = {'Value': nameid.text}
        for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
            value = nameid.get(attr, None)
            if value:
                nameid_data[attr] = value
        return nameid_data
Ejemplo n.º 8
0
    def __decrypt_assertion(self, dom):
        """
        Decrypts the Assertion

        :raises: Exception if no private key available

        :param dom: Encrypted Assertion
        :type dom: Element

        :returns: Decrypted Assertion
        :rtype: Element
        """
        key = self.__settings.get_sp_key()
        debug = self.__settings.is_debug_active()

        if not key:
            raise OneLogin_Saml2_Error(
                'No private key available to decrypt the assertion, check settings',
                OneLogin_Saml2_Error.PRIVATE_KEY_NOT_FOUND
            )

        encrypted_assertion_nodes = OneLogin_Saml2_Utils.query(dom, '/samlp:Response/saml:EncryptedAssertion')
        if encrypted_assertion_nodes:
            encrypted_data_nodes = OneLogin_Saml2_Utils.query(encrypted_assertion_nodes[0], '//saml:EncryptedAssertion/xenc:EncryptedData')
            if encrypted_data_nodes:
                keyinfo = OneLogin_Saml2_Utils.query(encrypted_assertion_nodes[0], '//saml:EncryptedAssertion/xenc:EncryptedData/ds:KeyInfo')
                if not keyinfo:
                    raise OneLogin_Saml2_ValidationError(
                        'No KeyInfo present, invalid Assertion',
                        OneLogin_Saml2_ValidationError.KEYINFO_NOT_FOUND_IN_ENCRYPTED_DATA
                    )
                keyinfo = keyinfo[0]
                children = keyinfo.getchildren()
                if not children:
                    raise OneLogin_Saml2_ValidationError(
                        'KeyInfo has no children nodes, invalid Assertion',
                        OneLogin_Saml2_ValidationError.CHILDREN_NODE_NOT_FOUND_IN_KEYINFO
                    )
                for child in children:
                    if 'RetrievalMethod' in child.tag:
                        if child.attrib['Type'] != 'http://www.w3.org/2001/04/xmlenc#EncryptedKey':
                            raise OneLogin_Saml2_ValidationError(
                                'Unsupported Retrieval Method found',
                                OneLogin_Saml2_ValidationError.UNSUPPORTED_RETRIEVAL_METHOD
                            )
                        uri = child.attrib['URI']
                        if not uri.startswith('#'):
                            break
                        uri = uri.split('#')[1]
                        encrypted_key = OneLogin_Saml2_Utils.query(encrypted_assertion_nodes[0], './xenc:EncryptedKey[@Id="' + uri + '"]')
                        if encrypted_key:
                            keyinfo.append(encrypted_key[0])

                encrypted_data = encrypted_data_nodes[0]
                decrypted = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key, debug=debug, inplace=True)
                dom.replace(encrypted_assertion_nodes[0], decrypted)

        return dom
Ejemplo n.º 9
0
    def __decrypt_assertion(self, dom):
        """
        Decrypts the Assertion

        :raises: Exception if no private key available

        :param dom: Encrypted Assertion
        :type dom: Element

        :returns: Decrypted Assertion
        :rtype: Element
        """
        key = self.__settings.get_sp_key()
        debug = self.__settings.is_debug_active()

        if not key:
            raise OneLogin_Saml2_Error(
                'No private key available to decrypt the assertion, check settings',
                OneLogin_Saml2_Error.PRIVATE_KEY_NOT_FOUND
            )

        encrypted_assertion_nodes = OneLogin_Saml2_Utils.query(dom, '/samlp:Response/saml:EncryptedAssertion')
        if encrypted_assertion_nodes:
            encrypted_data_nodes = OneLogin_Saml2_Utils.query(encrypted_assertion_nodes[0], '//saml:EncryptedAssertion/xenc:EncryptedData')
            if encrypted_data_nodes:
                keyinfo = OneLogin_Saml2_Utils.query(encrypted_assertion_nodes[0], '//saml:EncryptedAssertion/xenc:EncryptedData/ds:KeyInfo')
                if not keyinfo:
                    raise OneLogin_Saml2_ValidationError(
                        'No KeyInfo present, invalid Assertion',
                        OneLogin_Saml2_ValidationError.KEYINFO_NOT_FOUND_IN_ENCRYPTED_DATA
                    )
                keyinfo = keyinfo[0]
                children = keyinfo.getchildren()
                if not children:
                    raise OneLogin_Saml2_ValidationError(
                        'KeyInfo has no children nodes, invalid Assertion',
                        OneLogin_Saml2_ValidationError.CHILDREN_NODE_NOT_FOUND_IN_KEYINFO
                    )
                for child in children:
                    if 'RetrievalMethod' in child.tag:
                        if child.attrib['Type'] != 'http://www.w3.org/2001/04/xmlenc#EncryptedKey':
                            raise OneLogin_Saml2_ValidationError(
                                'Unsupported Retrieval Method found',
                                OneLogin_Saml2_ValidationError.UNSUPPORTED_RETRIEVAL_METHOD
                            )
                        uri = child.attrib['URI']
                        if not uri.startswith('#'):
                            break
                        uri = uri.split('#')[1]
                        encrypted_key = OneLogin_Saml2_Utils.query(encrypted_assertion_nodes[0], './xenc:EncryptedKey[@Id=$tagid]', None, uri)
                        if encrypted_key:
                            keyinfo.append(encrypted_key[0])

                encrypted_data = encrypted_data_nodes[0]
                decrypted = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key, debug=debug, inplace=True)
                dom.replace(encrypted_assertion_nodes[0], decrypted)

        return dom
Ejemplo n.º 10
0
    def __decrypt_assertion(self, xml):
        """
        Decrypts the Assertion

        :raises: Exception if no private key available
        :param xml: Encrypted Assertion
        :type xml: Element
        :returns: Decrypted Assertion
        :rtype: Element
        """
        key = self.__settings.get_sp_key()
        debug = self.__settings.is_debug_active()

        if not key:
            raise Exception('No private key available, check settings')

        encrypted_assertion_nodes = OneLogin_Saml2_XML.query(xml, '/samlp:Response/saml:EncryptedAssertion')
        if encrypted_assertion_nodes:
            encrypted_data_nodes = OneLogin_Saml2_XML.query(encrypted_assertion_nodes[0], '//saml:EncryptedAssertion/xenc:EncryptedData')
            if encrypted_data_nodes:
                keyinfo = OneLogin_Saml2_XML.query(encrypted_assertion_nodes[0], '//saml:EncryptedAssertion/xenc:EncryptedData/ds:KeyInfo')
                if not keyinfo:
                    raise Exception('No KeyInfo present, invalid Assertion')
                keyinfo = keyinfo[0]
                children = keyinfo.getchildren()
                if not children:
                    raise Exception('No child to KeyInfo, invalid Assertion')
                for child in children:
                    if 'RetrievalMethod' in child.tag:
                        if child.attrib['Type'] != 'http://www.w3.org/2001/04/xmlenc#EncryptedKey':
                            raise Exception('Unsupported Retrieval Method found')
                        uri = child.attrib['URI']
                        if not uri.startswith('#'):
                            break
                        uri = uri.split('#')[1]
                        encrypted_key = OneLogin_Saml2_XML.query(encrypted_assertion_nodes[0], './xenc:EncryptedKey[@Id="' + uri + '"]')
                        if encrypted_key:
                            keyinfo.append(encrypted_key[0])

                encrypted_data = encrypted_data_nodes[0]
                OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key, debug)
        return xml
Ejemplo n.º 11
0
    def get_nameid_data(self):
        """
        Gets the NameID Data provided by the SAML Response from the IdP

        :returns: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        nameid = None
        nameid_data = {}

        encrypted_id_data_nodes = self.__query_assertion(
            '/saml2:Subject/saml2:EncryptedID/xenc:EncryptedData')
        if encrypted_id_data_nodes:
            encrypted_data = encrypted_id_data_nodes[0]
            key = self.__settings.get_sp_key()
            nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        else:
            nameid_nodes = self.__query_assertion(
                '/saml2:Subject/saml2:NameID')
            if nameid_nodes:
                nameid = nameid_nodes[0]

        is_strict = self.__settings.is_strict()
        want_nameid = self.__settings.get_security_data().get(
            'wantNameId', True)
        if nameid is None:
            if is_strict and want_nameid:
                raise OneLogin_Saml2_ValidationError(
                    'NameID not found in the assertion of the Response',
                    OneLogin_Saml2_ValidationError.NO_NAMEID)
        else:
            if is_strict and want_nameid and not OneLogin_Saml2_XML.element_text(
                    nameid):
                raise OneLogin_Saml2_ValidationError(
                    'An empty NameID value found',
                    OneLogin_Saml2_ValidationError.EMPTY_NAMEID)

            nameid_data = {'Value': OneLogin_Saml2_XML.element_text(nameid)}
            for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
                value = nameid.get(attr, None)
                if value:
                    if is_strict and attr == 'SPNameQualifier':
                        sp_data = self.__settings.get_sp_data()
                        sp_entity_id = sp_data.get('entityId', '')
                        if sp_entity_id != value:
                            raise OneLogin_Saml2_ValidationError(
                                'The SPNameQualifier value mistmatch the SP entityID value.',
                                OneLogin_Saml2_ValidationError.
                                SP_NAME_QUALIFIER_NAME_MISMATCH)

                    nameid_data[attr] = value
        return nameid_data
Ejemplo n.º 12
0
    def __decrypt_assertion(self, dom):
        """
        Decrypts the Assertion

        :raises: Exception if no private key available
        :param dom: Encrypted Assertion
        :type dom: Element
        :returns: Decrypted Assertion
        :rtype: Element
        """
        key = self.__settings.get_sp_key()

        if not key:
            raise Exception('No private key available, check settings')

        encrypted_assertion_nodes = OneLogin_Saml2_Utils.query(dom, '//saml:EncryptedAssertion')
        if encrypted_assertion_nodes:
            encrypted_data_nodes = OneLogin_Saml2_Utils.query(encrypted_assertion_nodes[0], '//saml:EncryptedAssertion/xenc:EncryptedData')
            if encrypted_data_nodes:
                encrypted_data = encrypted_data_nodes[0]
                OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        return dom
Ejemplo n.º 13
0
    def get_nameid_data(request, key=None):
        """
        Gets the NameID Data of the the Logout Request
        :param request: Logout Request Message
        :type request: string|DOMDocument
        :param key: The SP key
        :type key: string
        :return: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        if isinstance(request, etree._Element):
            elem = request
        else:
            if isinstance(request, Document):
                request = request.toxml()
            elem = fromstring(request, forbid_dtd=True)

        name_id = None
        encrypted_entries = OneLogin_Saml2_Utils.query(
            elem, '/samlp:LogoutRequest/saml:EncryptedID')

        if len(encrypted_entries) == 1:
            if key is None:
                raise OneLogin_Saml2_Error(
                    'Private Key is required in order to decrypt the NameID, check settings',
                    OneLogin_Saml2_Error.PRIVATE_KEY_NOT_FOUND)

            encrypted_data_nodes = OneLogin_Saml2_Utils.query(
                elem,
                '/samlp:LogoutRequest/saml:EncryptedID/xenc:EncryptedData')
            if len(encrypted_data_nodes) == 1:
                encrypted_data = encrypted_data_nodes[0]
                name_id = OneLogin_Saml2_Utils.decrypt_element(
                    encrypted_data, key)
        else:
            entries = OneLogin_Saml2_Utils.query(
                elem, '/samlp:LogoutRequest/saml:NameID')
            if len(entries) == 1:
                name_id = entries[0]

        if name_id is None:
            raise OneLogin_Saml2_ValidationError(
                'NameID not found in the Logout Request',
                OneLogin_Saml2_ValidationError.NO_NAMEID)

        name_id_data = {'Value': OneLogin_Saml2_Utils.element_text(name_id)}
        for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
            if attr in name_id.attrib.keys():
                name_id_data[attr] = name_id.attrib[attr]

        return name_id_data
Ejemplo n.º 14
0
    def get_nameid_data(self):
        """
        Gets the NameID Data provided by the SAML Response from the IdP

        :returns: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        nameid = None
        nameid_data = {}

        encrypted_id_data_nodes = self.__query_assertion('/saml:Subject/saml:EncryptedID/xenc:EncryptedData')
        if encrypted_id_data_nodes:
            encrypted_data = encrypted_id_data_nodes[0]
            key = self.__settings.get_sp_key()
            nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        else:
            nameid_nodes = self.__query_assertion('/saml:Subject/saml:NameID')
            if nameid_nodes:
                nameid = nameid_nodes[0]

        is_strict = self.__settings.is_strict()
        want_nameid = self.__settings.get_security_data().get('wantNameId', True)
        if nameid is None:
            if is_strict and want_nameid:
                raise OneLogin_Saml2_ValidationError(
                    'NameID not found in the assertion of the Response',
                    OneLogin_Saml2_ValidationError.NO_NAMEID
                )
        else:
            if is_strict and want_nameid and not OneLogin_Saml2_Utils.element_text(nameid):
                raise OneLogin_Saml2_ValidationError(
                    'An empty NameID value found',
                    OneLogin_Saml2_ValidationError.EMPTY_NAMEID
                )

            nameid_data = {'Value': OneLogin_Saml2_Utils.element_text(nameid)}
            for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
                value = nameid.get(attr, None)
                if value:
                    if is_strict and attr == 'SPNameQualifier':
                        sp_data = self.__settings.get_sp_data()
                        sp_entity_id = sp_data.get('entityId', '')
                        if sp_entity_id != value:
                            raise OneLogin_Saml2_ValidationError(
                                'The SPNameQualifier value mistmatch the SP entityID value.',
                                OneLogin_Saml2_ValidationError.SP_NAME_QUALIFIER_NAME_MISMATCH
                            )

                    nameid_data[attr] = value
        return nameid_data
Ejemplo n.º 15
0
    def get_nameid_data(request, key=None):
        """
        Gets the NameID Data of the the Logout Request
        :param request: Logout Request Message
        :type request: string|DOMDocument
        :param key: The SP key
        :type key: string
        :return: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        if isinstance(request, etree._Element):
            elem = request
        else:
            if isinstance(request, Document):
                request = request.toxml()
            elem = fromstring(request, forbid_dtd=True)

        name_id = None
        encrypted_entries = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:EncryptedID')

        if len(encrypted_entries) == 1:
            if key is None:
                raise OneLogin_Saml2_Error(
                    'Private Key is required in order to decrypt the NameID, check settings',
                    OneLogin_Saml2_Error.PRIVATE_KEY_NOT_FOUND
                )

            encrypted_data_nodes = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:EncryptedID/xenc:EncryptedData')
            if len(encrypted_data_nodes) == 1:
                encrypted_data = encrypted_data_nodes[0]
                name_id = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        else:
            entries = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:NameID')
            if len(entries) == 1:
                name_id = entries[0]

        if name_id is None:
            raise OneLogin_Saml2_ValidationError(
                'NameID not found in the Logout Request',
                OneLogin_Saml2_ValidationError.NO_NAMEID
            )

        name_id_data = {
            'Value': OneLogin_Saml2_Utils.element_text(name_id)
        }
        for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
            if attr in name_id.attrib.keys():
                name_id_data[attr] = name_id.attrib[attr]

        return name_id_data
Ejemplo n.º 16
0
    def get_nameid_data(request, key=None):
        """
        Gets the NameID Data of the the Logout Request
        :param request: Logout Request Message
        :type request: string|DOMDocument
        :param key: The SP key
        :type key: string
        :return: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        if isinstance(request, etree._Element):
            elem = request
        else:
            if isinstance(request, Document):
                request = request.toxml()
            elem = fromstring(request)

        name_id = None
        encrypted_entries = OneLogin_Saml2_Utils.query(
            elem, '/samlp:LogoutRequest/saml:EncryptedID')

        if len(encrypted_entries) == 1:
            if key is None:
                raise Exception(
                    'Key is required in order to decrypt the NameID')

            encrypted_data_nodes = OneLogin_Saml2_Utils.query(
                elem,
                '/samlp:LogoutRequest/saml:EncryptedID/xenc:EncryptedData')
            if len(encrypted_data_nodes) == 1:
                encrypted_data = encrypted_data_nodes[0]
                name_id = OneLogin_Saml2_Utils.decrypt_element(
                    encrypted_data, key)
        else:
            entries = OneLogin_Saml2_Utils.query(
                elem, '/samlp:LogoutRequest/saml:NameID')
            if len(entries) == 1:
                name_id = entries[0]

        if name_id is None:
            raise Exception('Not NameID found in the Logout Request')

        name_id_data = {'Value': name_id.text}
        for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
            if attr in name_id.attrib.keys():
                name_id_data[attr] = name_id.attrib[attr]

        return name_id_data
Ejemplo n.º 17
0
    def get_nameid_data(self):
        """
        Gets the NameID Data provided by the SAML Response from the IdP

        :returns: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        nameid = None
        nameid_data = {}

        encrypted_id_data_nodes = self.__query_assertion(
            '/saml:Subject/saml:EncryptedID/xenc:EncryptedData')
        if encrypted_id_data_nodes:
            encrypted_data = encrypted_id_data_nodes[0]
            key = self.__settings.get_sp_key()
            nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        else:
            nameid_nodes = self.__query_assertion('/saml:Subject/saml:NameID')
            if nameid_nodes:
                nameid = nameid_nodes[0]
        if nameid is None:
            security = self.__settings.get_security_data()

            if security.get('wantNameId', True):
                raise Exception(
                    'Not NameID found in the assertion of the Response')
        else:
            if self.__settings.is_strict() and not nameid.text:
                raise Exception('An empty NameID value found')

            nameid_data = {'Value': nameid.text}
            for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
                value = nameid.get(attr, None)
                if value:
                    if self.__settings.is_strict(
                    ) and attr == 'SPNameQualifier':
                        sp_data = self.__settings.get_sp_data()
                        sp_entity_id = sp_data.get('entityId', '')
                        if sp_entity_id != value:
                            raise Exception(
                                'The SPNameQualifier value mistmatch the SP entityID value.'
                            )

                    nameid_data[attr] = value
        return nameid_data
Ejemplo n.º 18
0
    def get_nameid_data(request, key=None):
        """
        Gets the NameID Data of the the Logout Request
        :param request: Logout Request Message
        :type request: string|DOMDocument
        :param key: The SP key
        :type key: string
        :return: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        if isinstance(request, etree._Element):
            elem = request
        else:
            if isinstance(request, Document):
                request = request.toxml()
            elem = fromstring(request)

        name_id = None
        encrypted_entries = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:EncryptedID')

        if len(encrypted_entries) == 1:
            if key is None:
                raise Exception('Key is required in order to decrypt the NameID')

            encrypted_data_nodes = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:EncryptedID/xenc:EncryptedData')
            if len(encrypted_data_nodes) == 1:
                encrypted_data = encrypted_data_nodes[0]
                name_id = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        else:
            entries = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:NameID')
            if len(entries) == 1:
                name_id = entries[0]

        if name_id is None:
            raise Exception('Not NameID found in the Logout Request')

        name_id_data = {
            'Value': name_id.text
        }
        for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
            if attr in name_id.attrib.keys():
                name_id_data[attr] = name_id.attrib[attr]

        return name_id_data
Ejemplo n.º 19
0
    def get_nameid_data(self):
        """
        Gets the NameID Data provided by the SAML Response from the IdP

        :returns: Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
        :rtype: dict
        """
        nameid = None
        nameid_data = {}

        encrypted_id_data_nodes = self.__query_assertion(
            '/saml:Subject/saml:EncryptedID/xenc:EncryptedData')
        if encrypted_id_data_nodes:
            encrypted_data = encrypted_id_data_nodes[0]
            key = self.__settings.get_sp_key()
            nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        else:
            nameid_nodes = self.__query_assertion('/saml:Subject/saml:NameID')
            if nameid_nodes:
                nameid = nameid_nodes[0]

        if isinstance(nameid, str):
            nameid = nameid if nameid.strip() else None

        is_strict = self.__settings.is_strict()
        want_nameid = self.__settings.get_security_data().get(
            'wantNameId', True)
        if nameid is None:
            if is_strict and want_nameid:
                raise OneLogin_Saml2_ValidationError(
                    'NameID not found in the assertion of the Response',
                    OneLogin_Saml2_ValidationError.NO_NAMEID)
        else:
            if is_strict and want_nameid and not OneLogin_Saml2_XML.element_text(
                    nameid).strip():
                raise OneLogin_Saml2_ValidationError(
                    'An empty NameID value found',
                    OneLogin_Saml2_ValidationError.EMPTY_NAMEID)

            nameid_data = {'Value': OneLogin_Saml2_XML.element_text(nameid)}
            expected_format_name_id = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
            if nameid.get('Format', None) != expected_format_name_id:
                raise OneLogin_Saml2_ValidationError(
                    f'Format has a wrong format, {nameid.get("Format", None)} expected: {expected_format_name_id}',
                    OneLogin_Saml2_ValidationError.WRONG_ATTRIBUTE)

            for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
                value = nameid.get(attr, None)
                if value:
                    if is_strict and attr == 'SPNameQualifier':
                        sp_data = self.__settings.get_sp_data()
                        sp_entity_id = sp_data.get('entityId', '')
                        if sp_entity_id != value:
                            raise OneLogin_Saml2_ValidationError(
                                'The SPNameQualifier value mistmatch the SP entityID value.',
                                OneLogin_Saml2_ValidationError.
                                SP_NAME_QUALIFIER_NAME_MISMATCH)

                    nameid_data[attr] = value

                elif attr is 'SPNameQualifier':
                    continue

                elif value is None:
                    raise OneLogin_Saml2_ValidationError(
                        f'{attr} missing',
                        OneLogin_Saml2_ValidationError.MISSING_ATTRIBUTE)
                elif not value:
                    raise OneLogin_Saml2_ValidationError(
                        f'An empty {attr} value found',
                        OneLogin_Saml2_ValidationError.EMPTY_ATTRIBUTE)

        return nameid_data
Ejemplo n.º 20
0
    def testDecryptElement(self):
        """
        Tests the decrypt_element method of the OneLogin_Saml2_Utils
        """
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())

        key = settings.get_sp_key()

        xml_nameid_enc = b64decode(self.file_contents(join(self.data_path, 'responses', 'response_encrypted_nameid.xml.base64')))
        dom_nameid_enc = parseString(xml_nameid_enc)
        encrypted_nameid_nodes = dom_nameid_enc.getElementsByTagName('saml:EncryptedID')
        encrypted_data = encrypted_nameid_nodes[0].firstChild
        encrypted_data_str = str(encrypted_nameid_nodes[0].firstChild.toxml())
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        self.assertEqual('{%s}NameID' % (OneLogin_Saml2_Constants.NS_SAML), decrypted_nameid.tag)
        self.assertEqual('2de11defd199f8d5bb63f9b7deb265ba5c675c10', decrypted_nameid.text)

        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data_str, key)
        self.assertEqual('{%s}NameID' % (OneLogin_Saml2_Constants.NS_SAML), decrypted_nameid.tag)
        self.assertEqual('2de11defd199f8d5bb63f9b7deb265ba5c675c10', decrypted_nameid.text)

        xml_assertion_enc = b64decode(self.file_contents(join(self.data_path, 'responses', 'valid_encrypted_assertion_encrypted_nameid.xml.base64')))
        dom_assertion_enc = parseString(xml_assertion_enc)
        encrypted_assertion_enc_nodes = dom_assertion_enc.getElementsByTagName('saml:EncryptedAssertion')
        encrypted_data_assert = encrypted_assertion_enc_nodes[0].firstChild

        decrypted_assertion = OneLogin_Saml2_Utils.decrypt_element(encrypted_data_assert, key)
        self.assertEqual('{%s}Assertion' % (OneLogin_Saml2_Constants.NS_SAML), decrypted_assertion.tag)
        self.assertEqual('_6fe189b1c241827773902f2b1d3a843418206a5c97', decrypted_assertion.get('ID'))

        decrypted_assertion.xpath('/saml:Assertion/saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_nameid_nodes = decrypted_assertion.xpath('/saml:Assertion/saml:Subject/saml:EncryptedID', namespaces=OneLogin_Saml2_Constants.NSMAP)
        encrypted_data = encrypted_nameid_nodes[0][0]
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
        self.assertEqual('{%s}NameID' % (OneLogin_Saml2_Constants.NS_SAML), decrypted_nameid.tag)
        self.assertEqual('457bdb600de717891c77647b0806ce59c089d5b8', decrypted_nameid.text)

        key_2_file_name = join(self.data_path, 'misc', 'sp2.key')
        f = open(key_2_file_name, 'r')
        key2 = f.read()
        f.close()

        try:
            OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key2)
            self.assertTrue(False)
        except Exception as e:
            self.assertEqual('failed to decrypt', e[0])

        key_3_file_name = join(self.data_path, 'misc', 'sp3.key')
        f = open(key_3_file_name, 'r')
        key3 = f.read()
        f.close()
        try:
            OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key3)
            self.assertTrue(False)
        except Exception as e:
            self.assertEqual('failed to decrypt', e[0])

        xml_nameid_enc_2 = b64decode(self.file_contents(join(self.data_path, 'responses', 'invalids', 'encrypted_nameID_without_EncMethod.xml.base64')))
        dom_nameid_enc_2 = parseString(xml_nameid_enc_2)
        encrypted_nameid_nodes_2 = dom_nameid_enc_2.getElementsByTagName('saml:EncryptedID')
        encrypted_data_2 = encrypted_nameid_nodes_2[0].firstChild
        try:
            OneLogin_Saml2_Utils.decrypt_element(encrypted_data_2, key)
            self.assertTrue(False)
        except:
            pass

        xml_nameid_enc_3 = b64decode(self.file_contents(join(self.data_path, 'responses', 'invalids', 'encrypted_nameID_without_keyinfo.xml.base64')))
        dom_nameid_enc_3 = parseString(xml_nameid_enc_3)
        encrypted_nameid_nodes_3 = dom_nameid_enc_3.getElementsByTagName('saml:EncryptedID')
        encrypted_data_3 = encrypted_nameid_nodes_3[0].firstChild
        try:
            OneLogin_Saml2_Utils.decrypt_element(encrypted_data_3, key)
            self.assertTrue(False)
        except:
            pass