Skip to content

Commit b945749

Browse files
committed
Merge branch 'v3.2-devel' of https://github.com/MatthewHana/Radicale-newwebui into v3.2-devel
2 parents 7927b0c + c128b0d commit b945749

File tree

5 files changed

+64
-16
lines changed

5 files changed

+64
-16
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* Enhancement: autodetect logging to systemd journal
1515
* Enhancement: test code
1616
* Enhancement: option for global permit to delete collection
17+
* Enhancement: auth type 'htpasswd' supports now 'htpasswd_encryption' sha256/sha512 and "autodetect" for smooth transition
1718
* Improve: Dockerfiles
1819
* Update: documentations + examples
1920
* Dependency: limit typegard version < 3

DOCUMENTATION.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -758,10 +758,19 @@ Available methods:
758758

759759
`bcrypt`
760760
: This uses a modified version of the Blowfish stream cipher. It's very secure.
761-
The installation of **radicale[bcrypt]** is required for this.
761+
The installation of **bcrypt** is required for this.
762762

763763
`md5`
764-
: This uses an iterated md5 digest of the password with a salt.
764+
: This uses an iterated MD5 digest of the password with a salt.
765+
766+
`sha256`
767+
: This uses an iterated SHA-256 digest of the password with a salt.
768+
769+
`sha512`
770+
: This uses an iterated SHA-512 digest of the password with a salt.
771+
772+
`autodetect`
773+
: This selects autodetection of method per entry.
765774

766775
Default: `md5`
767776

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,11 @@ Radicale is a small but powerful CalDAV (calendars, to-do lists) and CardDAV
1818

1919
For the complete documentation, please visit
2020
[Radicale master Documentation](https://radicale.org/master.html).
21+
22+
Additional hints can be found
23+
* [Radicale Wiki](https://github.com/Kozea/Radicale/wiki)
24+
* [Radicale Issues](https://github.com/Kozea/Radicale/issues)
25+
* [Radicale Discussions](https://github.com/Kozea/Radicale/discussions)
26+
27+
Before reporting an issue, please check
28+
* [Radicale Wiki / Reporting Issues](https://github.com/Kozea/Radicale/wiki/Reporting-Issues)

config

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
#htpasswd_filename = /etc/radicale/users
6060

6161
# Htpasswd encryption method
62-
# Value: plain | bcrypt | md5
62+
# Value: plain | bcrypt | md5 | sha256 | sha512 | autodetect
6363
# bcrypt requires the installation of 'bcrypt' module.
6464
#htpasswd_encryption = md5
6565

radicale/auth/htpasswd.py

+43-13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Copyright © 2008 Pascal Halter
44
# Copyright © 2008-2017 Guillaume Ayoub
55
# Copyright © 2017-2019 Unrud <unrud@outlook.com>
6+
# Copyright © 2024 Peter Bieringer <pb@bieringer.de>
67
#
78
# This library is free software: you can redistribute it and/or modify
89
# it under the terms of the GNU General Public License as published by
@@ -22,12 +23,12 @@
2223
2324
Apache's htpasswd command (httpd.apache.org/docs/programs/htpasswd.html)
2425
manages a file for storing user credentials. It can encrypt passwords using
25-
different the methods BCRYPT or MD5-APR1 (a version of MD5 modified for
26-
Apache). MD5-APR1 provides medium security as of 2015. Only BCRYPT can be
26+
different the methods BCRYPT/SHA256/SHA512 or MD5-APR1 (a version of MD5 modified for
27+
Apache). MD5-APR1 provides medium security as of 2015. Only BCRYPT/SHA256/SHA512 can be
2728
considered secure by current standards.
2829
2930
MD5-APR1-encrypted credentials can be written by all versions of htpasswd (it
30-
is the default, in fact), whereas BCRYPT requires htpasswd 2.4.x or newer.
31+
is the default, in fact), whereas BCRYPT/SHA256/SHA512 requires htpasswd 2.4.x or newer.
3132
3233
The `is_authenticated(user, password)` function provided by this module
3334
verifies the user-given credentials by parsing the htpasswd credential file
@@ -37,23 +38,23 @@
3738
3839
The following htpasswd password encrpytion methods are supported by Radicale
3940
out-of-the-box:
40-
41-
- plain-text (created by htpasswd -p...) -- INSECURE
42-
- MD5-APR1 (htpasswd -m...) -- htpasswd's default method
41+
- plain-text (created by htpasswd -p ...) -- INSECURE
42+
- MD5-APR1 (htpasswd -m ...) -- htpasswd's default method, INSECURE
43+
- SHA256 (htpasswd -2 ...)
44+
- SHA512 (htpasswd -5 ...)
4345
4446
When bcrypt is installed:
45-
46-
- BCRYPT (htpasswd -B...) -- Requires htpasswd 2.4.x
47+
- BCRYPT (htpasswd -B ...) -- Requires htpasswd 2.4.x
4748
4849
"""
4950

5051
import functools
5152
import hmac
5253
from typing import Any
5354

54-
from passlib.hash import apr_md5_crypt
55+
from passlib.hash import apr_md5_crypt, sha256_crypt, sha512_crypt
5556

56-
from radicale import auth, config
57+
from radicale import auth, config, logger
5758

5859

5960
class Auth(auth.BaseAuth):
@@ -67,18 +68,24 @@ def __init__(self, configuration: config.Configuration) -> None:
6768
self._encoding = configuration.get("encoding", "stock")
6869
encryption: str = configuration.get("auth", "htpasswd_encryption")
6970

71+
logger.info("auth password encryption: %s", encryption)
72+
7073
if encryption == "plain":
7174
self._verify = self._plain
7275
elif encryption == "md5":
7376
self._verify = self._md5apr1
74-
elif encryption == "bcrypt":
77+
elif encryption == "bcrypt" or encryption == "autodetect":
7578
try:
7679
import bcrypt
7780
except ImportError as e:
7881
raise RuntimeError(
79-
"The htpasswd encryption method 'bcrypt' requires "
82+
"The htpasswd encryption method 'bcrypt' or 'auto' requires "
8083
"the bcrypt module.") from e
81-
self._verify = functools.partial(self._bcrypt, bcrypt)
84+
if encryption == "bcrypt":
85+
self._verify = functools.partial(self._bcrypt, bcrypt)
86+
else:
87+
self._verify = self._autodetect
88+
self._verify_bcrypt = functools.partial(self._bcrypt, bcrypt)
8289
else:
8390
raise RuntimeError("The htpasswd encryption method %r is not "
8491
"supported." % encryption)
@@ -93,6 +100,29 @@ def _bcrypt(self, bcrypt: Any, hash_value: str, password: str) -> bool:
93100
def _md5apr1(self, hash_value: str, password: str) -> bool:
94101
return apr_md5_crypt.verify(password, hash_value.strip())
95102

103+
def _sha256(self, hash_value: str, password: str) -> bool:
104+
return sha256_crypt.verify(password, hash_value.strip())
105+
106+
def _sha512(self, hash_value: str, password: str) -> bool:
107+
return sha512_crypt.verify(password, hash_value.strip())
108+
109+
def _autodetect(self, hash_value: str, password: str) -> bool:
110+
if hash_value.startswith("$apr1$", 0, 6) and len(hash_value) == 37:
111+
# MD5-APR1
112+
return self._md5apr1(hash_value, password)
113+
elif hash_value.startswith("$2y$", 0, 4) and len(hash_value) == 60:
114+
# BCRYPT
115+
return self._verify_bcrypt(hash_value, password)
116+
elif hash_value.startswith("$5$", 0, 3) and len(hash_value) == 63:
117+
# SHA-256
118+
return self._sha256(hash_value, password)
119+
elif hash_value.startswith("$6$", 0, 3) and len(hash_value) == 106:
120+
# SHA-512
121+
return self._sha512(hash_value, password)
122+
else:
123+
# assumed plaintext
124+
return self._plain(hash_value, password)
125+
96126
def login(self, login: str, password: str) -> str:
97127
"""Validate credentials.
98128

0 commit comments

Comments
 (0)