summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorP. Christeas <p_christ@hol.gr>2009-08-31 16:29:56 +0300
committerP. Christeas <p_christ@hol.gr>2009-08-31 16:29:56 +0300
commit0a838fba3aab924cdac524d27fcc22dee9e91c20 (patch)
tree4afa2b2edb530ab7cbf7232f42ef3a7aa05753a6 /bin
parenta267ef5d05e952df01e7f74c321ce77ae33a76ff (diff)
Fix https transports, certificates etc.
Now we can serve https: the send_error() must be fixed so that content-lenth is specified, certificates are configurable and connections get properly shutdown so that the client won't wait forever. bzr revid: p_christ@hol.gr-20090831132956-00atxsfcy3qkdw4j
Diffstat (limited to 'bin')
-rw-r--r--bin/service/http_server.py25
-rw-r--r--bin/service/websrv_lib.py46
2 files changed, 67 insertions, 4 deletions
diff --git a/bin/service/http_server.py b/bin/service/http_server.py
index 76cf5b2fc91..74a0f572771 100644
--- a/bin/service/http_server.py
+++ b/bin/service/http_server.py
@@ -88,6 +88,12 @@ class SecureMultiHandler2(SecureMultiHTTPHandler):
def log_message(self, format, *args):
netsvc.Logger().notifyChannel('https',netsvc.LOG_DEBUG,format % args)
+ def getcert_fnames(self):
+ tc = tools.config
+ fcert = tc.get_misc('httpsd','sslcert', 'ssl/server.cert')
+ fkey = tc.get_misc('httpsd','sslkey', 'ssl/server.key')
+ return (fcert,fkey)
+
class HttpDaemon(threading.Thread, netsvc.Server):
def __init__(self, interface, port):
threading.Thread.__init__(self)
@@ -141,6 +147,23 @@ class HttpSDaemon(threading.Thread, netsvc.Server):
netsvc.Logger().notifyChannel('httpd-ssl', netsvc.LOG_CRITICAL, "Error occur when starting the server daemon: %s" % (e,))
raise
+ def attach(self, path, gw):
+ pass
+
+ def stop(self):
+ self.running = False
+ if os.name != 'nt':
+ self.server.socket.shutdown( hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2 )
+ self.server.socket.close()
+
+ def run(self):
+ #self.server.register_introspection_functions()
+
+ self.running = True
+ while self.running:
+ self.server.handle_request()
+ return True
+
httpd = None
httpsd = None
@@ -175,7 +198,7 @@ def reg_http_service(hts, secure_only = False):
return
import SimpleXMLRPCServer
-class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
+class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,FixSendError,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
rpc_paths = []
protocol_version = 'HTTP/1.1'
def _dispatch(self, method, params):
diff --git a/bin/service/websrv_lib.py b/bin/service/websrv_lib.py
index 762cb9d8f2a..fe1db8f7bc9 100644
--- a/bin/service/websrv_lib.py
+++ b/bin/service/websrv_lib.py
@@ -146,7 +146,32 @@ class dummyconn:
def shutdown(self, tru):
pass
-class MultiHTTPHandler(BaseHTTPRequestHandler):
+def _quote_html(html):
+ return html.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
+
+class FixSendError:
+ def send_error(self, code, message=None):
+ #overriden from BaseHTTPRequestHandler, we also send the content-length
+ try:
+ short, long = self.responses[code]
+ except KeyError:
+ short, long = '???', '???'
+ if message is None:
+ message = short
+ explain = long
+ self.log_error("code %d, message %s", code, message)
+ # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201)
+ content = (self.error_message_format %
+ {'code': code, 'message': _quote_html(message), 'explain': explain})
+ self.send_response(code, message)
+ self.send_header("Content-Type", self.error_content_type)
+ self.send_header('Connection', 'close')
+ self.send_header('Content-Length', len(content) or 0)
+ self.end_headers()
+ if self.command != 'HEAD' and code >= 200 and code not in (204, 304):
+ self.wfile.write(content)
+
+class MultiHTTPHandler(FixSendError,BaseHTTPRequestHandler):
""" this is a multiple handler, that will dispatch each request
to a nested handler, iff it matches
@@ -304,17 +329,32 @@ class MultiHTTPHandler(BaseHTTPRequestHandler):
class SecureMultiHTTPHandler(MultiHTTPHandler):
+ def getcert_fnames(self):
+ """ Return a pair with the filenames of ssl cert,key
+
+ Override this to direct to other filenames
+ """
+ return ('server.cert','server.key')
+
def setup(self):
import ssl
+ certfile, keyfile = self.getcert_fnames()
self.connection = ssl.wrap_socket(self.request,
server_side=True,
- certfile="server.cert",
- keyfile="server.key",
+ certfile=certfile,
+ keyfile=keyfile,
ssl_version=ssl.PROTOCOL_SSLv23)
self.rfile = self.connection.makefile('rb', self.rbufsize)
self.wfile = self.connection.makefile('wb', self.wbufsize)
self.log_message("Secure %s connection from %s",self.connection.cipher(),self.client_address)
+ def finish(self):
+ # With ssl connections, closing the filehandlers alone may not
+ # work because of ref counting. We explicitly tell the socket
+ # to shutdown.
+ MultiHTTPHandler.finish(self)
+ self.connection.shutdown(socket.SHUT_RDWR)
+
import threading
class ConnThreadingMixIn:
"""Mix-in class to handle each _connection_ in a new thread.