Skip to content

Commit 562ad0d

Browse files
committed
Add ID to EntityDescriptor before sign it on add_sign method. Improve the way ds namespace is handled in add_sign method
1 parent 5e08bb2 commit 562ad0d

File tree

2 files changed

+23
-15
lines changed

2 files changed

+23
-15
lines changed

src/onelogin/saml2/utils.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,6 @@ def add_sign(xml, key, cert, debug=False, sign_algorithm=OneLogin_Saml2_Constant
869869
error_callback_method = print_xmlsec_errors
870870
xmlsec.set_error_callback(error_callback_method)
871871

872-
# Sign the metadata with our private key.
873872
sign_algorithm_transform_map = {
874873
OneLogin_Saml2_Constants.DSA_SHA1: xmlsec.TransformDsaSha1,
875874
OneLogin_Saml2_Constants.RSA_SHA1: xmlsec.TransformRsaSha1,
@@ -879,18 +878,31 @@ def add_sign(xml, key, cert, debug=False, sign_algorithm=OneLogin_Saml2_Constant
879878
}
880879
sign_algorithm_transform = sign_algorithm_transform_map.get(sign_algorithm, xmlsec.TransformRsaSha1)
881880

882-
signature = Signature(xmlsec.TransformExclC14N, sign_algorithm_transform)
881+
signature = Signature(xmlsec.TransformExclC14N, sign_algorithm_transform, nsPrefix='ds')
883882

884883
issuer = OneLogin_Saml2_Utils.query(elem, '//saml:Issuer')
885884
if len(issuer) > 0:
886885
issuer = issuer[0]
887886
issuer.addnext(signature)
887+
elem_to_sign = issuer.getparent()
888888
else:
889889
entity_descriptor = OneLogin_Saml2_Utils.query(elem, '//md:EntityDescriptor')
890890
if len(entity_descriptor) > 0:
891891
elem.insert(0, signature)
892892
else:
893893
elem[0].insert(0, signature)
894+
elem_to_sign = elem
895+
896+
elem_id = elem_to_sign.get('ID', None)
897+
if elem_id is not None:
898+
if elem_id:
899+
elem_id = '#' + elem_id
900+
else:
901+
generated_id = generated_id = OneLogin_Saml2_Utils.generate_unique_id()
902+
elem_id = '#' + generated_id
903+
elem_to_sign.attrib['ID'] = generated_id
904+
905+
xmlsec.addIDs(elem_to_sign, ["ID"])
894906

895907
digest_algorithm_transform_map = {
896908
OneLogin_Saml2_Constants.SHA1: xmlsec.TransformSha1,
@@ -901,6 +913,9 @@ def add_sign(xml, key, cert, debug=False, sign_algorithm=OneLogin_Saml2_Constant
901913
digest_algorithm_transform = digest_algorithm_transform_map.get(digest_algorithm, xmlsec.TransformSha1)
902914

903915
ref = signature.addReference(digest_algorithm_transform)
916+
if elem_id:
917+
ref.attrib['URI'] = elem_id
918+
904919
ref.addTransform(xmlsec.TransformEnveloped)
905920
ref.addTransform(xmlsec.TransformExclC14N)
906921

@@ -917,20 +932,8 @@ def add_sign(xml, key, cert, debug=False, sign_algorithm=OneLogin_Saml2_Constant
917932
dsig_ctx.signKey = sign_key
918933
dsig_ctx.sign(signature)
919934

935+
return tostring(elem, encoding='unicode').encode('utf-8')
920936
newdoc = parseString(tostring(elem, encoding='unicode').encode('utf-8'))
921-
922-
signature_nodes = newdoc.getElementsByTagName("Signature")
923-
924-
for signature in signature_nodes:
925-
signature.removeAttribute('xmlns')
926-
signature.setAttribute('xmlns:ds', OneLogin_Saml2_Constants.NS_DS)
927-
if not signature.tagName.startswith('ds:'):
928-
signature.tagName = 'ds:' + signature.tagName
929-
nodes = signature.getElementsByTagName("*")
930-
for node in nodes:
931-
if not node.tagName.startswith('ds:'):
932-
node.tagName = 'ds:' + node.tagName
933-
934937
return newdoc.saveXML(newdoc.firstChild)
935938

936939
@staticmethod

tests/src/OneLogin/saml2_tests/metadata_test.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from onelogin.saml2.metadata import OneLogin_Saml2_Metadata
1616
from onelogin.saml2.settings import OneLogin_Saml2_Settings
17+
from onelogin.saml2.utils import OneLogin_Saml2_Utils
1718
from onelogin.saml2.constants import OneLogin_Saml2_Constants
1819

1920

@@ -208,9 +209,11 @@ def testSignMetadata(self):
208209
cert = self.file_contents(join(cert_path, 'sp.crt'))
209210

210211
signed_metadata = OneLogin_Saml2_Metadata.sign_metadata(metadata, key, cert)
212+
self.assertTrue(OneLogin_Saml2_Utils.validate_metadata_sign(signed_metadata, cert))
211213

212214
self.assertIn('<md:SPSSODescriptor', signed_metadata)
213215
self.assertIn('entityID="http://stuff.com/endpoints/metadata.php"', signed_metadata)
216+
self.assertIn('ID="ONELOGIN_', signed_metadata)
214217
self.assertIn('AuthnRequestsSigned="false"', signed_metadata)
215218
self.assertIn('WantAssertionsSigned="false"', signed_metadata)
216219

@@ -231,8 +234,10 @@ def testSignMetadata(self):
231234
OneLogin_Saml2_Metadata.sign_metadata('', key, cert)
232235

233236
signed_metadata_2 = OneLogin_Saml2_Metadata.sign_metadata(metadata, key, cert, OneLogin_Saml2_Constants.RSA_SHA256, OneLogin_Saml2_Constants.SHA384)
237+
self.assertTrue(OneLogin_Saml2_Utils.validate_metadata_sign(signed_metadata_2, cert))
234238
self.assertIn('<md:SPSSODescriptor', signed_metadata_2)
235239
self.assertIn('entityID="http://stuff.com/endpoints/metadata.php"', signed_metadata_2)
240+
self.assertIn('ID="ONELOGIN_', signed_metadata_2)
236241
self.assertIn('AuthnRequestsSigned="false"', signed_metadata_2)
237242
self.assertIn('WantAssertionsSigned="false"', signed_metadata_2)
238243

0 commit comments

Comments
 (0)