Hi everybody,
For those who want to implement a SecureXMLRPCServer (HTTPS), here is
what I finally found in the Internet. I will summarise everything for
the people like me that need extra help just to get running an HTTPS
XMLRPC Server
This summary is not intended to be exhaustive, but just to give the
minimum steps to get running our server.
Here's the code (taken from
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496786):
"""SecureXMLRPCServer.py - simple XML RPC server supporting SSL.
Based on this article:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81549
For windows users:
http://webcleaner.sourceforge.net/pyOpenSSL-0.6.win32-py2.4.exe
"""
# Configure below
LISTEN_HOST='127.0.0.1' # You should not use '' here, unless you have a
real FQDN.
LISTEN_PORT=443
KEYFILE='your.key.pem' # Replace with your PEM formatted key file
CERTFILE=your.cert.pem' # Replace with your PEM formatted certificate
file
# Configure above
import SocketServer
import BaseHTTPServer
import SimpleHTTPServer
import SimpleXMLRPCServer
import socket, os
from OpenSSL import SSL
class
SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
def __init__(self, server_address, HandlerClass, logRequests=True):
"""Secure XML-RPC server.
It it very similar to SimpleXMLRPCServer but it uses HTTPS for
transporting XML data.
"""
self.logRequests = logRequests
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self)
SocketServer.BaseServer.__init__(self, server_address,
HandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_privatekey_file (KEYFILE)
ctx.use_certificate_file(CERTFILE)
self.socket = SSL.Connection(ctx,
socket.socket(self.address_family,
self.socket_type))
self.server_bind()
self.server_activate()
class
SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
"""Secure XML-RPC request handler class.
It it very similar to SimpleXMLRPCRequestHandler but it uses HTTPS
for transporting XML data.
"""
def setup(self):
self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb",
self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb",
self.wbufsize)
def do_POST(self):
"""Handles the HTTPS POST request.
It was copied out from SimpleXMLRPCServer.py and modified to
shutdown the socket cleanly.
"""
try:
# get arguments
data = self.rfile.read(int(self.headers["content-length"]))
# In previous versions of SimpleXMLRPCServer, _dispatch
# could be overridden in this class, instead of in
# SimpleXMLRPCDispatcher. To maintain backwards
compatibility,
# check to see if a subclass implements _dispatch and
dispatch
# using that method if present.
response = self.server._marshaled_dispatch(
data, getattr(self, '_dispatch', None)
)
except: # This should only happen if the module is buggy
# internal error, report as HTTP server error
self.send_response(500)
self.end_headers()
else:
# got a valid XML RPC response
self.send_response(200)
self.send_header("Content-type", "text/xml")
self.send_header("Content-length", str(len(response)))
self.end_headers()
self.wfile.write(response)
# shut down the connection
self.wfile.flush()
self.connection.shutdown() # Modified here!
def test(HandlerClass = SecureXMLRpcRequestHandler,ServerClass =
SecureXMLRPCServer):
"""Test xml rpc over https server"""
class xmlrpc_registers:
def __init__(self):
import string
self.python_string = string
def add(self, x, y):
return x + y
def mult(self,x,y):
return x*y
def div(self,x,y):
return x//y
server_address = (LISTEN_HOST, LISTEN_PORT) # (address, port)
server = ServerClass(server_address, HandlerClass)
server.register_instance(xmlrpc_registers())
sa = server.socket.getsockname()
print "Serving HTTPS on", sa[0], "port", sa[1]
server.serve_forever()
if __name__ == '__main__':
test()
# Here is the client for testing:
import xmlrpclib
server = xmlrpclib.Server('
https://localhost:443')
print server.add(1,2)
print server.div(10,4)
------------------------------------------------------------
Now, here are the steps to get running it:
1. Install OpenSSL from
www.openssl.org. If you are using Windows, go
to
http://www.slproweb.com/products/Win32OpenSSL.html and install the
binary.
2. In order to have our required .pem files, put the following in a
batch file (.sh or .bat) and run it from the directory where openssl is
(unless it is set as an environment variable):
openssl req -config openssl.cnf -new -out my-server.csr
openssl rsa -in privkey.pem -out my-server.key
openssl x509 -in my-server.csr -out my-server.cert -req -signkey
my-server.key -days 1500
openssl x509 -in my-server.cert -out my-server.der.crt -outform DER
mv my-server.csr $1.csr
mv my-server.cert $1.cert.pem
mv my-server.key $1.key.pem
mv my-server.der.crt $1.der.crt
rm privkey.pem
rm -f .rnd
(for .bat, just ignore the last line and use "move" instead of "mv",
"del" instead of "rm" and "yourdomain.com" instead of "$1")
It will generate 4 files. Take the two with .pem extension, and put it
on the same directory as the SecureXMLRPCServer code.
3. In order for get running the code, install pyOpenSSL available at
http://pyopenssl.sourceforge.net/. For Windows you may prefer
http://webcleaner.sourceforge.net/pyOpenSSL-0.6.win32-py2.4.exe
That's it.
Special thanks to Laszlo Nagy
Enjoy!
Daniel Crespo