Skip to content

Commit 87e51d6

Browse files
author
Roland Hedberg
committed
Fixed decryption/verification of signed and encrypted assertions.
1 parent 84a1453 commit 87e51d6

File tree

5 files changed

+30
-29
lines changed

5 files changed

+30
-29
lines changed

src/saml2/client_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,8 @@ def parse_authn_request_response(self, xmlstr, binding, outstanding=None,
545545
raise
546546
except UnravelError:
547547
return None
548-
except Exception:
549-
logger.error("XML parse error")
548+
except Exception as err:
549+
logger.error("XML parse error: %s" % err)
550550
raise
551551

552552
#logger.debug(">> %s", resp)

src/saml2/entity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ def _parse_response(self, xmlstr, response_cls, service, binding,
841841
response = None
842842

843843
if self.config.accepted_time_diff:
844-
timeslack = self.config.accepted_time_diff
844+
kwargs["timeslack"] = self.config.accepted_time_diff
845845

846846
if "asynchop" not in kwargs:
847847
if binding in [BINDING_SOAP, BINDING_PAOS]:

src/saml2/response.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ def __init__(self, sec_context, attribute_converters, entity_id,
475475
else:
476476
self.outstanding_queries = {}
477477
self.context = "AuthnReq"
478-
self.came_from = ""
478+
self.came_from = None
479479
self.ava = None
480480
self.assertion = None
481481
self.assertions = []
@@ -507,7 +507,7 @@ def loads(self, xmldata, decode=True, origxml=None):
507507
if self.asynchop:
508508
if self.in_response_to in self.outstanding_queries:
509509
self.came_from = self.outstanding_queries[self.in_response_to]
510-
del self.outstanding_queries[self.in_response_to]
510+
#del self.outstanding_queries[self.in_response_to]
511511
try:
512512
if not self.check_subject_confirmation_in_response_to(
513513
self.in_response_to):
@@ -529,7 +529,7 @@ def loads(self, xmldata, decode=True, origxml=None):
529529

530530
def clear(self):
531531
self._clear()
532-
self.came_from = ""
532+
self.came_from = None
533533
self.ava = None
534534
self.assertion = None
535535

@@ -667,12 +667,12 @@ def _bearer_confirmed(self, data):
667667
if not later_than(data.not_on_or_after, data.not_before):
668668
return False
669669

670-
if self.asynchop and not self.came_from:
670+
if self.asynchop and self.came_from is None:
671671
if data.in_response_to:
672672
if data.in_response_to in self.outstanding_queries:
673673
self.came_from = self.outstanding_queries[
674674
data.in_response_to]
675-
del self.outstanding_queries[data.in_response_to]
675+
#del self.outstanding_queries[data.in_response_to]
676676
elif self.allow_unsolicited:
677677
pass
678678
else:
@@ -744,7 +744,7 @@ def get_subject(self):
744744
logger.info("Subject NameID: %s" % self.name_id)
745745
return self.name_id
746746

747-
def _assertion(self, assertion):
747+
def _assertion(self, assertion, verified=False):
748748
"""
749749
Check the assertion
750750
:param assertion:
@@ -758,12 +758,13 @@ def _assertion(self, assertion):
758758
else:
759759
logger.debug("signed")
760760

761-
try:
762-
self.sec.check_signature(assertion, class_name(assertion),
763-
self.xmlstr)
764-
except Exception as exc:
765-
logger.error("correctly_signed_response: %s" % exc)
766-
raise
761+
if not verified:
762+
try:
763+
self.sec.check_signature(assertion, class_name(assertion),
764+
self.xmlstr)
765+
except Exception as exc:
766+
logger.error("correctly_signed_response: %s" % exc)
767+
raise
767768

768769
self.assertion = assertion
769770
logger.debug("assertion context: %s" % (self.context,))
@@ -791,23 +792,23 @@ def _assertion(self, assertion):
791792
if self.asynchop:
792793
if self.allow_unsolicited:
793794
pass
794-
elif not self.came_from:
795+
elif self.came_from is None:
795796
raise VerificationError("Came from")
796797
return True
797798
except Exception:
798799
logger.exception("get subject")
799800
raise
800801

801-
def decrypt_assertions(self, encrypted_assertions, key_file=""):
802+
def decrypt_assertions(self, encrypted_assertions, decr_txt):
802803
res = []
803804
for encrypted_assertion in encrypted_assertions:
804805
if encrypted_assertion.extension_elements:
805806
assertions = extension_elements_to_elements(
806807
encrypted_assertion.extension_elements, [saml, samlp])
807808
for assertion in assertions:
808809
if assertion.signature:
809-
if not self.sec.verify_signature(
810-
"%s" % assertion, key_file,
810+
if not self.sec.check_signature(
811+
assertion, origdoc=decr_txt,
811812
node_name=class_name(assertion)):
812813
logger.error(
813814
"Failed to verify signature on '%s'" % assertion)
@@ -826,21 +827,23 @@ def parse_assertion(self, key_file=""):
826827
except AssertionError:
827828
raise Exception("No assertion part")
828829

830+
res = []
829831
if self.response.encrypted_assertion:
830832
logger.debug("***Encrypted assertion/-s***")
831833
decr_text = self.sec.decrypt(self.xmlstr, key_file)
832834
resp = samlp.response_from_string(decr_text)
833-
res = self.decrypt_assertions(resp.encrypted_assertion, key_file)
835+
res = self.decrypt_assertions(resp.encrypted_assertion, decr_text)
834836
if self.response.assertion:
835837
self.response.assertion.extend(res)
836838
else:
837839
self.response.assertion = res
838840
self.response.encrypted_assertion = []
841+
self.xmlstr = decr_text
839842

840843
if self.response.assertion:
841844
logger.debug("***Unencrypted assertion***")
842845
for assertion in self.response.assertion:
843-
if not self._assertion(assertion):
846+
if not self._assertion(assertion, assertion in res):
844847
return False
845848
else:
846849
self.assertions.append(assertion)

src/saml2/sigver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,7 @@ def check_signature(self, item, node_name=NODE_NAME, origdoc=None,
13771377
"""
13781378
13791379
:param item: Parsed entity
1380-
:param node_name:
1380+
:param node_name: The name of the class that is signed
13811381
:param origdoc: The original XML string
13821382
:param id_attr:
13831383
:param must:

tests/test_41_response.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
from saml2.response import response_factory
99
from saml2.response import StatusResponse
1010
from saml2.response import AuthnResponse
11-
from saml2.sigver import security_context, SignatureError
12-
from saml2.sigver import MissingKey
13-
14-
from pytest import raises
11+
from saml2.sigver import SignatureError
1512

1613
FALSE_ASSERT_SIGNED = "saml_false_signed.xml"
1714

15+
TIMESLACK = 2592000 # Roughly 3 month
1816

1917
def _eq(l1, l2):
2018
return set(l1) == set(l2)
@@ -73,7 +71,7 @@ def test_1(self):
7371
"http://lingon.catalogix.se:8087/"],
7472
outstanding_queries={
7573
"id12": "http://localhost:8088/sso"},
76-
timeslack=10000, decode=False)
74+
timeslack=TIMESLACK, decode=False)
7775

7876
assert isinstance(resp, StatusResponse)
7977
assert isinstance(resp, AuthnResponse)
@@ -85,7 +83,7 @@ def test_2(self):
8583
"http://lingon.catalogix.se:8087/"],
8684
outstanding_queries={
8785
"id12": "http://localhost:8088/sso"},
88-
timeslack=10000, decode=False)
86+
timeslack=TIMESLACK, decode=False)
8987

9088
assert isinstance(resp, StatusResponse)
9189
assert isinstance(resp, AuthnResponse)
@@ -98,7 +96,7 @@ def test_false_sign(self):
9896
outstanding_queries={
9997
"bahigehogffohiphlfmplepdpcohkhhmheppcdie":
10098
"http://localhost:8088/sso"},
101-
timeslack=1000000, decode=False)
99+
timeslack=TIMESLACK, decode=False)
102100

103101
assert isinstance(resp, StatusResponse)
104102
assert isinstance(resp, AuthnResponse)

0 commit comments

Comments
 (0)