[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