Changeset 4074 for TI12-security


Ignore:
Timestamp:
30/07/08 09:49:54 (11 years ago)
Author:
cbyrom
Message:

Improve error handling - custom exceptions now all subclass WsSecurityError?
and this automatically logs the error to the server log.
Fix timestamp validation:

  • adjust the object parsing to actually retrieve the created + expires

date stamps

  • fix the handling of these - to cope with seconds fractions

Escape signing of the BinarySecurityToken? - as this does not seem
to be able to be set using a java client with Rampart.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/wsSecurity.py

    r4054 r4074  
    114114    """For WS-Security generic exceptions not covered by other exception 
    115115    classes in this module""" 
    116  
    117 class InvalidCertChain(Exception):     
     116    def __init__(self, errorMessage): 
     117        log.warning(errorMessage) 
     118        super(WSSecurityError, self).__init__(errorMessage) 
     119 
     120class InvalidCertChain(WSSecurityError):     
    118121    """Raised from SignatureHandler.verify if the certificate submitted to 
    119122    verify a signature is not from a known CA""" 
    120123     
    121 class VerifyError(Exception): 
     124class VerifyError(WSSecurityError): 
    122125    """Raised from SignatureHandler.verify if an error occurs in the signature 
    123126    verification""" 
    124127  
    125 class TimestampError(Exception): 
     128class TimestampError(WSSecurityError): 
    126129    """Raised from SignatureHandler._verifyTimestamp if there is a problem with 
    127130    the created or expiry times in an input message Timestamp""" 
    128131     
    129 class InvalidSignature(Exception): 
     132class InvalidSignature(WSSecurityError): 
    130133    """Raised from verify method for an invalid signature""" 
    131134 
    132 class SignatureError(Exception): 
     135class SignatureError(WSSecurityError): 
    133136    """Flag if an error occurs during signature generation""" 
    134137         
     
    769772        @param ctxt: XPath context object""" 
    770773 
     774        # TODO: do we need to be more rigorous in terms of handling the situation 
     775        # where no timestamp is found? 
     776         
    771777        try: 
    772778            timestampNode = xpath.Evaluate('//wsu:Timestamp', 
     
    783789        # Time now  
    784790        dtNow = datetime.utcnow() 
    785         try: 
    786             createdNodeText = getElements(timestampNode, "Created")[0].\ 
    787                                     childNodes[0].nodeValue 
    788         except IndexError: 
     791 
     792        createdNode = timestampNode.getElementsByTagName("wsu:Created") 
     793        if createdNode is None: 
    789794            raise TimestampError("Verifying message - No Created timestamp " 
    790795                                 "sub-element found") 
     
    792797        # Workaround for fractions of second 
    793798        try: 
    794             createdDateTime, strCreatedSecFraction = createdNodeText.split('.') 
     799            createdDateTime, createdSecFraction = createdNode[0].childNodes[0].nodeValue.split('.') 
     800            dtCreated = datetime.strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S') 
     801            dtCreated += timedelta(seconds=float("0." + createdSecFraction.replace('Z', ''))) 
    795802                                             
    796             strCreatedSecFraction = strCreatedSecFraction.split('Z')[0] 
    797             createdExp = -int(len(strCreatedSecFraction)) 
    798             createdSecFraction = int(strCreatedSecFraction) * 10 ** createdExp 
    799  
    800803        except ValueError, e: 
    801             raise ValueError("Parsing timestamp Created element: %s" % e) 
    802          
    803         dtCreated = datetime.strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S') 
    804         dtCreated += timedelta(seconds=createdSecFraction) 
     804            raise TimestampError("Failed to parse timestamp Created element: %s" % e) 
     805         
    805806        if dtCreated >= dtNow: 
    806807            raise TimestampError(\ 
    807         "Timestamp created time %s is equal to or after the current time %s" %\ 
     808            "Timestamp created time %s is equal to or after the current time %s" %\ 
    808809                (dtCreated, dtNow)) 
    809810         
     811        expiresNode = timestampNode.getElementsByTagName("wsu:Expires") 
     812        if expiresNode is None: 
     813            log.warning("Verifying message - No Expires element found in Timestamp") 
     814            return 
     815 
    810816        try: 
    811             expiresNodeText = getElements(timestampNode, "Expires")[0].\ 
    812                                     childNodes[0].nodeValue 
    813         except IndexError: 
    814             raise TimestampError("Verifying message - No Expires element " 
    815                                  "found in Timestamp") 
    816  
    817         try: 
    818             expiryDateTime, strExpirySecFraction = expiresNodeText.split('.') 
    819              
    820             strExpirySecFraction = strExpirySecFraction.split('Z')[0] 
    821             expiryExp = -int(len(strExpirySecFraction)) 
    822             expirySecFraction = int(strExpirySecFraction) * 10 ** expiryExp 
     817            expiresDateTime, expiresSecFraction = expiresNode[0].childNodes[0].nodeValue.split('.') 
     818            dtExpiry = datetime.strptime(expiresDateTime, '%Y-%m-%dT%H:%M:%S') 
     819            dtExpiry += timedelta(seconds=float("0." + expiresSecFraction.replace('Z', ''))) 
    823820 
    824821        except ValueError, e: 
    825             raise ValueError("Parsing timestamp Expires element: %s" % e) 
    826          
    827         dtExpiry = datetime.strptime(expiryDateTime, '%Y-%m-%dT%H:%M:%S') 
    828         dtExpiry += timedelta(seconds=expirySecFraction) 
     822            raise TimestampError("Failed to parse timestamp Expires element: %s" % e) 
     823 
    829824        if dtExpiry < dtNow: 
    830825            raise TimestampError(\ 
    831                 "Timestamp expiry time %s is after the current time %s" % \ 
    832                 (dtCreated, dtNow)) 
     826                "Timestamp expiry time %s is before the current time %s - i.e. the message has expired." % \ 
     827                (dtExpiry, dtNow)) 
    833828             
    834829                    
     
    990985        for refNode in refNodes: 
    991986             
     987            refID = refNode.attributes[(_WSU.UTILITY, 'Id')].value 
     988            # skip binary security token 
     989            # - NB, this cannot be signed by a java client using Rampart1.3 
     990            if refID == "binaryToken": 
     991                continue 
     992             
    992993            # Set URI attribute to point to reference to be signed 
    993994            #uri = u"#" + refNode.getAttribute('wsu:Id') 
    994             uri = u"#" + refNode.attributes[(_WSU.UTILITY, 'Id')].value 
     995            uri = u"#" + refID 
    995996             
    996997            # Canonicalize reference 
     
    11271128            # Get the URI for the reference 
    11281129            refURI = refNode.getAttributeNode('URI').value 
     1130                        # skip checking of binary token - since this cannot be 
     1131                        # included in the message if using a Java client with Rampart1.3 
     1132            if refURI == "binaryToken": 
     1133                continue 
    11291134                          
    11301135            try: 
Note: See TracChangeset for help on using the changeset viewer.