@@ -733,40 +733,16 @@ def validate_sign(xml, cert=None, fingerprint=None, fingerprintalg='sha1', valid
733733 xmlsec .enable_debug_trace (debug )
734734 xmlsec .tree .add_ids (elem , ["ID" ])
735735
736- signature_nodes = OneLogin_Saml2_XML .query (elem , '//ds:Signature' )
736+ signature_nodes = OneLogin_Saml2_XML .query (elem , '/samlp:Response /ds:Signature' )
737737
738- if len (signature_nodes ) > 0 :
738+ if not len (signature_nodes ) > 0 :
739+ signature_nodes += OneLogin_Saml2_XML .query (elem , '/samlp:Response/saml:EncryptedAssertion/saml:Assertion/ds:Signature' )
740+ signature_nodes += OneLogin_Saml2_XML .query (elem , '/samlp:Response/saml:Assertion/ds:Signature' )
741+
742+ if len (signature_nodes ) == 1 :
739743 signature_node = signature_nodes [0 ]
740744
741- if (cert is None or cert == '' ) and fingerprint :
742- x509_certificate_nodes = OneLogin_Saml2_XML .query (signature_node , '//ds:Signature/ds:KeyInfo/ds:X509Data/ds:X509Certificate' )
743- if len (x509_certificate_nodes ) > 0 :
744- x509_certificate_node = x509_certificate_nodes [0 ]
745- x509_cert_value = x509_certificate_node .text
746- x509_fingerprint_value = OneLogin_Saml2_Utils .calculate_x509_fingerprint (x509_cert_value , fingerprintalg )
747- if fingerprint == x509_fingerprint_value :
748- cert = OneLogin_Saml2_Utils .format_cert (x509_cert_value )
749-
750- if cert is None or cert == '' :
751- return False
752-
753- # Check if Reference URI is empty
754- reference_elem = OneLogin_Saml2_XML .query (signature_node , '//ds:Reference' )
755- if len (reference_elem ) > 0 :
756- if reference_elem [0 ].get ('URI' ) == '' :
757- reference_elem [0 ].set ('URI' , '#%s' % signature_node .getparent ().get ('ID' ))
758-
759- if validatecert :
760- manager = xmlsec .KeysManager ()
761- manager .load_cert_from_memory (cert , xmlsec .KeyFormat .CERT_PEM , xmlsec .KeyDataType .TRUSTED )
762- dsig_ctx = xmlsec .SignatureContext (manager )
763- else :
764- dsig_ctx = xmlsec .SignatureContext ()
765- dsig_ctx .key = xmlsec .Key .from_memory (cert , xmlsec .KeyFormat .CERT_PEM , None )
766-
767- dsig_ctx .set_enabled_key_data ([xmlsec .KeyData .X509 ])
768- dsig_ctx .verify (signature_node )
769- return True
745+ return OneLogin_Saml2_Utils .validate_node_sign (signature_node , elem , cert , fingerprint , fingerprintalg , validatecert , debug )
770746 else :
771747 return False
772748 except xmlsec .Error as e :
@@ -775,6 +751,116 @@ def validate_sign(xml, cert=None, fingerprint=None, fingerprintalg='sha1', valid
775751
776752 return False
777753
754+ @staticmethod
755+ def validate_metadata_sign (xml , cert = None , fingerprint = None , fingerprintalg = 'sha1' , validatecert = False , debug = False ):
756+ """
757+ Validates a signature of a EntityDescriptor.
758+
759+ :param xml: The element we should validate
760+ :type: string | Document
761+
762+ :param cert: The pubic cert
763+ :type: string
764+
765+ :param fingerprint: The fingerprint of the public cert
766+ :type: string
767+
768+ :param fingerprintalg: The algorithm used to build the fingerprint
769+ :type: string
770+
771+ :param validatecert: If true, will verify the signature and if the cert is valid.
772+ :type: bool
773+
774+ :param debug: Activate the xmlsec debug
775+ :type: bool
776+ """
777+ try :
778+ if xml is None or xml == '' :
779+ raise Exception ('Empty string supplied as input' )
780+
781+ elem = OneLogin_Saml2_XML .to_etree (xml )
782+ xmlsec .enable_debug_trace (debug )
783+ xmlsec .tree .add_ids (elem , ["ID" ])
784+
785+ signature_nodes = OneLogin_Saml2_XML .query (elem , '/md:EntitiesDescriptor/ds:Signature' )
786+
787+ if len (signature_nodes ) == 0 :
788+ signature_nodes += OneLogin_Saml2_XML .query (elem , '/md:EntityDescriptor/ds:Signature' )
789+
790+ if len (signature_nodes ) == 0 :
791+ signature_nodes += OneLogin_Saml2_XML .query (elem , '/md:EntityDescriptor/md:SPSSODescriptor/ds:Signature' )
792+ signature_nodes += OneLogin_Saml2_XML .query (elem , '/md:EntityDescriptor/md:IDPSSODescriptor/ds:Signature' )
793+
794+ if len (signature_nodes ) > 0 :
795+ for signature_node in signature_nodes :
796+ if not OneLogin_Saml2_Utils .validate_node_sign (signature_node , elem , cert , fingerprint , fingerprintalg , validatecert , debug ):
797+ return False
798+ return True
799+ else :
800+ return False
801+ except Exception :
802+ return False
803+
804+ @staticmethod
805+ def validate_node_sign (signature_node , elem , cert = None , fingerprint = None , fingerprintalg = 'sha1' , validatecert = False , debug = False ):
806+ """
807+ Validates a signature node.
808+
809+ :param signature_node: The signature node
810+ :type: Node
811+
812+ :param xml: The element we should validate
813+ :type: Document
814+
815+ :param cert: The pubic cert
816+ :type: string
817+
818+ :param fingerprint: The fingerprint of the public cert
819+ :type: string
820+
821+ :param fingerprintalg: The algorithm used to build the fingerprint
822+ :type: string
823+
824+ :param validatecert: If true, will verify the signature and if the cert is valid.
825+ :type: bool
826+
827+ :param debug: Activate the xmlsec debug
828+ :type: bool
829+ """
830+ try :
831+ if (cert is None or cert == '' ) and fingerprint :
832+ x509_certificate_nodes = OneLogin_Saml2_XML .query (signature_node , '//ds:Signature/ds:KeyInfo/ds:X509Data/ds:X509Certificate' )
833+ if len (x509_certificate_nodes ) > 0 :
834+ x509_certificate_node = x509_certificate_nodes [0 ]
835+ x509_cert_value = x509_certificate_node .text
836+ x509_fingerprint_value = OneLogin_Saml2_Utils .calculate_x509_fingerprint (x509_cert_value , fingerprintalg )
837+ if fingerprint == x509_fingerprint_value :
838+ cert = OneLogin_Saml2_Utils .format_cert (x509_cert_value )
839+
840+ if cert is None or cert == '' :
841+ return False
842+
843+ # Check if Reference URI is empty
844+ reference_elem = OneLogin_Saml2_XML .query (signature_node , '//ds:Reference' )
845+ if len (reference_elem ) > 0 :
846+ if reference_elem [0 ].get ('URI' ) == '' :
847+ reference_elem [0 ].set ('URI' , '#%s' % signature_node .getparent ().get ('ID' ))
848+
849+ if validatecert :
850+ manager = xmlsec .KeysManager ()
851+ manager .load_cert_from_memory (cert , xmlsec .KeyFormat .CERT_PEM , xmlsec .KeyDataType .TRUSTED )
852+ dsig_ctx = xmlsec .SignatureContext (manager )
853+ else :
854+ dsig_ctx = xmlsec .SignatureContext ()
855+ dsig_ctx .key = xmlsec .Key .from_memory (cert , xmlsec .KeyFormat .CERT_PEM , None )
856+
857+ dsig_ctx .set_enabled_key_data ([xmlsec .KeyData .X509 ])
858+ dsig_ctx .verify (signature_node )
859+ return True
860+ except xmlsec .Error as e :
861+ if debug :
862+ print (e )
863+
778864 @staticmethod
779865 def sign_binary (msg , key , algorithm = xmlsec .Transform .RSA_SHA1 , debug = False ):
780866 """
0 commit comments