summaryrefslogtreecommitdiff
path: root/examples/SecureXMLRPCServer.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/SecureXMLRPCServer.py')
-rw-r--r--examples/SecureXMLRPCServer.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/examples/SecureXMLRPCServer.py b/examples/SecureXMLRPCServer.py
new file mode 100644
index 0000000..757b49c
--- /dev/null
+++ b/examples/SecureXMLRPCServer.py
@@ -0,0 +1,102 @@
+"""
+SecureXMLRPCServer module using pyOpenSSL 0.5
+Written 0907.2002
+by Michal Wallace
+http://www.sabren.net/
+
+This acts exactly like SimpleXMLRPCServer
+from the standard python library, but
+uses secure connections. The technique
+and classes should work for any SocketServer
+style server. However, the code has not
+been extensively tested.
+
+This code is in the public domain.
+It is provided AS-IS WITH NO WARRANTY WHATSOEVER.
+"""
+import SocketServer
+import os, socket
+import SimpleXMLRPCServer
+from OpenSSL import SSL
+
+class SSLWrapper:
+ """
+ This whole class exists just to filter out a parameter
+ passed in to the shutdown() method in SimpleXMLRPC.doPOST()
+ """
+ def __init__(self, conn):
+ """
+ Connection is not yet a new-style class,
+ so I'm making a proxy instead of subclassing.
+ """
+ self.__dict__["conn"] = conn
+ def __getattr__(self,name):
+ return getattr(self.__dict__["conn"], name)
+ def __setattr__(self,name, value):
+ setattr(self.__dict__["conn"], name, value)
+ def shutdown(self, how=1):
+ """
+ SimpleXMLRpcServer.doPOST calls shutdown(1),
+ and Connection.shutdown() doesn't take
+ an argument. So we just discard the argument.
+ """
+ self.__dict__["conn"].shutdown()
+ def accept(self):
+ """
+ This is the other part of the shutdown() workaround.
+ Since servers create new sockets, we have to infect
+ them with our magic. :)
+ """
+ c, a = self.__dict__["conn"].accept()
+ return (SSLWrapper(c), a)
+
+
+
+class SecureTCPServer(SocketServer.TCPServer):
+ """
+ Just like TCPServer, but use a socket.
+ This really ought to let you specify the key and certificate files.
+ """
+ def __init__(self, server_address, RequestHandlerClass):
+ SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass)
+
+ ## Same as normal, but make it secure:
+ ctx = SSL.Context(SSL.SSLv23_METHOD)
+ ctx.set_options(SSL.OP_NO_SSLv2)
+
+ dir = os.curdir
+ ctx.use_privatekey_file (os.path.join(dir, 'server.pkey'))
+ ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
+
+ self.socket = SSLWrapper(SSL.Connection(ctx, socket.socket(self.address_family,
+ self.socket_type)))
+ self.server_bind()
+ self.server_activate()
+
+
+class SecureXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
+ def setup(self):
+ """
+ We need to use socket._fileobject Because SSL.Connection
+ doesn't have a 'dup'. Not exactly sure WHY this is, but
+ this is backed up by comments in socket.py and SSL/connection.c
+ """
+ self.connection = self.request # for doPOST
+ self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
+ self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
+
+
+class SecureXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, SecureTCPServer):
+ def __init__(self, addr,
+ requestHandler=SecureXMLRPCRequestHandler,
+ logRequests=1):
+ """
+ This is the exact same code as SimpleXMLRPCServer.__init__
+ except it calls SecureTCPServer.__init__ instead of plain
+ old TCPServer.__init__
+ """
+ self.funcs = {}
+ self.logRequests = logRequests
+ self.instance = None
+ SecureTCPServer.__init__(self, addr, requestHandler)
+