Skip to content

Commit c3f6311

Browse files
committed
Allow configuration and specification of id attribute name
The id attribute name is used by xmlsec1 to find the correct attribute in the given element that contains the id of the node that will be signed. Signed-off-by: Ivan Kanakarakis <[email protected]>
1 parent c9f4bf2 commit c3f6311

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed

src/saml2/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"extensions",
6767
"allow_unknown_attributes",
6868
"crypto_backend",
69+
"id_attr_name",
6970
]
7071

7172
SP_ARGS = [
@@ -221,6 +222,7 @@ def __init__(self, homedir="."):
221222
self.name_qualifier = ""
222223
self.entity_category = ""
223224
self.crypto_backend = 'xmlsec1'
225+
self.id_attr_name = None
224226
self.scope = ""
225227
self.allow_unknown_attributes = False
226228
self.extension_schema = {}

src/saml2/sigver.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ def _get_xmlsec_cryptobackend(path=None, search_paths=None):
205205
return CryptoBackendXmlSec1(path)
206206

207207

208-
ID_ATTR = 'ID'
209208
NODE_NAME = 'urn:oasis:names:tc:SAML:2.0:assertion:Assertion'
210209
ENC_NODE_NAME = 'urn:oasis:names:tc:SAML:2.0:assertion:EncryptedAssertion'
211210
ENC_KEY_CLASS = 'EncryptedKey'
@@ -653,7 +652,7 @@ def encrypt(self, text, recv_key, template, key_type):
653652
def encrypt_assertion(self, statement, enc_key, template, key_type, node_xpath):
654653
raise NotImplementedError()
655654

656-
def decrypt(self, enctext, key_file):
655+
def decrypt(self, enctext, key_file, id_attr):
657656
raise NotImplementedError()
658657

659658
def sign_statement(self, statement, node_name, key_file, node_id, id_attr):
@@ -779,7 +778,7 @@ def encrypt_assertion(self, statement, enc_key, template, key_type='des-192', no
779778

780779
return output.decode()
781780

782-
def decrypt(self, enctext, key_file):
781+
def decrypt(self, enctext, key_file, id_attr):
783782
"""
784783
785784
:param enctext: XML document containing an encrypted part
@@ -794,7 +793,7 @@ def decrypt(self, enctext, key_file):
794793
self.xmlsec,
795794
'--decrypt',
796795
'--privkey-pem', key_file,
797-
'--id-attr:{id_attr}'.format(id_attr=ID_ATTR),
796+
'--id-attr:{id_attr}'.format(id_attr=id_attr),
798797
ENC_KEY_CLASS,
799798
]
800799

@@ -1011,6 +1010,11 @@ def security_context(conf):
10111010
except AttributeError:
10121011
metadata = None
10131012

1013+
try:
1014+
id_attr = conf.id_attr_name
1015+
except AttributeError:
1016+
id_attr = None
1017+
10141018
sec_backend = None
10151019

10161020
if conf.crypto_backend == 'xmlsec1':
@@ -1069,7 +1073,8 @@ def security_context(conf):
10691073
validate_certificate=conf.validate_certificate,
10701074
enc_key_files=enc_key_files,
10711075
encryption_keypairs=conf.encryption_keypairs,
1072-
sec_backend=sec_backend)
1076+
sec_backend=sec_backend,
1077+
id_attr=id_attr)
10731078

10741079

10751080
def encrypt_cert_from_item(item):
@@ -1239,6 +1244,7 @@ def update_cert(self, active=False, client_crt=None):
12391244
# openssl x509 -inform pem -noout -in server.crt -pubkey > publickey.pem
12401245
# openssl rsa -inform pem -noout -in publickey.pem -pubin -modulus
12411246
class SecurityContext(object):
1247+
DEFAULT_ID_ATTR_NAME = 'ID'
12421248
my_cert = None
12431249

12441250
def __init__(
@@ -1257,7 +1263,10 @@ def __init__(
12571263
enc_key_files=None, enc_key_type='pem',
12581264
encryption_keypairs=None,
12591265
enc_cert_type='pem',
1260-
sec_backend=None):
1266+
sec_backend=None,
1267+
id_attr=''):
1268+
1269+
self.id_attr = id_attr or SecurityContext.DEFAULT_ID_ATTR_NAME
12611270

12621271
self.crypto = crypto
12631272
assert (isinstance(self.crypto, CryptoBackend))
@@ -1348,20 +1357,23 @@ def encrypt_assertion(self, statement, enc_key, template, key_type='des-192', no
13481357
return self.crypto.encrypt_assertion(
13491358
statement, enc_key, template, key_type, node_xpath)
13501359

1351-
def decrypt_keys(self, enctext, keys=None):
1360+
def decrypt_keys(self, enctext, keys=None, id_attr=''):
13521361
""" Decrypting an encrypted text by the use of a private key.
13531362
13541363
:param enctext: The encrypted text as a string
13551364
:return: The decrypted text
13561365
"""
13571366
_enctext = None
13581367

1368+
if not id_attr:
1369+
id_attr = self.id_attr
1370+
13591371
if not isinstance(keys, list):
13601372
keys = [keys]
13611373

13621374
if self.enc_key_files is not None:
13631375
for _enc_key_file in self.enc_key_files:
1364-
_enctext = self.crypto.decrypt(enctext, _enc_key_file)
1376+
_enctext = self.crypto.decrypt(enctext, _enc_key_file, id_attr)
13651377
if _enctext is not None and len(_enctext) > 0:
13661378
return _enctext
13671379

@@ -1370,28 +1382,31 @@ def decrypt_keys(self, enctext, keys=None):
13701382
if not isinstance(_key, six.binary_type):
13711383
_key = str(_key).encode('ascii')
13721384
_, key_file = make_temp(_key, decode=False)
1373-
_enctext = self.crypto.decrypt(enctext, key_file)
1385+
_enctext = self.crypto.decrypt(enctext, key_file, id_attr)
13741386
if _enctext is not None and len(_enctext) > 0:
13751387
return _enctext
13761388

13771389
return enctext
13781390

1379-
def decrypt(self, enctext, key_file=None):
1391+
def decrypt(self, enctext, key_file=None, id_attr=''):
13801392
""" Decrypting an encrypted text by the use of a private key.
13811393
13821394
:param enctext: The encrypted text as a string
13831395
:return: The decrypted text
13841396
"""
13851397
_enctext = None
13861398

1399+
if not id_attr:
1400+
id_attr = self.id_attr
1401+
13871402
if self.enc_key_files is not None:
13881403
for _enc_key_file in self.enc_key_files:
1389-
_enctext = self.crypto.decrypt(enctext, _enc_key_file)
1404+
_enctext = self.crypto.decrypt(enctext, _enc_key_file, id_attr)
13901405
if _enctext is not None and len(_enctext) > 0:
13911406
return _enctext
13921407

13931408
if key_file is not None and len(key_file.strip()) > 0:
1394-
_enctext = self.crypto.decrypt(enctext, key_file)
1409+
_enctext = self.crypto.decrypt(enctext, key_file, id_attr)
13951410
if _enctext is not None and len(_enctext) > 0:
13961411
return _enctext
13971412

@@ -1415,7 +1430,7 @@ def verify_signature(self, signedtext, cert_file=None, cert_type='pem', node_nam
14151430
cert_type = self.cert_type
14161431

14171432
if not id_attr:
1418-
id_attr = ID_ATTR
1433+
id_attr = self.id_attr
14191434

14201435
return self.crypto.validate_signature(
14211436
signedtext,
@@ -1650,7 +1665,7 @@ def sign_statement(self, statement, node_name, key=None, key_file=None, node_id=
16501665
:return: The signed statement
16511666
"""
16521667
if not id_attr:
1653-
id_attr = ID_ATTR
1668+
id_attr = self.id_attr
16541669

16551670
if not key_file and key:
16561671
_, key_file = make_temp(str(key).encode(), '.pem')

0 commit comments

Comments
 (0)