Changeset 5372


Ignore:
Timestamp:
09/06/09 16:41:23 (10 years ago)
Author:
pjkersha
Message:

Added code for validation of OpenID Provider by Relying Party using M2Crypto.m2urllib2 for SSL peer authN

Location:
TI12-security/trunk/python
Files:
6 added
2 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/Tests/m2Crypto/test_m2urllib2.py

    r5363 r5372  
    33from M2Crypto.m2urllib2 import HTTPSHandler 
    44from M2Crypto import SSL 
     5from M2Crypto.X509 import X509_Store_Context 
    56 
    67class M2Urllib2Fetcher(Urllib2Fetcher): 
     
    2930        req = urllib2.Request(url, data=body, headers=headers) 
    3031        try: 
     32            def verifyCallback(arg, x509StoreCtx): 
     33                '''@type x509StoreCtx: M2Crypto.X509_Store_Context 
     34                ''' 
     35                x509Cert = x509StoreCtx.get_current_cert() 
     36                x509Cert.get_subject() 
     37                x509CertChain = x509StoreCtx.get1_chain() 
     38                for cert in x509CertChain: 
     39                    subject = cert.get_subject() 
     40                    dn = subject.as_text() 
     41                    print dn 
     42                     
     43                return True 
     44                 
    3145            ctx = SSL.Context() 
    3246            caFilePath = '/home/pjkersha/Documents/BADC/Certificates/Cybertrust/cybertrustCombo.crt' 
    3347#            ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) 
    34             ctx.set_verify(SSL.verify_peer, 9) 
     48            ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert,  
     49                           9,  
     50                           callback=verifyCallback) 
    3551            ctx.load_verify_locations(cafile=caFilePath) 
    3652#            ctx.load_cert(certfile,  
     
    5066 
    5167        return resp 
     68 
     69class M2Urllib2Fetcher2(Urllib2Fetcher): 
     70    """M2Crypto urllib2 based fetcher to enable SSL based authentication of  
     71    peer 
     72    """ 
     73 
     74    def fetch(self, url, body=None, headers=None): 
     75         
     76        # Use parent class behaviour for non-SSL connections 
     77        if url.startswith('http://'): 
     78            return super(M2Urllib2Fetcher, self).fetch(url,  
     79                                                       body=body,  
     80                                                       headers=headers) 
     81             
     82        if not _allowedURL(url): 
     83            raise ValueError('Bad URL scheme: %r' % (url,)) 
     84 
     85        if headers is None: 
     86            headers = {} 
     87 
     88        headers.setdefault( 
     89            'User-Agent', 
     90            "%s Python-urllib/%s" % (USER_AGENT, urllib2.__version__,)) 
     91 
     92        req = urllib2.Request(url, data=body, headers=headers) 
     93        try: 
     94            def verifyCallback(arg, x509StoreCtx): 
     95                '''@type x509StoreCtx: M2Crypto.X509_Store_Context 
     96                ''' 
     97                x509Cert = x509StoreCtx.get_current_cert() 
     98                x509Cert.get_subject() 
     99                x509CertChain = x509StoreCtx.get1_chain() 
     100                for cert in x509CertChain: 
     101                    subject = cert.get_subject() 
     102                    dn = subject.as_text() 
     103                    print dn 
     104                     
     105                return True 
     106                 
     107            ctx = SSL.Context() 
     108            caFilePath = '/home/pjkersha/Documents/BADC/Certificates/Cybertrust/cybertrustCombo.crt' 
     109#            ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) 
     110            ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert,  
     111                           9,  
     112                           callback=verifyCallback) 
     113            ctx.load_verify_locations(cafile=caFilePath) 
     114#            ctx.load_cert(certfile,  
     115#                          keyfile=None,  
     116#                          callback=util.passphrase_callback) 
     117            httpsHandler = HTTPSHandler(ssl_context=ctx) 
     118            f = httpsHandler.https_open(req) 
     119            try: 
     120                return self._makeResponse(f) 
     121            finally: 
     122                f.close() 
     123        except urllib2.HTTPError, why: 
     124            try: 
     125                return self._makeResponse(why) 
     126            finally: 
     127                why.close() 
     128 
     129        return resp 
     130 
     131def installOpener(): 
     132    def verifyCallback(preVerifyOK, x509StoreCtx): 
     133        '''callback function used to control the behaviour when the  
     134        SSL_VERIFY_PEER flag is set 
     135         
     136        http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html 
     137         
     138        @type preVerifyOK: int 
     139        @param preVerifyOK: If a verification error is found, this parameter  
     140        will be set to 0 
     141        @type x509StoreCtx: M2Crypto.X509_Store_Context 
     142        @param x509StoreCtx: locate the certificate to be verified and perform  
     143        additional verification steps as needed 
     144        @rtype: int 
     145        @return: controls the strategy of the further verification process.  
     146        - If verify_callback returns 0, the verification process is immediately  
     147        stopped with "verification failed" state. If SSL_VERIFY_PEER is set,  
     148        a verification failure alert is sent to the peer and the TLS/SSL  
     149        handshake is terminated.  
     150        - If verify_callback returns 1, the verification process is continued.  
     151        If verify_callback always returns 1, the TLS/SSL handshake will not be  
     152        terminated with respect to verification failures and the connection  
     153        will be established. The calling process can however retrieve the error 
     154        code of the last verification error using SSL_get_verify_result(3) or  
     155        by maintaining its own error storage managed by verify_callback. 
     156        ''' 
     157        if preVerifyOK == 0: 
     158            # Something is wrong with the certificate don't bother proceeding 
     159            # any further 
     160            return preVerifyOK 
     161         
     162        x509Cert = x509StoreCtx.get_current_cert() 
     163        x509Cert.get_subject() 
     164        x509CertChain = x509StoreCtx.get1_chain() 
     165        for cert in x509CertChain: 
     166            subject = cert.get_subject() 
     167            dn = subject.as_text() 
     168            print dn 
     169             
     170        # If all is OK preVerifyOK will be 1.  Return this to the caller to 
     171        # that it's OK to proceed 
     172        return preVerifyOK 
     173         
     174    ctx = SSL.Context() 
     175#    caFilePath = '/home/pjkersha/Documents/BADC/Certificates/Cybertrust/cybertrustCombo.crt' 
     176    caDirPath = '/home/pjkersha/workspace/ndg.security.python/ndg.security.test/ndg/security/test/config/ca' 
     177    ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert,  
     178                   9,  
     179                   callback=verifyCallback) 
     180#    ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert, 1) 
     181 
     182    ctx.load_verify_locations(capath=caDirPath) 
     183#    ctx.load_cert(certfile,  
     184#                  keyfile=None,  
     185#                  callback=util.passphrase_callback) 
     186 
     187    from M2Crypto.m2urllib2 import build_opener 
     188    urllib2.install_opener(build_opener(ssl_context=ctx)) 
    52189     
    53190if __name__ == "__main__": 
    54     fetcher = M2Urllib2Fetcher() 
    55     resp = fetcher.fetch('https://ndg3beta.badc.rl.ac.uk/openid') 
    56     print resp 
     191    installOpener() 
     192    fetcher = Urllib2Fetcher() 
     193#    fetcher = M2Urllib2Fetcher() 
     194#    resp = fetcher.fetch('https://ndg3beta.badc.rl.ac.uk/openid') 
     195    resp = fetcher.fetch('https://localhost/openid') 
     196    print resp.body 
  • TI12-security/trunk/python/ndg.security.common/ndg/security/common/utils/classfactory.py

    r5330 r5372  
    3434    else: 
    3535        _moduleName = moduleName 
    36             
     36     
     37    log.debug("Importing class %s ..." % className)  
     38       
    3739    module = __import__(_moduleName) 
    3840    components = _moduleName.split('.') 
     
    7274    ''' 
    7375 
    74     log.debug("Instantiating class '%s'" % className) 
    7576     
    7677    # ensure that classproperties is a dict - NB, it may be passed in as a null 
     
    113114 
    114115    # Instantiate class 
     116    log.debug("Instantiating class '%s'" % importedClass.__name__) 
    115117    try: 
    116118        if classArgs: 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/relyingparty/__init__.py

    r5355 r5372  
    1717import urllib # decode quoted URI in query arg 
    1818from urlparse import urlsplit, urlunsplit 
     19 
    1920 
    2021from paste.request import parse_querystring, parse_formvars 
     
    4243    middleware to return to following OpenID sign in. 
    4344    ''' 
     45    sslPropertyDefaults = { 
     46        'certFilePath': '', 
     47        'priKeyFilePath': None, 
     48        'priKeyPwd': None, 
     49        'caCertDirPath': None, 
     50        'providerWhitelistFilePath': None 
     51    } 
    4452    propertyDefaults = { 
     53        'sslPeerCertAuthN': True, 
    4554        'signinInterfaceMiddlewareClass': None, 
    4655        'baseURL': '', 
    4756        'sessionKey': 'beaker.session.ndg.security' 
    4857    } 
     58    propertyDefaults.update(sslPropertyDefaults) 
    4959    propertyDefaults.update(NDGSecurityMiddlewareBase.propertyDefaults) 
    5060     
    5161    def __init__(self, app, global_conf, prefix='openid.relyingparty.',  
    5262                 **app_conf): 
    53         """Add AuthKit and Beaker middleware dependencies to WSGI stack 
     63        """Add AuthKit and Beaker middleware dependencies to WSGI stack and  
     64        set-up SSL Peer Certificate Authentication of OpenID Provider set by 
     65        the user 
    5466         
    5567        @type app: callable following WSGI interface signature 
     
    6476        format of propertyDefaults class variable"""     
    6577 
    66              
     78        # Default to set SSL peer cert authN where no flag is set in the config 
     79        # To override, it must explicitly be set to False in the config 
     80        if app_conf.get('sslPeerCertAuthN', 'true').lower() != 'false': 
     81             
     82            # Set parameters for SSL client connection to OpenID Provider Yadis 
     83            # retrieval URI 
     84            for paramName in self.__class__.sslPropertyDefaults: 
     85                paramDefault = self.__class__.sslPropertyDefaults[paramName] 
     86                setattr(self,  
     87                        paramName,  
     88                        app_conf.get(prefix+paramName, paramDefault)) 
     89                 
     90            self._initSSLPeerAuthN() 
     91         
    6792        # Check for sign in template settings 
    6893        if prefix+'signinInterfaceMiddlewareClass' in app_conf: 
     
    228253        return self._app(environ, _start_response) 
    229254 
     255    def _initSSLPeerAuthN(self): 
     256        """Initialise M2Crypto based urllib2 HTTPS handler to enable SSL  
     257        authentication of OpenID Providers""" 
     258        log.info("Setting parameters for SSL Authentication of OpenID " 
     259                 "Provider ...") 
     260         
     261        def verifySSLPeerCertCallback(preVerifyOK, x509StoreCtx): 
     262            '''SSL verify callback function used to control the behaviour when  
     263            the SSL_VERIFY_PEER flag is set 
     264             
     265            http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html 
     266             
     267            @type preVerifyOK: int 
     268            @param preVerifyOK: If a verification error is found, this parameter  
     269            will be set to 0 
     270            @type x509StoreCtx: M2Crypto.X509_Store_Context 
     271            @param x509StoreCtx: locate the certificate to be verified and perform  
     272            additional verification steps as needed 
     273            @rtype: int 
     274            @return: controls the strategy of the further verification process.  
     275            - If verify_callback returns 0, the verification process is immediately  
     276            stopped with "verification failed" state. If SSL_VERIFY_PEER is set,  
     277            a verification failure alert is sent to the peer and the TLS/SSL  
     278            handshake is terminated.  
     279            - If verify_callback returns 1, the verification process is continued.  
     280            If verify_callback always returns 1, the TLS/SSL handshake will not be  
     281            terminated with respect to verification failures and the connection  
     282            will be established. The calling process can however retrieve the error 
     283            code of the last verification error using SSL_get_verify_result or  
     284            by maintaining its own error storage managed by verify_callback. 
     285            ''' 
     286            if preVerifyOK == 0: 
     287                # Something is wrong with the certificate don't bother proceeding 
     288                # any further 
     289                log.error("verifyCallback: pre-verify OK flagged an error " 
     290                          "with the peer certificate, returning error state " 
     291                          "to caller ...") 
     292                return preVerifyOK 
     293             
     294            x509Cert = x509StoreCtx.get_current_cert() 
     295            x509Cert.get_subject() 
     296            x509CertChain = x509StoreCtx.get1_chain() 
     297            for cert in x509CertChain: 
     298                subject = cert.get_subject() 
     299                dn = subject.as_text() 
     300                log.debug("verifyCallback: dn = %r", dn) 
     301                 
     302            # If all is OK preVerifyOK will be 1.  Return this to the caller to 
     303            # that it's OK to proceed 
     304            return preVerifyOK 
     305            
     306        # Imports here so that if SSL Auth is not set the app will not need  
     307        # these packages  
     308        import urllib2 
     309        from M2Crypto import SSL 
     310        from M2Crypto.m2urllib2 import build_opener 
     311        from openid.fetchers import setDefaultFetcher, Urllib2Fetcher 
     312         
     313        # Create a context specifying verification of the peer but with an 
     314        # additional callback function 
     315        ctx = SSL.Context() 
     316        ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert,  
     317                       9,  
     318                       callback=verifySSLPeerCertCallback) 
     319 
     320        # Point to a directory containing CA certificates.  These must be named 
     321        # in their hashed form as expected by the OpenSSL API.  Use c_rehash 
     322        # utility to generate names or in the CA directory: 
     323        # 
     324        # $ for i in *.crt *.pem; do ln -s $i $(openssl x509 -hash -noout -in $i).0; done 
     325        ctx.load_verify_locations(capath=self.caCertDirPath) 
     326         
     327        # Load this client's certificate and private key to enable the peer  
     328        # OpenID Provider to authenticate it 
     329        ctx.load_cert(self.certFilePath,  
     330                      keyfile=self.priKeyFilePath,  
     331                      callback=lambda *arg, **kw: self.priKeyPwd) 
     332     
     333        setDefaultFetcher(Urllib2Fetcher()) 
     334         
     335        log.debug("Adding the M2Crypto SSL handler to urllib2's list of " 
     336                  "handlers...") 
     337        urllib2.install_opener(build_opener(ssl_context=ctx)) 
    230338     
    231339class SigninInterfaceError(Exception): 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securityservices.ini

    r5315 r5372  
    203203openid.relyingparty.sessionKey = beaker.session 
    204204openid.relyingparty.baseURL = %(authkit.openid.baseurl)s 
     205openid.relyingparty.certFilePath = %(testConfigDir)s/pki/localhost.crt 
     206openid.relyingparty.priKeyFilePath = %(testConfigDir)s/pki/localhost.key 
     207openid.relyingparty.priKeyPwd =  
     208openid.relyingparty.caCertDirPath = %(testConfigDir)s/ca 
     209openid.relyingparty.providerWhitelistFilePath = 
    205210#openid.relyingparty.signinInterfaceMiddlewareClass = ndg.security.test.integration.openid.openidrelyingparty.signin_interface.CombinedSigninAndLoginInterface 
    206211#openid.relyingparty.signinInterface.templatePackage = ndg.security.test.integration.openid.openidrelyingparty.templates 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/sslclientauthnmiddleware/localhost.crt

    r4609 r5372  
    22    Data: 
    33        Version: 3 (0x2) 
    4         Serial Number: 252 (0xfc) 
     4        Serial Number: 263 (0x107) 
    55        Signature Algorithm: md5WithRSAEncryption 
    66        Issuer: O=NDG, OU=BADC, CN=Test CA 
    77        Validity 
    8             Not Before: Dec 11 21:33:25 2008 GMT 
    9             Not After : Dec 11 21:33:25 2009 GMT 
     8            Not Before: Jun  9 09:28:37 2009 GMT 
     9            Not After : Jun  9 09:28:37 2010 GMT 
    1010        Subject: C=UK, ST=Oxfordshire, O=BADC, OU=Security, CN=localhost 
    1111        Subject Public Key Info: 
     
    3636                SSL Client, SSL Server, S/MIME, Object Signing 
    3737    Signature Algorithm: md5WithRSAEncryption 
    38         34:a0:99:74:f0:9d:2e:81:7d:a5:2c:d9:72:8d:cb:b1:1f:56: 
    39         ec:97:7d:1c:69:05:db:03:47:9a:ba:32:9d:ec:f9:a3:cf:eb: 
    40         d3:a9:e3:c4:8d:8d:7c:df:60:54:2e:35:8c:8c:30:a5:df:bb: 
    41         33:46:59:04:07:a8:00:0b:18:86:3d:8c:8e:e6:c6:0c:54:f1: 
    42         9e:34:5e:68:07:c5:78:1b:f4:40:ad:1b:70:99:dc:61:3b:e2: 
    43         4a:b2:81:c3:2c:bf:92:48:b6:ab:4b:4c:fd:f3:9d:25:d4:f9: 
    44         2f:3a:e7:47:0f:d7:f7:4f:4d:11:f0:8e:8f:cb:73:ee:18:8e: 
    45         10:7f 
     38        8b:8c:45:03:bb:90:4a:70:54:28:69:b7:02:3e:50:95:12:10: 
     39        ef:c7:d4:48:c2:56:be:7a:4d:0a:6e:28:9f:07:4d:71:8c:01: 
     40        fc:e0:e0:dd:6e:ef:5a:d7:b0:0c:df:14:be:af:e4:20:11:4c: 
     41        ca:9b:4b:ae:ce:4b:0f:1f:46:b0:57:74:e0:86:ff:94:b2:27: 
     42        0b:2a:7b:e9:09:d5:2b:72:14:fe:99:5c:66:12:87:31:2f:e0: 
     43        7b:5c:47:b5:52:09:bb:18:09:d8:0a:c2:95:8e:bf:23:e6:ac: 
     44        0d:ea:48:19:c8:11:e6:8f:da:10:d2:cd:a2:de:72:e7:b1:75: 
     45        c0:d8 
    4646-----BEGIN CERTIFICATE----- 
    47 MIICmDCCAgGgAwIBAgICAPwwDQYJKoZIhvcNAQEEBQAwLzEMMAoGA1UEChMDTkRH 
    48 MQ0wCwYDVQQLEwRCQURDMRAwDgYDVQQDEwdUZXN0IENBMB4XDTA4MTIxMTIxMzMy 
    49 NVoXDTA5MTIxMTIxMzMyNVowWTELMAkGA1UEBhMCVUsxFDASBgNVBAgTC094Zm9y 
     47MIICmDCCAgGgAwIBAgICAQcwDQYJKoZIhvcNAQEEBQAwLzEMMAoGA1UEChMDTkRH 
     48MQ0wCwYDVQQLEwRCQURDMRAwDgYDVQQDEwdUZXN0IENBMB4XDTA5MDYwOTA5Mjgz 
     49N1oXDTEwMDYwOTA5MjgzN1owWTELMAkGA1UEBhMCVUsxFDASBgNVBAgTC094Zm9y 
    5050ZHNoaXJlMQ0wCwYDVQQKEwRCQURDMREwDwYDVQQLEwhTZWN1cml0eTESMBAGA1UE 
    5151AxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOCU 
     
    5656Rx0ZaEBiWROL6+iJZCDso7fnso+Y8mS0qm7Q8XP86u0ZGWeYEfWVynYLx0M1PFMj 
    5757tWewtSZZ0cU+StFw3QIDAQABoxUwEzARBglghkgBhvhCAQEEBAMCBPAwDQYJKoZI 
    58 hvcNAQEEBQADgYEANKCZdPCdLoF9pSzZco3LsR9W7Jd9HGkF2wNHmroynez5o8/r 
    59 06njxI2NfN9gVC41jIwwpd+7M0ZZBAeoAAsYhj2MjubGDFTxnjReaAfFeBv0QK0b 
    60 cJncYTviSrKBwyy/kki2q0tM/fOdJdT5LzrnRw/X909NEfCOj8tz7hiOEH8= 
     58hvcNAQEEBQADgYEAi4xFA7uQSnBUKGm3Aj5QlRIQ78fUSMJWvnpNCm4onwdNcYwB 
     59/ODg3W7vWtewDN8Uvq/kIBFMyptLrs5LDx9GsFd04Ib/lLInCyp76QnVK3IU/plc 
     60ZhKHMS/ge1xHtVIJuxgJ2ArClY6/I+asDepIGcgR5o/aENLNot5y57F1wNg= 
    6161-----END CERTIFICATE----- 
Note: See TracChangeset for help on using the changeset viewer.