Changeset 3676


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.

Location:
TI12-security/trunk/python
Files:
3 added
4 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): 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/sso/sso.cfg

    r3658 r3676  
    88[NDG_SECURITY] 
    99# Server address for secure connections 
    10 sslServer: https://gabriel.badc.rl.ac.uk 
    11 server:    http://gabriel.badc.rl.ac.uk:4000 
     10sslServer: https://localhost 
     11server:    http://localhost:4000 
     12#sslServer: https://gabriel.badc.rl.ac.uk 
     13#server:    http://gabriel.badc.rl.ac.uk:4000 
    1214 
    1315# Redirect SOAP output to a file e.g. open(<somefile>, 'w') 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/sso/sso/controllers/login.py

    r3658 r3676  
    217217            log.debug('Login redirect to [%s]' % returnToURL) 
    218218 
    219             returnToURLHostname = urlsplit(returnToURL)[1] 
    220 #            returnToURLHostname = 'localhost' 
     219            hostnameWithPortNum = urlsplit(returnToURL)[1] 
     220             
     221            # Require hostname with port number striped to test SSL connection 
     222            # (will default to 443) 
     223            returnToURLHostname = hostnameWithPortNum.split(':')[0] 
     224             
    221225#            if thisHostname not in returnToURLHostname: 
    222             if True: 
     226            if True: # Ensure return args in URL regardless 
    223227                # Returning to a different domain - copy the security session 
    224228                # details into the URL query string 
     
    233237            # Inclusive namespace prefixes for WS-Security digital signature 
    234238            # (Exclusive C14N only) 
    235             refC14nKw={'unsuppressedPrefixes':g.securityCfg.wssRefInclNS} 
     239            refC14nKw = {'unsuppressedPrefixes':g.securityCfg.wssRefInclNS} 
    236240            signedInfoC14nKw = {'unsuppressedPrefixes': 
    237241                                g.securityCfg.wssSignedInfoInclNS} 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/sso/sso/lib/base.py

    r3658 r3676  
    3939        # Also, avoid returning to getCredentials and potentially exposing 
    4040        # username/pass-phrase on URL. 
    41         # TODO: rework getCredentials get-out for more modular solution 
    4241        pathInfo = urllib.quote(environ.get('PATH_INFO', ''))  
    4342        if 'getCredentials' in pathInfo: 
     
    4645        else: 
    4746            c.requestURL = g.securityCfg.server + pathInfo 
    48             query='&'.join(["%s=%s"%item for item in request.params.items()]) 
     47            query='&'.join(["%s=%s" % item for item in request.params.items()]) 
    4948            if query: 
    5049                c.requestURL += '?' + query 
Note: See TracChangeset for help on using the changeset viewer.