source: TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/__init__.py @ 5441

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/__init__.py@5441
Revision 5441, 28.7 KB checked in by pjkersha, 11 years ago (diff)

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.

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
111    def __init__(self, cfg=None, cfgFileSection='DEFAULT', cfgFilePrefix='',
112                 cfgClass=WSSecurityConfig, **kw):
113        '''
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
132        '''
133        log.debug("BaseSignatureHandler.__init__ ...")
134
135        # WSSecurityConfig is the default class for reading config params but
136        # alternative derivative class may be passed in instead.
137        if not issubclass(cfgClass, WSSecurityConfig):
138            raise TypeError("%s is not a sub-class of WSSecurityConfig" % 
139                            cfgClass)
140       
141        # Read parameters from config file if set
142        if isinstance(cfg, basestring):
143            log.debug("BaseSignatureHandler.__init__: config file path input "
144                      "...")
145            self.cfg = cfgClass()
146            self.cfg.read(cfg)
147            self.cfg.parse(section=cfgFileSection, prefix=cfgFilePrefix)
148
149        elif isinstance(cfg, RawConfigParser):
150            log.debug("BaseSignatureHandler.__init__: config object input ...")
151            self.cfg = cfgClass(cfg=cfg)
152            self.cfg.parse(section=cfgFileSection, prefix=cfgFilePrefix)
153           
154        elif isinstance(cfg, WSSecurityConfig):
155            log.debug("BaseSignatureHandler.__init__:  WSSSecurityConfig "
156                      "object input ...")
157            self.cfg = cfg
158        else:
159            self.cfg = cfgClass()
160               
161        # Also update config from keywords set
162        log.debug("BaseSignatureHandler.__init__: updating config from "
163                  "keywords...")
164       
165        # Filter keywords if a prefix is set removing any that don't start with
166        # the prefix given
167        self.cfg.update(kw, prefix=cfgFilePrefix)
168       
169        # set default value type, if none specified in config file
170        if not self.cfg['reqBinSecTokValType']:
171            self.cfg['reqBinSecTokValType'] = "X509v3"
172           
173        self.reqBinSecTokValType = self.cfg['reqBinSecTokValType']
174
175        # Set keywords for canonicalization of SignedInfo and reference
176        # elements
177        self.refC14nKw = {'inclusive_namespaces': self.cfg['refC14nInclNS']}
178
179        self.signedInfoC14nKw = {'inclusive_namespaces': 
180                                 self.cfg['signedInfoC14nInclNS']}
181
182        self.verifyingCert = self.cfg['verifyingCert']
183        self.verifyingCertFilePath = self.cfg['verifyingCertFilePath']
184       
185        self.signingCert = self.cfg['signingCert']
186        self.signingCertFilePath = self.cfg['signingCertFilePath']
187
188        self.signingCertChain = self.cfg['signingCertChain']
189             
190        # MUST be set before _setSigningPriKeyFilePath / _setSigningPriKey
191        # are called
192        self.signingPriKeyPwd = self.cfg['signingPriKeyPwd']
193       
194        if self.cfg.get('signingPriKey'):
195            # Don't allow None for private key setting
196            self.signingPriKey = self.cfg['signingPriKey']
197           
198        self.signingPriKeyFilePath = self.cfg['signingPriKeyFilePath']
199       
200        # CA certificate(s) for verification of X.509 certificate used with
201        # signature.
202        if self.cfg.get('caCertDirPath'):
203            self.caCertDirPath = self.cfg['caCertDirPath']
204           
205        elif self.cfg.get('caCertFilePathList'):
206            self.caCertFilePathList = self.cfg['caCertFilePathList']
207       
208        # Configure signature generation to add/omit a timestamp
209        self.addTimestamp = self.cfg['addTimestamp']
210       
211        # Configure timestamp checking in Signature verification handler
212        self.timestampClockSkew = self.cfg['timestampClockSkew']
213        self.timestampMustBeSet = self.cfg['timestampMustBeSet']
214        self.createdElemMustBeSet = self.cfg['createdElemMustBeSet']
215        self.expiresElemMustBeSet = self.cfg['expiresElemMustBeSet']
216       
217        # set default value, if none specified in config file
218        if not self.cfg['applySignatureConfirmation']:
219            self.cfg['applySignatureConfirmation'] = False
220
221        self.applySignatureConfirmation=self.cfg['applySignatureConfirmation']
222        self.b64EncSignatureValue = None
223       
224        log.debug("WSSE Config = %s" % self.cfg)
225
226               
227    def _setReqBinSecTokValType(self, value):
228        """Set ValueType attribute for BinarySecurityToken used in a request
229         
230        @type value: string
231        @param value: name space for BinarySecurityToken ValueType check
232        'binSecTokValType' class variable for supported types.  Input can be
233        shortened to binSecTokValType keyword if desired.
234        """
235        log.debug("Setting reqBinSecTokValType - to %s" %value)
236        if value in self.__class__.binSecTokValType:
237            self._reqBinSecTokValType = self.__class__.binSecTokValType[value]
238 
239        elif value in self.__class__.binSecTokValType.values():
240            self._reqBinSecTokValType = value
241        else:
242            raise WSSecurityError('Request BinarySecurityToken ValueType '
243                                  '"%s" not recognised' % value)
244           
245    def _getReqBinSecTokValType(self):
246        """
247        Get ValueType attribute for BinarySecurityToken used in a request
248        """
249        log.debug("Getting reqBinSecTokValType value")
250        if hasattr(self, '_reqBinSecTokValType'):
251            return self._reqBinSecTokValType
252        else:
253            return ""
254       
255    reqBinSecTokValType = property(fset=_setReqBinSecTokValType,
256                                   fget=_getReqBinSecTokValType,
257         doc="ValueType attribute for BinarySecurityToken used in request")
258       
259
260    def __checkC14nKw(self, kw):
261        """Check keywords for canonicalization in signing process - generic
262        method for setting keywords for reference element and SignedInfo
263        element C14N
264       
265        @type kw: dict
266        @param kw: keyword used with ZSI.wstools.Utility.Canonicalization"""
267       
268        # Check for dict/None - Set to None in order to use inclusive
269        # canonicalization
270        if kw is not None and not isinstance(kw, dict):
271            # Otherwise keywords must be a dictionary
272            raise AttributeError("Expecting dictionary type for reference "
273                                 "C14N keywords")
274               
275        elif kw.get('inclusive_namespaces') and \
276             not isinstance(kw['inclusive_namespaces'], (list, tuple)):
277            raise AttributeError('Expecting list or tuple of prefix names for '
278                                 '"%s" keyword' % 'inclusive_namespaces')
279       
280               
281    def _setRefC14nKw(self, kw):
282        """Set keywords for canonicalization of reference elements in the
283        signing process"""
284        self.__checkC14nKw(kw)                   
285        self._refC14nKw = kw
286       
287    def _getRefC14nKw(self):
288        if hasattr(self, '_refC14nKw'):
289            return self._refC14nKw
290        else:
291            return {}
292       
293    refC14nKw = property(fset=_setRefC14nKw,
294                         fget=_getRefC14nKw,
295                         doc="Keywords for C14N of reference elements")
296       
297               
298    def _setSignedInfoC14nKw(self, kw):
299        """Set keywords for canonicalization of SignedInfo element in the
300        signing process"""
301        self.__checkC14nKw(kw)                   
302        self._signedInfoC14nKw = kw
303       
304    def _getSignedInfoC14nKw(self):
305        if hasattr(self, '_signedInfoC14nKw'):
306            return self._signedInfoC14nKw
307        else:
308            return {}
309       
310    signedInfoC14nKw = property(fset=_setSignedInfoC14nKw,
311                                fget=_getSignedInfoC14nKw,
312                                doc="Keywords for C14N of SignedInfo element")
313
314
315    def _refC14nIsExcl(self):
316        '''
317        @rtype: bool
318        @return: true if Exclusive C14N is set as algorithm to apply to
319        reference elements
320        '''
321        # TODO: alter logic here if inclusive C14N is re-instated.
322        return True
323               
324    refC14nIsExcl = property(fget=_refC14nIsExcl,
325    doc="Return True/False C14N for reference elements set to exclusive type")
326
327     
328    def _signedInfoC14nIsExcl(self):
329        '''
330        @rtype: bool
331        @return: true if Exclusive C14N is set as algorithm to apply to
332        the signed info elements of the XML Digital Signature
333        '''
334        # TODO: alter logic here if inclusive C14N is re-instated.
335        return True
336       
337    signedInfoC14nIsExcl = property(fget=_signedInfoC14nIsExcl,
338                                    doc="Return True/False C14N for "
339                                    "SignedInfo element set to exclusive type")
340   
341   
342    def _setCert(self, cert):
343        """filter and convert input cert to signing verifying cert set
344        property methods.  For signingCert, set to None if it is not to be
345        included in the SOAP header.  For verifyingCert, set to None if this
346        cert can be expected to be retrieved from the SOAP header of the
347        message to be verified
348       
349        @type: ndg.security.common.X509.X509Cert / M2Crypto.X509.X509 /
350        PEM encoded string or None
351        @param cert: X.509 certificate. 
352       
353        @rtype ndg.security.common.X509.X509Cert
354        @return X.509 certificate object"""
355       
356        if not cert or isinstance(cert, X509Cert):
357            # ndg.security.common.X509.X509Cert type / None
358            x509Cert = cert
359           
360        elif isinstance(cert, X509.X509):
361            # M2Crypto.X509.X509 type
362            x509Cert = X509Cert(m2CryptoX509=cert)
363           
364        elif isinstance(cert, basestring):
365            # Nb. Assume PEM encoded string!
366            x509Cert = X509CertParse(cert)
367       
368        else:
369            raise AttributeError("X.509 Cert. must be type: ndg.security."
370                                 "common.X509.X509Cert, M2Crypto.X509.X509 or "
371                                 "a base64 encoded string")
372       
373        # Check for expired certificate
374        if x509Cert:   
375            x509Cert.isValidTime(raiseExcep=True)
376           
377        return x509Cert
378
379   
380    def _getVerifyingCert(self):
381        '''Return X.509 cert object corresponding to cert used to verify the
382        signature in the last call to verify
383       
384         * Cert will correspond to one used in the LATEST call to verify, on
385         the next call it will be replaced
386         * if verify hasn't been called, the cert will be None
387       
388        @rtype: M2Crypto.X509.X509
389        @return: certificate object
390        '''
391        return self._verifyingCert
392
393
394    def _setVerifyingCert(self, verifyingCert):
395        "Set property method for X.509 cert. used to verify a signature"
396        self._verifyingCert = self._setCert(verifyingCert)
397       
398        # Reset file path as it may no longer apply
399        self._verifyingCertFilePath = None
400       
401    verifyingCert = property(fset=_setVerifyingCert,
402                             fget=_getVerifyingCert,
403                             doc="Set X.509 Cert. for verifying signature")
404
405
406    def _setVerifyingCertFilePath(self, verifyingCertFilePath):
407        "Set method for Service X.509 cert. file path property"
408        if verifyingCertFilePath:
409            if isinstance(verifyingCertFilePath, basestring):
410                self._verifyingCert = X509CertRead(verifyingCertFilePath)
411            else:
412                raise AttributeError, "X.509 Cert file path is not a valid string"
413       
414        self._verifyingCertFilePath = verifyingCertFilePath
415       
416    verifyingCertFilePath = property(fset=_setVerifyingCertFilePath,
417                    doc="file path of X.509 Cert. for verifying signature")
418
419   
420    def _getSigningCert(self):
421        '''Return X.509 certificate object corresponding to certificate used
422        with signature
423       
424        @rtype: M2Crypto.X509.X509
425        @return: certificate object
426        '''
427        return self._signingCert
428
429
430    def _setSigningCert(self, signingCert):
431        "Set property method for X.509 cert. to be included with signature"
432        self._signingCert = self._setCert(signingCert)
433   
434        # Reset file path as it may no longer apply
435        self._signingCertFilePath = None
436       
437    signingCert = property(fget=_getSigningCert,
438                           fset=_setSigningCert,
439                           doc="X.509 Certificate to include signature")
440
441 
442    def _setSigningCertFilePath(self, signingCertFilePath):
443        "Set signature X.509 certificate property method"
444       
445        if isinstance(signingCertFilePath, basestring):
446            self._signingCert = X509CertRead(signingCertFilePath)
447           
448        elif signingCertFilePath is not None:
449            raise AttributeError("Signature X.509 certificate file path must "
450                                 "be a valid string")
451       
452        self._signingCertFilePath = signingCertFilePath
453       
454       
455    signingCertFilePath = property(fset=_setSigningCertFilePath,
456                   doc="File path X.509 cert. to include with signed message")
457
458   
459    def _setSigningCertChain(self, signingCertChain):
460        '''Signature set-up with "X509PKIPathv1" BinarySecurityToken
461        ValueType.  Use an X.509 Stack to store certificates that make up a
462        chain of trust to certificate used to verify a signature
463       
464        @type signingCertChain: list or tuple of M2Crypto.X509.X509Cert or
465        ndg.security.common.X509.X509Cert types.
466        @param signingCertChain: list of certificate objects making up the
467        chain of trust.  The last certificate is the one associated with the
468        private key used to sign the message.'''
469       
470        if not isinstance(signingCertChain, (list, tuple)):
471            log.warning('Expecting a list or tuple for "signingCertChain" - '
472                        'ignoring value set, "%s"' % signingCertChain)
473            self._signingCertChain = None
474            return
475       
476        self._signingCertChain = X509Stack()
477           
478        for cert in signingCertChain:
479            self._signingCertChain.push(cert)
480           
481    def _getSigningCertChain(self):
482        return self._signingCertChain
483   
484    signingCertChain = property(fset=_setSigningCertChain,
485                                fget=_getSigningCertChain,
486                                doc="Cert.s in chain of trust to cert. used "
487                                    "to verify msg.")
488
489 
490    def _setSigningPriKeyPwd(self, signingPriKeyPwd):
491        "Set method for private key file password used to sign message"
492        if signingPriKeyPwd is not None and \
493           not isinstance(signingPriKeyPwd, basestring):
494            raise AttributeError("Signing private key password must be None "
495                                 "or a valid string")
496       
497        self._signingPriKeyPwd = signingPriKeyPwd
498
499    def _getSigningPriKeyPwd(self):
500        if hasattr(self, '_signingPriKeyPwd'):
501            return self._signingPriKeyPwd
502        else:
503            return ""
504       
505    signingPriKeyPwd = property(fset=_setSigningPriKeyPwd,
506                                fget=_getSigningPriKeyPwd,
507                                doc="Password protecting private key file "
508                                    "used to sign message")
509
510 
511    def _setSigningPriKey(self, signingPriKey):
512        """Set method for client private key
513       
514        Nb. if input is a string, signingPriKeyPwd will need to be set if
515        the key is password protected.
516       
517        @type signingPriKey: M2Crypto.RSA.RSA / string
518        @param signingPriKey: private key used to sign message"""
519       
520        if isinstance(signingPriKey, basestring):
521            pwdCallback = lambda *ar, **kw: self._signingPriKeyPwd
522            self._signingPriKey = RSA.load_key_string(signingPriKey,
523                                                       callback=pwdCallback)
524
525        elif isinstance(signingPriKey, RSA.RSA):
526            self._signingPriKey = signingPriKey
527                   
528        else:
529            raise AttributeError("Signing private key must be a valid "
530                                  "M2Crypto.RSA.RSA type or a string")
531               
532    def _getSigningPriKey(self):
533        return self._signingPriKey
534
535    signingPriKey = property(fset=_setSigningPriKey,
536                             fget=_getSigningPriKey,
537                             doc="Private key used to sign outbound message")
538
539 
540    def _setSigningPriKeyFilePath(self, signingPriKeyFilePath):
541        """Set method for client private key file path
542       
543        signingPriKeyPwd MUST be set prior to a call to this method"""
544        if isinstance(signingPriKeyFilePath, basestring):                           
545            try:
546                # Read Private key to sign with   
547                priKeyFile = BIO.File(open(signingPriKeyFilePath)) 
548                pwdCallback = lambda *ar, **kw: self._signingPriKeyPwd                                           
549                self._signingPriKey = RSA.load_key_bio(priKeyFile, 
550                                                        callback=pwdCallback)           
551            except Exception, e:
552                raise AttributeError("Setting private key for signature: %s"%e)
553       
554        elif signingPriKeyFilePath is not None:
555            raise AttributeError("Private key file path must be a valid "
556                                 "string or None")
557       
558        self.__signingPriKeyFilePath = signingPriKeyFilePath
559       
560    signingPriKeyFilePath = property(fset=_setSigningPriKeyFilePath,
561                      doc="File path for private key used to sign message")
562
563    def __caCertIsSet(self):
564        '''Check for CA certificate set (X.509 Stack has been created)'''
565        return hasattr(self, '_caX509Stack')
566   
567    caCertIsSet = property(fget=__caCertIsSet,
568           doc='Check for CA certificate set (X.509 Stack has been created)')
569   
570    def __appendCAX509Stack(self, caCertList):
571        '''Store CA certificates in an X.509 Stack
572       
573        @param caCertList: list or tuple
574        @type caCertList: M2Crypto.X509.X509 certificate objects'''
575       
576        if not hasattr(self, '_caX509Stack'):
577            self._caX509Stack = X509Stack()
578           
579        for cert in caCertList:
580            self._caX509Stack.push(cert)
581
582
583    def __setCAX509StackFromDir(self, caCertDir):
584        '''Read CA certificates from directory and add them to the X.509
585        stack
586       
587        @param caCertDir: string
588        @type caCertDir: directory from which to read CA certificate files'''
589       
590        # Mimic OpenSSL -CApath option which expects directory of CA files
591        # of form <Hash cert subject name>.0
592        reg = re.compile('\d+\.0')
593        try:
594            caCertList = [X509CertRead(caFile) \
595                          for caFile in os.listdir(caCertDir) \
596                          if reg.match(caFile)]
597        except Exception, e:
598            raise WSSecurityError('Loading CA certificate "%s" from CA '
599                                  'directory: %s' % (caFile, str(e)))
600                   
601        # Add to stack
602        self.__appendCAX509Stack(caCertList)
603       
604    caCertDirPath = property(fset=__setCAX509StackFromDir,
605                             doc="Dir. containing CA cert.s used for "
606                                "verification")
607
608
609    def __setCAX509StackFromCertFileList(self, caCertFilePathList):
610        '''Read CA certificates from file and add them to the X.509
611        stack
612       
613        @type caCertFilePathList: list or tuple
614        @param caCertFilePathList: list of file paths for CA certificates to
615        be used to verify certificate used to sign message'''
616       
617        if not isinstance(caCertFilePathList, (list, tuple)):
618            raise WSSecurityError('Expecting a list or tuple for '
619                                  '"caCertFilePathList"')
620
621        # Mimic OpenSSL -CApath option which expects directory of CA files
622        # of form <Hash cert subject name>.0
623        try:
624            caCertList=[X509CertRead(caFile) for caFile in caCertFilePathList]
625        except Exception, e:
626            raise WSSecurityError('Loading CA certificate "%s" from file '
627                                  'list: %s' % (caFile, str(e)))
628                   
629        # Add to stack
630        self.__appendCAX509Stack(caCertList)
631       
632    caCertFilePathList = property(fset=__setCAX509StackFromCertFileList,
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   
659    def _setBool(self, val):
660        """Convert input string, float or int to bool type
661       
662        @type val: int, float or basestring
663        @param val: input value to be converted
664        @rtype: bool
665        @return: input value converted to bool type
666        """
667       
668        if isinstance(val, bool):
669            return val
670       
671        elif isinstance(val, basestring):
672            val = val.lower()
673            if val not in ("true", "false"):
674                raise ValueError("String conversion failed for input: %r"%val)
675           
676            return val == "true"
677           
678        elif isinstance(val, (int, float)): 
679            return bool(val)
680        else:
681            raise TypeError("Invalid type for bool conversion: %r" % 
682                            val.__class__)
683       
684    def _get_timestampMustBeSet(self):
685        return getattr(self, "_timestampMustBeSet", False)
686
687    def _set_timestampMustBeSet(self, val):
688        self._timestampMustBeSet = self._setBool(val)
689       
690    timestampMustBeSet = property(fset=_set_timestampMustBeSet,
691                                  fget=_get_timestampMustBeSet,
692                                  doc="Set to True to raise an exception if a "
693                                      "message to be verified doesn't have a "
694                                      "timestamp element.  Set to False to "
695                                      "log a warning message and continue "
696                                      "processing")
697   
698    def _get_createdElemMustBeSet(self):
699        return getattr(self, "_createdElemMustBeSet", False)
700
701    def _set_createdElemMustBeSet(self, val):
702        self._createdElemMustBeSet = self._setBool(val)
703       
704    createdElemMustBeSet = property(fset=_set_createdElemMustBeSet,
705                                    fget=_get_createdElemMustBeSet,
706                                    doc="Set to True to raise an exception if "
707                                        "a message to be verified doesn't "
708                                        "have <wsu:Created/> element with its "
709                                        "timestamp element.  Set to False to "
710                                        "log a warning message and continue "
711                                        "processing")
712   
713    def _get_expiresElemMustBeSet(self):
714        return getattr(self, "_expiresElemMustBeSet", False)
715
716    def _set_expiresElemMustBeSet(self, val):
717        self._expiresElemMustBeSet = self._setBool(val)
718       
719    expiresElemMustBeSet = property(fset=_set_expiresElemMustBeSet,
720                                    fget=_get_expiresElemMustBeSet,
721                                    doc="Set to True to raise an exception if "
722                                        "a message to be verified doesn't "
723                                        "have <wsu:Expires/> element with its "
724                                        "timestamp element.  Set to False to "
725                                        "log a warning message and continue "
726                                        "processing")                                 
727
728                             
Note: See TracBrowser for help on using the repository browser.