Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
)
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:
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
)
# Check that reference URI matches the parent ID and no duplicate References or IDs
ref = OneLogin_Saml2_Utils.query(sign_node, './/ds:Reference')
if ref:
ref = ref[0]
if ref.get('URI'):
sei = ref.get('URI')[1:]
if sei != id_value:
raise OneLogin_Saml2_ValidationError(
'Found an invalid Signed Element. SAML Response rejected',
OneLogin_Saml2_ValidationError.INVALID_SIGNED_ELEMENT
)
if sei in verified_seis:
raise OneLogin_Saml2_ValidationError(
'Duplicated Reference URI. SAML Response rejected',
OneLogin_Saml2_ValidationError.DUPLICATED_REFERENCE_IN_SIGNED_ELEMENTS
)
verified_seis.append(sei)
signed_elements.append(signed_element)
if signed_elements:
if not self.validate_signed_elements(signed_elements, raise_exceptions=True):
raise OneLogin_Saml2_ValidationError(
'Found an unexpected Signature Element. SAML Response rejected',
OneLogin_Saml2_ValidationError.UNEXPECTED_SIGNED_ELEMENTS
)
return signed_elements
signed_element = sign_node.getparent().tag
if signed_element != response_tag and signed_element != assertion_tag:
raise OneLogin_Saml2_ValidationError(
'Invalid Signature Element %s SAML Response rejected' % signed_element,
OneLogin_Saml2_ValidationError.WRONG_SIGNED_ELEMENT
)
if not sign_node.getparent().get('ID'):
raise OneLogin_Saml2_ValidationError(
'Signed Element must contain an ID. SAML Response rejected',
OneLogin_Saml2_ValidationError.ID_NOT_FOUND_IN_SIGNED_ELEMENT
)
id_value = sign_node.getparent().get('ID')
if id_value in verified_ids:
raise OneLogin_Saml2_ValidationError(
'Duplicated ID. SAML Response rejected',
OneLogin_Saml2_ValidationError.DUPLICATED_ID_IN_SIGNED_ELEMENTS
)
verified_ids.append(id_value)
# Check that reference URI matches the parent ID and no duplicate References or IDs
ref = OneLogin_Saml2_Utils.query(sign_node, './/ds:Reference')
if ref:
ref = ref[0]
if ref.get('URI'):
sei = ref.get('URI')[1:]
if sei != id_value:
raise OneLogin_Saml2_ValidationError(
'Found an invalid Signed Element. SAML Response rejected',
OneLogin_Saml2_ValidationError.INVALID_SIGNED_ELEMENT
response_tag = '{%s}Response' % OneLogin_Saml2_Constants.NS_SAMLP
assertion_tag = '{%s}Assertion' % OneLogin_Saml2_Constants.NS_SAML
if (response_tag in signed_elements and signed_elements.count(response_tag) > 1) or \
(assertion_tag in signed_elements and signed_elements.count(assertion_tag) > 1) or \
(response_tag not in signed_elements and assertion_tag not in signed_elements):
return False
# Check that the signed elements found here, are the ones that will be verified
# by OneLogin_Saml2_Utils.validate_sign
if response_tag in signed_elements:
expected_signature_nodes = OneLogin_Saml2_Utils.query(self.document, OneLogin_Saml2_Utils.RESPONSE_SIGNATURE_XPATH)
if len(expected_signature_nodes) != 1:
raise OneLogin_Saml2_ValidationError(
'Unexpected number of Response signatures found. SAML Response rejected.',
OneLogin_Saml2_ValidationError.WRONG_NUMBER_OF_SIGNATURES_IN_RESPONSE
)
if assertion_tag in signed_elements:
expected_signature_nodes = self.__query(OneLogin_Saml2_Utils.ASSERTION_SIGNATURE_XPATH)
if len(expected_signature_nodes) != 1:
raise OneLogin_Saml2_ValidationError(
'Unexpected number of Assertion signatures found. SAML Response rejected.',
OneLogin_Saml2_ValidationError.WRONG_NUMBER_OF_SIGNATURES_IN_ASSERTION
)
return True
if len(message_issuer_nodes) > 0:
if len(message_issuer_nodes) == 1:
issuers.append(OneLogin_Saml2_Utils.element_text(message_issuer_nodes[0]))
else:
raise OneLogin_Saml2_ValidationError(
'Issuer of the Response is multiple.',
OneLogin_Saml2_ValidationError.ISSUER_MULTIPLE_IN_RESPONSE
)
assertion_issuer_nodes = self.__query_assertion('/saml:Issuer')
if len(assertion_issuer_nodes) == 1:
issuers.append(OneLogin_Saml2_Utils.element_text(assertion_issuer_nodes[0]))
else:
raise OneLogin_Saml2_ValidationError(
'Issuer of the Assertion not found or multiple.',
OneLogin_Saml2_ValidationError.ISSUER_NOT_FOUND_IN_ASSERTION
)
return list(set(issuers))
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
if request_id is not None and in_response_to != request_id:
raise OneLogin_Saml2_ValidationError(
'The InResponseTo of the Response: %s, does not match the ID of the AuthNRequest sent by the SP: %s' % (in_response_to, request_id),
OneLogin_Saml2_ValidationError.WRONG_INRESPONSETO
)
if not self.encrypted and security.get('wantAssertionsEncrypted', False):
raise OneLogin_Saml2_ValidationError(
'The assertion of the Response is not encrypted and the SP require it',
OneLogin_Saml2_ValidationError.NO_ENCRYPTED_ASSERTION
)
if security.get('wantNameIdEncrypted', False):
encrypted_nameid_nodes = self.__query_assertion('/saml:Subject/saml:EncryptedID/xenc:EncryptedData')
if len(encrypted_nameid_nodes) != 1:
raise OneLogin_Saml2_ValidationError(
'The NameID of the Response is not encrypted and the SP require it',
OneLogin_Saml2_ValidationError.NO_ENCRYPTED_NAMEID
)
# Checks that a Conditions element exists
if not self.check_one_condition():
raise OneLogin_Saml2_ValidationError(
'The Assertion must include a Conditions element',
OneLogin_Saml2_ValidationError.MISSING_CONDITIONS
)
# Validates Assertion timestamps
self.validate_timestamps(raise_exceptions=True)
# Checks that an AuthnStatement element exists and is unique
if not self.check_one_authnstatement():
)
# Checks destination
destination = self.document.get('Destination', None)
if destination:
if not destination.startswith(current_url):
# TODO: Review if following lines are required, since we can control the
# request_data
# current_url_routed = OneLogin_Saml2_Utils.get_self_routed_url_no_query(request_data)
# if not destination.startswith(current_url_routed):
raise OneLogin_Saml2_ValidationError(
'The response was received at %s instead of %s' % (current_url, destination),
OneLogin_Saml2_ValidationError.WRONG_DESTINATION
)
elif destination == '':
raise OneLogin_Saml2_ValidationError(
'The response has an empty Destination value',
OneLogin_Saml2_ValidationError.EMPTY_DESTINATION
)
# Checks audience
valid_audiences = self.get_audiences()
if valid_audiences and sp_entity_id not in valid_audiences:
raise OneLogin_Saml2_ValidationError(
'%s is not a valid audience for this Response' % sp_entity_id,
OneLogin_Saml2_ValidationError.WRONG_AUDIENCE
)
# Checks the issuers
issuers = self.get_issuers()
for issuer in issuers:
if issuer is None or issuer != idp_entity_id:
if validatecert:
mngr = xmlsec.KeysMngr()
mngr.loadCert(file_cert.name, xmlsec.KeyDataFormatCertPem, xmlsec.KeyDataTypeTrusted)
dsig_ctx = xmlsec.DSigCtx(mngr)
else:
dsig_ctx = xmlsec.DSigCtx()
dsig_ctx.signKey = xmlsec.Key.load(file_cert.name, xmlsec.KeyDataFormatCertPem, None)
file_cert.close()
dsig_ctx.setEnabledKeyData([xmlsec.KeyDataX509])
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,
err.__str__()
)
return True