From: Dan W. <dc...@re...> - 2006-06-16 02:29:51
|
On Thu, 2006-06-15 at 10:14 -0500, Andrew Gaffney wrote: > I'm trying to integrate xmlrpclib and pyopenssl. I'm mostly there, but I'm > running into a problem: If you need some example code of doing SSL and all things XMLRPC, take a look at the files here: http://cvs.fedora.redhat.com/viewcvs/extras-buildsys/common/?root=fedora specifically SSLCommon.py and SSLConnection.py. Furthermore, XMLRPCServerProxy.py, URLopener.py, FileTranser.py, FileDownloader.py, and FileUploader.py might be of of interest as well. These implementations use nonblocking sockets by default, which have a few other complications, but you can safely turn that off by passing timeout values of None, I think. We've been running variations on this code for almost a year now in the Fedora Extras build system, and it's been working pretty well. Dan > Traceback (most recent call last): > File "./scirec.py", line 39, in ? > print client.say_hello() > File "/usr/lib/python2.4/xmlrpclib.py", line 1096, in __call__ > return self.__send(self.__name, args) > File "/usr/lib/python2.4/xmlrpclib.py", line 1383, in __request > verbose=self.__verbose > File "/usr/lib/python2.4/xmlrpclib.py", line 1147, in request > return self._parse_response(h.getfile(), sock) > File "/usr/lib/python2.4/xmlrpclib.py", line 1276, in _parse_response > response = file.read(1024) > File "/usr/lib64/python2.4/socket.py", line 303, in read > data = self._sock.recv(recv_size) > OpenSSL.SSL.SysCallError: (9, 'Bad file descriptor') > > > My wrapper module code is below. Is there something I'm doing wrong? > > > import httplib > import xmlrpclib > import socket > from OpenSSL import SSL > > class SecureXMLRPCClient(xmlrpclib.ServerProxy): > > def __init__(self, host, port, client_cert, client_key, verify_cert_func=None): > xmlrpclib.ServerProxy.__init__(self, "https://" + host + ":" + str(port), > transport=SafeTransport(self.__host, client_cert, client_key, verify_cert_func), > encoding="utf-8", allow_none=True) > > class SafeTransport(xmlrpclib.Transport): > > def __init__(self, host, client_cert, client_key, verify_cert_func=None): > self.__host = host > self.__client_cert = client_cert > self.__client_key = client_key > self.__verify_cert_func = verify_cert_func > > def make_connection(self, host): > host, extra_headers, x509 = self.get_host_info(host) > return HTTPS(host, self.__client_key, self.__client_cert, self.__verify_cert_func) > > class HTTPS(httplib.HTTP): > > def __init__(self, host='', key_file=None, cert_file=None, verify_cert_func=None): > self._setup(HTTPSConnection(host, key_file, cert_file, verify_cert_func)) > > # we never actually use these for anything, but we keep them > # here for compatibility with post-1.5.2 CVS. > self.key_file = key_file > self.cert_file = cert_file > > class HTTPSConnection(httplib.HTTPConnection): > > def __init__(self, host, key_file=None, cert_file=None, verify_cert_func=None): > httplib.HTTPConnection.__init__(self, host, None, None) > self.verify_cert_func = verify_cert_func > self.key_file = key_file > self.cert_file = cert_file > > def connect(self): > # Initialize context > ctx = SSL.Context(SSL.SSLv23_METHOD) > if self.verify_cert_func: > ctx.set_verify(SSL.VERIFY_PEER, self.verify_cert_func) # Demand a certificate > ctx.use_privatekey_file(self.key_file) > ctx.use_certificate_file(self.cert_file) > > # Set up client > # self.sock = SSL.Connection(ctx, socket.socket(socket.AF_INET, > socket.SOCK_STREAM)) > real_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) > ssl_sock = SSL.Connection(ctx, real_sock) > ssl_sock.connect((self.host, self.port)) > self.sock = SSLConnWrapper(ssl_sock) > print str(self.sock) > > class SSLConnWrapper: > ''' > Proxy class to provide makefile function on SSL Connection objects. > ''' > def __init__(self, connection): > print "SSLConnWrapper.__init__()" > self.connection = connection > > def __getattr__(self, function) : > return getattr(self.connection, function) > > def makefile(self, mode, bufsize=0): > print "SSLConnWrapper.makefile()" > fo = socket._fileobject(self.connection) #, mode, bufsize) > return fo > > def shutdown(self, _) : > return self.connection.shutdown() > |