- Timestamp:
- 21/04/10 15:04:59 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/branches/MyProxyClient-pyopenssl/myproxy/client.py
r6829 r6835 26 26 import os 27 27 import socket 28 from M2Crypto import X509, RSA, EVP, m2, BIO, SSL, util29 28 import base64 29 import traceback 30 from cStringIO import StringIO 30 31 from ConfigParser import SafeConfigParser 32 33 from OpenSSL import crypto, SSL 31 34 32 35 from myproxy.utils.openssl import OpenSSLConfig, OpenSSLConfigError … … 43 46 44 47 45 class _HostCheck(SSL.Checker.Checker):46 """Override SSL.Checker.Checker to allow additional check of MyProxy47 server identity. If hostname doesn't match, allow match of host's48 Distinguished Name against MYPROXY_SERVER_DN setting"""49 50 def __init__(self,51 myProxyServerDN=os.environ.get('MYPROXY_SERVER_DN'),52 cnHostPfx='host/',53 **kw):54 """Override parent class __init__ to enable setting of myProxyServerDN55 setting56 57 @type myProxyServerDN: string58 @param myProxyServerDN: Set the expected Distinguished Name of the59 MyProxy server to avoid errors matching hostnames. This is useful60 where the hostname is not fully qualified61 62 @type cnHostPfx: string63 @param cnHostPfx: globus host certificates are64 generated by default with a 'host/' prefix to the host name. Set65 this keyword to '' or None to override and omit the prefix"""66 67 SSL.Checker.Checker.__init__(self, **kw)68 69 self.myProxyServerDN = myProxyServerDN70 self.cnHostPfx = cnHostPfx71 72 73 def __call__(self, peerCert, host=None):74 """Carry out checks on server ID75 @type peerCert: basestring76 @param peerCert: MyProxy server host certificate as M2Crypto.X509.X50977 instance78 @type host: basestring79 @param host: name of host to check80 """81 82 # Globus host certificate has a "host/" prefix - see explanation in83 # __init__.__doc__84 cnHostPfx = isinstance(self.cnHostPfx, basestring) \85 and self.cnHostPfx or ''86 host = None or cnHostPfx + self.host87 88 try:89 SSL.Checker.Checker.__call__(self, peerCert, host=host)90 91 except SSL.Checker.WrongHost, e:92 # Try match against DN set from MYPROXY_SERVER_DN / config93 # file setting94 peerCertDN = '/'+peerCert.get_subject().as_text().replace(', ','/')95 96 # If they match drop the exception and return all OK instead97 if peerCertDN != self.myProxyServerDN:98 raise99 100 return True48 #class _HostCheck(SSL.Checker.Checker): 49 # """Override SSL.Checker.Checker to allow additional check of MyProxy 50 # server identity. If hostname doesn't match, allow match of host's 51 # Distinguished Name against MYPROXY_SERVER_DN setting""" 52 # 53 # def __init__(self, 54 # myProxyServerDN=os.environ.get('MYPROXY_SERVER_DN'), 55 # cnHostPfx='host/', 56 # **kw): 57 # """Override parent class __init__ to enable setting of myProxyServerDN 58 # setting 59 # 60 # @type myProxyServerDN: string 61 # @param myProxyServerDN: Set the expected Distinguished Name of the 62 # MyProxy server to avoid errors matching hostnames. This is useful 63 # where the hostname is not fully qualified 64 # 65 # @type cnHostPfx: string 66 # @param cnHostPfx: globus host certificates are 67 # generated by default with a 'host/' prefix to the host name. Set 68 # this keyword to '' or None to override and omit the prefix""" 69 # 70 # SSL.Checker.Checker.__init__(self, **kw) 71 # 72 # self.myProxyServerDN = myProxyServerDN 73 # self.cnHostPfx = cnHostPfx 74 # 75 # 76 # def __call__(self, peerCert, host=None): 77 # """Carry out checks on server ID 78 # @type peerCert: basestring 79 # @param peerCert: MyProxy server host certificate as M2Crypto.X509.X509 80 # instance 81 # @type host: basestring 82 # @param host: name of host to check 83 # """ 84 # 85 # # Globus host certificate has a "host/" prefix - see explanation in 86 # # __init__.__doc__ 87 # cnHostPfx = isinstance(self.cnHostPfx, basestring) \ 88 # and self.cnHostPfx or '' 89 # host = None or cnHostPfx + self.host 90 # 91 # try: 92 # SSL.Checker.Checker.__call__(self, peerCert, host=host) 93 # 94 # except SSL.Checker.WrongHost, e: 95 # # Try match against DN set from MYPROXY_SERVER_DN / config 96 # # file setting 97 # peerCertDN = '/'+peerCert.get_subject().as_text().replace(', ','/') 98 # 99 # # If they match drop the exception and return all OK instead 100 # if peerCertDN != self.myProxyServerDN: 101 # raise 102 # 103 # return True 101 104 102 105 … … 503 506 not needed in the case of a proxy private key 504 507 """ 505 506 508 # Must be version 3 for MyProxy 507 context = SSL.Context( protocol='sslv3')508 509 context = SSL.Context(SSL.SSLv3_METHOD) 510 509 511 if self.caCertFilePath or self.caCertDir: 510 context.load_verify_locations(cafile=self.caCertFilePath, 511 capath=self.caCertDir) 512 513 # Stop if peer's certificate can't be verified 514 context.set_allow_unknown_ca(False) 515 else: 516 context.set_allow_unknown_ca(True) 512 context.load_verify_locations(self.caCertFilePath, self.caCertDir) 517 513 518 514 if ownerCertFile: 519 515 try: 520 context.load_cert_chain(ownerCertFile, 521 keyfile=ownerKeyFile, 522 callback=lambda *ar, **kw: ownerPassphrase) 523 except Exception, e: 516 # context.use_certificate_file(ownerCertFile) 517 context.use_certificate_chain_file(ownerCertFile) 518 def pwdCallback(passphraseMaxLen, 519 promptPassphraseTwice, 520 passphrase): 521 if passphrase is None: 522 return True 523 else: 524 if len(passphrase) > passphraseMaxLen: 525 log.error('Passphrase length %d is greater than ' 526 'the maximum length allowed %d', 527 len(passphrase), passphraseMaxLen) 528 return '' 529 return passphrase 530 531 context.set_passwd_cb(pwdCallback, ownerPassphrase) 532 context.use_privatekey_file(ownerKeyFile) 533 except Exception: 524 534 raise MyProxyClientConfigError("Loading certificate " 525 535 "and private key for SSL " 526 536 "connection [also check CA " 527 "certificate settings]: %s" % e) 528 529 # Verify peer's certificate 530 context.set_verify(SSL.verify_peer, 1) 537 "certificate settings]: %s" % 538 traceback.format_exc()) 539 540 # Verify peer's certificate 541 def callback(connection, x509Cert, *arg, **kw): 542 return True 543 544 context.set_verify(SSL.VERIFY_PEER, callback) 531 545 532 546 … … 534 548 # globus doesn't handle this case, apparently, and instead 535 549 # chokes in proxy delegation code 536 context.set_options( m2.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)550 context.set_options(SSL.OP_DONT_INSERT_EMPTY_FRAGMENTS) 537 551 538 552 # connect to myproxy server 539 conn = SSL.Connection(context, sock =socket.socket())553 conn = SSL.Connection(context, socket.socket()) 540 554 541 555 # Check server host identity - if host doesn't match use explicit 542 556 # 'serverDN' 543 557 # host/<hostname> one 544 hostCheck = _HostCheck(host=self.hostname,545 myProxyServerDN=self.serverDN,546 cnHostPfx=self.serverCNPrefix)547 conn.set_post_connection_check_callback(hostCheck)558 # hostCheck = _HostCheck(host=self.hostname, 559 # myProxyServerDN=self.serverDN, 560 # cnHostPfx=self.serverCNPrefix) 561 # conn.set_post_connection_check_callback(hostCheck) 548 562 549 563 return conn 550 564 551 def _createKey s(self, nBitsForKey=PRIKEY_NBITS):565 def _createKeyPair(self, nBitsForKey=PRIKEY_NBITS): 552 566 """Generate key pair and return as PEM encoded string 553 567 @type nBitsForKey: int … … 557 571 @return: public/private key pair 558 572 """ 559 keyPair = RSA.gen_key(nBitsForKey, 65537L,#m2.RSA_F4,560 callback=lambda *arg, **kw: None)573 keyPair = crypto.PKey() 574 keyPair.generate_key(crypto.TYPE_RSA, nBitsForKey) 561 575 562 576 return keyPair … … 578 592 # Check all required certifcate request DN parameters are set 579 593 # Create certificate request 580 req = X509.Request()594 certReq = crypto.X509Req() 581 595 582 596 # Create public key object 583 pubKey = EVP.PKey() 584 pubKey.assign_rsa(keyPair) 597 certReq.set_pubkey(keyPair) 585 598 586 599 # Add the public key to the request 587 req.set_version(0) 588 req.set_pubkey(pubKey) 589 590 defaultReqDN = self._openSSLConfig.reqDN 591 592 # Set DN 593 x509Name = X509.X509_Name() 594 x509Name.CN = CN 595 596 if defaultReqDN: 597 x509Name.OU = defaultReqDN['OU'] 598 x509Name.O = defaultReqDN['O'] 599 600 req.set_subject_name(x509Name) 601 req.sign(pubKey, messageDigest) 602 603 return req.as_der() 600 certReq.sign(keyPair, messageDigest) 601 602 derCertReq = crypto.dump_certificate_request(crypto.FILETYPE_ASN1, 603 certReq) 604 605 return derCertReq 604 606 605 607 def _deserializeResponse(self, msg, *fieldNames): … … 648 650 649 651 @return list containing the equivalent to the input in PEM format""" 650 pemCerts = [] 652 pemCerts = [] 651 653 dat = inputDat 652 654 653 while dat: 655 while dat: 654 656 # find start of cert, get length 655 657 ind = dat.find('\x30\x82') … … 661 663 # extract der-format cert, and convert to pem 662 664 derCert = dat[ind:ind+len+4] 663 664 x509 = X509.load_cert_der_string(derCert) 665 pemCert = x509.as_pem() 666 665 x509Cert = crypto.load_certificate(crypto.FILETYPE_ASN1, derCert) 666 pemCert = crypto.dump_certificate(crypto.FILETYPE_PEM, x509Cert) 667 667 pemCerts.append(pemCert) 668 668 … … 1009 1009 1010 1010 # Send certificate and private key 1011 certTxt = X509.load_cert(certFile).as_pem()1011 certTxt = open(certFile).read() 1012 1012 keyTxt = open(keyFile).read() 1013 1013 … … 1051 1051 # If no key pair was passed, generate here 1052 1052 if keyPair is None: 1053 keyPair = self._createKey s(nBitsForKey=nBitsForKey)1053 keyPair = self._createKeyPair(nBitsForKey=nBitsForKey) 1054 1054 1055 1055 certReq = self._createCertReq(username, keyPair) 1056 1056 1057 1057 if keyPair is not None: 1058 pemKeyPair = keyPair.as_pem(cipher=None, 1059 callback=util.no_passphrase_callback) 1058 pemKeyPair = crypto.dump_privatekey(crypto.FILETYPE_PEM, keyPair) 1060 1059 1061 1060 # Set-up SSL connection … … 1147 1146 for tries in range(MyProxyClient.MAX_RECV_TRIES): 1148 1147 dat += conn.recv(MyProxyClient.SERVER_RESP_BLK_SIZE) 1149 except SSL.S SLError:1148 except SSL.SysCallError: 1150 1149 # Expect this exception when response content exhausted 1151 1150 pass
Note: See TracChangeset
for help on using the changeset viewer.