Skip to content

Commit 3bda379

Browse files
authored
Merge pull request #205 from novafloss/get-nameid-when-element-decrypted-twice
Get nameid when element decrypted twice
2 parents 2953640 + fac4767 commit 3bda379

File tree

5 files changed

+84
-5
lines changed

5 files changed

+84
-5
lines changed

changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# python-saml changelog
2+
### 2.2.4 (unreleased)
3+
* Get NameID when element decrypted twice
4+
25
### 2.2.3 (Jun 15, 2017)
36
* Replace some etree.tostring calls, that were introduced recfently, by the sanitized call provided by defusedxml
47
* Update dm.xmlsec.binding requirement to 1.3.3 version

src/onelogin/saml2/response.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,8 +798,9 @@ def __decrypt_assertion(self, dom):
798798
keyinfo.append(encrypted_key[0])
799799

800800
encrypted_data = encrypted_data_nodes[0]
801-
decrypted = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key, debug)
801+
decrypted = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key, debug=debug, inplace=True)
802802
dom.replace(encrypted_assertion_nodes[0], decrypted)
803+
803804
return dom
804805

805806
def get_error(self):

src/onelogin/saml2/utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"""
1111

1212
import base64
13+
from copy import deepcopy
1314
from datetime import datetime
1415
import calendar
1516
from hashlib import sha1, sha256, sha384, sha512
@@ -746,7 +747,7 @@ def get_status(dom):
746747
return status
747748

748749
@staticmethod
749-
def decrypt_element(encrypted_data, key, debug=False):
750+
def decrypt_element(encrypted_data, key, debug=False, inplace=False):
750751
"""
751752
Decrypts an encrypted element.
752753
@@ -759,13 +760,18 @@ def decrypt_element(encrypted_data, key, debug=False):
759760
:param debug: Activate the xmlsec debug
760761
:type: bool
761762
763+
:param inplace: update passed data with decrypted result
764+
:type: bool
765+
762766
:returns: The decrypted element.
763767
:rtype: lxml.etree.Element
764768
"""
765769
if isinstance(encrypted_data, Element):
766770
encrypted_data = fromstring(str(encrypted_data.toxml()))
767771
elif isinstance(encrypted_data, basestring):
768772
encrypted_data = fromstring(str(encrypted_data))
773+
elif not inplace and isinstance(encrypted_data, etree._Element):
774+
encrypted_data = deepcopy(encrypted_data)
769775

770776
error_callback_method = None
771777
if debug:

tests/data/misc/sp4.key

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD4ZrcXcjCBOQS7
3+
stUabuXPYnXKvcoJUrMVPRX1zfrXvpfghCrykbL1TKoqGfmEA9oNRoMBOmZCgLlK
4+
eb0TfuEO/u1jf4rRFcK7U/dYEiX74bQgUnJUWTfFlhwPjxGhn9zDrc2tSpworJBV
5+
amyBZIo5Beap5OJLote/Wqp1DZjNyEZ2m8m+lv8udmejmlo5RMoIzuG3VdH6ADC9
6+
LKF+QsXC/HRZBhLE/y+75/XrNODvX8eM8+9Xp21QlVF1EIZDfNQ2iHsA8GEpJDC5
7+
aomTW/xExBysejnwP2ROrfm3PIfP64EbB4G01f8eErlXeUD0oQ0gECgIXsJpfBkD
8+
IWMHwx3/AgMBAAECggEAdbLNvFlJ7GDlAj75RJ4ZXAuOPrNw4LwDyON53U9tNP7F
9+
HgfiBa/NuPdLhclq9geRMUsg1dsjCw3NPiGy2mL7JszaFJQhZXLHI1Xk1CE9SD0o
10+
yUvniln/2CqJP0IOG6QQydM3qo24snkZpq9XnHPUHrLSGdwu8aHGUpAWRoJbzdzR
11+
tBWBn6SlkuaE52vcGh7eMdKSICRCg2/gg6LIi89pkiI9tfozAL2LPcDTRGp3DA3w
12+
U6OO8k+d1La4s9G0i22OGSwPxGerTHnBIzpeM/ivRwBypFy3EV9bbjQlheI53xAo
13+
ZMmGeSnQ89MWgY64pnWrX862Mf1EZYTjumDe2dl1kQKBgQD9pBG2BbcQ8qieTf84
14+
92LeOYTPRdd0N+gdyDKKorRO772zgxBwpSwO285nzy/FKSnpJIDtuee6OFClnDor
15+
Ui6lG1WPQeoSEdH1V10XkfSaoFOz7Hyv9H2dCLvW/VO9KYq07VAmQcvNZnqIW+tI
16+
edSHcQ3I8tnw4CiFa0BPvdhk9wKBgQD6tiuN2NvuNFFLvwpBGp3hjGyn6siyXDyP
17+
8IXQmP66NxKqcX/NafVO3bVh6VrPGd7PL1PloQZ5EBG2PPtRdf/g4aeZKZleCUXm
18+
9OgMEOUqdbTP9TGrmgNPtNBx3jnhnX/GTy/7GK77YlXEVplezWaerwRM7NCFCtp2
19+
W6K1M961OQKBgQDDSznr2hirrvuP8GRMW4a/rrAI3DDZplZN4CCySDbm9IcvGgJl
20+
iXgT9MDHg2q3t0sy3U18PYEkDEpkSZcsVfneXN6TEGCHCzuLWXovNM2O5VWtmrAi
21+
1vCFIf1nuuRoKP1I89SbsFuYyogcSBIwWsX+h1ji2cJfSmlI2VzKSVW93wKBgQDA
22+
sqwfRoMkP0oM8jUrfQ3Egm4xUiAYFxTlfXUcs7t13UaXgs08USifCYGUVAvcCoJa
23+
tIHDiVS0UEmMzKpOHmghrM9oxbR/tpjnv21reMDrNbVX8ZnPz3ykEtHz816BrtC6
24+
17qFQJ+d0CMj2XvghfdOGC8yAQL0fzcSqbQRmmCe4QKBgFWY9fqHEKdG/UlxZfBB
25+
C/QRNTJsrbZf9Ok/o1h6BHnK64xUc4elShEwV9IdC4QNW0UCr7WXoGLUkhfUphId
26+
q//KUDNc7VrWj5URsZcGi7WMkqNm9kPkpeuh3iSvh3+q7tK0/yfuj9ZQOjKzQnit
27+
VZBooJAJGdSqYgitpyxB71/n
28+
-----END PRIVATE KEY-----

tests/src/OneLogin/saml2_tests/utils_test.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from base64 import b64decode
77
import json
8+
from defusedxml.lxml import fromstring
89
from lxml import etree
910
from os.path import dirname, join, exists
1011
import unittest
@@ -718,15 +719,28 @@ def testDecryptElement(self):
718719
key2 = f.read()
719720
f.close()
720721

721-
with self.assertRaisesRegexp(Exception, "('failed to decrypt', -1)"):
722-
OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key2)
722+
# sp.key and sp2.key are equivalent we should be able to decrypt the nameID again
723+
decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key2)
724+
self.assertIn('{%s}NameID' % (OneLogin_Saml2_Constants.NS_SAML), decrypted_nameid.tag)
725+
self.assertEqual('457bdb600de717891c77647b0806ce59c089d5b8', decrypted_nameid.text)
723726

724727
key_3_file_name = join(self.data_path, 'misc', 'sp3.key')
725728
f = open(key_3_file_name, 'r')
726729
key3 = f.read()
727730
f.close()
731+
732+
# sp.key and sp3.key are equivalent we should be able to decrypt the nameID again
733+
decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key3)
734+
self.assertIn('{%s}NameID' % (OneLogin_Saml2_Constants.NS_SAML), decrypted_nameid.tag)
735+
self.assertEqual('457bdb600de717891c77647b0806ce59c089d5b8', decrypted_nameid.text)
736+
737+
key_4_file_name = join(self.data_path, 'misc', 'sp4.key')
738+
f = open(key_4_file_name, 'r')
739+
key4 = f.read()
740+
f.close()
741+
728742
with self.assertRaisesRegexp(Exception, "('failed to decrypt', -1)"):
729-
OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key3)
743+
OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key4)
730744

731745
xml_nameid_enc_2 = b64decode(self.file_contents(join(self.data_path, 'responses', 'invalids', 'encrypted_nameID_without_EncMethod.xml.base64')))
732746
dom_nameid_enc_2 = parseString(xml_nameid_enc_2)
@@ -744,6 +758,33 @@ def testDecryptElement(self):
744758
with self.assertRaisesRegexp(Exception, "('failed to decrypt', -1)"):
745759
OneLogin_Saml2_Utils.decrypt_element(encrypted_data_3, key)
746760

761+
def testDecryptElementInplace(self):
762+
"""
763+
Tests the decrypt_element method of the OneLogin_Saml2_Utils with inplace=True
764+
"""
765+
settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
766+
767+
key = settings.get_sp_key()
768+
769+
xml_nameid_enc = b64decode(self.file_contents(join(self.data_path, 'responses', 'response_encrypted_nameid.xml.base64')))
770+
dom = fromstring(xml_nameid_enc)
771+
encrypted_node = dom.xpath('//saml:EncryptedID/xenc:EncryptedData', namespaces=OneLogin_Saml2_Constants.NSMAP)[0]
772+
773+
# can be decrypted twice when copy the node first
774+
for _ in range(2):
775+
decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=False)
776+
self.assertIn('NameID', decrypted_nameid.tag)
777+
self.assertEqual('2de11defd199f8d5bb63f9b7deb265ba5c675c10', decrypted_nameid.text)
778+
779+
# can only be decrypted once in place
780+
decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=True)
781+
self.assertIn('NameID', decrypted_nameid.tag)
782+
self.assertEqual('2de11defd199f8d5bb63f9b7deb265ba5c675c10', decrypted_nameid.text)
783+
784+
# can't be decrypted twice since it has been dcrypted inplace
785+
with self.assertRaisesRegexp(Exception, "('failed to decrypt', -1)"):
786+
OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=True)
787+
747788
def testAddSign(self):
748789
"""
749790
Tests the add_sign method of the OneLogin_Saml2_Utils

0 commit comments

Comments
 (0)