Skip to content

Commit 9d901af

Browse files
committed
Fix strings/bytes python3 issues in sigver
Various points require binary data to feed into xmlsec or strings to make logical sense of things. This may introduce some requirement that saml documents are utf-8, where previously binary data would be passed through without problems. Without the proper encoding metadata passed through that is not a simple problem to solve.
1 parent 9c2b951 commit 9d901af

File tree

3 files changed

+30
-19
lines changed

3 files changed

+30
-19
lines changed

src/saml2/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ def create_class_from_xml_string(target_class, xml_string):
8383
the contents of the XML - or None if the root XML tag and namespace did
8484
not match those of the target class.
8585
"""
86+
if not isinstance(xml_string, six.binary_type):
87+
xml_string = xml_string.encode('utf-8')
8688
tree = ElementTree.fromstring(xml_string)
8789
return create_class_from_element_tree(target_class, tree)
8890

src/saml2/sigver.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ def _instance(klass, ava, seccont, base64encode=False, elements_to_sign=None):
266266
#print("# %s" % (prop))
267267
if prop in ava:
268268
if isinstance(ava[prop], bool):
269-
setattr(instance, prop, "%s" % ava[prop])
269+
setattr(instance, prop, str(ava[prop]).encode('utf-8'))
270270
elif isinstance(ava[prop], int):
271271
setattr(instance, prop, "%d" % ava[prop])
272272
else:
@@ -313,7 +313,7 @@ def signed_instance_factory(instance, seccont, elements_to_sign=None):
313313
:return: A class instance if not signed otherwise a string
314314
"""
315315
if elements_to_sign:
316-
signed_xml = "%s" % instance
316+
signed_xml = str(instance).encode('utf-8')
317317
for (node_name, nodeid) in elements_to_sign:
318318
signed_xml = seccont.sign_statement(
319319
signed_xml, node_name=node_name, node_id=nodeid)
@@ -351,6 +351,7 @@ def make_temp(string, suffix="", decode=True, delete=True):
351351
xmlsec function).
352352
"""
353353
ntf = NamedTemporaryFile(suffix=suffix, delete=delete)
354+
assert isinstance(string, six.binary_type)
354355
if decode:
355356
ntf.write(base64.b64decode(string))
356357
else:
@@ -543,7 +544,7 @@ def extract_rsa_key_from_x509_cert(pem):
543544

544545
def pem_format(key):
545546
return "\n".join(["-----BEGIN CERTIFICATE-----",
546-
key, "-----END CERTIFICATE-----"])
547+
key, "-----END CERTIFICATE-----"]).encode('ascii')
547548

548549

549550
def import_rsa_key_from_file(filename):
@@ -740,8 +741,9 @@ def __init__(self, xmlsec_binary, **kwargs):
740741
def version(self):
741742
com_list = [self.xmlsec, "--version"]
742743
pof = Popen(com_list, stderr=PIPE, stdout=PIPE)
744+
content = pof.stdout.read().decode('ascii')
743745
try:
744-
return pof.stdout.read().split(" ")[1]
746+
return content.split(" ")[1]
745747
except IndexError:
746748
return ""
747749

@@ -757,7 +759,7 @@ def encrypt(self, text, recv_key, template, session_key_type, xpath=""):
757759
:return:
758760
"""
759761
logger.debug("Encryption input len: %d" % len(text))
760-
_, fil = make_temp("%s" % text, decode=False)
762+
_, fil = make_temp(str(text).encode('utf-8'), decode=False)
761763

762764
com_list = [self.xmlsec, "--encrypt", "--pubkey-cert-pem", recv_key,
763765
"--session-key", session_key_type, "--xml-data", fil]
@@ -768,6 +770,8 @@ def encrypt(self, text, recv_key, template, session_key_type, xpath=""):
768770
(_stdout, _stderr, output) = self._run_xmlsec(com_list, [template],
769771
exception=DecryptError,
770772
validate_output=False)
773+
if isinstance(output, six.binary_type):
774+
output = output.decode('utf-8')
771775
return output
772776

773777
def encrypt_assertion(self, statement, enc_key, template,
@@ -785,8 +789,8 @@ def encrypt_assertion(self, statement, enc_key, template,
785789
if isinstance(statement, SamlBase):
786790
statement = pre_encrypt_assertion(statement)
787791

788-
_, fil = make_temp("%s" % statement, decode=False, delete=False)
789-
_, tmpl = make_temp("%s" % template, decode=False)
792+
_, fil = make_temp(str(statement).encode('utf-8'), decode=False, delete=False)
793+
_, tmpl = make_temp(str(template).encode('utf-8'), decode=False)
790794

791795
if not node_xpath:
792796
node_xpath = ASSERT_XPATH
@@ -815,7 +819,7 @@ def decrypt(self, enctext, key_file):
815819
"""
816820

817821
logger.debug("Decrypt input len: %d" % len(enctext))
818-
_, fil = make_temp("%s" % enctext, decode=False)
822+
_, fil = make_temp(str(enctext).encode('utf-8'), decode=False)
819823

820824
com_list = [self.xmlsec, "--decrypt", "--privkey-pem",
821825
key_file, "--id-attr:%s" % ID_ATTR, ENC_KEY_CLASS]
@@ -838,9 +842,11 @@ def sign_statement(self, statement, node_name, key_file, node_id,
838842
'id','Id' or 'ID'
839843
:return: The signed statement
840844
"""
845+
if not isinstance(statement, six.binary_type):
846+
statement = str(statement).encode('utf-8')
841847

842-
_, fil = make_temp("%s" % statement, suffix=".xml", decode=False,
843-
delete=self._xmlsec_delete_tmpfiles)
848+
_, fil = make_temp(statement, suffix=".xml",
849+
decode=False, delete=self._xmlsec_delete_tmpfiles)
844850

845851
com_list = [self.xmlsec, "--sign",
846852
"--privkey-pem", key_file,
@@ -875,6 +881,8 @@ def validate_signature(self, signedtext, cert_file, cert_type, node_name,
875881
:param id_attr: Should normally be one of "id", "Id" or "ID"
876882
:return: Boolean True if the signature was correct otherwise False.
877883
"""
884+
if not isinstance(signedtext, six.binary_type):
885+
signedtext = signedtext.encode('utf-8')
878886
_, fil = make_temp(signedtext, suffix=".xml",
879887
decode=False, delete=self._xmlsec_delete_tmpfiles)
880888

@@ -924,8 +932,8 @@ def _run_xmlsec(self, com_list, extra_args, validate_output=True,
924932

925933
pof = Popen(com_list, stderr=PIPE, stdout=PIPE)
926934

927-
p_out = pof.stdout.read()
928-
p_err = pof.stderr.read()
935+
p_out = pof.stdout.read().decode('utf-8')
936+
p_err = pof.stderr.read().decode('utf-8')
929937

930938
if pof.returncode is not None and pof.returncode < 0:
931939
logger.error(LOG_LINE % (p_out, p_err))
@@ -1685,7 +1693,7 @@ def sign_statement(self, statement, node_name, key=None,
16851693
id_attr = ID_ATTR
16861694

16871695
if not key_file and key:
1688-
_, key_file = make_temp("%s" % key, ".pem")
1696+
_, key_file = make_temp(str(key).encode('utf-8'), ".pem")
16891697

16901698
if not key and not key_file:
16911699
key_file = self.key_file

tests/test_40_sigver.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,10 +299,11 @@ def test_sign_verify(self):
299299
to_sign = [(class_name(self._assertion), self._assertion.id),
300300
(class_name(response), response.id)]
301301

302-
s_response = sigver.signed_instance_factory(response, self.sec, to_sign)
302+
s_response = sigver.signed_instance_factory(response, self.sec,
303+
to_sign)
303304

304305
print(s_response)
305-
res = self.sec.verify_signature("%s" % s_response,
306+
res = self.sec.verify_signature(s_response,
306307
node_name=class_name(samlp.Response()))
307308

308309
print(res)
@@ -327,7 +328,7 @@ def test_sign_verify_with_cert_from_instance(self):
327328

328329
assert ci == self.sec.my_cert
329330

330-
res = self.sec.verify_signature("%s" % s_response,
331+
res = self.sec.verify_signature(s_response,
331332
node_name=class_name(samlp.Response()))
332333

333334
assert res
@@ -358,7 +359,7 @@ def test_sign_verify_assertion_with_cert_from_instance(self):
358359
ci = "".join(sigver.cert_from_instance(ass)[0].split())
359360
assert ci == self.sec.my_cert
360361

361-
res = self.sec.verify_signature("%s" % s_assertion,
362+
res = self.sec.verify_signature(s_assertion,
362363
node_name=class_name(ass))
363364
assert res
364365

@@ -447,9 +448,9 @@ def test_xbox():
447448
encrypted_assertion = EncryptedAssertion()
448449
encrypted_assertion.add_extension_element(_ass0)
449450

450-
_, pre = make_temp("%s" % pre_encryption_part(), decode=False)
451+
_, pre = make_temp(str(pre_encryption_part()).encode('utf-8'), decode=False)
451452
enctext = sec.crypto.encrypt(
452-
"%s" % encrypted_assertion, conf.cert_file, pre, "des-192",
453+
str(encrypted_assertion), conf.cert_file, pre, "des-192",
453454
'/*[local-name()="EncryptedAssertion"]/*[local-name()="Assertion"]')
454455

455456

0 commit comments

Comments
 (0)