[FIX] XML-RPC SSL
bzr revid: stephane@tinyerp.com-20081218235433-cnsc5a4iyfzqvbdx
This commit is contained in:
parent
70bd7ea91a
commit
12e2aef08c
|
@ -21,27 +21,23 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import threading
|
||||
|
||||
import SimpleXMLRPCServer
|
||||
from ssl import SecureXMLRPCServer
|
||||
|
||||
import signal
|
||||
import sys
|
||||
import xmlrpclib
|
||||
import SocketServer
|
||||
import socket
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import signal
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import xmlrpclib
|
||||
|
||||
_service = {}
|
||||
_group = {}
|
||||
_res_id = 1
|
||||
_res = {}
|
||||
|
||||
|
||||
class ServiceEndPointCall(object):
|
||||
def __init__(self, id, method):
|
||||
self._id = id
|
||||
|
@ -280,7 +276,45 @@ class GenericXMLRPCRequestHandler:
|
|||
pdb.post_mortem(tb)
|
||||
raise xmlrpclib.Fault(s, tb_s)
|
||||
|
||||
# refactoring from Tryton (B2CK, Cedric Krier, Bertrand Chenal)
|
||||
class SSLSocket(object):
|
||||
def __init__(self, socket):
|
||||
if not hasattr(socket, 'sock_shutdown'):
|
||||
from OpenSSL import SSL
|
||||
ctx = SSL.Context(SSL.SSLv23_METHOD)
|
||||
ctx.use_privatekey_file('server.pkey')
|
||||
ctx.use_certificate_file('server.cert')
|
||||
self.socket = SSL.Connection(ctx, socket)
|
||||
else:
|
||||
self.socket = socket
|
||||
|
||||
def shutdown(self, how):
|
||||
return self.socket.sock_shutdown(how)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.socket, name)
|
||||
|
||||
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
||||
rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service)
|
||||
|
||||
class SecureXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||
def setup(self):
|
||||
self.connection = SSLSocket(self.request)
|
||||
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
|
||||
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
|
||||
|
||||
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
|
||||
def server_bind(self):
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
|
||||
|
||||
class SecureThreadedXMLRPCServer(SimpleThreadedXMLRPCServer):
|
||||
def __init__(self, server_address, HandlerClass, logRequests=1):
|
||||
SimpleThreadedXMLRPCServer.__init__(self, server_address, HandlerClass, logRequests)
|
||||
self.socket = SSLSocket(socket.socket(self.address_family, self.socket_type))
|
||||
self.server_bind()
|
||||
self.server_activate()
|
||||
# end of refactoring from Tryton
|
||||
|
||||
class HttpDaemon(threading.Thread):
|
||||
def __init__(self, interface, port, secure=False):
|
||||
|
@ -288,22 +322,9 @@ class HttpDaemon(threading.Thread):
|
|||
self.__port = port
|
||||
self.__interface = interface
|
||||
self.secure = bool(secure)
|
||||
|
||||
base_handler_class = [SimpleXMLRPCServer.SimpleXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler][self.secure]
|
||||
class OpenERPXMLRPCRequestHandler(GenericXMLRPCRequestHandler, base_handler_class):
|
||||
base_handler_class.rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service)
|
||||
|
||||
base_server_class = [SimpleXMLRPCServer.SimpleXMLRPCServer, SecureXMLRPCServer.SecureXMLRPCServer][self.secure]
|
||||
class OpenERPThreadedXMLRPCServer(SocketServer.ThreadingMixIn, base_server_class):
|
||||
def server_bind(self):
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
base_server_class.server_bind(self)
|
||||
except:
|
||||
Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use')
|
||||
sys.exit(1)
|
||||
|
||||
self.server = OpenERPThreadedXMLRPCServer((interface, port), OpenERPXMLRPCRequestHandler, 0)
|
||||
handler_class = (SimpleXMLRPCRequestHandler, SecureXMLRPCRequestHandler)[self.secure]
|
||||
server_class = (SimpleThreadedXMLRPCServer, SecureThreadedXMLRPCServer)[self.secure]
|
||||
self.server = server_class((interface, port), handler_class, 0)
|
||||
|
||||
def attach(self, path, gw):
|
||||
pass
|
||||
|
@ -311,11 +332,7 @@ class HttpDaemon(threading.Thread):
|
|||
def stop(self):
|
||||
self.running = False
|
||||
if os.name != 'nt':
|
||||
value = hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2
|
||||
if self.secure:
|
||||
self.server.socket.sock_shutdown(value)
|
||||
else:
|
||||
self.server.socket.shutdown(value)
|
||||
self.server.socket.shutdown( hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2 )
|
||||
self.server.socket.close()
|
||||
|
||||
def run(self):
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
"""
|
||||
SecureXMLRPCServer module using pyOpenSSL 0.5
|
||||
Extremely kludgey code written 0907.2002
|
||||
by Michal Wallace ( http://www.sabren.net/ )
|
||||
|
||||
This acts as a drop-in replacement for
|
||||
SimpleXMLRPCServer from the standard python
|
||||
library.
|
||||
|
||||
This code is in the public domain and is
|
||||
provided AS-IS WITH NO WARRANTY WHATSOEVER.
|
||||
"""
|
||||
import SocketServer
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
import SimpleXMLRPCServer
|
||||
from OpenSSL import SSL
|
||||
|
||||
|
||||
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, 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.path.join(os.getcwd(), os.path.dirname(sys.argv[0]))
|
||||
ctx.use_privatekey_file (os.path.join(dir, 'server.pkey'))
|
||||
ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
|
||||
|
||||
self.socket = SSLBugFix(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)
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
import SecureXMLRPCServer
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICNDCCAZ0CAQEwDQYJKoZIhvcNAQEEBQAweTEQMA4GA1UEChMHVGlueUVSUDEM
|
||||
MAoGA1UECxMDRVJQMRkwFwYJKoZIhvcNAQkBFgpmcEB0aW55LmJlMRAwDgYDVQQH
|
||||
EwdXYWxoYWluMQswCQYDVQQIEwJCVzELMAkGA1UEBhMCQkUxEDAOBgNVBAMTB1Rp
|
||||
bnlFUlAwHhcNMDYwNTI0MDgzODUxWhcNMDcwNTI0MDgzODUxWjBMMQswCQYDVQQG
|
||||
EwJCRTELMAkGA1UECBMCQlcxEDAOBgNVBAoTB1RpbnlFUlAxDDAKBgNVBAsTA0VS
|
||||
UDEQMA4GA1UEAxMHVGlueUVSUDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
|
||||
xzIDlU2PrczPsgXtxCskYxuwMPgNCNSCBfWsUZ9nJzlZfRAEXEq4LxaTPIgkzkIF
|
||||
82bmJLgFz6/CyCFid4mkBLQBj30Opp2Vco39WRncNKHKxbk+/wZpZtQ0bSpvf+F4
|
||||
MBqCLldYIqsoyenombVCb8X62IUu0ENF1wR22owvyKcCAwEAATANBgkqhkiG9w0B
|
||||
AQQFAAOBgQB2yUqJ3gbQ8I6rcmaVJlcLDHfC5w1Jr1cUzcJevOPh3wygSZYYoUoe
|
||||
yeYlzEag/DpPSHyRiJJVOKdiwU0yfmZPhfDNtDiBr47bz8qzIsYq5VeMmSeXrq/f
|
||||
AA3iI4xE8YFzJHWtiBCqqyUok+j9pVad7iV7+UVIePHZLEkGGWIjDA==
|
||||
-----END CERTIFICATE-----
|
|
@ -1,15 +0,0 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQDHMgOVTY+tzM+yBe3EKyRjG7Aw+A0I1IIF9axRn2cnOVl9EARc
|
||||
SrgvFpM8iCTOQgXzZuYkuAXPr8LIIWJ3iaQEtAGPfQ6mnZVyjf1ZGdw0ocrFuT7/
|
||||
Bmlm1DRtKm9/4XgwGoIuV1giqyjJ6eiZtUJvxfrYhS7QQ0XXBHbajC/IpwIDAQAB
|
||||
AoGAVwAxMHS/3FkoHckZICT3r5HYUosEpmaqo4+5w6yrkSYrP8RPI0A/UdG6XSXZ
|
||||
bXzIvJakzkTRxPQvTtnF+A/V4rF9hxwB8cGXSywv5eDGmZ91qIsxY7Sv99VqSKNH
|
||||
dNr9aZHloTvI51e/oramIJ/O3A+TbAS5i+u1DJC2IIFJcAECQQD8iRPTlPIqzjYD
|
||||
Lg7KYGvwW9TE4ONAhC86kJbzV5o3amlV5duJgnkl/mNlfN1ihA7f3Gx9dfCjfRKp
|
||||
V1rcjtCBAkEAye2aMw2v1m+MEqcPxyTUzVf5Y8BIXWbk15T43czXec9YclZSOBCX
|
||||
Dgv4a3Fk+yxQUE0cZUH0U4FJq6mTgpuFJwJASFqZ9KATNlJ4xTZ4BGHV6zrUXkg0
|
||||
tDJrObNdnID37XKulW7TFLXuMgWNwvEgmO5POLJ13whglubp5tzhapn8gQJAJz9Z
|
||||
U0b7wFAaB54VAP31ppvMy0iaSB0xqX05CdNAplpYtJB2lpMS6RYGiMuXdwJb8d+q
|
||||
/ztcg8aDTSw+kYoszQJBAPBrt694VkGT1k9Be6e5wyVDrE05bkHhFxPk/HMeWMDX
|
||||
sZqHPs9vVaLBqu/uU84FdwRMOV71RG90g6eUEl7HWsg=
|
||||
-----END RSA PRIVATE KEY-----
|
Loading…
Reference in New Issue