Ignore:
Timestamp:
25/01/10 14:17:49 (11 years ago)
Author:
pjkersha
Message:
 
File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/WSSecurity/ndg/wssecurity/common/signaturehandler/__init__.py

    r6392 r6396  
    2727 
    2828from ndg.wssecurity.common import WSSecurityConfigError, WSSecurityError 
    29 from ndg.wssecurity.utils.configfileparsers import CaseSensitiveConfigParser 
    30 from ndg.wssecurity.utils.pki import (X509Cert, X509CertParse, X509CertRead,  
    31                                       X509Stack, X509StackParseFromDER) 
     29from ndg.wssecurity.common.utils import classfactory 
     30from ndg.wssecurity.common.utils.configfileparsers import ( 
     31                                            CaseSensitiveConfigParser,  
     32                                            WithGetListConfigParser) 
     33from ndg.wssecurity.common.utils.pki import (X509Cert, X509Stack,  
     34                                             X509StackParseFromDER) 
    3235 
    3336 
     
    6568 
    6669 
     70_isIterable = lambda obj: getattr(obj, '__iter__', False)  
     71  
     72 
    6773class BaseSignatureHandler(object): 
    6874    """Class to handle signature and verification of signature with  
     
    8591    message verified 
    8692    @type b64EncSignatureValue: string/None""" 
     93    isIterable = staticmethod(_isIterable) 
    8794 
    8895    BINARY_SECURITY_TOK_ENCODING_TYPE = ( 
     
    100107    ZSI_C14N_KEYWORD_NAME = 'inclusive_namespaces' 
    101108     
    102     CFG_PARSER_CLASS = CaseSensitiveConfigParser 
     109    CFG_PARSER_CLASS = WithGetListConfigParser 
    103110    PROPERTY_DEFAULTS = dict( 
     111        className=('',), 
    104112        reqBinarySecurityTokValType=(OASIS.X509TOKEN.X509,), 
    105113        verifyingCert=(None,), 
    106         verifyingCertFilePath=(None,), 
     114        verifyingCertFilePath=(None, ''), 
    107115        signingCert=(None,), 
    108         signingCertFilePath=(None,),  
     116        signingCertFilePath=(None, ''),  
    109117        signingCertChain=([],), 
    110118        signingPriKey=(None,), 
    111         signingPriKeyFilePath=(None,''),  
    112         signingPriKeyPwd=(None,), 
    113         caCertDirPath=(None,), 
     119        signingPriKeyFilePath=(None, ''),  
     120        signingPriKeyPwd=(None, ''), 
     121        caCertDirPath=(None, ''), 
    114122        caCertFilePathList=([],), 
    115123        addTimestamp=(True,), 
     
    123131        cfg=(CFG_PARSER_CLASS(),)) 
    124132     
    125     LIST_STRING_PAT = re.compile(',\s*') 
    126     _parseListString = lambda opt, section: LIST_STRING_PAT.split( 
    127                                             CFG_PARSER_CLASS.get(opt, section)) 
    128     parseListString = classmethod(_parseListString) 
    129      
    130133    CFG_PARSER_GET_FUNC_MAP = { 
    131         basestring: CFG_PARSER_CLASS.get, 
     134        str: CFG_PARSER_CLASS.get, 
     135        unicode: CFG_PARSER_CLASS.get, 
    132136        bool: CFG_PARSER_CLASS.getboolean, 
    133137        float: CFG_PARSER_CLASS.getfloat, 
    134138        int: CFG_PARSER_CLASS.getint, 
    135         list: parseListString 
     139        list: CFG_PARSER_CLASS.getlist 
    136140    } 
    137141     
    138142    TYPE_MAP = dict([(k, tuple([type(i) for i in v])) 
    139143                     for k,v in PROPERTY_DEFAULTS.items()]) 
    140     __slots__ = TYPE_MAP 
     144     
     145    __slots__ = TYPE_MAP.copy() 
     146    __slots__.update({}.fromkeys(['__%s' % i for i in TYPE_MAP.keys()]))    
     147    __slots__.update( 
     148        __caX509Stack=None, 
     149        __refC14nKw=None, 
     150        __signedInfoC14nKw=None 
     151    ) 
    141152     
    142153    def __init__(self): 
     
    145156        for name, val in BaseSignatureHandler.PROPERTY_DEFAULTS.items(): 
    146157            setattr(self, name, val[0]) 
     158 
     159        self.__caX509Stack = X509Stack() 
     160        self.__refC14nKw = {} 
     161        self.__signedInfoC14nKw = {} 
     162 
     163    @classmethod 
     164    def fromConfigFile(cls, filePath, **kw): 
     165        """Instantiate from settings in a config file""" 
     166        signatureHandler = cls() 
     167        signatureHandler.read(filePath) 
     168        signatureHandler.parse(**kw) 
     169        return signatureHandler 
     170 
     171    @classmethod 
     172    def fromKeywords(cls, *arg, **kw): 
     173        """Instantiate from keyword settings - this is useful when integrating 
     174        with Paste WSGI apps app_conf settings""" 
     175        signatureHandler = cls() 
     176        signatureHandler.update(**kw) 
     177        return signatureHandler 
     178     
     179    @classmethod 
     180    def expandVars(cls, val): 
     181        if cls.isIterable(val): 
     182            for i, v in zip(range(len(val)), val): 
     183                if isinstance(v, basestring): 
     184                    val[i] = os.path.expandvars(v)  
     185            return val 
     186         
     187        elif isinstance(val, basestring): 
     188            return os.path.expandvars(val) 
     189        else: 
     190            return val 
    147191         
    148192    def __setattr__(self, name, val): 
     
    189233             
    190234        paramSettings = zip(optNames,  
    191                             BaseSignatureHandler.PROPERTY_DEFAULTS.keys(), 
    192                             BaseSignatureHandler.TYPE_MAP)  
     235                            BaseSignatureHandler.PROPERTY_DEFAULTS.keys())  
    193236            
    194         for optName, attrName, types in paramSettings: 
     237        for optName, attrName in paramSettings: 
    195238             
    196239            # Parameters may be omitted and set later 
    197240            if self.cfg.has_option(sectionName, optName): 
     241                types = BaseSignatureHandler.TYPE_MAP.get(attrName) 
     242                if types is None: 
     243                    raise WSSecurityConfigError("No type set for %r attribute" % 
     244                                                attrName) 
     245                     
    198246                getFunc = BaseSignatureHandler.CFG_PARSER_GET_FUNC_MAP.get( 
    199                                                                     types[0]) 
     247                                                                    types[-1]) 
    200248                if getFunc is None: 
    201249                    raise WSSecurityConfigError("No Config parser get method " 
    202                         "configured for attribute %r with type %r" % 
    203                         (attrName, type[0])) 
     250                                                "configured for attribute %r " 
     251                                                "with type %r" % 
     252                                                (attrName, types[-1])) 
    204253                      
    205254                val = getFunc(self.cfg, sectionName, optName) 
    206                 setattr(self, attrName, val) 
     255                setattr(self, attrName, BaseSignatureHandler.expandVars(val)) 
    207256                  
    208257    def update(self, prefix=None, **kw): 
     
    220269            if prefix: 
    221270                optName = optName.replace(prefix, '', 1) 
    222                 setattr(self, optName, val) 
     271                setattr(self, optName, BaseSignatureHandler.expandVars(val)) 
    223272                                   
    224273    def _setReqBinarySecurityTokValType(self, value): 
     
    352401        elif isinstance(cert, basestring): 
    353402            # Nb. Assume PEM encoded string! 
    354             x509Cert = X509CertParse(cert) 
     403            x509Cert = X509Cert.Parse(cert) 
    355404         
    356405        else: 
     
    376425        @return: certificate object 
    377426        ''' 
    378         return self._verifyingCert 
     427        return self.__verifyingCert 
    379428 
    380429    def _setVerifyingCert(self, verifyingCert): 
    381430        "Set property method for X.509 cert. used to verify a signature" 
    382         self._verifyingCert = self._setCert(verifyingCert) 
     431        self.__verifyingCert = self._setCert(verifyingCert) 
    383432         
    384433        # Reset file path as it may no longer apply 
    385         self._verifyingCertFilePath = None 
     434        self.__verifyingCertFilePath = None 
    386435         
    387436    verifyingCert = property(fset=_setVerifyingCert, 
     
    393442        if verifyingCertFilePath: 
    394443            if isinstance(verifyingCertFilePath, basestring): 
    395                 self._verifyingCert = X509CertRead(verifyingCertFilePath) 
     444                self.__verifyingCert = X509Cert.Read(verifyingCertFilePath) 
    396445            else: 
    397446                raise TypeError("X.509 Cert file path is not a valid string") 
    398447         
    399         self._verifyingCertFilePath = verifyingCertFilePath 
     448        self.__verifyingCertFilePath = verifyingCertFilePath 
    400449         
    401450    verifyingCertFilePath = property(fset=_setVerifyingCertFilePath, 
     
    409458        @return: certificate object 
    410459        ''' 
    411         return self._signingCert 
     460        return self.__signingCert 
    412461 
    413462    def _setSigningCert(self, signingCert): 
    414463        "Set property method for X.509 cert. to be included with signature" 
    415         self._signingCert = self._setCert(signingCert) 
     464        self.__signingCert = self._setCert(signingCert) 
    416465     
    417466        # Reset file path as it may no longer apply 
    418         self._signingCertFilePath = None 
     467        self.__signingCertFilePath = None 
    419468         
    420469    signingCert = property(fget=_getSigningCert, 
     
    427476         
    428477        if isinstance(signingCertFilePath, basestring): 
    429             self._signingCert = X509CertRead(signingCertFilePath) 
     478            self.__signingCert = X509Cert.Read(signingCertFilePath) 
    430479             
    431480        elif signingCertFilePath is not None: 
     
    433482                                 "be a valid string") 
    434483         
    435         self._signingCertFilePath = signingCertFilePath 
     484        self.__signingCertFilePath = signingCertFilePath 
    436485         
    437486    signingCertFilePath = property(fset=_setSigningCertFilePath, 
     
    449498        chain of trust.  The last certificate is the one associated with the 
    450499        private key used to sign the message.''' 
    451          
    452         if not isinstance(signingCertChain, (list, tuple)): 
    453             log.warning('Expecting a list or tuple for "signingCertChain" - ' 
    454                         'ignoring value set, "%s"' % signingCertChain) 
    455             self._signingCertChain = None 
    456             return 
    457          
    458         self._signingCertChain = X509Stack() 
    459              
    460500        for cert in signingCertChain: 
    461             self._signingCertChain.push(cert) 
     501            self.__signingCertChain.push(cert) 
    462502             
    463503    def _getSigningCertChain(self): 
    464         return self._signingCertChain 
     504        return self.__signingCertChain 
    465505     
    466506    signingCertChain = property(fset=_setSigningCertChain, 
     
    476516                                 "or a valid string") 
    477517         
    478         self._signingPriKeyPwd = signingPriKeyPwd 
    479  
    480     def _getSigningPriKeyPwd(self): 
    481         if hasattr(self, '_signingPriKeyPwd'): 
    482             return self._signingPriKeyPwd 
    483         else: 
    484             return "" 
    485          
     518        self.__signingPriKeyPwd = signingPriKeyPwd 
     519 
     520    def _getSigningPriKeyPwd(self):        
     521        return self.__signingPriKeyPwd 
     522 
    486523    signingPriKeyPwd = property(fset=_setSigningPriKeyPwd, 
    487524                                fget=_getSigningPriKeyPwd, 
     
    489526                                    "used to sign message") 
    490527 
    491   
    492528    def _setSigningPriKey(self, signingPriKey): 
    493529        """Set method for client private key 
     
    496532        the key is password protected. 
    497533         
    498         @type signingPriKey: M2Crypto.RSA.RSA / string 
     534        @type signingPriKey: M2Crypto.RSA.RSA / string / None 
    499535        @param signingPriKey: private key used to sign message""" 
    500536         
    501537        if isinstance(signingPriKey, basestring): 
    502             pwdCallback = lambda *ar, **kw: self._signingPriKeyPwd 
    503             self._signingPriKey = RSA.load_key_string(signingPriKey, 
     538            pwdCallback = lambda *ar, **kw: self.__signingPriKeyPwd 
     539            self.__signingPriKey = RSA.load_key_string(signingPriKey, 
    504540                                                       callback=pwdCallback) 
    505  
    506541        elif isinstance(signingPriKey, RSA.RSA): 
    507             self._signingPriKey = signingPriKey  
    508                     
     542            self.__signingPriKey = signingPriKey 
     543             
     544        elif signingPriKey is None: 
     545            self.__signingPriKey = None         
    509546        else: 
    510             raise AttributeError("Signing private key must be a valid " 
    511                                   "M2Crypto.RSA.RSA type or a string") 
     547            raise TypeError("Signing private key must be a valid " 
     548                            "M2Crypto.RSA.RSA type or a string") 
    512549                 
    513550    def _getSigningPriKey(self): 
    514         return self._signingPriKey 
     551        return self.__signingPriKey 
    515552 
    516553    signingPriKey = property(fset=_setSigningPriKey, 
     
    527564                # Read Private key to sign with     
    528565                priKeyFile = BIO.File(open(signingPriKeyFilePath))  
    529                 pwdCallback = lambda *ar, **kw: self._signingPriKeyPwd                                            
    530                 self._signingPriKey = RSA.load_key_bio(priKeyFile,  
     566                pwdCallback = lambda *ar, **kw: self.__signingPriKeyPwd                                            
     567                self.__signingPriKey = RSA.load_key_bio(priKeyFile,  
    531568                                                        callback=pwdCallback)            
    532569            except Exception, e: 
     
    554591        @param caCertList: list or tuple 
    555592        @type caCertList: M2Crypto.X509.X509 certificate objects''' 
    556          
    557         if not hasattr(self, '_caX509Stack'): 
    558             self.__caX509Stack = X509Stack() 
    559              
    560593        for cert in caCertList: 
    561594            self.__caX509Stack.push(cert) 
     
    566599        stack 
    567600         
    568         @param caCertDir: string 
     601        @param caCertDir: string / None type 
    569602        @type caCertDir: directory from which to read CA certificate files''' 
     603         
     604        if caCertDir is None: 
     605            return 
    570606         
    571607        # Mimic OpenSSL -CApath option which expects directory of CA files 
     
    573609        reg = re.compile('\d+\.0') 
    574610        try: 
    575             caCertList = [X509CertRead(caFile)  
     611            caCertList = [X509Cert.Read(caFile)  
    576612                          for caFile in os.listdir(caCertDir)  
    577613                          if reg.match(caFile)] 
     
    594630        @param caCertFilePathList: list of file paths for CA certificates to 
    595631        be used to verify certificate used to sign message''' 
    596          
    597         if not isinstance(caCertFilePathList, (list, tuple)): 
    598             raise WSSecurityError('Expecting a list or tuple for ' 
    599                                   '"caCertFilePathList"') 
    600632 
    601633        # Mimic OpenSSL -CApath option which expects directory of CA files 
    602634        # of form <Hash cert subject name>.0 
    603635        try: 
    604             caCertList = [X509CertRead(caFile) for caFile in caCertFilePathList] 
     636            caCertList = [X509Cert.Read(caFile) for caFile in caCertFilePathList] 
    605637        except Exception: 
    606638            raise WSSecurityError('Loading CA certificate "%s" from file ' 
     
    615647         
    616648    def _get_timestampClockSkew(self): 
    617         return getattr(self, "_timestampClockSkew", 0.) 
     649        return self.__timestampClockSkew 
    618650 
    619651    def _set_timestampClockSkew(self, val): 
     
    627659            raise TypeError("Expecting string, float or int type for " 
    628660                            "timestampClockSkew attribute, got %r" %  
    629                             getattr(val, "__class__", val)) 
     661                            type(val)) 
    630662         
    631663    timestampClockSkew = property(fset=_set_timestampClockSkew, 
     
    704736                                        "timestamp element.  Set to False to " 
    705737                                        "log a warning message and continue " 
    706                                         "processing")                                   
    707  
    708                                
     738                                        "processing")            
     739     
     740     
     741class SignatureHandlerFactory(object): 
     742    """Create a new signature handler from the given class name and other  
     743    configuration settings 
     744    """ 
     745    CLASS_NAME_OPTNAME = 'className' 
     746     
     747    @classmethod 
     748    def fromConfigFile(cls, filePath, sectionName='DEFAULT', prefix=''): 
     749        """Instantiate a new signature handler from a config file""" 
     750         
     751        # Expand environment variables in file path 
     752        expandedFilePath = os.path.expandvars(filePath) 
     753         
     754        # Add 'here' item to enable convenient path substitutions in the config 
     755        # file 
     756        defaultItems = dict(here=os.path.dirname(expandedFilePath)) 
     757        cfg = CaseSensitiveConfigParser(defaults=defaultItems) 
     758         
     759        readFilePaths = cfg.read(expandedFilePath) 
     760         
     761        # Check file was read in OK 
     762        if len(readFilePaths) == 0: 
     763            raise IOError('Missing config file: "%s"' % expandedFilePath)  
     764                
     765        optName = prefix + cls.CLASS_NAME_OPTNAME 
     766        className = cfg.get(sectionName, optName) 
     767        signatureHandlerClass = classfactory.importClass(className,  
     768                                            objectType=BaseSignatureHandler) 
     769         
     770        return signatureHandlerClass.fromConfigFile(filePath, 
     771                                                    sectionName=sectionName,  
     772                                                    prefix=prefix) 
     773     
     774    @classmethod 
     775    def fromKeywords(cls, prefix='', **kw): 
     776        """Instantiate a new signature handler from keyword settings""" 
     777        optName = prefix + cls.CLASS_NAME_OPTNAME 
     778        className = kw.get(optName) 
     779        if className is None: 
     780            raise KeyError("No %r keyword setting" % cls.CLASS_NAME_OPTNAME) 
     781         
     782        signatureHandlerClass = classfactory.importClass(className,  
     783                                            objectType=BaseSignatureHandler) 
     784         
     785        return signatureHandlerClass.fromKeywords(prefix, **kw) 
     786     
Note: See TracChangeset for help on using the changeset viewer.