Changeset 2510


Ignore:
Timestamp:
24/05/07 14:13:53 (12 years ago)
Author:
pjkersha
Message:

ndg.security.server/ndg/security/server/AttAuthority/server-config.tac:
fix to caCertFilePathList input to SignatureHandler?. Correctly initialise
if not set.

ndg.security.server/ndg/security/server/AttAuthority/init.py:
Corrected error message text for where a user is not registered or no
mapping is available: ref. userId rather than AC holder DN to allow for the
case in DEWS where a userId distinct from a Proxy cert. DN is used.

ndg.security.test/ndg/security/test/AttAuthority/AttAuthorityClientTest.py:
added test8GetMappedAttCertStressTest test for WebSphere? integration tests.
It makes multiple calls with different ACs input to check for errors in
signature or verification.

ndg.security.test/ndg/security/test/AttAuthority/attAuthorityClientTest.cfg:
added additional config params for the above.

ndg.security.test/ndg/security/test/MyProxy/myProxyProperties.xml and
ndg.security.test/ndg/security/test/MyProxy/myProxyClientTest.cfg:
switched cert ID of test machine.

ndg.security.common/ndg/security/common/X509.py:

  • new X509Cert methods asDER and asPEM to convert to these formats.

toString now calls to asPEM

  • new class X509Stack to wrap M2Crypto.X509.X509_Stack. This includes an

extra method, verifyCertChain, to verify a chain of trust in the certs
contained in the stack.

  • standalone function, X509StackParseFromDER, wraps

M2Crypto.X509.new_stack_from_der

  • fix to X500DN class to enable correct parsing of proxy certificate DNs.

These have multiple CN entries. These are represented by changing the CN
dict entry to a tuple when initialised.

ndg.security.common/ndg/security/common/wsSecurity.py: changes to enable
handling of certificate chains in WSSE BinarySecurityToken? elements. This
will enable use of proxy certificates with signatures as their chain of
trust is proxy cert -> user cert -> CA cert rather than just cert -> CA cert.

types.

BinarySecurityToken? ValueType? to use

  • SignatureHandler?.init includes new signingCertChain keyword.
  • signingCertChain attribute of class enables setting of an X509Stack object

to assign to BinarySecurityToken?.

then Base 64 encode rather than converting into PEM and then having to
strip BEGIN CERT / END CERT delimiters.

to enable check of Canonicalization - REMOVE in future check in.

BinarySecurityToken? ValueTypes? - 'X509PKIPathv1', 'X509' and 'X509v3'

Location:
TI12-security/trunk/python
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python

    • Property svn:ignore
      •  

        old new  
        22dist 
        33ndg_security.egg-info 
         4.metadata 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/X509.py

    r2270 r2510  
    4646        if m2CryptoX509: 
    4747            self.__setM2CryptoX509(m2CryptoX509) 
    48                  
    49  
    50     def __str__(self): 
    51         """Override to display current certificate file setting.""" 
    52  
    53         if self.__filePath is None: 
    54             return '<X509 Cert>' 
    55         else: 
    56             return '<X509 Cert \'%s\'>' % self.__filePath 
    57  
    58  
    59     def __repr__(self): 
    60         """Override to display current certificate file setting."""  
    61         return str(self) 
    6248         
    6349 
     
    160146 
    161147         
    162     def toString(self, filePath=None): 
    163         """Return certificate file content as a string""" 
     148    def toString(self, **kw): 
     149        """Return certificate file content as a PEM format  
     150        string""" 
     151        self.asPEM(**kw) 
     152         
     153    def asPEM(self, filePath=None): 
     154        """Return certificate file content as a PEM format  
     155        string""" 
    164156         
    165157        # Check M2Crypto.X509 object has been instantiated - if not call 
     
    169161             
    170162        return self.__m2CryptoX509.as_pem() 
     163 
     164         
     165    def asDER(self): 
     166        """Return certificate file content in DER format""" 
     167         
     168        # Check M2Crypto.X509 object has been instantiated  
     169        assert(self.__m2CryptoX509) 
     170        return self.__m2CryptoX509.as_der() 
    171171 
    172172     
     
    224224         
    225225    def __getPubKey(self): 
    226         """Get public key""" 
     226        """Get public key 
     227         
     228        @return: RSA public key for certificate 
     229        @rtype: M2Crypto.RSA.RSA_pub""" 
    227230        if self.__m2CryptoX509 is None: 
    228231            return None 
     
    308311            raise X509CertError(msg) 
    309312         
    310  
     313    def verify(self, pubKey, **kw): 
     314        """Verify a certificate against the public key of the 
     315        issuer 
     316         
     317        @param pubKey: public key of cert that issued self 
     318        @type pubKey: M2Crypto.RSA.RSA_pub 
     319        @param **kw: keywords to pass to M2Crypto.X509.X509 - 
     320        'pkey' 
     321        @type: dict 
     322        @return: True if verifies OK, False otherwise 
     323        @rtype: bool 
     324        """ 
     325        return bool(self.__m2Crypto.verify(pubKey, **kw)) 
    311326 
    312327#_____________________________________________________________________________ 
     
    322337 
    323338 
    324  
    325  
     339#_____________________________________________________________________________ 
    326340def X509CertParse(x509CertTxt): 
    327341    """Create a new X509 certificate from string of file content""" 
     
    331345     
    332346    return x509Cert 
     347 
     348 
     349#_____________________________________________________________________________ 
     350class X509StackError(Exception): 
     351    """Error from X509Stack type""" 
     352     
     353#_____________________________________________________________________________ 
     354class X509Stack(object): 
     355    """Wrapper for M2Crypto X509_Stack""" 
     356     
     357    def __init__(self, m2X509Stack=None): 
     358        """Initialise from an M2Crypto stack object 
     359         
     360        @param m2X509Stack: M2Crypto X.509 stack object 
     361        @type m2X509Stack: M2Crypto.X509.X509_Stack""" 
     362         
     363        self.__m2X509Stack = m2X509Stack 
     364         
     365    def __len__(self): 
     366        """@return: length of stack 
     367        @rtype: int""" 
     368        return self.__m2X509Stack.__len__() 
     369 
     370    def __getitem__(self, idx): 
     371        """Index stack as an array 
     372        @param idx: stack index 
     373        @type idx: int 
     374        @return: X.509 cert object 
     375        @rtype: ndg.security.common.X509.X509Cert""" 
     376         
     377        return X509Cert(m2Crypto=self.__m2X509Stack.__getitem__(idx)) 
     378     
     379    def __iter__(self): 
     380        """@return: next element in stack 
     381        @rtype: ndg.security.common.X509.X509Cert""" 
     382        return X509Cert(m2Crypto=self.__m2X509Stack.__iter__()) 
     383 
     384    def push(self, x509Cert): 
     385        """Push an X509 certificate onto the stack. 
     386         
     387        @param x509Cert: X509 object. 
     388        @type x509Cert: M2Crypto.X509.X509 or 
     389        ndg.security.common.X509.X509Cert 
     390        @return: The number of X509 objects currently on the stack. 
     391        @rtype: int""" 
     392        if isinstance(x509Cert, M2Crypto.X509.X509): 
     393            return self.__m2X509Stack.push(x509Cert) 
     394        elif isinstance(x509Cert, X509Cert): 
     395            return self.__m2X509Stack.push(x509Cert.m2CryptoX509) 
     396        else: 
     397            raise X509StackError, "Expecting M2Crypto.X509.X509 or " + \ 
     398                "ndg.security.common.X509.X509Cert type" 
     399                 
     400    def pop(self): 
     401        """Pop a certificate from the stack. 
     402         
     403        @return: X509 object that was popped, or None if there is nothing 
     404        to pop. 
     405        @rtype: ndg.security.common.X509.X509Cert 
     406        """ 
     407        return X509Cert(m2CryptoX509=self.__m2X509Stack.pop()) 
     408 
     409 
     410    def asDER(self): 
     411        """Return the stack as a DER encoded string 
     412        @return: DER string 
     413        @rtype: string""" 
     414        return self.__m2X509Stack.as_der() 
     415 
     416 
     417    def verifyCertChain(self, x509Cert2Verify=None): 
     418        """Treat stack as a list of certificates in a chain of 
     419        trust.  Validate the signatures through to a single root issuer.   
     420 
     421        @param x509Cert2Verify: X.509 certificate to be verified default is 
     422        last in the stack 
     423        @type x509Cert2Verify: X509Cert 
     424        @return: stack in the order of issuer with root as the first element 
     425        @rtype: X509Stack""" 
     426         
     427        if x509Cert2Verify is None: 
     428            x509Cert2Verify = self[-1] 
     429 
     430        # Exit loop if all certs have been validated or if find a self  
     431        # signed cert. 
     432        nValidated = 0  
     433        while nValidated < len(self.__m2X509Stack):             
     434            issuerDN = x509Cert2Verify.issuer 
     435            issuerX509Cert = None 
     436             
     437            # Search for issuing certificate in stack 
     438            for x509Cert in self: 
     439                if x509Cert.dn == issuerDN: 
     440                    issuerX509Cert = x509Cert 
     441                    break 
     442                     
     443            if issuerX509Cert: 
     444                if not x509Cert2Verify.verify(issuerX509Cert.pubKey): 
     445                    X509CertError, 'Signature is invalid for cert. "%s"' % \ 
     446                                    x509Cert2Verify.dn 
     447            else: 
     448                raise X509StackError, 'No issuer cert. found for cert."%s"' %\ 
     449                                    x509Cert2Verify.dn 
     450               
     451            # Check for self signed certificate                                 
     452            if x509Cert2Verify.dn == issuerX509Cert.dn: 
     453                return 
     454            else: 
     455                x509Cert2Verify = issuerX509Cert 
     456                nValidated += 1 
     457                 
     458        raise X509CertError, 'Can\'t find issuer cert "%s" for cert "%s"' % \ 
     459                          (x509Cert2Verify.issuer, x509Cert2Verify.dn)   
     460 
     461 
     462#_____________________________________________________________________________ 
     463def X509StackParseFromDER(derString): 
     464    """Make a new stack from a DER string 
     465     
     466    @param derString: DER formatted X.509 stack data 
     467    @type derString: string 
     468    @return: new stack object 
     469    @rtype: X509Stack"""  
     470    return X509Stack(m2X509Stack=new_stack_from_der(derString)) 
    333471 
    334472 
     
    376514                            """ 
    377515        # Private key data 
    378         self.__dat = {  'CN':           '', 
     516        self.__dat = {  'CN':           '', 
    379517                        'OU':           '', 
    380518                        'O':            '', 
     
    386524                        'DC':           '', 
    387525                        'UID':          ''} 
    388  
     526     
    389527        dict.__init__(self) 
    390  
    391  
     528     
    392529        self.__separator = None 
    393530         
    394531        # Check for separator from input 
    395         if separator is not None: 
     532        if separator is not None: 
    396533            if not isinstance(separator, basestring): 
    397534                raise X500DNError("dn Separator must be a valid string") 
     
    407544         
    408545            # the argument is an x509 dn in m2crypto format 
    409             self.__dat['CN'] = m2CryptoX509Name.CN 
    410  
    411             # M2Crypto seems to default Email and L variables to None - in 
    412             # this case avoid making an assignment because it upsets calls to 
    413             # __cmp__() - None could be compared to '' conceptually the same 
    414             # but not equal progammatically 
    415             # 
    416             # P J Kershaw 13/06/05 
    417             if m2CryptoX509Name.L is not None: 
    418                 self.__dat['L'] = m2CryptoX509Name.L 
    419  
    420             self.__dat['O'] = m2CryptoX509Name.O 
    421             self.__dat['OU'] = m2CryptoX509Name.OU 
    422  
    423             if m2CryptoX509Name.Email is not None: 
    424                 self.__dat['EMAILADDRESS'] = m2CryptoX509Name.Email 
    425  
     546#            self.__dat['CN'] = m2CryptoX509Name.CN 
     547# 
     548#            # M2Crypto seems to default Email and L variables to None - in 
     549#            # this case avoid making an assignment because it upsets calls to 
     550#            # __cmp__() - None could be compared to '' conceptually the same 
     551#            # but not equal progammatically 
     552#            # 
     553#            # P J Kershaw 13/06/05 
     554#            if m2CryptoX509Name.L is not None: 
     555#                self.__dat['L'] = m2CryptoX509Name.L 
     556# 
     557#            self.__dat['O'] = m2CryptoX509Name.O 
     558#            self.__dat['OU'] = m2CryptoX509Name.OU 
     559# 
     560#            if m2CryptoX509Name.Email is not None: 
     561#                self.__dat['EMAILADDRESS'] = m2CryptoX509Name.Email 
     562            self.deserialise(m2CryptoX509Name.as_text()) 
     563             
    426564        elif dn is not None: 
    427565 
     
    567705        else: 
    568706            sDN = '' 
    569              
    570  
    571         sDN += separator.join(["%s=%s" % field \ 
    572                                 for field in self.__dat.items() if field[1]]) 
     707      
     708        dnList = [] 
     709        for (key, val) in self.__dat.items(): 
     710            if val: 
     711                if isinstance(val, tuple): 
     712                    dnList += [separator.join(["%s=%s" % (key, valSub) \ 
     713                                            for valSub in val])] 
     714                else: 
     715                    dnList += ["%s=%s" % (key, val)] 
     716                 
     717        sDN += separator.join(dnList) 
    573718                                 
    574719        return sDN 
     
    601746            # found e.g. a leading '/' in the DN would yield a null field 
    602747            # when split 
    603             keyVals = [field.split('=') for field in dnFields if field] 
     748             
     749            items = [field.split('=') for field in dnFields if field] 
    604750 
    605751            # Reset existing dictionary values 
     
    608754            # Strip leading and trailing space chars and convert into a 
    609755            # dictionary 
    610             parsedDN = dict([(keyVal[0].strip(), keyVal[1].strip()) \ 
    611                                                       for keyVal in keyVals]) 
    612  
     756#            parsedDN = dict([(keyVal[0].strip(), keyVal[1].strip()) \ 
     757#                                                      for keyVal in items]) 
     758            parsedDN = {} 
     759            for (key, val) in items: 
     760                key = key.strip() 
     761                if key in parsedDN: 
     762                    if isinstance(parsedDN[key], tuple): 
     763                        parsedDN[key] = tuple(list(parsedDN[key]) + [val])                     
     764                    else: 
     765                        parsedDN[key] = (parsedDN[key], val) 
     766                else: 
     767                    parsedDN[key] = val 
     768                 
    613769            # Copy matching DN fields 
    614770            for i in parsedDN.items(): 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/wsSecurity.py

    r2437 r2510  
    9999    @type __x509CertPat: regular expression pattern object 
    100100    @cvar __x509CertPat: regular expression for extracting the base64 encoded  
    101     portion of a PEM encoded X.509 certificate""" 
     101    portion of a PEM encoded X.509 certificate 
     102    @cvar binSecTokValType: supported ValueTypes for BinarySecurityToken 
     103    element in WSSE header 
     104    @type binSecTokValType: dict""" 
    102105     
    103106    __beginCert = '-----BEGIN CERTIFICATE-----\n' 
     
    107110                               re.S) 
    108111     
     112    binSecTokValType = { 
     113        "X509PKIPathv1": "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1", 
     114        "X509":          "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3", 
     115        "X509v3":        "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" 
     116    } 
    109117     
    110118    #_________________________________________________________________________ 
     
    114122                 signingCert=None, 
    115123                 signingCertFilePath=None,  
     124                 signingCertChain=None, 
    116125                 signingPriKey=None, 
    117126                 signingPriKeyFilePath=None,  
     
    133142                                                             'wsse',  
    134143                                                             'ec']}): 
    135  
     144        ''' 
     145        @reqBinSecTokValType: set the ValueType for the BinarySecurityToken 
     146        added to the WSSE header for a signed message.  See  
     147        __setReqBinSecTokValType method and binSecTokValType class variable 
     148        for options.  binSecTokValType determines whether signingCert or 
     149        signingCertChain attributes will be used.         
     150        @type binSecTokValType: string 
     151         
     152        @keyword verifyingCert: X.509 certificate used by verify method to 
     153        verify a message.  This argument can be omitted if the message to 
     154        be verified contains the X.509 certificate in the  
     155        BinarySecurityToken element.  In this case, the cert read from the 
     156        message will be assigned to the verifyingCert attribute. 
     157        @type verifyingCert: M2Crypto.X509.X509 /  
     158        ndg.security.common.X509.X509Cert 
     159         
     160        @keyword verifyingCertFilePath: alternative input to the above, pass  
     161        the file path to the certificate stored in a file 
     162        @type verifyingCertFilePath: string 
     163         
     164        @keyword signingCert: certificate associated with private key used to 
     165        sign a message.  The sign method will add this to the  
     166        BinarySecurityToken element of the WSSE header.  binSecTokValType 
     167        attribute must be set to 'X509' or 'X509v3' ValueTyep.  As an  
     168        alternative, use signingCertChain - see below... 
     169        @type signingCert: M2Crypto.X509.X509 /  
     170        ndg.security.common.X509.X509Cert 
     171         
     172        @keyword signingCertFilePath: alternative input to the above, pass  
     173        the file path to the certificate stored in a file 
     174        @type signingCertFilePath: string 
     175         
     176        @keyword signingCertChain: pass a list of certificates constituting a  
     177        chain of trust from the certificate used to verifying the signature  
     178        backward to the CA cert.  The CA cert need not be included.  To use  
     179        this option, reqBinSecTokValType must be set to the 'X509PKIPathv1' 
     180        ValueType 
     181        @type signingCertChain: list or tuple  
     182         
     183        @keyword signingPriKey: private key used to be sign method to sign 
     184        message 
     185        @type signingPriKey: M2Crypto.RSA. 
     186         
     187        @keyword signingPriKeyFilePath: equivalent to the above but pass  
     188        private key from PEM file 
     189        @type signingPriKeyFilePath: string 
     190         
     191        @keyword signingPriKeyPwd: password protecting private key.  Set / 
     192        default to None if there is no password. 
     193        @type signingPriKeyPwd: string or None 
     194         
     195        @keyword caCertDirPath: establish trust for signature verification.  
     196        This is a directory containing CA certificates.  These are used to 
     197        verify the certificate used to verify the message signature. 
     198        @type caCertDirPath: string 
     199         
     200        @keyword caCertFilePathList: same as above except pass in a list of 
     201        file paths instead of a single directory name. 
     202        @type caCertFilePathList: list or tuple 
     203         
     204        @keyword refC14nKw: dictionary of keywords to reference  
     205        Canonicalization.  Use 'unsuppressedPrefixes' keyword to set  
     206        unsuppressedPrefixes. 
     207        @type refC14nKw: dict 
     208         
     209        @keyword signedInfoC14nKw: keywords to Signed Info Canonicalization. 
     210        It uses the same format as refC14nKw above. 
     211        @type signedInfoC14nKw: dict 
     212        ''' 
    136213        # Set keywords for canonicalization of SignedInfo and reference  
    137214        # elements 
     
    146223        self.__setSigningCertFilePath(signingCertFilePath) 
    147224 
     225        if signingCertChain: 
     226            self.__setSigningCertChain(signingCertChain) 
     227             
    148228        # MUST be set before __setSigningPriKeyFilePath / __setSigningPriKey 
    149229        # are called 
     
    164244            self.caCertFilePathList = caCertFilePathList 
    165245         
    166  
    167     #_________________________________________________________________________ 
    168     def __checkC14nKw(self, Kw): 
     246                 
     247    #_________________________________________________________________________ 
     248    def __setReqBinSecTokValType(self, value): 
     249        """Set ValueType attribute for BinarySecurityToken used in a request 
     250          
     251        @type value: string 
     252        @param value: name space for BinarySecurityToken ValueType check 
     253        'binSecValueType' class variable for supported types.  Input can be  
     254        shortened to binSecValueType keyword if desired. 
     255        """ 
     256         
     257        if value in self.__class__.binSecValueType: 
     258            self.__reqBinSecTokValType = self.__class__.binSecValueType[value] 
     259  
     260        elif value in self.__class__.binSecValueType.values(): 
     261            self.__reqBinSecTokValType = value 
     262        else: 
     263            raise WSSecurityError, \ 
     264                'Request BinarySecurityToken ValueType "%s" not recognised' %\ 
     265                value 
     266             
     267         
     268    reqBinSecTokValType = property(fset=__setReqBinSecTokValType, 
     269         doc="ValueType attribute for BinarySecurityToken used in request") 
     270         
     271 
     272    #_________________________________________________________________________ 
     273    def __checkC14nKw(self, kw): 
    169274        """Check keywords for canonicalization in signing process - generic 
    170275        method for setting keywords for reference element and SignedInfo 
    171         element c14n""" 
     276        element c14n 
     277         
     278        @type kw: dict 
     279        @param kw: keyword used with ZSI.wstools.Utility.Canonicalization""" 
    172280         
    173281        # Check for dict/None - Set to None in order to use inclusive  
    174282        # canonicalization 
    175         if Kw is not None and not isinstance(Kw, dict): 
     283        if kw is not None and not isinstance(kw, dict): 
    176284            # Otherwise keywords must be a dictionary 
    177285            raise AttributeError, \ 
    178286                "Expecting dictionary type for reference c14n keywords" 
    179287                 
    180         elif Kw.get('unsuppressedPrefixes') and \ 
    181              not isinstance(Kw['unsuppressedPrefixes'], list) and \ 
    182              not isinstance(Kw['unsuppressedPrefixes'], tuple): 
     288        elif kw.get('unsuppressedPrefixes') and \ 
     289             not isinstance(kw['unsuppressedPrefixes'], list) and \ 
     290             not isinstance(kw['unsuppressedPrefixes'], tuple): 
    183291            raise AttributeError, \ 
    184292                'Expecting list or tuple of prefix names for "%s" keyword' % \ 
     
    187295                 
    188296    #_________________________________________________________________________ 
    189     def __setRefC14nKw(self, Kw): 
     297    def __setRefC14nKw(self, kw): 
    190298        """Set keywords for canonicalization of reference elements in the  
    191299        signing process""" 
    192         self.__checkC14nKw(Kw)                     
    193         self.__refC14nKw = Kw 
     300        self.__checkC14nKw(kw)                     
     301        self.__refC14nKw = kw 
    194302         
    195303    refC14nKw = property(fset=__setRefC14nKw, 
     
    198306                 
    199307    #_________________________________________________________________________ 
    200     def __setSignedInfoC14nKw(self, Kw): 
     308    def __setSignedInfoC14nKw(self, kw): 
    201309        """Set keywords for canonicalization of SignedInfo element in the  
    202310        signing process""" 
    203         self.__checkC14nKw(Kw)                     
    204         self.__signedInfoC14nKw = Kw 
     311        self.__checkC14nKw(kw)                     
     312        self.__signedInfoC14nKw = kw 
    205313         
    206314    signedInfoC14nKw = property(fset=__setSignedInfoC14nKw, 
     
    333441    signingCertFilePath = property(fset=__setSigningCertFilePath, 
    334442                   doc="File path X.509 cert. to include with signed message") 
     443 
     444     
     445    #_________________________________________________________________________ 
     446    def __setSigningCertChain(self, signingCertChain): 
     447        '''Signature set-up with "X509PKIPathv1" BinarySecurityToken  
     448        ValueType.  Use an X.509 Stack to store certificates that make up a  
     449        chain of trust to certificate used to verify a signature 
     450         
     451        @type signingCertChain: list or tuple 
     452        @param signingCertChain: list of file paths for CA certificates to 
     453        be used to verify certificate used to sign message''' 
     454         
     455        if not isinstance(signingCertChain, list) and \ 
     456           not isinstance(signingCertChain, tuple): 
     457            raise WSSecurityError, \ 
     458                        'Expecting a list or tuple for "signingCertChain"' 
     459         
     460        self.__signingCertChain = X509.X509_Stack() 
     461             
     462        for cert in signingCertChain: 
     463            self.__signingCertChain.push(self.__setCert(cert).m2CryptoX509) 
     464             
     465    signingCertChain = property(fset=__setSigningCertChain, 
     466               doc="Cert.s in chain of trust to cert. used to verify msg.") 
    335467 
    336468  
     
    409541    #_________________________________________________________________________ 
    410542    def __appendCAX509Stack(self, caCertList): 
    411         '''Store CA certificates in an X.509 Stack''' 
     543        '''Store CA certificates in an X.509 Stack 
     544         
     545        @param caCertList: list or tuple 
     546        @type caCertList: M2Crypto.X509.X509 certificate objects''' 
    412547         
    413548        if not self.caCertIsSet: 
     
    421556    def __setCAX509StackFromDir(self, caCertDir): 
    422557        '''Read CA certificates from directory and add them to the X.509 
    423         stack''' 
     558        stack 
     559         
     560        @param caCertDir: string 
     561        @type caCertDir: directory from which to read CA certificate files''' 
    424562         
    425563        # Mimic OpenSSL -CApath option which expects directory of CA files 
     
    447585        stack 
    448586         
    449         @type caCertFilePathList: string 
     587        @type caCertFilePathList: list or tuple 
    450588        @param caCertFilePathList: list of file paths for CA certificates to 
    451589        be used to verify certificate used to sign message''' 
     
    526664        } 
    527665 
    528         # Add X.509 cert as binary security token stripping BEGIN CERT and 
    529         # END CERT delimiters 
    530         x509CertStr = self.__class__.__x509CertPat.findall(\ 
    531                                            self.__signingCert.toString())[0] 
     666        # Add X.509 cert as binary security token 
     667        if self.__reqBinSecTokValType==self.binSecTokValType['X509PKIPathv1']: 
     668            binSecTokVal=base64.encodestring(self.__signingCertChain.as_der()) 
     669        else: 
     670            # Assume X.509 / X.509 vers 3 
     671            binSecTokVal = base64.encodestring(self.__signingCert.asDER()) 
    532672 
    533673        soapWriter._header.setNamespaceAttribute('wsse', OASIS.WSSE) 
     
    559699                                                     'BinarySecurityToken') 
    560700         
    561         # Value and encoding types to suite WebSphere WSSE implementation 
    562         valueType = \ 
    563 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509" 
    564         binSecTokElem.node.setAttribute('ValueType', valueType) 
     701        # Value type can be any be any one of those supported via  
     702        # binSecTokValType 
     703        binSecTokElem.node.setAttribute('ValueType',  
     704                                        self.__reqBinSecTokValType) 
    565705 
    566706        encodingType = \ 
     
    571711        binSecTokElem.node.setAttribute('wsu:Id', "binaryToken") 
    572712 
    573         binSecTokElem.createAppendTextNode(x509CertStr) 
     713        binSecTokElem.createAppendTextNode(binSecTokVal) 
    574714 
    575715         
     
    691831 
    692832        # Calculate digest of SignedInfo 
    693         # 
    694         # TODO: check status for strip call - almost certainly wrong and not 
    695         # needed 
    696         signedInfoDigestValue = sha(c14nSignedInfo).digest()#.strip() 
     833        signedInfoDigestValue = sha(c14nSignedInfo).digest() 
    697834         
    698835        # Sign using the private key and base 64 encode the result 
     
    839976        # Canonicalize the SignedInfo node and take digest 
    840977        c14nSignedInfo = Canonicalize(signedInfoNode, **signedInfoC14nKw)  
    841                 
    842         # TODO: strip() call? - almost certainly wrong - leave out!        
    843         signedInfoDigestValue = sha(c14nSignedInfo).digest()#.strip() 
     978        hdrNode = Reader().fromString(Canonicalize(parsedSOAP.header)) 
     979        hdrCtxt = Context(hdrNode, processorNss=processorNss) 
     980        signedInfoNode2 = xpath.Evaluate('//ds:SignedInfo', 
     981                                        contextNode=hdrNode,  
     982                                        context=hdrCtxt)[0] 
     983        c14nSignedInfo2 = Canonicalize(signedInfoNode, **signedInfoC14nKw) 
     984        signedInfoDigestValue2 = sha(c14nSignedInfo2).digest() 
     985                               
     986        signedInfoDigestValue = sha(c14nSignedInfo).digest() 
    844987         
    845988        # Get the signature value in order to check against the digest just 
     
    8701013            pass  
    8711014         
    872         #import pdb;pdb.set_trace()         
     1015        import pdb;pdb.set_trace()         
    8731016        if binSecTokNode: 
    8741017            try: 
    8751018                x509CertTxt=str(binSecTokNode.childNodes[0]._get_nodeValue()) 
    8761019                 
    877                 # Convert parsed cert text into PEM form that can be read 
    878                 # by X.509 string parser 
    879                 # 
    880                 # Check for line breaks at 64th byte as expected for PEM  
    881                 # encoding 
    882                 if x509CertTxt[64] != "\n": 
    883                     # Check for other whitespace and reomve  
    884                     # Expecting cert split into lines of length 64 bytes 
    885                     x509CertTxt = re.sub('\s', '', x509CertTxt) 
     1020                valueType = binSecTokNode.getAttributeNode("ValueType").value 
     1021                if valueType in (self.__class__.binSecTokValType['X509v3'], 
     1022                                 self.__class__.binSecTokValType['X509']): 
     1023                 
     1024                    # Convert parsed cert text into PEM form that can be read 
     1025                    # by X.509 string parser 
     1026                    # 
     1027                    # Check for line breaks at 64th byte as expected for PEM  
     1028                    # encoding 
     1029                    if x509CertTxt[64] != "\n": 
     1030                        # Check for other whitespace and reomve  
     1031                        # Expecting cert split into lines of length 64 bytes 
     1032                        x509CertTxt = re.sub('\s', '', x509CertTxt) 
     1033                         
     1034                        # Split into lines of length 64 
     1035                        x509CertSpl = re.split('(.{64})', x509CertTxt) 
     1036                        x509CertTxt = '\n'.join([i for i in x509CertSpl if i]) 
     1037                         
     1038                    b64EncX509Cert = self.__class__.__beginCert+x509CertTxt+\ 
     1039                             self.__class__.__endCert 
     1040                    self.__setVerifyingCert(b64EncX509Cert) 
    8861041                     
    887                     # Split into lines of length 64 
    888                     x509CertSpl = re.split('(.{64})', x509CertTxt) 
    889                     x509CertTxt = '\n'.join([i for i in x509CertSpl if i]) 
     1042                elif valueType == \ 
     1043                    self.__class__.binSecTokValType['X509PKIPathv1']: 
    8901044                     
    891                 b64EncX509Cert = self.__class__.__beginCert + x509CertTxt + \ 
    892                          self.__class__.__endCert 
    893                               
    894                 self.__setVerifyingCert(b64EncX509Cert) 
     1045                    derString = base64.decodestring(x509CertTxt) 
     1046                    x509Stack=X509.new_stack_from_der(derString) 
     1047                     
     1048                    # TODO: Check ordering - is the first off the stack the 
     1049                    # one to use to verify the message? 
     1050                    m2CryptoX509Cert = x509Stack.pop() 
     1051                    self.__verifyCert = \ 
     1052                        X509Cert(m2CryptoX509=m2CryptoX509Cert) 
     1053                else: 
     1054                    raise WSSecurityError, "BinarySecurityToken ValueType " +\ 
     1055                        'attribute is not recognised: "%s"' % valueType 
     1056                                
    8951057            except Exception, e: 
    8961058                raise VerifyError, "Error extracting BinarySecurityToken " + \ 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/AttAuthority/__init__.py

    r2420 r2510  
    481481            else: 
    482482                raise AttAuthorityAccessDenied, \ 
    483                     "User \"%s\" is not registered " % attCert['holder'] + \ 
    484                     "and no external attribute certificate is available " + \ 
    485                     "to make a mapping." 
     483                    "User \"%s\" is not registered and no " % userId + \ 
     484                    "external attribute certificate is available to make " + \ 
     485                    "a mapping." 
    486486 
    487487 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/AttAuthority/server-config.tac

    r2401 r2510  
    121121    # Initialise WS-Security signature handler passing Attribute Authority 
    122122    # public and private keys 
     123    caCertFile = srv.aa.get('caCertFile') 
     124    if caCertFile: 
     125        caCertFilePathList = (caCertFile,)  
     126    else: 
     127                caCertFilePathList = None 
     128     
    123129    WSSecurityHandler.signatureHandler = SignatureHandler(\ 
    124                                 verifyingCertFilePath=srv.aa['clntCertFile'], 
    125                                 signingCertFilePath=srv.aa['certFile'], 
    126                                 signingPriKeyFilePath=srv.aa['keyFile'], 
    127                                 signingPriKeyPwd=srv.aa['keyPwd'], 
    128                                 caCertFilePathList=(srv.aa['caCertFile'],)) 
     130                                verifyingCertFilePath=srv.aa['clntCertFile'], 
     131                                signingCertFilePath=srv.aa['certFile'], 
     132                                signingPriKeyFilePath=srv.aa['keyFile'], 
     133                                signingPriKeyPwd=srv.aa['keyPwd'], 
     134                                caCertFilePathList=caCertFilePathList) 
    129135 
    130136# Add Service to Attribute Authority branch 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/AttAuthority/AttAuthorityClientTest.py

    r2420 r2510  
    205205                    self.cfg['test7GetMappedAttCert']['mappedattcertfilepath'] 
    206206        attCert.write() 
    207   
    208   
     207         
     208         
     209    def test8GetMappedAttCertStressTest(self):         
     210        """test8GetMappedAttCertStressTest: Request mapped attribute certificate from  
     211        NDG Attribute Authority Web Service.""" 
     212     
     213        # Read user Certificate into a string ready for passing via WS 
     214        try: 
     215            userCertFilePath = \ 
     216    self.cfg['test8GetMappedAttCertStressTest'].get('issuingusercertfilepath') 
     217            userCertTxt = open(userCertFilePath, 'r').read() 
     218         
     219        except TypeError: 
     220            # No issuing cert set 
     221            userCertTxt = None 
     222                 
     223        except IOError, ioErr: 
     224            raise "Error reading certificate file \"%s\": %s" % \ 
     225                                    (ioErr.filename, ioErr.strerror) 
     226 
     227        try: 
     228            if self.cfg['test8GetMappedAttCertStressTest'].get('userprikeypwd') is None: 
     229                userPriKeyPwd = getpass.getpass(\ 
     230                            prompt="\nsetUp - client private key password: ") 
     231            else: 
     232                userPriKeyPwd = \ 
     233            self.cfg['test8GetMappedAttCertStressTest'].get('userprikeypwd') 
     234        except KeyboardInterrupt: 
     235            sys.exit(0) 
     236 
     237        # List of CA certificates for use in validation of certs used in 
     238        # signature for server reponse 
     239        try: 
     240            caCertFilePathList=self.cfg['setUp']['cacertfilepathlist'].split() 
     241        except: 
     242            caCertFilePathList = [] 
     243        
     244        # Make client to site B Attribute Authority 
     245        clnt = AttAuthorityClient(\ 
     246uri=self.cfg['test8GetMappedAttCertStressTest']['uri'],  
     247signingCertFilePath=self.cfg['test8GetMappedAttCertStressTest'].get('usercertfilepath'), 
     248signingPriKeyFilePath=self.cfg['test8GetMappedAttCertStressTest'].get('userprikeyfilepath'), 
     249signingPriKeyPwd=userPriKeyPwd, 
     250caCertFilePathList=caCertFilePathList, 
     251tracefile=sys.stderr) 
     252 
     253        acFilePathList = \ 
     254self.cfg['test8GetMappedAttCertStressTest']['userattcertfilepathlist'].split() 
     255 
     256        for acFilePath in acFilePathList: 
     257            try: 
     258                userAttCert = AttCertRead(acFilePath) 
     259                 
     260            except IOError, ioErr: 
     261                raise "Error reading attribute certificate file \"%s\": %s" %\ 
     262                                        (ioErr.filename, ioErr.strerror) 
     263         
     264            # Make attribute certificate request 
     265            try: 
     266                attCert = clnt.getAttCert(userCert=userCertTxt, 
     267                                          userAttCert=userAttCert) 
     268            except Exception, e: 
     269                msgFile = open(outFilePfx+".msg", 'w') 
     270                msgFile.write('Failed for "%s": %s\n' % (acFilePath, e)) 
     271              
    209272#_____________________________________________________________________________        
    210273class AttAuthorityClientTestSuite(unittest.TestSuite): 
     
    219282                    "test6GetAttCertWithUserIdSet", 
    220283                    "test7GetMappedAttCert", 
     284                    "test8GetMappedAttCertStressTest", 
    221285                  )) 
    222286        unittest.TestSuite.__init__(self, map) 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/AttAuthority/attAuthorityClientTest.cfg

    r2420 r2510  
    1010# ! SiteBMapConfig.xml trusted site A aaURI setting must agree with this  
    1111# setting for test6GetMappedAttCert 
    12 uri = http://localhost:5000/AttributeAuthority 
     12#uri = http://localhost:5000/AttributeAuthority 
    1313#uri = https://localhost:5000/AttributeAuthority 
    1414#uri = http://glue.badc.rl.ac.uk/DEWS/MarineDataServer/AttributeAuthority 
     
    5353 
    5454[test6GetAttCertWithUserIdSet] 
    55 userId = dewsPortalUser 
     55userId = system 
    5656issuingusercertfilepath = ./aa-cert.pem 
    5757 
     
    7676mappedAttCertFilePath = ./mapped-ac.xml 
    7777 
     78[test8GetMappedAttCertStressTest] 
     79# Comment out to set for no signature handling 
     80userprikeypwd =  
     81usercertfilepath = ./aa-cert.pem 
     82userprikeyfilepath = ./aa-key.pem 
    7883 
     84# Space separated list of CA certificate files used to verify certificate used 
     85# in message signature 
     86cacertfilepathlist = ./cacert.pem 
     87 
     88uri = http://localhost:5000/AttributeAuthority 
     89userAttCertFilePathList = ../AttCert/badSignature2.xml ../AttCert/badSignature.xml ../AttCert/badSignature3.xml 
     90 
     91 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/MyProxy/myProxyClientTest.cfg

    r2420 r2510  
    1111 
    1212[test1Store] 
    13 #username: sstljakTestUser 
    14 username: gabriel 
     13username: raphaelTest 
     14#username: gabriel 
    1515passphrase: 
    16 certFile: ./userCert.pem 
    17 keyFile: ./userKey.pem 
    18 ownerCertFile: ./userCert.pem 
    19 ownerKeyFile: ./userKey.pem 
     16certFile: ./user-cert.pem 
     17keyFile: ./user-key.pem 
     18ownerCertFile: ./user-cert.pem 
     19ownerKeyFile: ./user-key.pem 
    2020ownerPassphrase: 
    2121 
    2222[test2GetDelegation] 
    23 #username: sstljakTestUser 
    24 username: gabriel 
     23username: raphaelTest 
     24#username: gabriel 
    2525passphrase: 
    2626 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/MyProxy/myProxyProperties.xml

    r2420 r2510  
    1515        CN is usually set to "host/<fqdn>".  Delete this element and set from  
    1616        MYPROXY_SERVER_DN environment variable if prefered 
    17         <serverDN>/O=NDG/OU=sstljak/CN=host/sstljak</serverDN> 
     17        <serverDN>/O=NDG/OU=Raphael/CN=raphael</serverDN> 
    1818        --> 
    1919        <!-- 
Note: See TracChangeset for help on using the changeset viewer.