From 1f25d6e27d536cbdf7bd3afaba8109380d1a3fd8 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Mon, 11 Mar 2024 18:36:40 +0100 Subject: [PATCH 1/6] Update README.md add some links --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index aed74fcef..acbde25b1 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,11 @@ Radicale is a small but powerful CalDAV (calendars, to-do lists) and CardDAV For the complete documentation, please visit [Radicale master Documentation](https://radicale.org/master.html). + +Additional hints can be found +* [Radicale Wiki](https://github.com/Kozea/Radicale/wiki) +* [Radicale Issues](https://github.com/Kozea/Radicale/issues) +* [Radicale Discussions](https://github.com/Kozea/Radicale/discussions) + +Before reporting an issue, please check +* [Radicale Wiki / Reporting Issues](https://github.com/Kozea/Radicale/wiki/Reporting-Issues) From 947cb08bb992f629ec70f0cefcd79cc2a01f9613 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Mon, 11 Mar 2024 07:49:37 +0100 Subject: [PATCH 2/6] fix brcypt leftover --- DOCUMENTATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 95af9e8bf..d72fb6b37 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -758,7 +758,7 @@ Available methods: `bcrypt` : This uses a modified version of the Blowfish stream cipher. It's very secure. - The installation of **radicale[bcrypt]** is required for this. + The installation of **bcrypt** is required for this. `md5` : This uses an iterated md5 digest of the password with a salt. From b5d022fe089219aad1c4603194bc182eb1ad4cc4 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Tue, 12 Mar 2024 06:06:40 +0100 Subject: [PATCH 3/6] extend htpasswd_encryption options with sha256/512/autodetect --- config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config b/config index bf28479a2..1d08c9b73 100644 --- a/config +++ b/config @@ -59,7 +59,7 @@ #htpasswd_filename = /etc/radicale/users # Htpasswd encryption method -# Value: plain | bcrypt | md5 +# Value: plain | bcrypt | md5 | sha256 | sha512 | autodetect # bcrypt requires the installation of 'bcrypt' module. #htpasswd_encryption = md5 From 401b68fe0860284dc14e539917d08350900f4ed4 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Tue, 12 Mar 2024 06:08:26 +0100 Subject: [PATCH 4/6] extend htpasswd_encryption options with sha256/512/autodetect --- radicale/auth/htpasswd.py | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/radicale/auth/htpasswd.py b/radicale/auth/htpasswd.py index 8bba1f780..098f7b783 100644 --- a/radicale/auth/htpasswd.py +++ b/radicale/auth/htpasswd.py @@ -3,6 +3,7 @@ # Copyright © 2008 Pascal Halter # Copyright © 2008-2017 Guillaume Ayoub # Copyright © 2017-2019 Unrud +# Copyright © 2024 Peter Bieringer # # 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 @@ -22,12 +23,12 @@ Apache's htpasswd command (httpd.apache.org/docs/programs/htpasswd.html) manages a file for storing user credentials. It can encrypt passwords using -different the methods BCRYPT or MD5-APR1 (a version of MD5 modified for -Apache). MD5-APR1 provides medium security as of 2015. Only BCRYPT can be +different the methods BCRYPT/SHA256/SHA512 or MD5-APR1 (a version of MD5 modified for +Apache). MD5-APR1 provides medium security as of 2015. Only BCRYPT/SHA256/SHA512 can be considered secure by current standards. MD5-APR1-encrypted credentials can be written by all versions of htpasswd (it -is the default, in fact), whereas BCRYPT requires htpasswd 2.4.x or newer. +is the default, in fact), whereas BCRYPT/SHA256/SHA512 requires htpasswd 2.4.x or newer. The `is_authenticated(user, password)` function provided by this module verifies the user-given credentials by parsing the htpasswd credential file @@ -37,13 +38,13 @@ The following htpasswd password encrpytion methods are supported by Radicale out-of-the-box: - - - plain-text (created by htpasswd -p...) -- INSECURE - - MD5-APR1 (htpasswd -m...) -- htpasswd's default method + - plain-text (created by htpasswd -p ...) -- INSECURE + - MD5-APR1 (htpasswd -m ...) -- htpasswd's default method, INSECURE + - SHA256 (htpasswd -2 ...) + - SHA512 (htpasswd -5 ...) When bcrypt is installed: - - - BCRYPT (htpasswd -B...) -- Requires htpasswd 2.4.x + - BCRYPT (htpasswd -B ...) -- Requires htpasswd 2.4.x """ @@ -51,9 +52,9 @@ import hmac from typing import Any -from passlib.hash import apr_md5_crypt +from passlib.hash import apr_md5_crypt, sha256_crypt, sha512_crypt -from radicale import auth, config +from radicale import auth, config, logger class Auth(auth.BaseAuth): @@ -67,18 +68,24 @@ def __init__(self, configuration: config.Configuration) -> None: self._encoding = configuration.get("encoding", "stock") encryption: str = configuration.get("auth", "htpasswd_encryption") + logger.info("auth password encryption: %s", encryption) + if encryption == "plain": self._verify = self._plain elif encryption == "md5": self._verify = self._md5apr1 - elif encryption == "bcrypt": + elif encryption == "bcrypt" or encryption == "autodetect": try: import bcrypt except ImportError as e: raise RuntimeError( - "The htpasswd encryption method 'bcrypt' requires " + "The htpasswd encryption method 'bcrypt' or 'auto' requires " "the bcrypt module.") from e - self._verify = functools.partial(self._bcrypt, bcrypt) + if encryption == "bcrypt": + self._verify = functools.partial(self._bcrypt, bcrypt) + else: + self._verify = self._autodetect + self._verify_bcrypt = functools.partial(self._bcrypt, bcrypt) else: raise RuntimeError("The htpasswd encryption method %r is not " "supported." % encryption) @@ -93,6 +100,29 @@ def _bcrypt(self, bcrypt: Any, hash_value: str, password: str) -> bool: def _md5apr1(self, hash_value: str, password: str) -> bool: return apr_md5_crypt.verify(password, hash_value.strip()) + def _sha256(self, hash_value: str, password: str) -> bool: + return sha256_crypt.verify(password, hash_value.strip()) + + def _sha512(self, hash_value: str, password: str) -> bool: + return sha512_crypt.verify(password, hash_value.strip()) + + def _autodetect(self, hash_value: str, password: str) -> bool: + if hash_value.startswith("$apr1$", 0, 6) and len(hash_value) == 37: + # MD5-APR1 + return self._md5apr1(hash_value, password) + elif hash_value.startswith("$2y$", 0, 4) and len(hash_value) == 60: + # BCRYPT + return self._verify_bcrypt(hash_value, password) + elif hash_value.startswith("$5$", 0, 3) and len(hash_value) == 63: + # SHA-256 + return self._sha256(hash_value, password) + elif hash_value.startswith("$6$", 0, 3) and len(hash_value) == 106: + # SHA-512 + return self._sha512(hash_value, password) + else: + # assumed plaintext + return self._plain(hash_value, password) + def login(self, login: str, password: str) -> str: """Validate credentials. From 80bf824b918be285098f089ced0356e40bd5beee Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Tue, 12 Mar 2024 06:10:16 +0100 Subject: [PATCH 5/6] extend htpasswd_encryption options with sha256/512/autodetect --- DOCUMENTATION.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index d72fb6b37..d553f542d 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -761,7 +761,16 @@ Available methods: The installation of **bcrypt** is required for this. `md5` -: This uses an iterated md5 digest of the password with a salt. +: This uses an iterated MD5 digest of the password with a salt. + +`sha256` +: This uses an iterated SHA-256 digest of the password with a salt. + +`sha512` +: This uses an iterated SHA-512 digest of the password with a salt. + +`autodetect` +: This selects autodetection of method per entry. Default: `md5` From bb185a941d3eedaba8aac704f53ac3e6bdbcbe98 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Tue, 12 Mar 2024 06:13:54 +0100 Subject: [PATCH 6/6] extend htpasswd_encryption options with sha256/512/autodetect --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d64fa253..a2659bb63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * Enhancement: autodetect logging to systemd journal * Enhancement: test code * Enhancement: option for global permit to delete collection +* Enhancement: auth type 'htpasswd' supports now 'htpasswd_encryption' sha256/sha512 and "autodetect" for smooth transition * Improve: Dockerfiles * Update: documentations + examples * Dependency: limit typegard version < 3