Просмотр исходного кода

Add option for CA certificate for validating clients

This can be used to secure TCP traffic between Radicale and a reverse proxy
Unrud 8 лет назад
Родитель
Сommit
3af5809d71
4 измененных файлов с 21 добавлено и 1 удалено
  1. 4 0
      config
  2. 7 0
      radicale/__init__.py
  3. 5 1
      radicale/__main__.py
  4. 5 0
      radicale/config.py

+ 4 - 0
config

@@ -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
 

+ 7 - 0
radicale/__init__.py

@@ -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

+ 5 - 1
radicale/__main__.py

@@ -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()

+ 5 - 0
radicale/config.py

@@ -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",