Add option for CA certificate for validating clients

This can be used to secure TCP traffic between Radicale and a reverse proxy
This commit is contained in:
Unrud 2017-06-02 12:41:03 +02:00
parent 6bb0e9d956
commit 3af5809d71
4 changed files with 21 additions and 1 deletions

4
config
View File

@ -41,6 +41,10 @@
# SSL private key
#key = /etc/ssl/radicale.key.pem
# CA certificate for validating clients. This can be used to secure
# TCP traffic between Radicale and a reverse proxy
#certificate_authority =
# SSL Protocol used. See python's ssl module for available values
#protocol = PROTOCOL_TLSv1_2

View File

@ -143,6 +143,7 @@ class HTTPSServer(HTTPServer):
key = None
protocol = None
ciphers = None
certificate_authority = None
def __init__(self, address, handler):
"""Create server by wrapping HTTP socket in an SSL socket."""
@ -150,6 +151,9 @@ class HTTPSServer(HTTPServer):
self.socket = ssl.wrap_socket(
self.socket, self.key, self.certificate, server_side=True,
cert_reqs=ssl.CERT_REQUIRED if self.certificate_authority else
ssl.CERT_NONE,
ca_certs=self.certificate_authority or None,
ssl_version=self.protocol, ciphers=self.ciphers)
self.server_bind()
@ -187,6 +191,9 @@ class RequestHandler(wsgiref.simple_server.WSGIRequestHandler):
def get_environ(self):
env = super().get_environ()
if hasattr(self.connection, "getpeercert"):
# The certificate can be evaluated by the auth module
env["REMOTE_CERTIFICATE"] = self.connection.getpeercert()
# Parent class only tries latin1 encoding
env["PATH_INFO"] = unquote(self.path.split("?", 1)[0])
return env

View File

@ -169,11 +169,15 @@ def serve(configuration, logger):
server_class = ThreadedHTTPSServer
server_class.certificate = configuration.get("server", "certificate")
server_class.key = configuration.get("server", "key")
server_class.certificate_authority = configuration.get(
"server", "certificate_authority")
server_class.ciphers = configuration.get("server", "ciphers")
server_class.protocol = getattr(
ssl, configuration.get("server", "protocol"), ssl.PROTOCOL_SSLv23)
# Test if the SSL files can be read
for name in ("certificate", "key"):
for name in ["certificate", "key"] + (
["certificate_authority"]
if server_class.certificate_authority else []):
filename = getattr(server_class, name)
try:
open(filename, "r").close()

View File

@ -74,6 +74,11 @@ INITIAL_CONFIG = OrderedDict([
"help": "set private key file",
"aliases": ["-k", "--key"],
"type": str}),
("certificate_authority", {
"value": "",
"help": "set CA certificate for validating clients",
"aliases": ["--certificate-authority"],
"type": str}),
("protocol", {
"value": "PROTOCOL_TLSv1_2",
"help": "SSL protocol used",