From 7198d9e88d3ac8942bc3cc26d2afa096b92d21e2 Mon Sep 17 00:00:00 2001 From: Sixto Martin Date: Thu, 26 Jun 2014 05:14:11 +0200 Subject: [PATCH] Validate in SAMLResponse the Audience --- example.py | 1 + onelogin/saml/Response.py | 61 ++++++++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/example.py b/example.py index 4261f6eb..89a79fae 100644 --- a/example.py +++ b/example.py @@ -79,6 +79,7 @@ def do_POST(self): res = Response( query['SAMLResponse'].pop(), self.settings['idp_cert_fingerprint'], + issuer=self.settings['issuer'] ) valid = res.is_valid() name_id = res.name_id diff --git a/onelogin/saml/Response.py b/onelogin/saml/Response.py index 77060e47..da2182fc 100644 --- a/onelogin/saml/Response.py +++ b/onelogin/saml/Response.py @@ -38,9 +38,8 @@ def __init__(self, msg): def __str__(self): return '%s: %s' % (self.__doc__, self._msg) - class Response(object): - def __init__(self, response, signature, _base64=None, _etree=None): + def __init__(self, response, signature, _base64=None, _etree=None, issuer=None): """ Extract information from an samlp:Response Arguments: @@ -55,6 +54,7 @@ def __init__(self, response, signature, _base64=None, _etree=None): decoded_response = _base64.b64decode(response) self._document = _etree.fromstring(decoded_response) self._signature = signature + self._issuer = issuer def _parse_datetime(self, dt): try: @@ -110,29 +110,44 @@ def is_valid(self, _clock=None, _verifier=None): now = _clock() - not_before = None - not_on_or_after = None + foundCondition = False + fountConditionAndAudience = False + for condition in conditions: - not_on_or_after = condition.attrib.get('NotOnOrAfter', None) + not_before = condition.attrib.get('NotBefore', None) - - if not_before is None: - #notbefore condition is not mandatory. If it is not specified, use yesterday as not_before condition - not_before = (now - timedelta(1, 0, 0)).strftime('%Y-%m-%dT%H:%M:%SZ') - if not_on_or_after is None: - raise ResponseConditionError('Did not find NotOnOrAfter condition') - - not_before = self._parse_datetime(not_before) - not_on_or_after = self._parse_datetime(not_on_or_after) - - if now < not_before: - raise ResponseValidationError( - 'Current time is earlier than NotBefore condition' - ) - if now >= not_on_or_after: - raise ResponseValidationError( - 'Current time is on or after NotOnOrAfter condition' - ) + not_on_or_after = condition.attrib.get('NotOnOrAfter', None) + + if not_before is None: + #notbefore condition is not mandatory. If it is not specified, use yesterday as not_before condition + not_before = (now - timedelta(0, 5, 0)).strftime('%Y-%m-%dT%H:%M:%SZ') + if not_on_or_after is None: + continue + + not_before = self._parse_datetime(not_before) + not_on_or_after = self._parse_datetime(not_on_or_after) + + if now < not_before: + continue + if now >= not_on_or_after: + continue + foundCondition = True + + if self._issuer: + audiences = condition.xpath( + '/samlp:Response/saml:Assertion/saml:Conditions/saml:AudienceRestriction/saml:Audience', + namespaces=namespaces, + ) + audienceValues = [] + for audience in audiences: + audienceValues.append(audience.text) + if self._issuer in audienceValues: + fountConditionAndAudience = True + + if not foundCondition: + raise ResponseConditionError('Timmig issue') + if foundCondition and not fountConditionAndAudience: + raise ResponseConditionError('Not valid Audience') return _verifier( self._document,