source: TI12-security/trunk/WSSecurity/ndg/wssecurity/common/wssecurity/signaturehandler/__init__.py @ 6385

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/WSSecurity/ndg/wssecurity/common/wssecurity/signaturehandler/__init__.py@6385
Revision 6385, 29.6 KB checked in by pjkersha, 10 years ago (diff)
Line 
1""" Base class for the WS-Security digital signature handlers - to allow
2sharing of common code
3
4NERC DataGrid Project
5"""
6__author__ = "C Byrom"
7__date__ = "18/08/08"
8__copyright__ = ""
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = '$Id: $'
12
13import re
14
15# Digest and signature/verify
16from sha import sha
17from M2Crypto import X509, BIO, RSA
18import base64
19
20import os
21
22import ZSI
23from ZSI.wstools.Namespaces import ENCRYPTION, WSU
24from ZSI.wstools.Namespaces import OASIS as _OASIS
25from ConfigParser import RawConfigParser
26
27# Enable settings from a config file
28from ndg.security.common.wssecurity import WSSecurityConfig, WSSecurityError
29
30from ndg.security.common.X509 import X509Cert, X509CertParse, X509CertRead, \
31X509Stack, X509StackParseFromDER
32
33from datetime import datetime, timedelta
34import logging
35log = logging.getLogger(__name__)
36
37
38class _WSU(WSU):
39    '''Try different utility namespace for use with WebSphere'''
40    #UTILITY = "http://schemas.xmlsoap.org/ws/2003/06/utility"
41    UTILITY = ("http://docs.oasis-open.org/wss/2004/01/"
42               "oasis-200401-wss-wssecurity-utility-1.0.xsd")
43
44class OASIS(_OASIS):
45    # wss4j 1.5.3
46    WSSE11 = ("http://docs.oasis-open.org/wss/"
47              "oasis-wss-wssecurity-secext-1.1.xsd")
48    # wss4j 1.5.1
49#    WSSE11 = ("http://docs.oasis-open.org/wss/2005/xx/"
50#              "oasis-2005xx-wss-wssecurity-secext-1.1.xsd")
51
52
53class InvalidCertChain(WSSecurityError):   
54    """Raised from SignatureHandler.verify if the certificate submitted to
55    verify a signature is not from a known CA"""
56   
57class VerifyError(WSSecurityError):
58    """Raised from SignatureHandler.verify if an error occurs in the signature
59    verification"""
60 
61class TimestampError(WSSecurityError):
62    """Raised from SignatureHandler._verifyTimestamp if there is a problem with
63    the created or expiry times in an input message Timestamp"""
64
65class MessageExpired(TimestampError):
66    """Raised from SignatureHandler._verifyTimestamp if the timestamp of
67    the message being processed is before the current time.  Can be caught in
68    order to set a wsu:MessageExpired fault code"""
69   
70class InvalidSignature(WSSecurityError):
71    """Raised from verify method for an invalid signature"""
72
73class SignatureError(WSSecurityError):
74    """Flag if an error occurs during signature generation"""
75
76class NoSignatureFound(WSSecurityError):
77    """Raise from SignatureHandler.verify if inbound message is not signed"""
78
79
80class BaseSignatureHandler(object):
81    """Class to handle signature and verification of signature with
82    WS-Security
83   
84    @cvar binSecTokValType: supported ValueTypes for BinarySecurityToken
85    element in WSSE header
86    @type binSecTokValType: dict
87   
88    @ivar addTimestamp: set to true to add a timestamp to outbound messages
89    @type addTimestamp: bool
90
91    @ivar applySignatureConfirmation: for servers - set this flag to enable the
92    signature value of a request to be recorded and included with a
93    SignatureConfirmation element in the response.
94    @type applySignatureConfirmation: bool
95   
96    @param b64EncSignatureValue: base 64 encoded signature value for the last
97    message verified
98    @type b64EncSignatureValue: string/None"""
99
100    _binSecTokEncType = ("http://docs.oasis-open.org/wss/2004/01/"
101                         "oasis-200401-wss-soap-message-security-1.0#"
102                         "Base64Binary")
103   
104    binSecTokValType = {
105        "X509PKIPathv1": OASIS.X509TOKEN.X509PKIPathv1,
106        "X509":          OASIS.X509TOKEN.X509,
107        "X509v3":        OASIS.X509TOKEN.X509+"v3"
108    }
109
110    PROPERTY_DEFAULTS = dict(
111        reqBinSecTokValType=(OASIS.X509TOKEN.X509,),
112        verifyingCert=(None,),
113        verifyingCertFilePath=(None,),
114        signingCert=(None,),
115        signingCertFilePath=(None,), 
116        signingCertChain=([],),
117        signingPriKey=(None,),
118        signingPriKeyFilePath=(None,''), 
119        signingPriKeyPwd=(None,),
120        caCertDirPath=(None,),
121        caCertFilePathList=([],),
122        addTimestamp=(True,),
123        timestampClockSkew=(0.,),
124        timestampMustBeSet=(False,),
125        createdElemMustBeSet=(True,),
126        expiresElemMustBeSet=(True,),
127        applySignatureConfirmation=(False,),
128        refC14nInclNS=([],),
129        signedInfoC14nInclNS=([],),
130        cfg=(None,))
131   
132    TYPE_MAP = dict([(k, tuple([type(i) for i in v]))
133                     for k,v in PROPERTY_DEFAULTS.items()])
134    __slots__ = TYPE_MAP
135   
136    def __init__(self, cfg=None, cfgFileSection='DEFAULT', cfgFilePrefix='',
137                 cfgClass=WSSecurityConfig, **kw):
138        '''
139        @param cfg: object from which to read config items - a file path,
140        config parser object or WSSecurityConfig object
141        @type cfg: basestring/RawConfigParser/WSSecurityConfig
142       
143        @param cfgFileSection: section name in config file containing
144        parameters
145        @type cfgFileSection: basestring
146       
147        @param cfgFilePrefix: prefix for parameter names in the config file.
148        This enables these parameters to be filtered from other unrelated
149        parameters in the same section
150        @type cfgFilePrefix: basestring
151       
152        @param cfgClass: class used to parse the settings
153        @type cfgClass: WSSecurityConfig derived class type
154       
155        @param kw: any config parameters as specified by WSSecurityConfig class
156        @type kw: dict
157        '''
158        log.debug("BaseSignatureHandler.__init__ ...")
159
160        # WSSecurityConfig is the default class for reading config params but
161        # alternative derivative class may be passed in instead.
162        if not issubclass(cfgClass, WSSecurityConfig):
163            raise TypeError("%s is not a sub-class of WSSecurityConfig" % 
164                            cfgClass)
165       
166        # Read parameters from config file if set
167        if isinstance(cfg, basestring):
168            log.debug("BaseSignatureHandler.__init__: config file path input "
169                      "...")
170            self.cfg = cfgClass()
171            self.cfg.read(cfg)
172            self.cfg.parse(section=cfgFileSection, prefix=cfgFilePrefix)
173
174        elif isinstance(cfg, RawConfigParser):
175            log.debug("BaseSignatureHandler.__init__: config object input ...")
176            self.cfg = cfgClass(cfg=cfg)
177            self.cfg.parse(section=cfgFileSection, prefix=cfgFilePrefix)
178           
179        elif isinstance(cfg, WSSecurityConfig):
180            log.debug("BaseSignatureHandler.__init__:  WSSSecurityConfig "
181                      "object input ...")
182            self.cfg = cfg
183        else:
184            self.cfg = cfgClass()
185               
186        # Also update config from keywords set
187        log.debug("BaseSignatureHandler.__init__: updating config from "
188                  "keywords...")
189       
190        # Filter keywords if a prefix is set removing any that don't start with
191        # the prefix given
192        self.cfg.update(kw, prefix=cfgFilePrefix)
193       
194        # set default value type, if none specified in config file
195        if not self.cfg['reqBinSecTokValType']:
196            self.cfg['reqBinSecTokValType'] = "X509v3"
197           
198        self.reqBinSecTokValType = self.cfg['reqBinSecTokValType']
199
200        # Set keywords for canonicalization of SignedInfo and reference
201        # elements
202        self.refC14nKw = {'inclusive_namespaces': self.cfg['refC14nInclNS']}
203
204        self.signedInfoC14nKw = {'inclusive_namespaces': 
205                                 self.cfg['signedInfoC14nInclNS']}
206
207        self.verifyingCert = self.cfg['verifyingCert']
208        self.verifyingCertFilePath = self.cfg['verifyingCertFilePath']
209       
210        self.signingCert = self.cfg['signingCert']
211        self.signingCertFilePath = self.cfg['signingCertFilePath']
212
213        self.signingCertChain = self.cfg['signingCertChain']
214             
215        # MUST be set before _setSigningPriKeyFilePath / _setSigningPriKey
216        # are called
217        self.signingPriKeyPwd = self.cfg['signingPriKeyPwd']
218       
219        if self.cfg.get('signingPriKey'):
220            # Don't allow None for private key setting
221            self.signingPriKey = self.cfg['signingPriKey']
222           
223        self.signingPriKeyFilePath = self.cfg['signingPriKeyFilePath']
224       
225        # CA certificate(s) for verification of X.509 certificate used with
226        # signature.
227        if self.cfg.get('caCertDirPath'):
228            self.caCertDirPath = self.cfg['caCertDirPath']
229           
230        elif self.cfg.get('caCertFilePathList'):
231            self.caCertFilePathList = self.cfg['caCertFilePathList']
232       
233        # Configure signature generation to add/omit a timestamp
234        self.addTimestamp = self.cfg['addTimestamp']
235       
236        # Configure timestamp checking in Signature verification handler
237        self.timestampClockSkew = self.cfg['timestampClockSkew']
238        self.timestampMustBeSet = self.cfg['timestampMustBeSet']
239        self.createdElemMustBeSet = self.cfg['createdElemMustBeSet']
240        self.expiresElemMustBeSet = self.cfg['expiresElemMustBeSet']
241       
242        # set default value, if none specified in config file
243        if not self.cfg['applySignatureConfirmation']:
244            self.cfg['applySignatureConfirmation'] = False
245
246        self.applySignatureConfirmation=self.cfg['applySignatureConfirmation']
247        self.b64EncSignatureValue = None
248       
249        log.debug("WSSE Config = %s" % self.cfg)
250
251               
252    def _setReqBinSecTokValType(self, value):
253        """Set ValueType attribute for BinarySecurityToken used in a request
254         
255        @type value: string
256        @param value: name space for BinarySecurityToken ValueType check
257        'binSecTokValType' class variable for supported types.  Input can be
258        shortened to binSecTokValType keyword if desired.
259        """
260        log.debug("Setting reqBinSecTokValType - to %s" %value)
261        if value in self.__class__.binSecTokValType:
262            self._reqBinSecTokValType = self.__class__.binSecTokValType[value]
263 
264        elif value in self.__class__.binSecTokValType.values():
265            self._reqBinSecTokValType = value
266        else:
267            raise WSSecurityError('Request BinarySecurityToken ValueType '
268                                  '"%s" not recognised' % value)
269           
270    def _getReqBinSecTokValType(self):
271        """
272        Get ValueType attribute for BinarySecurityToken used in a request
273        """
274        log.debug("Getting reqBinSecTokValType value")
275        if hasattr(self, '_reqBinSecTokValType'):
276            return self._reqBinSecTokValType
277        else:
278            return ""
279       
280    reqBinSecTokValType = property(fset=_setReqBinSecTokValType,
281                                   fget=_getReqBinSecTokValType,
282         doc="ValueType attribute for BinarySecurityToken used in request")
283       
284
285    def __checkC14nKw(self, kw):
286        """Check keywords for canonicalization in signing process - generic
287        method for setting keywords for reference element and SignedInfo
288        element C14N
289       
290        @type kw: dict
291        @param kw: keyword used with ZSI.wstools.Utility.Canonicalization"""
292       
293        # Check for dict/None - Set to None in order to use inclusive
294        # canonicalization
295        if kw is not None and not isinstance(kw, dict):
296            # Otherwise keywords must be a dictionary
297            raise AttributeError("Expecting dictionary type for reference "
298                                 "C14N keywords")
299               
300        elif kw.get('inclusive_namespaces') and \
301             not isinstance(kw['inclusive_namespaces'], (list, tuple)):
302            raise AttributeError('Expecting list or tuple of prefix names for '
303                                 '"%s" keyword' % 'inclusive_namespaces')
304       
305               
306    def _setRefC14nKw(self, kw):
307        """Set keywords for canonicalization of reference elements in the
308        signing process"""
309        self.__checkC14nKw(kw)                   
310        self._refC14nKw = kw
311       
312    def _getRefC14nKw(self):
313        if hasattr(self, '_refC14nKw'):
314            return self._refC14nKw
315        else:
316            return {}
317       
318    refC14nKw = property(fset=_setRefC14nKw,
319                         fget=_getRefC14nKw,
320                         doc="Keywords for C14N of reference elements")
321       
322               
323    def _setSignedInfoC14nKw(self, kw):
324        """Set keywords for canonicalization of SignedInfo element in the
325        signing process"""
326        self.__checkC14nKw(kw)                   
327        self._signedInfoC14nKw = kw
328       
329    def _getSignedInfoC14nKw(self):
330        if hasattr(self, '_signedInfoC14nKw'):
331            return self._signedInfoC14nKw
332        else:
333            return {}
334       
335    signedInfoC14nKw = property(fset=_setSignedInfoC14nKw,
336                                fget=_getSignedInfoC14nKw,
337                                doc="Keywords for C14N of SignedInfo element")
338
339
340    def _refC14nIsExcl(self):
341        '''
342        @rtype: bool
343        @return: true if Exclusive C14N is set as algorithm to apply to
344        reference elements
345        '''
346        # TODO: alter logic here if inclusive C14N is re-instated.
347        return True
348               
349    refC14nIsExcl = property(fget=_refC14nIsExcl,
350    doc="Return True/False C14N for reference elements set to exclusive type")
351
352     
353    def _signedInfoC14nIsExcl(self):
354        '''
355        @rtype: bool
356        @return: true if Exclusive C14N is set as algorithm to apply to
357        the signed info elements of the XML Digital Signature
358        '''
359        # TODO: alter logic here if inclusive C14N is re-instated.
360        return True
361       
362    signedInfoC14nIsExcl = property(fget=_signedInfoC14nIsExcl,
363                                    doc="Return True/False C14N for "
364                                    "SignedInfo element set to exclusive type")
365   
366   
367    def _setCert(self, cert):
368        """filter and convert input cert to signing verifying cert set
369        property methods.  For signingCert, set to None if it is not to be
370        included in the SOAP header.  For verifyingCert, set to None if this
371        cert can be expected to be retrieved from the SOAP header of the
372        message to be verified
373       
374        @type: ndg.security.common.X509.X509Cert / M2Crypto.X509.X509 /
375        PEM encoded string or None
376        @param cert: X.509 certificate. 
377       
378        @rtype ndg.security.common.X509.X509Cert
379        @return X.509 certificate object"""
380       
381        if not cert or isinstance(cert, X509Cert):
382            # ndg.security.common.X509.X509Cert type / None
383            x509Cert = cert
384           
385        elif isinstance(cert, X509.X509):
386            # M2Crypto.X509.X509 type
387            x509Cert = X509Cert(m2CryptoX509=cert)
388           
389        elif isinstance(cert, basestring):
390            # Nb. Assume PEM encoded string!
391            x509Cert = X509CertParse(cert)
392       
393        else:
394            raise AttributeError("X.509 Cert. must be type: ndg.security."
395                                 "common.X509.X509Cert, M2Crypto.X509.X509 or "
396                                 "a base64 encoded string")
397       
398        # Check for expired certificate
399        if x509Cert:   
400            x509Cert.isValidTime(raiseExcep=True)
401           
402        return x509Cert
403
404   
405    def _getVerifyingCert(self):
406        '''Return X.509 cert object corresponding to cert used to verify the
407        signature in the last call to verify
408       
409         * Cert will correspond to one used in the LATEST call to verify, on
410         the next call it will be replaced
411         * if verify hasn't been called, the cert will be None
412       
413        @rtype: M2Crypto.X509.X509
414        @return: certificate object
415        '''
416        return self._verifyingCert
417
418
419    def _setVerifyingCert(self, verifyingCert):
420        "Set property method for X.509 cert. used to verify a signature"
421        self._verifyingCert = self._setCert(verifyingCert)
422       
423        # Reset file path as it may no longer apply
424        self._verifyingCertFilePath = None
425       
426    verifyingCert = property(fset=_setVerifyingCert,
427                             fget=_getVerifyingCert,
428                             doc="Set X.509 Cert. for verifying signature")
429
430
431    def _setVerifyingCertFilePath(self, verifyingCertFilePath):
432        "Set method for Service X.509 cert. file path property"
433        if verifyingCertFilePath:
434            if isinstance(verifyingCertFilePath, basestring):
435                self._verifyingCert = X509CertRead(verifyingCertFilePath)
436            else:
437                raise AttributeError, "X.509 Cert file path is not a valid string"
438       
439        self._verifyingCertFilePath = verifyingCertFilePath
440       
441    verifyingCertFilePath = property(fset=_setVerifyingCertFilePath,
442                    doc="file path of X.509 Cert. for verifying signature")
443
444   
445    def _getSigningCert(self):
446        '''Return X.509 certificate object corresponding to certificate used
447        with signature
448       
449        @rtype: M2Crypto.X509.X509
450        @return: certificate object
451        '''
452        return self._signingCert
453
454
455    def _setSigningCert(self, signingCert):
456        "Set property method for X.509 cert. to be included with signature"
457        self._signingCert = self._setCert(signingCert)
458   
459        # Reset file path as it may no longer apply
460        self._signingCertFilePath = None
461       
462    signingCert = property(fget=_getSigningCert,
463                           fset=_setSigningCert,
464                           doc="X.509 Certificate to include signature")
465
466 
467    def _setSigningCertFilePath(self, signingCertFilePath):
468        "Set signature X.509 certificate property method"
469       
470        if isinstance(signingCertFilePath, basestring):
471            self._signingCert = X509CertRead(signingCertFilePath)
472           
473        elif signingCertFilePath is not None:
474            raise AttributeError("Signature X.509 certificate file path must "
475                                 "be a valid string")
476       
477        self._signingCertFilePath = signingCertFilePath
478       
479       
480    signingCertFilePath = property(fset=_setSigningCertFilePath,
481                   doc="File path X.509 cert. to include with signed message")
482
483   
484    def _setSigningCertChain(self, signingCertChain):
485        '''Signature set-up with "X509PKIPathv1" BinarySecurityToken
486        ValueType.  Use an X.509 Stack to store certificates that make up a
487        chain of trust to certificate used to verify a signature
488       
489        @type signingCertChain: list or tuple of M2Crypto.X509.X509Cert or
490        ndg.security.common.X509.X509Cert types.
491        @param signingCertChain: list of certificate objects making up the
492        chain of trust.  The last certificate is the one associated with the
493        private key used to sign the message.'''
494       
495        if not isinstance(signingCertChain, (list, tuple)):
496            log.warning('Expecting a list or tuple for "signingCertChain" - '
497                        'ignoring value set, "%s"' % signingCertChain)
498            self._signingCertChain = None
499            return
500       
501        self._signingCertChain = X509Stack()
502           
503        for cert in signingCertChain:
504            self._signingCertChain.push(cert)
505           
506    def _getSigningCertChain(self):
507        return self._signingCertChain
508   
509    signingCertChain = property(fset=_setSigningCertChain,
510                                fget=_getSigningCertChain,
511                                doc="Cert.s in chain of trust to cert. used "
512                                    "to verify msg.")
513
514 
515    def _setSigningPriKeyPwd(self, signingPriKeyPwd):
516        "Set method for private key file password used to sign message"
517        if signingPriKeyPwd is not None and \
518           not isinstance(signingPriKeyPwd, basestring):
519            raise AttributeError("Signing private key password must be None "
520                                 "or a valid string")
521       
522        self._signingPriKeyPwd = signingPriKeyPwd
523
524    def _getSigningPriKeyPwd(self):
525        if hasattr(self, '_signingPriKeyPwd'):
526            return self._signingPriKeyPwd
527        else:
528            return ""
529       
530    signingPriKeyPwd = property(fset=_setSigningPriKeyPwd,
531                                fget=_getSigningPriKeyPwd,
532                                doc="Password protecting private key file "
533                                    "used to sign message")
534
535 
536    def _setSigningPriKey(self, signingPriKey):
537        """Set method for client private key
538       
539        Nb. if input is a string, signingPriKeyPwd will need to be set if
540        the key is password protected.
541       
542        @type signingPriKey: M2Crypto.RSA.RSA / string
543        @param signingPriKey: private key used to sign message"""
544       
545        if isinstance(signingPriKey, basestring):
546            pwdCallback = lambda *ar, **kw: self._signingPriKeyPwd
547            self._signingPriKey = RSA.load_key_string(signingPriKey,
548                                                       callback=pwdCallback)
549
550        elif isinstance(signingPriKey, RSA.RSA):
551            self._signingPriKey = signingPriKey
552                   
553        else:
554            raise AttributeError("Signing private key must be a valid "
555                                  "M2Crypto.RSA.RSA type or a string")
556               
557    def _getSigningPriKey(self):
558        return self._signingPriKey
559
560    signingPriKey = property(fset=_setSigningPriKey,
561                             fget=_getSigningPriKey,
562                             doc="Private key used to sign outbound message")
563
564 
565    def _setSigningPriKeyFilePath(self, signingPriKeyFilePath):
566        """Set method for client private key file path
567       
568        signingPriKeyPwd MUST be set prior to a call to this method"""
569        if isinstance(signingPriKeyFilePath, basestring):                           
570            try:
571                # Read Private key to sign with   
572                priKeyFile = BIO.File(open(signingPriKeyFilePath)) 
573                pwdCallback = lambda *ar, **kw: self._signingPriKeyPwd                                           
574                self._signingPriKey = RSA.load_key_bio(priKeyFile, 
575                                                        callback=pwdCallback)           
576            except Exception, e:
577                raise AttributeError("Setting private key for signature: %s"%e)
578       
579        elif signingPriKeyFilePath is not None:
580            raise AttributeError("Private key file path must be a valid "
581                                 "string or None")
582       
583        self.__signingPriKeyFilePath = signingPriKeyFilePath
584       
585    signingPriKeyFilePath = property(fset=_setSigningPriKeyFilePath,
586                      doc="File path for private key used to sign message")
587
588    def __caCertIsSet(self):
589        '''Check for CA certificate set (X.509 Stack has been created)'''
590        return hasattr(self, '_caX509Stack')
591   
592    caCertIsSet = property(fget=__caCertIsSet,
593           doc='Check for CA certificate set (X.509 Stack has been created)')
594   
595    def __appendCAX509Stack(self, caCertList):
596        '''Store CA certificates in an X.509 Stack
597       
598        @param caCertList: list or tuple
599        @type caCertList: M2Crypto.X509.X509 certificate objects'''
600       
601        if not hasattr(self, '_caX509Stack'):
602            self._caX509Stack = X509Stack()
603           
604        for cert in caCertList:
605            self._caX509Stack.push(cert)
606
607
608    def __setCAX509StackFromDir(self, caCertDir):
609        '''Read CA certificates from directory and add them to the X.509
610        stack
611       
612        @param caCertDir: string
613        @type caCertDir: directory from which to read CA certificate files'''
614       
615        # Mimic OpenSSL -CApath option which expects directory of CA files
616        # of form <Hash cert subject name>.0
617        reg = re.compile('\d+\.0')
618        try:
619            caCertList = [X509CertRead(caFile) \
620                          for caFile in os.listdir(caCertDir) \
621                          if reg.match(caFile)]
622        except Exception, e:
623            raise WSSecurityError('Loading CA certificate "%s" from CA '
624                                  'directory: %s' % (caFile, str(e)))
625                   
626        # Add to stack
627        self.__appendCAX509Stack(caCertList)
628       
629    caCertDirPath = property(fset=__setCAX509StackFromDir,
630                             doc="Dir. containing CA cert.s used for "
631                                "verification")
632
633
634    def __setCAX509StackFromCertFileList(self, caCertFilePathList):
635        '''Read CA certificates from file and add them to the X.509
636        stack
637       
638        @type caCertFilePathList: list or tuple
639        @param caCertFilePathList: list of file paths for CA certificates to
640        be used to verify certificate used to sign message'''
641       
642        if not isinstance(caCertFilePathList, (list, tuple)):
643            raise WSSecurityError('Expecting a list or tuple for '
644                                  '"caCertFilePathList"')
645
646        # Mimic OpenSSL -CApath option which expects directory of CA files
647        # of form <Hash cert subject name>.0
648        try:
649            caCertList=[X509CertRead(caFile) for caFile in caCertFilePathList]
650        except Exception, e:
651            raise WSSecurityError('Loading CA certificate "%s" from file '
652                                  'list: %s' % (caFile, str(e)))
653                   
654        # Add to stack
655        self.__appendCAX509Stack(caCertList)
656       
657    caCertFilePathList = property(fset=__setCAX509StackFromCertFileList,
658                      doc="List of CA cert. files used for verification")             
659       
660    def _get_timestampClockSkew(self):
661        return getattr(self, "_timestampClockSkew", 0.)
662
663    def _set_timestampClockSkew(self, val):
664        if isinstance(val, basestring):
665            self._timestampClockSkew = float(val)
666           
667        elif isinstance(val, (float, int)):
668            self._timestampClockSkew = val
669           
670        else:
671            raise TypeError("Expecting string, float or int type for "
672                            "timestampClockSkew attribute, got %r" % 
673                            getattr(val, "__class__", val))
674       
675    timestampClockSkew = property(fset=_set_timestampClockSkew,
676                                  fget=_get_timestampClockSkew,
677                                  doc="adjust the current time calculated by "
678                                      "the number of seconds specified in "
679                                      "this parameter.  This enables "
680                                      "allowance to be made for clock skew "
681                                      "between a client and server system "
682                                      "clocks.")
683   
684    def _setBool(self, val):
685        """Convert input string, float or int to bool type
686       
687        @type val: int, float or basestring
688        @param val: input value to be converted
689        @rtype: bool
690        @return: input value converted to bool type
691        """
692       
693        if isinstance(val, bool):
694            return val
695       
696        elif isinstance(val, basestring):
697            val = val.lower()
698            if val not in ("true", "false"):
699                raise ValueError("String conversion failed for input: %r"%val)
700           
701            return val == "true"
702           
703        elif isinstance(val, (int, float)): 
704            return bool(val)
705        else:
706            raise TypeError("Invalid type for bool conversion: %r" % 
707                            val.__class__)
708       
709    def _get_timestampMustBeSet(self):
710        return getattr(self, "_timestampMustBeSet", False)
711
712    def _set_timestampMustBeSet(self, val):
713        self._timestampMustBeSet = self._setBool(val)
714       
715    timestampMustBeSet = property(fset=_set_timestampMustBeSet,
716                                  fget=_get_timestampMustBeSet,
717                                  doc="Set to True to raise an exception if a "
718                                      "message to be verified doesn't have a "
719                                      "timestamp element.  Set to False to "
720                                      "log a warning message and continue "
721                                      "processing")
722   
723    def _get_createdElemMustBeSet(self):
724        return getattr(self, "_createdElemMustBeSet", False)
725
726    def _set_createdElemMustBeSet(self, val):
727        self._createdElemMustBeSet = self._setBool(val)
728       
729    createdElemMustBeSet = property(fset=_set_createdElemMustBeSet,
730                                    fget=_get_createdElemMustBeSet,
731                                    doc="Set to True to raise an exception if "
732                                        "a message to be verified doesn't "
733                                        "have <wsu:Created/> element with its "
734                                        "timestamp element.  Set to False to "
735                                        "log a warning message and continue "
736                                        "processing")
737   
738    def _get_expiresElemMustBeSet(self):
739        return getattr(self, "_expiresElemMustBeSet", False)
740
741    def _set_expiresElemMustBeSet(self, val):
742        self._expiresElemMustBeSet = self._setBool(val)
743       
744    expiresElemMustBeSet = property(fset=_set_expiresElemMustBeSet,
745                                    fget=_get_expiresElemMustBeSet,
746                                    doc="Set to True to raise an exception if "
747                                        "a message to be verified doesn't "
748                                        "have <wsu:Expires/> element with its "
749                                        "timestamp element.  Set to False to "
750                                        "log a warning message and continue "
751                                        "processing")                                 
752
753                             
Note: See TracBrowser for help on using the repository browser.