remove 'default_password_scheme' for dovecot configs as hashes can be different now and are read by given hash-algo prefix;

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann
2022-11-12 09:38:43 +01:00
parent f49fd5f0f7
commit 1d938f2a43
14 changed files with 248 additions and 194 deletions

View File

@@ -93,7 +93,7 @@ if ($action == 'delete' && $id > 0) {
'page' => $page
]);
}
} elseif ($action == 'add') {
} elseif (isset($_POST['send']) && $_POST['send'] == 'send' && $action == 'add') {
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_API_KEYS . "` SET
`apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''

View File

@@ -916,7 +916,7 @@ INSERT INTO `cronjobs_run` (`id`, `module`, `cronfile`, `cronclass`, `interval`,
DROP TABLE IF EXISTS `ftp_quotalimits`;
CREATE TABLE IF NOT EXISTS `ftp_quotalimits` (
`name` varchar(30) default NULL,
`name` varchar(255) default NULL,
`quota_type` enum('user','group','class','all') NOT NULL default 'user',
`per_session` enum('false','true') NOT NULL default 'false',
`limit_type` enum('soft','hard') NOT NULL default 'hard',
@@ -935,7 +935,7 @@ INSERT INTO `ftp_quotalimits` (`name`, `quota_type`, `per_session`, `limit_type`
DROP TABLE IF EXISTS `ftp_quotatallies`;
CREATE TABLE IF NOT EXISTS `ftp_quotatallies` (
`name` varchar(30) NOT NULL,
`name` varchar(255) NOT NULL,
`quota_type` enum('user','group','class','all') NOT NULL,
`bytes_in_used` float NOT NULL,
`bytes_out_used` float NOT NULL,

View File

@@ -37,11 +37,11 @@ if (!defined('_CRON_UPDATE')) {
}
// last 0.10.x release
if (Froxlor::isFroxlorVersion('0.10.38')) {
if (Froxlor::isFroxlorVersion('0.10.38.2')) {
$update_to = '2.0.0-beta1';
Update::showUpdateStep("Updating from 0.10.38 to ".$update_to, false);
Update::showUpdateStep("Updating from 0.10.38.2 to ".$update_to, false);
Update::showUpdateStep("Removing unused table");
Database::query("DROP TABLE IF EXISTS `panel_sessions`;");
@@ -70,6 +70,8 @@ if (Froxlor::isFroxlorVersion('0.10.38')) {
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `allowed_mysqlserver` varchar(500) NOT NULL default '[0]';");
// ftp_users adjustments
Database::query("ALTER TABLE `" . TABLE_FTP_USERS . "` CHANGE `password` varchar(255) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_FTP_QUOTALIMITS . "` CHANGE `name` varchar(255) default NULL;");
Database::query("ALTER TABLE `" . TABLE_FTP_QUOTATALLIES . "` CHANGE `name` varchar(255) default NULL;");
// mail_users adjustments
Database::query("ALTER TABLE `" . TABLE_MAIL_USERS . "` CHANGE `password` varchar(255) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_MAIL_USERS . "` CHANGE `password_enc` varchar(255) NOT NULL default '';");
@@ -174,6 +176,13 @@ if (Froxlor::isFroxlorVersion('0.10.38')) {
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'letsencryptstate'");
Update::lastStepStatus(0);
Update::showUpdateStep("Updating email account password-hashes");
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = REPLACE(`password`, '$1$', '{MD5-CRYPT}$1$') WHERE SUBSTRING(`password`, 1, 3) = '$1$'");
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = REPLACE(`password`, '$5$', '{SHA256-CRYPT}$5$') WHERE SUBSTRING(`password`, 1, 3) = '$5$'");
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = REPLACE(`password`, '$6$', '{SHA512-CRYPT}$6$') WHERE SUBSTRING(`password`, 1, 3) = '$6$'");
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = REPLACE(`password`, '$2y$', '{BLF-CRYPT}$2y$') WHERE SUBSTRING(`password`, 1, 4) = '$2y$'");
Update::lastStepStatus(0);
Froxlor::updateToVersion($update_to);
}

View File

@@ -251,6 +251,10 @@ class Ajax
$allowed_from = isset($_POST['allowed_from']) ? $_POST['allowed_from'] : "";
$valid_until = isset($_POST['valid_until']) ? $_POST['valid_until'] : "";
if (empty($keyid)) {
return $this->errorResponse('Invalid call', 406);
}
// validate allowed_from
if (!empty($allowed_from)) {
$ip_list = array_map('trim', explode(",", $allowed_from));

View File

@@ -555,7 +555,7 @@ abstract class ApiCommand extends ApiParameter
* @param boolean $internal
* optional whether called internally, default false
*
* @return ApiCommand
* @return static
* @throws Exception
*/
public static function getLocal($userinfo = null, $params = null, $internal = false)

View File

@@ -146,8 +146,20 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
Response::standardError('passwordshouldnotbeusername', '', true);
}
// prefix hash-algo
switch (Settings::Get('system.passwordcryptfunc')) {
case PASSWORD_ARGON2I:
$cpPrefix = '{ARGON2I}';
break;
case PASSWORD_ARGON2ID:
$cpPrefix = '{ARGON2ID}';
break;
default:
$cpPrefix = '{BLF-CRYPT}';
break;
}
// encrypt the password
$cryptPassword = Crypt::makeCryptPassword($password);
$cryptPassword = $cpPrefix . Crypt::makeCryptPassword($password);
$email_user = substr($email_full, 0, strrpos($email_full, "@"));
$email_domain = substr($email_full, strrpos($email_full, "@") + 1);
@@ -376,7 +388,20 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
Response::standardError('passwordshouldnotbeusername', '', true);
}
$password = Crypt::validatePassword($password, true);
$cryptPassword = Crypt::makeCryptPassword($password);
// prefix hash-algo
switch (Settings::Get('system.passwordcryptfunc')) {
case PASSWORD_ARGON2I:
$cpPrefix = '{ARGON2I}';
break;
case PASSWORD_ARGON2ID:
$cpPrefix = '{ARGON2ID}';
break;
default:
$cpPrefix = '{BLF-CRYPT}';
break;
}
// encrypt the password
$cryptPassword = $cpPrefix . Crypt::makeCryptPassword($password);
$upd_query .= (Settings::Get('system.mailpwcleartext') == '1' ? "`password` = :password, " : '') . "`password_enc`= :password_enc";
$upd_params['password_enc'] = $cryptPassword;
if (Settings::Get('system.mailpwcleartext') == '1') {

View File

@@ -2692,7 +2692,7 @@ connect = host=<SQL_HOST> dbname=<SQL_DB> user=<SQL_UNPRIVILEGED_USER> password=
# List of supported schemes is in
# http://wiki2.dovecot.org/Authentication/PasswordSchemes
#
default_pass_scheme = CRYPT
#default_pass_scheme = CRYPT
# passdb query to retrieve the password. It can return fields:
# password - The user's password. This field must be returned.

View File

@@ -2468,7 +2468,7 @@ dovecot unix - n n - - pipe
<content><![CDATA[
driver = mysql
connect = host=<SQL_HOST> dbname=<SQL_DB> user=<SQL_UNPRIVILEGED_USER> password=<SQL_UNPRIVILEGED_PASSWORD>
default_pass_scheme = CRYPT
#default_pass_scheme = CRYPT
user_query = SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir, maildir) AS mail, uid, gid, CONCAT('*:storage=', quota, 'M') as quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u')
password_query = SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota, 'M') as userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve')))
iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)"

View File

@@ -2654,7 +2654,7 @@ connect = host=<SQL_HOST> dbname=<SQL_DB> user=<SQL_UNPRIVILEGED_USER> password=
# List of supported schemes is in
# http://wiki2.dovecot.org/Authentication/PasswordSchemes
#
default_pass_scheme = CRYPT
#default_pass_scheme = CRYPT
# passdb query to retrieve the password. It can return fields:
# password - The user's password. This field must be returned.

View File

@@ -2654,7 +2654,7 @@ connect = host=<SQL_HOST> dbname=<SQL_DB> user=<SQL_UNPRIVILEGED_USER> password=
# List of supported schemes is in
# http://wiki2.dovecot.org/Authentication/PasswordSchemes
#
default_pass_scheme = CRYPT
#default_pass_scheme = CRYPT
# passdb query to retrieve the password. It can return fields:
# password - The user's password. This field must be returned.

View File

@@ -2109,7 +2109,7 @@ connect = host=<SQL_HOST> dbname=<SQL_DB> user=<SQL_UNPRIVILEGED_USER> password=
# List of supported schemes is in
# http://wiki2.dovecot.org/Authentication/PasswordSchemes
#
default_pass_scheme = CRYPT
#default_pass_scheme = CRYPT
# passdb query to retrieve the password. It can return fields:
# password - The user's password. This field must be returned.

View File

@@ -2097,7 +2097,7 @@ protocol lda {
<content><![CDATA[
driver = mysql
connect = host=<SQL_HOST> dbname=<SQL_DB> user=<SQL_UNPRIVILEGED_USER> password=<SQL_UNPRIVILEGED_PASSWORD>
default_pass_scheme = CRYPT
#default_pass_scheme = CRYPT
password_query = "SELECT username AS user, password_enc AS password, CONCAT(homedir, maildir) AS userdb_home, uid AS userdb_uid, gid AS userdb_gid, CONCAT('maildir:', homedir, maildir) AS userdb_mail, CONCAT('*:storage=', quota,'M') AS userdb_quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u') AND ((imap = 1 AND '%Ls' = 'imap') OR (pop3 = 1 AND '%Ls' = 'pop3') OR ((postfix = 'Y' AND '%Ls' = 'smtp') OR (postfix = 'Y' AND '%Ls' = 'sieve')))"
user_query = "SELECT CONCAT(homedir, maildir) AS home, CONCAT('maildir:', homedir, maildir) AS mail, uid, gid, CONCAT('*:storage=', quota,'M') AS quota_rule FROM mail_users WHERE (username = '%u' OR email = '%u')"
iterate_query = "SELECT username AS user FROM mail_users WHERE (imap = 1 OR pop3 = 1)"

View File

@@ -2109,7 +2109,7 @@ connect = host=<SQL_HOST> dbname=<SQL_DB> user=<SQL_UNPRIVILEGED_USER> password=
# List of supported schemes is in
# http://wiki2.dovecot.org/Authentication/PasswordSchemes
#
default_pass_scheme = CRYPT
#default_pass_scheme = CRYPT
# passdb query to retrieve the password. It can return fields:
# password - The user's password. This field must be returned.

View File

@@ -424,6 +424,22 @@ class MailsTest extends TestCase
$json_result = EmailAccounts::getLocal($customer_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['popaccountid']);
switch (Settings::Get('system.passwordcryptfunc')) {
case PASSWORD_ARGON2I:
$cpPrefix = '{ARGON2I}';
break;
case PASSWORD_ARGON2ID:
$cpPrefix = '{ARGON2ID}';
break;
default:
$cpPrefix = '{BLF-CRYPT}';
break;
}
// password is not being returned by API, so query directly
$sel_stmt = Database::prepare("SELECT `password_enc` FROM `" . TABLE_MAIL_USERS . "` WHERE `email` = :email");
$result2 = Database::pexecute_first($sel_stmt, ['email' => $result['email']]);
$this->assertEquals($cpPrefix, substr($result2['password_enc'], 0, strlen($cpPrefix)));
}
public function testAdminEmailAccountsUpdate()