From b863e8390e06c9dc4d27b519fcec125edca89e3d Mon Sep 17 00:00:00 2001 From: deronnax Date: Mon, 20 Oct 2014 17:03:23 +0200 Subject: [PATCH 1/3] add ".well-known" addresses feature (closes #126) --- config | 4 ++++ radicale/__init__.py | 19 +++++++++++++++++++ radicale/config.py | 3 +++ 3 files changed, 26 insertions(+) diff --git a/config b/config index 9c7b8a9a..7af788c6 100644 --- a/config +++ b/config @@ -46,6 +46,10 @@ request = utf-8 # Encoding for storing local collections stock = utf-8 +[well-known] +caldav = '/%(user)s/caldav/' +carddav = '/%(user)s/carddav/' + [auth] # Authentication method diff --git a/radicale/__init__.py b/radicale/__init__.py index 2824efd2..32237c37 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -286,6 +286,25 @@ class Application(object): user = environ.get("REMOTE_USER") password = None + if path.startswith('/.well-known/'): + fragment = path.rstrip("/").rsplit('/', 1)[-1] + redirect = config.get("well-known", fragment) + if redirect: + if not user and "%(user)s" in redirect: + status = client.UNAUTHORIZED + headers = { + "WWW-Authenticate": + "Basic realm=\"%s\"" % config.get("server", "realm")} + log.LOGGER.info("refused /.well-known/ redirection to anonymous user") + else: + redirect = redirect % locals() + status = client.SEE_OTHER + log.LOGGER.info("/.well-known/ redirection to: %s" % redirect) + headers = {"Location": redirect.encode('utf8')} + status = "%i %s" % (status, client.responses.get(status, "Unknown")) + start_response(status, headers.items()) + return [] + is_authenticated = auth.is_authenticated(user, password) is_valid_user = is_authenticated or not user diff --git a/radicale/config.py b/radicale/config.py index 3ba983eb..5d2b7997 100644 --- a/radicale/config.py +++ b/radicale/config.py @@ -51,6 +51,9 @@ INITIAL_CONFIG = { "base_prefix": "/", "can_skip_base_prefix": "False", "realm": "Radicale - Password Required"}, + "well-known": { + "caldav": "/%(user)s/caldav/", + "carddav": "/%(user)s/carddav/"}, "encoding": { "request": "utf-8", "stock": "utf-8"}, From f846f107e6dee9b750e57235280897a794818af0 Mon Sep 17 00:00:00 2001 From: deronnax Date: Tue, 21 Oct 2014 11:47:39 +0200 Subject: [PATCH 2/3] now with regex --- radicale/__init__.py | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index 32237c37..4a81d197 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -36,6 +36,7 @@ import posixpath import socket import ssl import wsgiref.simple_server +import re # Manage Python2/3 different modules # pylint: disable=F0401,E0611 try: @@ -55,6 +56,7 @@ VERSION = "0.9" # Standard "not allowed" response that is returned when an authenticated user # tries to access information they don't have rights to NOT_ALLOWED = (client.FORBIDDEN, {}, None) +WELLKNOWNRE = re.compile(r'/.well-known/(carddav|caldav)/?') class HTTPServer(wsgiref.simple_server.WSGIServer, object): @@ -286,24 +288,23 @@ class Application(object): user = environ.get("REMOTE_USER") password = None - if path.startswith('/.well-known/'): - fragment = path.rstrip("/").rsplit('/', 1)[-1] - redirect = config.get("well-known", fragment) - if redirect: - if not user and "%(user)s" in redirect: - status = client.UNAUTHORIZED - headers = { - "WWW-Authenticate": - "Basic realm=\"%s\"" % config.get("server", "realm")} - log.LOGGER.info("refused /.well-known/ redirection to anonymous user") - else: - redirect = redirect % locals() - status = client.SEE_OTHER - log.LOGGER.info("/.well-known/ redirection to: %s" % redirect) - headers = {"Location": redirect.encode('utf8')} - status = "%i %s" % (status, client.responses.get(status, "Unknown")) - start_response(status, headers.items()) - return [] + wkfragment = WELLKNOWNRE.match(path) + if wkfragment: + redirect = config.get("well-known", wkfragment.group(1)) + if not user and "%(user)s" in redirect: + status = client.UNAUTHORIZED + headers = { + "WWW-Authenticate": + "Basic realm=\"%s\"" % config.get("server", "realm")} + log.LOGGER.info("refused /.well-known/ redirection to anonymous user") + else: + redirect = redirect % locals() + status = client.SEE_OTHER + log.LOGGER.info("/.well-known/ redirection to: %s" % redirect) + headers = {"Location": redirect.encode('utf8')} + status = "%i %s" % (status, client.responses.get(status, "Unknown")) + start_response(status, headers.items()) + return [] is_authenticated = auth.is_authenticated(user, password) is_valid_user = is_authenticated or not user From 8ec00f08df4c6bc1605b44fdca75a77d5eb1ba29 Mon Sep 17 00:00:00 2001 From: deronnax Date: Tue, 21 Oct 2014 12:30:14 +0200 Subject: [PATCH 3/3] throw 401 in case of failed variable substition for .well-known url --- radicale/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index 4a81d197..56d09b5a 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -290,18 +290,19 @@ class Application(object): wkfragment = WELLKNOWNRE.match(path) if wkfragment: + if not user: del user redirect = config.get("well-known", wkfragment.group(1)) - if not user and "%(user)s" in redirect: + try: + redirect = redirect % locals() + status = client.SEE_OTHER + log.LOGGER.info("/.well-known/ redirection to: %s" % redirect) + headers = {"Location": redirect.encode('utf8')} + except KeyError: status = client.UNAUTHORIZED headers = { "WWW-Authenticate": "Basic realm=\"%s\"" % config.get("server", "realm")} log.LOGGER.info("refused /.well-known/ redirection to anonymous user") - else: - redirect = redirect % locals() - status = client.SEE_OTHER - log.LOGGER.info("/.well-known/ redirection to: %s" % redirect) - headers = {"Location": redirect.encode('utf8')} status = "%i %s" % (status, client.responses.get(status, "Unknown")) start_response(status, headers.items()) return []