[pyOpenSSL] pyopenssl and xmlrpclib
Dan Williams
dcbw at redhat.com
Fri Jun 16 04:30:08 CEST 2006
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()
>
More information about the pyopenssl-users
mailing list