Support of different default pass schemes + support of BLF-CRYPT (#3832)

* Introduce MAILCOW_PASS_SCHEME in order to support blowfish (cf. mailcow/mailcow-dockerized#1019)

* Furthermore added dovecot to support new environment varible for MAILCOW_PASS_SCHEME defaulted to SSHA256

* Revert changes regarding gitignore.

* Added fallback to SSHA256 if environment is not proper prepared.

* No fallback within management frontend, as it must match to other components.

* Unified and corrected alignment; implemented support of SSHA512

* Currently, password_hash of PHP is using by default bcrypt (BLF). As this might change later, we must ensure, that BLF is still used after PHP changes its default.

* Switched to BLF-CRYPT by default (even on update)

* Switched to BLF-CRYPT by default (even on update)

* Adding information in config generation / update with link to supported hash algorithm

* Bump sogo version to 1.92

* Fallback to BLF-CRYPT in case password scheme is not proper defined for Mailcow administration.
master
Lukas Schreiner 2020-11-15 20:22:35 +01:00 committed by GitHub
parent 6d4555eb38
commit d96bf91a0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 5 deletions

View File

@ -141,7 +141,7 @@ cat <<EOF > /etc/dovecot/sql/dovecot-dict-sql-passdb.conf
# Autogenerated by mailcow # Autogenerated by mailcow
driver = mysql driver = mysql
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
default_pass_scheme = SSHA256 default_pass_scheme = ${MAILCOW_PASS_SCHEME}
password_query = SELECT password FROM mailbox WHERE active = '1' AND username = '%u' AND domain IN (SELECT domain FROM domain WHERE domain='%d' AND active='1') AND JSON_UNQUOTE(JSON_VALUE(attributes, '$.force_pw_update')) != '1' AND (JSON_UNQUOTE(JSON_VALUE(attributes, '$.%s_access')) = '1' OR ('%s' != 'imap' AND '%s' != 'pop3')) password_query = SELECT password FROM mailbox WHERE active = '1' AND username = '%u' AND domain IN (SELECT domain FROM domain WHERE domain='%d' AND active='1') AND JSON_UNQUOTE(JSON_VALUE(attributes, '$.force_pw_update')) != '1' AND (JSON_UNQUOTE(JSON_VALUE(attributes, '$.%s_access')) = '1' OR ('%s' != 'imap' AND '%s' != 'pop3'))
EOF EOF

View File

@ -204,7 +204,7 @@ while read -r line gal
<key>type</key> <key>type</key>
<string>sql</string> <string>sql</string>
<key>userPasswordAlgorithm</key> <key>userPasswordAlgorithm</key>
<string>ssha256</string> <string>${MAILCOW_PASS_SCHEME}</string>
<key>prependPasswordScheme</key> <key>prependPasswordScheme</key>
<string>YES</string> <string>YES</string>
<key>viewURL</key> <key>viewURL</key>

View File

@ -84,8 +84,25 @@ function ip_acl($ip, $networks) {
return false; return false;
} }
function hash_password($password) { function hash_password($password) {
$salt_str = bin2hex(openssl_random_pseudo_bytes(8)); // default_pass_scheme is determined in vars.inc.php (or corresponding local file)
return "{SSHA256}".base64_encode(hash('sha256', $password . $salt_str, true) . $salt_str); // in case default pass scheme is not defined, falling back to BLF-CRYPT.
global $default_pass_scheme;
$pw_hash = NULL;
switch (strtoupper($default_pass_scheme)) {
case "SSHA256":
$salt_str = bin2hex(openssl_random_pseudo_bytes(8));
$pw_hash = "{SSHA256}".base64_encode(hash('sha256', $password . $salt_str, true) . $salt_str);
break;
case "SSHA512":
$salt_str = bin2hex(openssl_random_pseudo_bytes(8));
$pw_hash = "{SSHA512}".base64_encode(hash('sha512', $password . $salt_str, true) . $salt_str);
break;
case "BLF-CRYPT":
default:
$pw_hash = "{BLF-CRYPT}" . password_hash($password, PASSWORD_BCRYPT);
break;
}
return $pw_hash;
} }
function last_login($user) { function last_login($user) {
global $pdo; global $pdo;
@ -502,6 +519,12 @@ function verify_hash($hash, $password) {
if (password_verify($password, $hash)) { if (password_verify($password, $hash)) {
return true; return true;
} }
}
elseif (preg_match('/^{BLF-CRYPT}/i', $hash)) {
$hash = preg_replace('/^{BLF-CRYPT}/i', '', $hash);
if (password_verify($password, $hash)) {
return true;
}
} }
return false; return false;
} }

View File

@ -17,6 +17,7 @@ $database_name = getenv('DBNAME');
// Other variables // Other variables
$mailcow_hostname = getenv('MAILCOW_HOSTNAME'); $mailcow_hostname = getenv('MAILCOW_HOSTNAME');
$default_pass_scheme = getenv('MAILCOW_PASS_SCHEME');
// Autodiscover settings // Autodiscover settings
// === // ===

View File

@ -133,6 +133,7 @@ services:
- DBUSER=${DBUSER} - DBUSER=${DBUSER}
- DBPASS=${DBPASS} - DBPASS=${DBPASS}
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- IMAP_PORT=${IMAP_PORT:-143} - IMAP_PORT=${IMAP_PORT:-143}
- IMAPS_PORT=${IMAPS_PORT:-993} - IMAPS_PORT=${IMAPS_PORT:-993}
- POP_PORT=${POP_PORT:-110} - POP_PORT=${POP_PORT:-110}
@ -159,7 +160,7 @@ services:
- phpfpm - phpfpm
sogo-mailcow: sogo-mailcow:
image: mailcow/sogo:1.91 image: mailcow/sogo:1.92
environment: environment:
- DBNAME=${DBNAME} - DBNAME=${DBNAME}
- DBUSER=${DBUSER} - DBUSER=${DBUSER}
@ -167,6 +168,7 @@ services:
- TZ=${TZ} - TZ=${TZ}
- LOG_LINES=${LOG_LINES:-9999} - LOG_LINES=${LOG_LINES:-9999}
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- ACL_ANYONE=${ACL_ANYONE:-disallow} - ACL_ANYONE=${ACL_ANYONE:-disallow}
- ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
- IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
@ -221,6 +223,7 @@ services:
- DBPASS=${DBPASS} - DBPASS=${DBPASS}
- TZ=${TZ} - TZ=${TZ}
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
- MAILCOW_PASS_SCHEME=${MAILCOW_PASS_SCHEME:-BLF-CRYPT}
- IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
- MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-1440} - MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-1440}

View File

@ -117,6 +117,11 @@ cat << EOF > mailcow.conf
MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
# Password hash algorithm
# Only certain password hash algorithm are supported. For a fully list of supported schemes,
# see https://mailcow.github.io/mailcow-dockerized-docs/model-passwd/
MAILCOW_PASS_SCHEME=BLF-CRYPT
# ------------------------------ # ------------------------------
# SQL database configuration # SQL database configuration
# ------------------------------ # ------------------------------

View File

@ -217,6 +217,7 @@ CONFIG_ARRAY=(
"REDIS_PORT" "REDIS_PORT"
"DOVECOT_MASTER_USER" "DOVECOT_MASTER_USER"
"DOVECOT_MASTER_PASS" "DOVECOT_MASTER_PASS"
"MAILCOW_PASS_SCHEME"
) )
sed -i --follow-symlinks '$a\' mailcow.conf sed -i --follow-symlinks '$a\' mailcow.conf
@ -390,6 +391,14 @@ for option in ${CONFIG_ARRAY[@]}; do
echo '# LEAVE EMPTY IF UNSURE' >> mailcow.conf echo '# LEAVE EMPTY IF UNSURE' >> mailcow.conf
echo "DOVECOT_MASTER_PASS=" >> mailcow.conf echo "DOVECOT_MASTER_PASS=" >> mailcow.conf
fi fi
elif [[ ${option} == "MAILCOW_PASS_SCHEME" ]]; then
if ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
echo '# Password hash algorithm' >> mailcow.conf
echo '# Only certain password hash algorithm are supported. For a fully list of supported schemes,' >> mailcow.conf
echo '# see https://mailcow.github.io/mailcow-dockerized-docs/model-passwd/' >> mailcow.conf
echo "MAILCOW_PASS_SCHEME=BLF-CRYPT" >> mailcow.conf
fi
elif ! grep -q ${option} mailcow.conf; then elif ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf" echo "Adding new option \"${option}\" to mailcow.conf"
echo "${option}=n" >> mailcow.conf echo "${option}=n" >> mailcow.conf