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
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)
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)
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)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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