From 34163c5020b96dbada7b0d5c91fcc8299d966464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Schmidts?= Date: Tue, 27 Aug 2013 10:55:30 +0200 Subject: [PATCH 1/3] making radicale support authenticated user from apache --- config | 6 +++--- radicale/__init__.py | 5 +++++ radicale/auth/apache.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 radicale/auth/apache.py diff --git a/config b/config index 2d93905e..ea14ebb6 100644 --- a/config +++ b/config @@ -3,7 +3,7 @@ # Config file for Radicale - A simple calendar server # -# Place it into /etc/radicale/config (global) +# Place it into /etc/radicale/config (global) # or ~/.config/radicale/config (user) # # The current values are the default ones @@ -47,7 +47,7 @@ stock = utf-8 [auth] # Authentication method -# Value: None | htpasswd | IMAP | LDAP | PAM | courier | http | custom +# Value: None | htpasswd | IMAP | LDAP | PAM | courier | http | custom | apache type = None # custom auth handler @@ -69,7 +69,7 @@ ldap_attribute = uid # placed as X in a query of the form (&(...)X) # example: (objectCategory=Person)(objectClass=User)(memberOf=cn=calenderusers,ou=users,dc=example,dc=org) # leave empty if no additional filter is needed -ldap_filter = +ldap_filter = # LDAP dn for initial login, used if LDAP server does not allow anonymous searches # Leave empty if searches are anonymous ldap_binddn = diff --git a/radicale/__init__.py b/radicale/__init__.py index 9222e9c3..0a851d96 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -273,10 +273,15 @@ class Application(object): # Ask authentication backend to check rights authorization = environ.get("HTTP_AUTHORIZATION", None) + # Get the apache authentified user + remote_user = environ.get("REMOTE_USER", None) + if authorization: authorization = authorization.lstrip("Basic").strip() user, password = self.decode(base64.b64decode( authorization.encode("ascii")), environ).split(":", 1) + elif remote_user: + user, password = remote_user, None else: user = password = None diff --git a/radicale/auth/apache.py b/radicale/auth/apache.py new file mode 100644 index 00000000..7c3cf161 --- /dev/null +++ b/radicale/auth/apache.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Radicale Server - Calendar Server +# Copyright © 2012 Ehsanul Hoque +# Copyright © 2013 Guillaume Ayoub +# +# This library is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Radicale. If not, see . + +""" +Trusting apache auth mechanism. +""" + +from .. import log + + +def is_authenticated(user, password): + """Check if ``user`` is defined and assuming it's valid.""" + log.LOGGER.debug('Got user %r from apache.' % user) + return user is not None From 18ea7e49429f03a956ee4faf47b81d811ace82f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Schmidts?= Date: Wed, 15 Jan 2014 22:28:36 +0100 Subject: [PATCH 2/3] removing the user and password getting from main __call__ function --- radicale/__init__.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index 0a851d96..79644779 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -234,6 +234,18 @@ class Application(object): return read_allowed_items, write_allowed_items + def get_creds_from_env(self, env): + """Extract a user and a password from the request environ.""" + # Ask authentication backend to check rights + if 'HTTP_AUTHORIZATION' in env: + authorization = env['HTTP_AUTHORIZATION'].lstrip("Basic").strip() + return self.decode(base64.b64decode( + authorization.encode("ascii")), env).split(":", 1) + # Get the webserver authentified user + elif 'REMOTE_USER' in env: + return env['REMOTE_USER'], None + return None, None + def __call__(self, environ, start_response): """Manage a request.""" log.LOGGER.info("%s request at %s received" % ( @@ -270,20 +282,7 @@ class Application(object): # Get function corresponding to method function = getattr(self, environ["REQUEST_METHOD"].lower()) - # Ask authentication backend to check rights - authorization = environ.get("HTTP_AUTHORIZATION", None) - - # Get the apache authentified user - remote_user = environ.get("REMOTE_USER", None) - - if authorization: - authorization = authorization.lstrip("Basic").strip() - user, password = self.decode(base64.b64decode( - authorization.encode("ascii")), environ).split(":", 1) - elif remote_user: - user, password = remote_user, None - else: - user = password = None + user, password = self.get_creds_from_env(environ) read_allowed_items, write_allowed_items = \ self.collect_allowed_items(items, user) From b9ff564c1f71a3c45e75c59bebe278f4da11af6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Schmidts?= Date: Wed, 15 Jan 2014 23:01:36 +0100 Subject: [PATCH 3/3] not only apache uses REMOTE_USER removing the apache mention to make the config more "webserver agnostic" --- config | 2 +- radicale/auth/{apache.py => remote_user.py} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename radicale/auth/{apache.py => remote_user.py} (90%) diff --git a/config b/config index ea14ebb6..976a3b70 100644 --- a/config +++ b/config @@ -47,7 +47,7 @@ stock = utf-8 [auth] # Authentication method -# Value: None | htpasswd | IMAP | LDAP | PAM | courier | http | custom | apache +# Value: None | htpasswd | IMAP | LDAP | PAM | courier | http | custom | remote_user type = None # custom auth handler diff --git a/radicale/auth/apache.py b/radicale/auth/remote_user.py similarity index 90% rename from radicale/auth/apache.py rename to radicale/auth/remote_user.py index 7c3cf161..d61c26c4 100644 --- a/radicale/auth/apache.py +++ b/radicale/auth/remote_user.py @@ -18,7 +18,7 @@ # along with Radicale. If not, see . """ -Trusting apache auth mechanism. +Trusting the HTTP server auth mechanism. """ from .. import log @@ -26,5 +26,5 @@ from .. import log def is_authenticated(user, password): """Check if ``user`` is defined and assuming it's valid.""" - log.LOGGER.debug('Got user %r from apache.' % user) + log.LOGGER.debug('Got user %r from HTTP server.' % user) return user is not None