[FIX] XML-RPC SSL
authorStephane Wirtel <stephane@tinyerp.com>
Thu, 18 Dec 2008 23:54:33 +0000 (00:54 +0100)
committerStephane Wirtel <stephane@tinyerp.com>
Thu, 18 Dec 2008 23:54:33 +0000 (00:54 +0100)
bzr revid: stephane@tinyerp.com-20081218235433-cnsc5a4iyfzqvbdx

bin/netsvc.py
bin/ssl/SecureXMLRPCServer.py [deleted file]
bin/ssl/__init__.py [deleted file]
bin/ssl/server.cert [deleted file]
bin/ssl/server.pkey [deleted file]

index ced46c4..888117b 100644 (file)
 #
 ##############################################################################
 
-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):
diff --git a/bin/ssl/SecureXMLRPCServer.py b/bin/ssl/SecureXMLRPCServer.py
deleted file mode 100644 (file)
index bdcf11d..0000000
+++ /dev/null
@@ -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:
-
diff --git a/bin/ssl/__init__.py b/bin/ssl/__init__.py
deleted file mode 100644 (file)
index 613a9cf..0000000
+++ /dev/null
@@ -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:
-
diff --git a/bin/ssl/server.cert b/bin/ssl/server.cert
deleted file mode 100644 (file)
index de04f1c..0000000
+++ /dev/null
@@ -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-----
diff --git a/bin/ssl/server.pkey b/bin/ssl/server.pkey
deleted file mode 100644 (file)
index 1b1b7d6..0000000
+++ /dev/null
@@ -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-----