From 6389411edd8e18e2d31f230f5c30a59507398bcf Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Sun, 1 May 2011 15:25:52 +0200 Subject: [PATCH] Add support for SSL back --- radicale.py | 8 ++++++-- radicale/__init__.py | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/radicale.py b/radicale.py index 190176f6..7b7aa9a9 100755 --- a/radicale.py +++ b/radicale.py @@ -96,12 +96,14 @@ radicale.log.LOGGER.info("Starting Radicale") # Create calendar servers servers = [] +server_class = radicale.HTTPSServer if options.ssl else radicale.HTTPServer shutdown_program = threading.Event() for host in options.hosts.split(','): address, port = host.strip().rsplit(':', 1) address, port = address.strip('[] '), int(port) - servers.append(make_server(address, port, radicale.Application())) + servers.append( + make_server(address, port, radicale.Application(), server_class)) # SIGTERM and SIGINT (aka KeyboardInterrupt) should just mark this for shutdown signal.signal(signal.SIGTERM, lambda *_: shutdown_program.set()) @@ -117,9 +119,11 @@ def serve_forever(server): # Start the servers in a different loop to avoid possible race-conditions, when # a server exists but another server is added to the list at the same time for server in servers: - threading.Thread(target=serve_forever, args=(server,)).start() radicale.log.LOGGER.debug( "Listening to %s port %s" % (server.server_name, server.server_port)) + if options.ssl: + radicale.log.LOGGER.debug("Using SSL") + threading.Thread(target=serve_forever, args=(server,)).start() radicale.log.LOGGER.debug("Radicale server ready") diff --git a/radicale/__init__.py b/radicale/__init__.py index 2b9fa72a..71f9c544 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -31,6 +31,8 @@ should have been included in this package. import os import posixpath import base64 +import socket +import wsgiref.simple_server # Manage Python2/3 different modules # pylint: disable=F0401 try: @@ -46,6 +48,49 @@ from radicale import acl, config, ical, log, xmlutils VERSION = "git" +class HTTPServer(wsgiref.simple_server.WSGIServer): + """HTTP server.""" + def __init__(self, address, handler, bind_and_activate=True): + """Create server.""" + ipv6 = ":" in address[0] + + if ipv6: + self.address_family = socket.AF_INET6 + + # Do not bind and activate, as we might change socketopts + wsgiref.simple_server.WSGIServer.__init__(self, address, handler, False) + + if ipv6: + # Only allow IPv6 connections to the IPv6 socket + self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) + + if bind_and_activate: + self.server_bind() + self.server_activate() + + +class HTTPSServer(HTTPServer): + """HTTPS server.""" + def __init__(self, address, handler, bind_and_activate=True): + """Create server by wrapping HTTP socket in an SSL socket.""" + # Fails with Python 2.5, import if needed + # pylint: disable=F0401 + import ssl + # pylint: enable=F0401 + + HTTPServer.__init__(self, address, handler, False) + self.socket = ssl.wrap_socket( + self.socket, + server_side=True, + certfile=config.get("server", "certificate"), + keyfile=config.get("server", "key"), + ssl_version=ssl.PROTOCOL_SSLv23) + + if bind_and_activate: + self.server_bind() + self.server_activate() + + class Application(object): """WSGI application managing calendars.""" def __init__(self):