Merge pull request #622 from Unrud/clientcertificate

Add option for CA certificate for validating clients
This commit is contained in:
Unrud 2017-06-02 12:59:35 +02:00 committed by GitHub
commit 7687afc4c6
4 changed files with 21 additions and 1 deletions

4
config
View File

@ -41,6 +41,10 @@
# SSL private key # SSL private key
#key = /etc/ssl/radicale.key.pem #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 # SSL Protocol used. See python's ssl module for available values
#protocol = PROTOCOL_TLSv1_2 #protocol = PROTOCOL_TLSv1_2

View File

@ -143,6 +143,7 @@ class HTTPSServer(HTTPServer):
key = None key = None
protocol = None protocol = None
ciphers = None ciphers = None
certificate_authority = None
def __init__(self, address, handler): def __init__(self, address, handler):
"""Create server by wrapping HTTP socket in an SSL socket.""" """Create server by wrapping HTTP socket in an SSL socket."""
@ -150,6 +151,9 @@ class HTTPSServer(HTTPServer):
self.socket = ssl.wrap_socket( self.socket = ssl.wrap_socket(
self.socket, self.key, self.certificate, server_side=True, 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) ssl_version=self.protocol, ciphers=self.ciphers)
self.server_bind() self.server_bind()
@ -187,6 +191,9 @@ class RequestHandler(wsgiref.simple_server.WSGIRequestHandler):
def get_environ(self): def get_environ(self):
env = super().get_environ() 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 # Parent class only tries latin1 encoding
env["PATH_INFO"] = unquote(self.path.split("?", 1)[0]) env["PATH_INFO"] = unquote(self.path.split("?", 1)[0])
return env return env

View File

@ -169,11 +169,15 @@ def serve(configuration, logger):
server_class = ThreadedHTTPSServer server_class = ThreadedHTTPSServer
server_class.certificate = configuration.get("server", "certificate") server_class.certificate = configuration.get("server", "certificate")
server_class.key = configuration.get("server", "key") 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.ciphers = configuration.get("server", "ciphers")
server_class.protocol = getattr( server_class.protocol = getattr(
ssl, configuration.get("server", "protocol"), ssl.PROTOCOL_SSLv23) ssl, configuration.get("server", "protocol"), ssl.PROTOCOL_SSLv23)
# Test if the SSL files can be read # 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) filename = getattr(server_class, name)
try: try:
open(filename, "r").close() open(filename, "r").close()

View File

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