Ignore:
Timestamp:
25/03/08 16:50:35 (11 years ago)
Author:
pjkersha
Message:

Added Timestamp capability to wsSecurity module. Currently testing against Apache2 Rampart.

File:
1 edited

Legend:

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

    r3652 r3676  
    5454X509Stack, X509StackParseFromDER 
    5555 
     56from datetime import datetime, timedelta 
     57import logging 
     58log = logging.getLogger(__name__) 
     59 
    5660 
    5761class _ENCRYPTION(ENCRYPTION): 
     
    100104    """Raised from SignatureHandler.verify if an error occurs in the signature 
    101105    verification""" 
    102     
     106  
     107class TimestampError(Exception): 
     108    """Raised from SignatureHandler._verifyTimestamp if there is a problem with 
     109    the created or expiry times in an input message Timestamp""" 
     110     
    103111class InvalidSignature(Exception): 
    104112    """Raised from verify method for an invalid signature""" 
     
    149157                 caCertDirPath=None, 
    150158                 caCertFilePathList=[], 
     159                 addTimestamp=True, 
    151160                 refC14nKw={'unsuppressedPrefixes': ['xmlns',  
    152161                                                     'xsi',  
     
    223232        @type caCertFilePathList: list or tuple 
    224233         
     234        @param addTimestamp: set to true to add a timestamp to outbound  
     235        messages 
     236        @type addTimestamp: bool  
     237         
    225238        @param refC14nKw: dictionary of keywords to reference  
    226239        Canonicalization.  Use 'unsuppressedPrefixes' keyword to set  
     
    269282        elif caCertFilePathList: 
    270283            self.caCertFilePathList = caCertFilePathList 
     284             
     285        self.addTimestamp = addTimestamp 
    271286         
    272287                 
     
    714729        binSecTokElem.createAppendTextNode(binSecTokVal) 
    715730 
    716          
     731 
     732        # Timestamp 
     733        if self.addTimestamp: 
     734            self._addTimeStamp(wsseElem) 
     735             
     736             
    717737        # Signature 
    718738        signatureElem = wsseElem.createAppendElement(DSIG.BASE, 'Signature') 
     
    866886        signatureValueElem.createAppendTextNode(b64EncSignatureValue) 
    867887 
     888    def _addTimeStamp(self, wsseElem, elapsedSec=60*5): 
     889        '''Add a timestamp to wsse:Security section of message to be signed 
     890        e.g. 
     891            <wsu:Timestamp wsu:Id="timestamp"> 
     892               <wsu:Created>2008-03-25T14:40:37.319Z</wsu:Created> 
     893               <wsu:Expires>2008-03-25T14:45:37.319Z</wsu:Expires> 
     894            </wsu:Timestamp> 
     895        ''' 
     896        # Nb. wsu ns declaration is in the SOAP header elem 
     897        timestampElem = wsseElem.createAppendElement(_WSU.UTILITY, 'Timestamp') 
     898 
     899        # Add ID so that the timestamp element can be included in the signature 
     900        timestampElem.node.setAttribute('wsu:Id', "timestamp") 
     901         
     902        # Value type can be any be any one of those supported via  
     903        # binSecTokValType 
     904        createdElem = timestampElem.createAppendElement(_WSU.UTILITY,'Created') 
     905        dtCreatedTime = datetime.utcnow() 
     906        createdElem.createAppendTextNode(dtCreatedTime.isoformat('T')+'Z') 
     907         
     908        dtExpiryTime = dtCreatedTime + timedelta(seconds=elapsedSec) 
     909        expiresElem = timestampElem.createAppendElement(_WSU.UTILITY,'Expires') 
     910        expiresElem.createAppendTextNode(dtExpiryTime.isoformat('T')+'Z') 
     911         
     912 
     913    def _verifyTimeStamp(self, parsedSOAP, ctxt): 
     914        """Call from verify to check timestamp if found.   
     915         
     916        TODO: refactor input args - maybe these should by object attributes 
     917         
     918        @type parsedSOAP: ZSI.parse.ParsedSoap 
     919        @param parsedSOAP: object contain parsed SOAP message received from 
     920        sender 
     921        @type ctxt: 
     922        @param ctxt: XPath context object""" 
     923 
     924        try: 
     925            timestampNode = xpath.Evaluate('//wsse:Timestamp', 
     926                                           contextNode=parsedSOAP.dom, 
     927                                           context=ctxt)[0] 
     928        except: 
     929            log.warning("Verifying message - No timestamp element found") 
     930            return 
     931         
     932        # Time now  
     933        dtNow = datetime.utcnow() 
     934         
     935        createdNode = timestampNode.getElementsByTagName("Created") 
     936         
     937        # Workaround for fractions of second 
     938        try: 
     939            [createdDateTime, createdSecFraction]=createdNode.nodeValue.split() 
     940        except ValueError, e: 
     941            raise ValueError("Parsing timestamp Created element: %s" % e) 
     942         
     943        dtCreated = datetime.strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S') 
     944        dtCreated += timedelta(seconds=int(createdSecFraction)) 
     945        if dtCreated >= dtNow: 
     946            raise TimestampError(\ 
     947        "Timestamp created time %s is equal to or after the current time %s" %\ 
     948                (dtCreated, dtNow)) 
     949         
     950        expiresNode = timestampNode.getElementsByTagName("Expires") 
     951        if expiresNode is None: 
     952            log.warning(\ 
     953                "Verifying message - No Expires element found in Timestamp") 
     954            return 
     955 
     956        try: 
     957            [expiresDateTime, expiresSecFraction]=expiresNode.nodeValue.split() 
     958        except ValueError, e: 
     959            raise ValueError("Parsing timestamp Expires element: %s" % e) 
     960         
     961        dtCreated = datetime.strptime(expiresDateTime, '%Y-%m-%dT%H:%M:%S') 
     962        dtCreated += timedelta(seconds=int(createdSecFraction)) 
     963        if dtExpiry > dtNow: 
     964            raise TimestampError(\ 
     965                "Timestamp expiry time %s is after the current time %s" % \ 
     966                (dtCreated, dtNow)) 
     967 
    868968 
    869969    def verify(self, parsedSOAP): 
     
    894994        except: 
    895995            # Message wasn't signed 
     996            log.warning("Input message wasn't signed!") 
    896997            return 
    897998         
     
    9761077                raise InvalidSignature, \ 
    9771078                        'Digest Values do not match for URI: "%s"' % refURI 
     1079             
     1080            log.info("Verified canonicalization for element %s" % refURI[1:]) 
    9781081                 
    9791082        # 2) Signature Validation 
     
    10411144            # elsewhere 
    10421145            binSecTokNode = None 
    1043             pass  
    10441146         
    10451147        if binSecTokNode: 
     
    10961198        x509Stack.verifyCertChain(x509Cert2Verify=self.__verifyingCert, 
    10971199                                  caX509Stack=self.__caX509Stack) 
    1098              
    1099         #print "Signature OK" 
    1100  
     1200         
     1201        self._verifyTimeStamp(parsedSOAP, ctxt)  
     1202        log.info("Signature OK")         
     1203         
    11011204 
    11021205class EncryptionError(Exception): 
Note: See TracChangeset for help on using the changeset viewer.