modifs à la gateway pour qu'elle fasse serveur xml-rpc/ssl avec pyopenssl

plutôt que m2crypto
This commit is contained in:
fpeters 2004-01-20 21:58:34 +00:00
parent a86839e432
commit 32b271b35d
2 changed files with 96 additions and 59 deletions

View File

@ -53,7 +53,7 @@ import sys
import traceback
try:
from M2Crypto import SSL
from OpenSSL import SSL
except ImportError:
SSL = None
@ -223,23 +223,19 @@ class Gateway(applications.Application):
def startRpcServer(self):
if SSL:
from glasnost.server.xmlrpcServer import XmlRpcSslThreadingServer
from glasnost.server.xmlrpcServer import SecureXmlRpcThreadingServer
certificatePath = '/etc/%s/server.pem' % glasnost.applicationName
certificateAutorityPath = '/etc/%s/ca.pem' \
% glasnost.applicationName
verifyDepth = 10
sslContext = SSL.Context('sslv2')
sslContext.load_cert(certificatePath)
sslContext.load_client_ca(certificateAutorityPath)
sslContext.load_verify_info(certificateAutorityPath)
sslContext.set_verify(SSL.verify_none, verifyDepth)
sslContext.set_allow_unknown_ca(1)
sslContext.set_session_id_ctx('xmlrpc')
sslContext.set_info_callback()
self.rpcServer = XmlRpcSslThreadingServer(
('', self.port), sslContext = sslContext)
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_options(SSL.OP_NO_SSLv2)
ctx.use_privatekey_file ('/etc/%s/server.pkey' % glasnost.applicationName)
ctx.use_certificate_file('/etc/%s/server.cert' % glasnost.applicationName)
self.rpcServer = SecureXmlRpcThreadingServer(
('', self.port), sslContext = ctx)
else:
from glasnost.server.xmlrpcServer import XmlRpcThreadingServer
self.rpcServer = XmlRpcThreadingServer(('', self.port))

View File

@ -80,6 +80,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
# This files also contains code derived from SecureXMLRPCServer.py by Michal
# Wallace and distributed with pyopenssl (and placed in the public domain).
__version__ = '$Revision$'[11:-2]
@ -97,7 +99,7 @@ import traceback
import xmlrpclib
try:
from M2Crypto import SSL
from OpenSSL import SSL
except ImportError:
SSL = None
@ -489,23 +491,11 @@ class FastThreadingServer(SocketServer.ThreadingMixIn, FastServer):
class XmlRpcServer(ServerMixin, SocketServer.TCPServer):
__server_version = 'XmlRpcServer/' + __version__
allow_reuse_address = 1
def __init__(self, serverAddress):
# Try five time to obtain the socket.
i = 0
while 1:
try:
SocketServer.TCPServer.__init__(self, serverAddress,
XmlRpcRequestHandler)
break
except socket.error, e:
if e.args[0] == 98:
i += 1
if i == 5:
raise
time.sleep(2)
continue
raise
SocketServer.TCPServer.__init__(self, serverAddress,
XmlRpcRequestHandler)
if serverAddress[0] == '':
host = socket.gethostbyaddr(socket.gethostname())[0]
@ -531,25 +521,72 @@ class XmlRpcForkingServer(SocketServer.ForkingMixIn, XmlRpcServer):
if SSL:
class XmlRpcSslServer(ServerMixin, SSL.SSLServer):
__server_version = 'XmlRpcSslServer/' + __version__
class SSLBugFix:
"""
SSL Connection tends to die on sendall,
so I use send() as a workaround. This is
called by socket._fileobject, which is needed
so SocketServer (and kids) can treat the connection
as a regular file.
"""
def __init__(self, conn):
"""
For some reason, I can't subclass Connection,
so I'm making a proxy, instead.
"""
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 sendall(self, data):
"""
This is the bugfix. Connection.sendall() segfaults
on socket._fileobject.flush(), so just rewire it
to use send() instead.
"""
self.__dict__["conn"].send(data)
def shutdown(self, how=1):
"""
This isn't part of the bugfix. SimpleXMLRpcServer.doPOST
calls shutdown(1), and Connection.shutdown() doesn't take
an argument. So we just discard it:
"""
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 (SSLBugFix(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, sslContext, RequestHandlerClass):
SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass)
self.socket = SSLBugFix(SSL.Connection(sslContext,
socket.socket(self.address_family, self.socket_type)))
self.server_bind()
self.server_activate()
class SecureXmlRpcServer(ServerMixin, SecureTCPServer):
__server_version = 'SecureXmlRpcServer/' + __version__
def __init__(self, serverAddress, sslContext):
# Try five time to obtain the socket.
i = 0
while 1:
try:
SSL.SSLServer.__init__(self, serverAddress,
XmlRpcRequestHandler, sslContext)
break
except socket.error, e:
if e.args[0] == 98:
i += 1
if i == 5:
raise
time.sleep(2)
continue
raise
SecureTCPServer.__init__(self, serverAddress, sslContext,
SecureXmlRpcRequestHandler)
if serverAddress[0] == '':
host = socket.gethostbyaddr(socket.gethostname())[0]
@ -559,25 +596,17 @@ if SSL:
ServerMixin.__init__(self)
def finish(self):
print 'Finishing request'
self.request.set_shutdown(
SSL.SSL_RECEIVED_SHUTDOWN | SSL.SSL_SENT_SHUTDOWN)
print 'Almost done'
self.request.close()
print 'Done'
def serve_forever(self):
self.log_message('Awaiting XML-RPC SSL connections')
SSL.SSLServer.serve_forever(self)
self.log_message('Finished serving XML-RPC SSL connections')
self.log_message('Awaiting XML-RPC/SSL connections')
SecureTCPServer.serve_forever(self)
self.log_message('Finished serving XML-RPC/SSL connections')
class XmlRpcSslThreadingServer(SocketServer.ThreadingMixIn, XmlRpcSslServer):
class SecureXmlRpcThreadingServer(SocketServer.ThreadingMixIn, SecureXmlRpcServer):
pass
class XmlRpcSslForkingServer(SocketServer.ForkingMixIn, XmlRpcSslServer):
class SecureXmlRpcForkingServer(SocketServer.ForkingMixIn, SecureXmlRpcServer):
pass
@ -664,3 +693,15 @@ class XmlRpcRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.wfile.flush()
self.connection.shutdown(1)
class SecureXmlRpcRequestHandler(XmlRpcRequestHandler):
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)