source: TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/BaseSignatureHandler.py @ 4133

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/BaseSignatureHandler.py@4133
Revision 4133, 29.0 KB checked in by cbyrom, 12 years ago (diff)

Fix checks for inclusive/exclusive namespace use + set default use
of exclusive NS canonicalisation for the dom class - since the ZSI
Canonicalization method does not seem to work without this.

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