Changeset 5441


Ignore:
Timestamp:
01/07/09 14:29:14 (10 years ago)
Author:
pjkersha
Message:

Added capability to allow for clock skew between client and server for WS-Security timestamp handling. This is included in the 4Suite and DOM based implementations.

Location:
TI12-security/trunk/python
Files:
8 edited

Legend:

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

    r5436 r5441  
    106106 
    107107    excepMap = { 
    108         'SessionNotFound':                         SessionNotFound, 
     108        'SessionNotFound':                 SessionNotFound, 
    109109        'UserSessionNotBeforeTimeError':   SessionCertTimeError, 
    110         'UserSessionExpired':                      SessionExpired, 
    111         'InvalidUserSession':                      InvalidSession 
     110        'UserSessionExpired':              SessionExpired, 
     111        'InvalidUserSession':              InvalidSession 
    112112    } 
    113113     
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/__init__.py

    r5359 r5441  
    4141    """ 
    4242    propertyDefaults = dict( 
    43              reqBinSecTokValType=OASIS.X509TOKEN.X509, 
    44              verifyingCert=None, 
    45              verifyingCertFilePath=None, 
    46              signingCert=None, 
    47              signingCertFilePath=None,  
    48              signingCertChain=[], 
    49              signingPriKey=None, 
    50              signingPriKeyFilePath=None,  
    51              signingPriKeyPwd=None, 
    52              caCertDirPath=None, 
    53              caCertFilePathList=[], 
    54              addTimestamp=True, 
    55              timestampMustBeSet=False, 
    56              createdElemMustBeSet=True, 
    57              expiresElemMustBeSet=True, 
    58              applySignatureConfirmation=False, 
    59              refC14nInclNS=[], 
    60              signedInfoC14nInclNS=[]) 
     43        reqBinSecTokValType=OASIS.X509TOKEN.X509, 
     44        verifyingCert=None, 
     45        verifyingCertFilePath=None, 
     46        signingCert=None, 
     47        signingCertFilePath=None,  
     48        signingCertChain=[], 
     49        signingPriKey=None, 
     50        signingPriKeyFilePath=None,  
     51        signingPriKeyPwd=None, 
     52        caCertDirPath=None, 
     53        caCertFilePathList=[], 
     54        addTimestamp=True, 
     55        timestampClockSkew=0., 
     56        timestampMustBeSet=False, 
     57        createdElemMustBeSet=True, 
     58        expiresElemMustBeSet=True, 
     59        applySignatureConfirmation=False, 
     60        refC14nInclNS=[], 
     61        signedInfoC14nInclNS=[]) 
    6162     
    6263    def __init__(self, cfg=SafeConfigParser()): 
     
    128129                            exVar(self._cfg.get(section, optName)).split() 
    129130                    except AttributeError: 
    130                         raise SecurityConfigError('Setting "%s"' % paramName) 
     131                        raise WSSecurityConfigError('Setting "%s"' % paramName) 
    131132                     
    132133                elif isinstance(WSSecurityConfig.propertyDefaults[paramName],  
     
    254255        badKeys=[i for i in seq if i not in WSSecurityConfig.propertyDefaults] 
    255256        if badKeys: 
    256             raise KeyError("Parameter key(s) %s not recognised" % \ 
     257            raise KeyError("Parameter key(s) %s not recognised" %  
    257258                           ','.join(badKeys)) 
    258         return self._param.fromkeys(*arg) 
     259        return self._param.fromkeys(seq) 
    259260     
    260261    def setdefault(self, key, *arg): 
    261         badKeys = [i for i in b if i not in WSSecurityConfig.propertyDefaults] 
     262        badKeys=[i for i in arg if i not in WSSecurityConfig.propertyDefaults] 
    262263        if badKeys: 
    263264            raise KeyError("Parameter keys '%s' not recognised" % badKeys) 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/__init__.py

    r5433 r5441  
    112112                 cfgClass=WSSecurityConfig, **kw): 
    113113        ''' 
    114         @keyword reqBinSecTokValType: set the ValueType for the  
    115         BinarySecurityToken added to the WSSE header for a signed message.  See  
    116         __setReqBinSecTokValType method and binSecTokValType class variable 
    117         for options.  binSecTokValType determines whether signingCert or 
    118         signingCertChain attributes will be used.         
    119         @type binSecTokValType: string 
    120          
    121         @keyword verifyingCert: X.509 certificate used by verify method to 
    122         verify a message.  This argument can be omitted if the message to 
    123         be verified contains the X.509 certificate in the  
    124         BinarySecurityToken element.  In this case, the cert read from the 
    125         message will be assigned to the verifyingCert attribute. 
    126         @type verifyingCert: M2Crypto.X509.X509 /  
    127         ndg.security.common.X509.X509Cert 
    128          
    129         @keyword verifyingCertFilePath: alternative input to the above, pass  
    130         the file path to the certificate stored in a file 
    131         @type verifyingCertFilePath: string 
    132          
    133         @keyword signingCert: certificate associated with private key used to 
    134         sign a message.  The sign method will add this to the  
    135         BinarySecurityToken element of the WSSE header.  binSecTokValType 
    136         attribute must be set to 'X509' or 'X509v3' ValueTyep.  As an  
    137         alternative, use signingCertChain - see below... 
    138         @type signingCert: M2Crypto.X509.X509 /  
    139         ndg.security.common.X509.X509Cert 
    140          
    141         @keyword signingCertFilePath: alternative input to the above, pass  
    142         the file path to the certificate stored in a file 
    143         @type signingCertFilePath: string 
    144          
    145         @keyword signingCertChain: pass a list of certificates constituting a  
    146         chain of trust from the certificate used to verifying the signature  
    147         backward to the CA cert.  The CA cert need not be included.  To use  
    148         this option, reqBinSecTokValType must be set to the 'X509PKIPathv1' 
    149         ValueType 
    150         @type signingCertChain: list or tuple  
    151          
    152         @keyword signingPriKey: private key used to be sign method to sign 
    153         message 
    154         @type signingPriKey: M2Crypto.RSA. 
    155          
    156         @keyword signingPriKeyFilePath: equivalent to the above but pass  
    157         private key from PEM file 
    158         @type signingPriKeyFilePath: string 
    159          
    160         @keyword signingPriKeyPwd: password protecting private key.  Set / 
    161         default to None if there is no password. 
    162         @type signingPriKeyPwd: string or None 
    163          
    164         @keyword caCertDirPath: establish trust for signature verification.  
    165         This is a directory containing CA certificates.  These are used to 
    166         verify the certificate used to verify the message signature. 
    167         @type caCertDirPath: string 
    168          
    169         @keyword caCertFilePathList: same as above except pass in a list of 
    170         file paths instead of a single directory name. 
    171         @type caCertFilePathList: list or tuple 
    172          
    173         @keyword addTimestamp: set to true to add a timestamp to outbound  
    174         messages 
    175         @type addTimestamp: bool  
    176          
    177         @keyword applySignatureConfirmation: for servers - set this flag to  
    178         enable the signature value of a request to be recorded and included  
    179         with a SignatureConfirmation element in the response. 
    180         @type : bool  
    181          
    182         @param refC14nInclNS: list of namespaces to include in reference  
    183         Canonicalization. 
    184         @type refC14nInclNS: list 
    185          
    186         @param signedInfoC14nInclNS: list of namespaces to include in  
    187         Signed Info Canonicalization. 
    188         @type signedInfoC14nInclNS: list 
     114        @param cfg: object from which to read config items - a file path, 
     115        config parser object or WSSecurityConfig object 
     116        @type cfg: basestring/RawConfigParser/WSSecurityConfig 
     117         
     118        @param cfgFileSection: section name in config file containing  
     119        parameters 
     120        @type cfgFileSection: basestring 
     121         
     122        @param cfgFilePrefix: prefix for parameter names in the config file. 
     123        This enables these parameters to be filtered from other unrelated 
     124        parameters in the same section 
     125        @type cfgFilePrefix: basestring 
     126         
     127        @param cfgClass: class used to parse the settings 
     128        @type cfgClass: WSSecurityConfig derived class type 
     129         
     130        @param kw: any config parameters as specified by WSSecurityConfig class 
     131        @type kw: dict 
    189132        ''' 
    190133        log.debug("BaseSignatureHandler.__init__ ...") 
     
    267210         
    268211        # Configure timestamp checking in Signature verification handler 
     212        self.timestampClockSkew = self.cfg['timestampClockSkew'] 
    269213        self.timestampMustBeSet = self.cfg['timestampMustBeSet'] 
    270214        self.createdElemMustBeSet = self.cfg['createdElemMustBeSet'] 
     
    687631         
    688632    caCertFilePathList = property(fset=__setCAX509StackFromCertFileList, 
    689                       doc="List of CA cert. files used for verification") 
    690                  
    691  
     633                      doc="List of CA cert. files used for verification")               
     634         
     635    def _get_timestampClockSkew(self): 
     636        return getattr(self, "_timestampClockSkew", 0.) 
     637 
     638    def _set_timestampClockSkew(self, val): 
     639        if isinstance(val, basestring): 
     640            self._timestampClockSkew = float(val) 
     641             
     642        elif isinstance(val, (float, int)): 
     643            self._timestampClockSkew = val 
     644             
     645        else: 
     646            raise TypeError("Expecting string, float or int type for " 
     647                            "timestampClockSkew attribute, got %r" %  
     648                            getattr(val, "__class__", val)) 
     649         
     650    timestampClockSkew = property(fset=_set_timestampClockSkew, 
     651                                  fget=_get_timestampClockSkew, 
     652                                  doc="adjust the current time calculated by " 
     653                                      "the number of seconds specified in " 
     654                                      "this parameter.  This enables " 
     655                                      "allowance to be made for clock skew " 
     656                                      "between a client and server system " 
     657                                      "clocks.") 
     658     
    692659    def _setBool(self, val): 
    693660        """Convert input string, float or int to bool type 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/dom.py

    r5433 r5441  
    148148    def _verifyTimeStamp(self,  
    149149                         parsedSOAP,  
    150                          ctxt,  
     150                         ctxt, 
     151                         timestampClockSkew=0.,  
    151152                         timestampMustBeSet=False, 
    152153                         createdElemMustBeSet=True, 
     
    154155        """Call from verify to check timestamp if found.   
    155156         
    156         TODO: refactor input args - maybe these should by object attributes 
     157        TODO: refactor as separate timestamp handler independent of  
     158        signature handler? 
    157159         
    158160        @type parsedSOAP: ZSI.parse.ParsedSoap 
     
    161163        @type ctxt: 
    162164        @param ctxt: XPath context object 
     165        @type timestampClockSkew: int/float 
     166        @param timestampClockSkew: adjust the current time calculated by the  
     167        number of seconds specified in this parameter.  This enables allowance 
     168        to be made for clock skew between a client and server system clocks.        
    163169        @type timestampMustBeSet: bool 
    164170        @param timestampMustBeSet: if set to True, raise an exception if no 
     
    171177        """ 
    172178 
    173         # TODO: do we need to be more rigorous in terms of handling the  
    174         # situation where no timestamp is found? 
    175          
    176179        try: 
    177180            timestampNode = xpath.Evaluate('//wsu:Timestamp', 
     
    187190         
    188191        # Time now  
    189         dtNow = datetime.utcnow() 
     192        dtNow = datetime.utcnow() + timedelta(seconds=timestampClockSkew) 
    190193 
    191194        createdNode = timestampNode.getElementsByTagName("wsu:Created") 
     
    749752                                  caX509Stack=self._caX509Stack) 
    750753         
    751 #        self._verifyTimeStamp(parsedSOAP,  
    752 #                              ctxt, 
    753 #                              timestampMustBeSet=self.timestampMustBeSet, 
    754 #                              createdElemMustBeSet=self.createdElemMustBeSet, 
    755 #                              expiresElemMustBeSet=self.expiresElemMustBeSet)  
     754        self._verifyTimeStamp(parsedSOAP,  
     755                              ctxt, 
     756                              timestampClockSkew=self.timestampClockSkew, 
     757                              timestampMustBeSet=self.timestampMustBeSet, 
     758                              createdElemMustBeSet=self.createdElemMustBeSet, 
     759                              expiresElemMustBeSet=self.expiresElemMustBeSet)  
    756760 
    757761        log.info("Signature OK")         
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/foursuite.py

    r5359 r5441  
    117117                         parsedSOAP,  
    118118                         processorNss, 
     119                         timestampClockSkew=0., 
    119120                         timestampMustBeSet=False, 
    120121                         createdElemMustBeSet=True, 
     
    132133        @param processorNss: namespaces to be used in XPath query to locate 
    133134        timestamp. 
     135        @type timestampClockSkew: int/float 
     136        @param timestampClockSkew: adjust the current time calculated by the  
     137        number of seconds specified in this parameter.  This enables allowance 
     138        to be made for clock skew between a client and server system clocks.  
    134139        @type timestampMustBeSet: bool 
    135140        @param timestampMustBeSet: if set to True, raise an exception if no 
     
    156161         
    157162        # Time now  
    158         dtNow = datetime.utcnow() 
     163        dtNow = datetime.utcnow() + timedelta(seconds=timestampClockSkew) 
    159164 
    160165        createdElem = getElements(timestampElem, "Created")            
     
    686691        self._verifyTimeStamp(parsedSOAP,  
    687692                              processorNss, 
     693                              timestampClockSkew=self.timestampClockSkew, 
    688694                              timestampMustBeSet=self.timestampMustBeSet, 
    689695                              createdElemMustBeSet=self.createdElemMustBeSet, 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/sessionmanager.py

    r5436 r5441  
    292292        self.__usernameDict = {} 
    293293         
     294        self._propFileSection = '' 
     295        self._propPrefix = '' 
     296         
    294297        # Credential Repository interface only set if properties file is set 
    295         # otherwise explicit calls are necessary to set credentialRepositoryProp via 
    296         # setProperties/readProperties and then loadCredentialRepositoryInterface 
     298        # otherwise explicit calls are necessary to set  
     299        # credentialRepositoryProp via setProperties/readProperties and then  
     300        # loadCredentialRepositoryInterface 
    297301        self._credentialRepository = None 
    298302     
     
    447451        @return: section name''' 
    448452        log.debug("Getting property file section name") 
    449         if hasattr(self, '_propFileSection'): 
    450             return self._propFileSection 
    451         else: 
    452             return ""     
     453        return self._propFileSection   
    453454     
    454455    def setPropFileSection(self, val=None): 
     
    494495        self._propPrefix = val 
    495496        log.debug("Properties file section set to: %s" % val) 
    496             
    497     def setPropPrefix(self, val=None): 
    498         """Set prefix for properties read from ini file.  This is set from 
    499         input or based on environment variable setting  
    500         NDGSEC_SM_PROPFILEPREFIX 
    501          
    502         DOES NOT apply to XML file properties 
    503          
    504         @type val: basestring 
    505         @param val: section name""" 
    506         log.debug("Setting property file section name") 
    507         if val is None: 
    508             val = os.environ.get('NDGSEC_SM_PROPFILEPREFIX', 'DEFAULT') 
    509                  
    510         if not isinstance(val, basestring): 
    511             raise AttributeError("Input Properties file section name " 
    512                                  "must be a valid string.") 
    513        
    514         self._propPrefix = val 
    515         log.debug("Properties file section set to: %s" % val) 
    516497         
    517498    def getPropPrefix(self): 
     
    522503        @return: section name''' 
    523504        log.debug("Getting property file prefix") 
    524         if hasattr(self, '_propPrefix'): 
    525             return self._propPrefix 
    526         else: 
    527             return ""     
     505        return self._propPrefix 
    528506         
    529507    # Also set up as a property 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wssecurity/dom/client/test_echoclient.py

    r5359 r5441  
    22"""WS-Security Digital Signature unit tests 
    33 
    4 NERC Data Grid Project 
     4NERC DataGrid Project 
    55""" 
    66__author__ = "P J Kershaw" 
     
    1616import os 
    1717import sys 
    18 import getpass 
    1918import traceback 
    2019 
     
    2928from ndg.security.common.wssecurity.signaturehandler.dom import \ 
    3029    SignatureHandler 
    31 from ndg.security.common.wssecurity.signaturehandler import NoSignatureFound 
     30from ndg.security.common.wssecurity.signaturehandler import NoSignatureFound, \ 
     31    TimestampError 
    3232 
    3333class EchoClientTestCase(BaseTestCase): 
     
    4545         
    4646        configFilePath = mkPath('echoClientTest.cfg') 
    47         self.cfg = SafeConfigParser() 
    48         self.cfg.read(configFilePath) 
    49         uri = self.cfg.get('setUp', 'uri') 
    50         signingPriKeyFilePath = \ 
    51                         xpdVars(self.cfg.get('setUp', 'signingPriKeyFilePath')) 
    52         signingPriKeyPwd = self.cfg.get('setUp', 'signingPriKeyPwd') 
    53         signingCertFilePath = \ 
    54                         xpdVars(self.cfg.get('setUp', 'signingCertFilePath')) 
    55         caCertFilePathList = [xpdVars(file) for file in \ 
    56                               self.cfg.get('setUp',  
    57                                           'caCertFilePathList').split()] 
     47        cfg = SafeConfigParser() 
     48        cfg.read(configFilePath) 
     49        uri = cfg.get('setUp', 'uri') 
    5850         
    5951        # Signature handler object is passed to binding 
    60         sigHandler = SignatureHandler( 
    61                                  signingPriKeyFilePath=signingPriKeyFilePath, 
    62                                  signingPriKeyPwd=signingPriKeyPwd, 
    63                                  signingCertFilePath=signingCertFilePath, 
    64                                  caCertFilePathList=caCertFilePathList, 
    65                                  refC14nInclNS=[], 
    66                                  signedInfoC14nInclNS=[]) 
    67  
     52        sigHandler = SignatureHandler(cfg=configFilePath, 
     53                                      cfgFileSection='setUp') 
    6854        locator = EchoServiceLocator() 
    6955        self.clnt = locator.getEcho(uri,  
     
    7157                                    tracefile=sys.stderr) 
    7258         
    73  
    7459    def test01Echo(self): 
    7560             
    76         try: 
    77             resp = self.clnt.Echo("Hello from client") 
    78             print "Message returned was: %s" % resp 
    79         except: 
    80             self.fail(traceback.print_exc()) 
    81          
     61        resp = self.clnt.Echo("Hello from client") 
     62        print("Message returned was: %s" % resp)         
    8263 
    8364    def test02ServerRaiseMissingTimestampError(self): 
     
    9374            self.fail("Expecting error from server because client didn't set " 
    9475                      "a timestamp element") 
    95                                          
     76 
     77    def test03ClientRaiseTimestampError(self): 
     78        # Get client to catch a mismatch in the created time for the server 
     79        # response by adding a clock skew to the client 
     80         
     81        self.clnt.binding.sig_handler.timestampClockSkew = -300.0 
     82        try: 
     83            resp = self.clnt.Echo("Hello again from client") 
     84             
     85        except TimestampError: 
     86            print "PASSED - client rejected server message created timestamp" 
     87        else: 
     88            self.fail("Expecting error from client because client set a " 
     89                      "a timestamp clock skew") 
     90                                        
    9691if __name__ == "__main__": 
    9792    unittest.main() 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wssecurity/foursuite/client/test_echoclient.py

    r5359 r5441  
    22"""WS-Security Digital Signature unit tests 
    33 
    4 NERC Data Grid Project 
     4NERC DataGrid Project 
    55""" 
    66__author__ = "P J Kershaw" 
     
    1616import os 
    1717import sys 
    18 import getpass 
    1918import traceback 
    2019 
    2120from os.path import expandvars as xpdVars 
    22 from os.path import join as jnPath 
    23 mkPath = lambda file: jnPath(os.environ['NDGSEC_WSSECLNT_UNITTEST_DIR'], file) 
    2421from os.path import join, dirname, abspath 
     22mkPath = lambda file: join(os.environ['NDGSEC_WSSECLNT_UNITTEST_DIR'], file) 
     23 
    2524from ConfigParser import SafeConfigParser 
    2625 
     
    3029from ndg.security.common.wssecurity.signaturehandler.foursuite import \ 
    3130    SignatureHandler 
    32 from ndg.security.common.wssecurity.signaturehandler import NoSignatureFound 
     31from ndg.security.common.wssecurity.signaturehandler import NoSignatureFound, \ 
     32    TimestampError 
    3333from ndg.security.common.wssecurity.utils import DomletteReader, \ 
    3434    DomletteElementProxy 
     
    5656        self.cfg.read(configFilePath) 
    5757        uri = self.cfg.get('setUp', 'uri') 
    58         signingPriKeyFilePath = \ 
    59                         xpdVars(self.cfg.get('setUp', 'signingPriKeyFilePath')) 
    60         signingPriKeyPwd = self.cfg.get('setUp', 'signingPriKeyPwd') 
    61         signingCertFilePath = \ 
    62                         xpdVars(self.cfg.get('setUp', 'signingCertFilePath')) 
    63         caCertFilePathList = [xpdVars(file) for file in \ 
    64                               self.cfg.get('setUp',  
    65                                           'caCertFilePathList').split()] 
    6658         
    6759        # Signature handler object is passed to binding 
    68         sigHandler = SignatureHandler( 
    69                                  signingPriKeyFilePath=signingPriKeyFilePath, 
    70                                  signingPriKeyPwd=signingPriKeyPwd, 
    71                                  signingCertFilePath=signingCertFilePath, 
    72                                  caCertFilePathList=caCertFilePathList, 
    73                                  refC14nInclNS=[], 
    74                                  signedInfoC14nInclNS=[]) 
     60        sigHandler = SignatureHandler(cfg=configFilePath, 
     61                                      cfgFileSection='setUp') 
    7562 
    7663        locator = EchoServiceLocator() 
     
    8471    def test01Echo(self): 
    8572             
    86         try: 
    87             resp = self.clnt.Echo("Hello from client") 
    88             print "Message returned was: %s" % resp 
    89         except: 
    90             self.fail(traceback.print_exc()) 
     73        resp = self.clnt.Echo("Hello from client") 
     74        print "Message returned was: %s" % resp 
    9175 
    9276 
     
    9983             
    10084        except NoSignatureFound: 
    101             print "PASSED - server rejected client message with no timestamp" 
     85            print("PASSED - server rejected client message with no timestamp") 
    10286        else: 
    10387            self.fail("Expecting error from server because client didn't set " 
    10488                      "a timestamp element") 
    10589 
     90    def test03ClientRaiseTimestampError(self): 
     91        # Get client to catch a mismatch in the created time for the server 
     92        # response by adding a clock skew to the client 
     93         
     94        self.clnt.binding.sig_handler.timestampClockSkew = -300.0 
     95        try: 
     96            resp = self.clnt.Echo("Hello again from client") 
     97             
     98        except TimestampError: 
     99            print "PASSED - client rejected server message created timestamp" 
     100        else: 
     101            self.fail("Expecting error from client because client set a " 
     102                      "a timestamp clock skew") 
     103 
    106104if __name__ == "__main__": 
    107105    unittest.main() 
Note: See TracChangeset for help on using the changeset viewer.