Ignore:
Timestamp:
04/03/10 15:15:56 (10 years ago)
Author:
pjkersha
Message:

Fixes to SAML timestamp checking

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/branches/ndg-security-1.5.x/ndg_security_common/ndg/security/common/saml_utils/bindings.py

    r6069 r6674  
    243243    ISSUER_NAME_OPTNAME = 'issuerName' 
    244244    CLOCK_SKEW_OPTNAME = 'clockSkew' 
     245    VERIFY_TIME_CONDITIONS_OPTNAME = 'verifyTimeConditions' 
    245246     
    246247    CONFIG_FILE_OPTNAMES = ( 
    247248        SUBJECT_ID_OPTNAME, 
    248249        ISSUER_NAME_OPTNAME,                  
    249         CLOCK_SKEW_OPTNAME             
     250        CLOCK_SKEW_OPTNAME,  
     251        VERIFY_TIME_CONDITIONS_OPTNAME       
    250252    ) 
    251253     
     
    265267        self.__queryAttributes = TypedList(Attribute) 
    266268        self.__clockSkew = timedelta(seconds=0.) 
    267                  
     269        self.__verifyTimeConditions = True 
     270     
    268271        super(AttributeQuerySOAPBinding, self).__init__(**kw) 
    269272 
     
    339342                raise 
    340343 
     344    def _getVerifyTimeConditions(self): 
     345        return self.__verifyTimeConditions 
     346 
     347    def _setVerifyTimeConditions(self, value): 
     348        if isinstance(value, bool): 
     349            self.__verifyTimeConditions = value 
     350             
     351        if isinstance(value, basestring): 
     352            self.__verifyTimeConditions = str2Bool(value) 
     353        else: 
     354            raise TypeError('Expecting bool or string type for ' 
     355                            '"verifyTimeConditions"; got %r instead' %  
     356                            type(value)) 
     357 
     358    verifyTimeConditions = property(_getVerifyTimeConditions,  
     359                                    _setVerifyTimeConditions,  
     360                                    doc='Set to True to verify any time ' 
     361                                        'Conditions set in the returned ' 
     362                                        'response assertions')  
     363     
    341364    def _getSubjectID(self): 
    342365        return self.__subjectID 
     
    426449             
    427450        return attributeQuery 
    428  
     451     
     452    def _verifyTimeConditions(self, response): 
     453        """Verify time conditions set in a response 
     454        @param response: SAML Response returned from remote service 
     455        @type response: ndg.saml.saml2.core.Response 
     456        @raise SubjectQueryResponseError: if a timestamp is invalid 
     457        """ 
     458         
     459        if not self.verifyTimeConditions: 
     460            log.debug("Skipping verification of SAML Response time conditions") 
     461             
     462        utcNow = datetime.utcnow()  
     463        nowMinusSkew = utcNow - self.clockSkew 
     464        nowPlusSkew = utcNow + self.clockSkew 
     465         
     466        if response.issueInstant > nowPlusSkew: 
     467            msg = ('SAML Attribute Response issueInstant [%s] is after ' 
     468                   'the clock time [%s] (skewed +%s)' %  
     469                   (response.issueInstant,  
     470                    SAMLDateTime.toString(nowPlusSkew), 
     471                    self.clockSkew)) 
     472             
     473            samlRespError = AttributeQueryResponseError(msg)                   
     474            samlRespError.response = response 
     475            raise samlRespError 
     476         
     477        for assertion in response.assertions: 
     478            if assertion.issueInstant is None: 
     479                samlRespError = AttributeQueryResponseError("No issueInstant " 
     480                                                            "set in response " 
     481                                                            "assertion") 
     482                samlRespError.response = response 
     483                raise samlRespError 
     484             
     485            elif nowPlusSkew < assertion.issueInstant: 
     486                msg = ('The clock time [%s] (skewed +%s) is before the ' 
     487                       'SAML Attribute Response assertion issue instant [%s]' %  
     488                       (SAMLDateTime.toString(utcNow), 
     489                        self.clockSkew, 
     490                        assertion.issueInstant)) 
     491                samlRespError = AttributeQueryResponseError(msg) 
     492                samlRespError.response = response 
     493                raise samlRespError 
     494 
     495            if assertion.conditions is not None: 
     496                if nowPlusSkew < assertion.conditions.notBefore: 
     497                    msg = ('The clock time [%s] (skewed +%s) is before the ' 
     498                           'SAML Attribute Response assertion conditions not ' 
     499                           'before time [%s]' %  
     500                           (SAMLDateTime.toString(utcNow), 
     501                            self.clockSkew, 
     502                            assertion.conditions.notBefore)) 
     503                               
     504                    samlRespError = AttributeQueryResponseError(msg) 
     505                    samlRespError.response = response 
     506                    raise samlRespError 
     507                  
     508                if nowMinusSkew >= assertion.conditions.notOnOrAfter:            
     509                    msg = ('The clock time [%s] (skewed -%s) is on or after ' 
     510                           'the SAML Attribute Response assertion conditions ' 
     511                           'not on or after time [%s]' %  
     512                           (SAMLDateTime.toString(utcNow), 
     513                            self.clockSkew, 
     514                            assertion.conditions.notOnOrAfter)) 
     515                     
     516                    samlRespError = AttributeQueryResponseError(msg)  
     517                    samlRespError.response = response 
     518                    raise samlRespError 
     519                 
    429520    def send(self, **kw): 
    430521        '''Make an attribute query to a remote SAML service 
     
    458549            raise samlRespError 
    459550         
    460         utcNow = datetime.utcnow() + self.clockSkew 
    461         if response.issueInstant > utcNow: 
    462             msg = ('SAML Attribute Response issueInstant [%s] is after ' 
    463                    'the current clock time [%s]' %  
    464                    (attributeQuery.issueInstant, SAMLDateTime.toString(utcNow))) 
    465              
    466             samlRespError = AttributeQueryResponseError(msg)                   
    467             samlRespError.response = response 
    468             raise samlRespError 
    469          
    470         for assertion in response.assertions: 
    471             if utcNow < assertion.conditions.notBefore:             
    472                 msg = ('The current clock time [%s] is before the SAML ' 
    473                        'Attribute Response assertion conditions not before ' 
    474                        'time [%s]' %  
    475                        (SAMLDateTime.toString(utcNow), 
    476                         assertion.conditions.notBefore)) 
    477                            
    478                 samlRespError = AttributeQueryResponseError(msg) 
    479                 samlRespError.response = response 
    480                 raise samlRespError 
    481               
    482             if utcNow >= assertion.conditions.notOnOrAfter:            
    483                 msg = ('The current clock time [%s] is on or after the SAML ' 
    484                        'Attribute Response assertion conditions not on or ' 
    485                        'after time [%s]' %  
    486                        (SAMLDateTime.toString(utcNow), 
    487                         response.assertion.conditions.notOnOrAfter)) 
    488                  
    489                 samlRespError = AttributeQueryResponseError(msg)  
    490                 samlRespError.response = response 
    491                 raise samlRespError    
    492              
     551        self._verifyTimeConditions(response) 
     552         
    493553        return response  
    494554 
Note: See TracChangeset for help on using the changeset viewer.