Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
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]
decrypted = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key, debug)
xml.replace(encrypted_assertion_nodes[0], decrypted)
return xml
: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]
"""
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('#'):
if len(entity_descriptor_nodes) > 0:
for entity_descriptor_node in entity_descriptor_nodes:
idp_descriptor_nodes = OneLogin_Saml2_XML.query(entity_descriptor_node, './md:IDPSSODescriptor')
if len(idp_descriptor_nodes) > 0:
idp_descriptor_node = idp_descriptor_nodes[0]
idp_entity_id = entity_descriptor_node.get('entityID', None)
want_authn_requests_signed = entity_descriptor_node.get('WantAuthnRequestsSigned', None)
name_id_format_nodes = OneLogin_Saml2_XML.query(idp_descriptor_node, './md:NameIDFormat')
if len(name_id_format_nodes) > 0:
idp_name_id_format = name_id_format_nodes[0].text
sso_nodes = OneLogin_Saml2_XML.query(
idp_descriptor_node,
"./md:SingleSignOnService[@Binding='%s']" % required_sso_binding
)
if len(sso_nodes) > 0:
idp_sso_url = sso_nodes[0].get('Location', None)
slo_nodes = OneLogin_Saml2_XML.query(
idp_descriptor_node,
"./md:SingleLogoutService[@Binding='%s']" % required_slo_binding
)
if len(slo_nodes) > 0:
idp_slo_url = slo_nodes[0].get('Location', None)
cert_nodes = OneLogin_Saml2_XML.query(idp_descriptor_node, "./md:KeyDescriptor[@use='signing']/ds:KeyInfo/ds:X509Data/ds:X509Certificate")
: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
"""
elem = OneLogin_Saml2_XML.to_etree(request)
name_id = None
encrypted_entries = OneLogin_Saml2_XML.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_XML.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_XML.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:
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[0].insert(0, signature)
elem_id = elem.get('ID', None)
if elem_id:
elem_id = '#' + elem_id
ref = xmlsec.template.add_reference(signature, xmlsec.Transform.SHA1, 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)
xmlsec.template.add_x509_data(key_info)
: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
"""
try:
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 = x509_certificate_node.text
x509_fingerprint_value = OneLogin_Saml2_Utils.calculate_x509_fingerprint(x509_cert_value, fingerprintalg)
if fingerprint == x509_fingerprint_value:
cert = OneLogin_Saml2_Utils.format_cert(x509_cert_value)
if cert is None or cert == '':
return False
# 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'))
idp_descriptor_node,
"./md:SingleSignOnService[@Binding='%s']" % required_sso_binding
)
if len(sso_nodes) > 0:
idp_sso_url = sso_nodes[0].get('Location', None)
slo_nodes = OneLogin_Saml2_XML.query(
idp_descriptor_node,
"./md:SingleLogoutService[@Binding='%s']" % required_slo_binding
)
if len(slo_nodes) > 0:
idp_slo_url = slo_nodes[0].get('Location', None)
cert_nodes = OneLogin_Saml2_XML.query(idp_descriptor_node, "./md:KeyDescriptor[@use='signing']/ds:KeyInfo/ds:X509Data/ds:X509Certificate")
if len(cert_nodes) > 0:
idp_x509_cert = cert_nodes[0].text
data['idp'] = {}
if idp_entity_id is not None:
data['idp']['entityId'] = idp_entity_id
if idp_sso_url is not None:
data['idp']['singleSignOnService'] = {}
data['idp']['singleSignOnService']['url'] = idp_sso_url
data['idp']['singleSignOnService']['binding'] = required_sso_binding
if idp_slo_url is not None:
data['idp']['singleLogoutService'] = {}
data['idp']['singleLogoutService']['url'] = idp_slo_url
:param debug: Activate the xmlsec debug
:type: bool
"""
try:
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, '/samlp:Response/ds:Signature')
if not len(signature_nodes) > 0:
signature_nodes += OneLogin_Saml2_XML.query(elem, '/samlp:Response/ds:Signature')
signature_nodes += OneLogin_Saml2_XML.query(elem, '/samlp:Response/saml:Assertion/ds:Signature')
if len(signature_nodes) == 1:
signature_node = signature_nodes[0]
return OneLogin_Saml2_Utils.validate_node_sign(signature_node, elem, cert, fingerprint, fingerprintalg, validatecert, debug)
else:
return False
except xmlsec.Error as e:
if debug:
print(e)
return False