From 5aa059bb24338f4d56b3b76d76e32fc56c2a53bb Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 30 Oct 2022 14:22:25 +0100 Subject: [PATCH] prefer sha256 (the old-way) over sha1 mixup for two different ftpds Signed-off-by: Michael Kaufmann --- install/froxlor.sql.php | 1 - install/updates/froxlor/update_2.x.inc.php | 3 --- lib/Froxlor/Api/Commands/Ftps.php | 7 ++---- lib/Froxlor/System/Crypt.php | 29 +++++++++++++--------- lib/configfiles/bionic.xml | 2 +- lib/configfiles/bookworm.xml | 2 +- lib/configfiles/bullseye.xml | 2 +- lib/configfiles/buster.xml | 2 +- lib/configfiles/focal.xml | 2 +- lib/configfiles/gentoo.xml | 2 +- lib/configfiles/jammy.xml | 2 +- 11 files changed, 26 insertions(+), 28 deletions(-) diff --git a/install/froxlor.sql.php b/install/froxlor.sql.php index c51e1c5e..8ec52008 100644 --- a/install/froxlor.sql.php +++ b/install/froxlor.sql.php @@ -43,7 +43,6 @@ CREATE TABLE `ftp_users` ( `uid` int(5) NOT NULL default '0', `gid` int(5) NOT NULL default '0', `password` varchar(255) NOT NULL, - `password_compat` varchar(255) NOT NULL, `homedir` varchar(255) NOT NULL default '', `shell` varchar(255) NOT NULL default '/bin/false', `login_enabled` enum('N','Y') NOT NULL default 'N', diff --git a/install/updates/froxlor/update_2.x.inc.php b/install/updates/froxlor/update_2.x.inc.php index fceeeaf1..405aabfd 100644 --- a/install/updates/froxlor/update_2.x.inc.php +++ b/install/updates/froxlor/update_2.x.inc.php @@ -70,9 +70,6 @@ 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_USERS . "` ADD `password_compat` varchar(255) NOT NULL default '' AFTER `password`;"); - // update existing entries - Database::query("UPDATE `" . TABLE_FTP_USERS . "` SET `password_compat` = `password`;"); // 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 '';"); diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 99e2e4d6..67950a73 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -173,17 +173,15 @@ class Ftps extends ApiCommand implements ResourceEntity } else { $path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); $cryptPassword = Crypt::makeCryptPassword($password, false, true); - $cryptPasswordCompat = Crypt::makeCryptPassword($password, true, true); $stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_USERS . "` - (`customerid`, `username`, `description`, `password`, `password_compat`, `homedir`, `login_enabled`, `uid`, `gid`, `shell`) + (`customerid`, `username`, `description`, `password`, `homedir`, `login_enabled`, `uid`, `gid`, `shell`) VALUES (:customerid, :username, :description, :password, :passwordc, :homedir, 'y', :guid, :guid, :shell)"); $params = [ "customerid" => $customer['customerid'], "username" => $username, "description" => $description, "password" => $cryptPassword, - "passwordc" => $cryptPasswordCompat, "homedir" => $path, "guid" => $customer['guid'], "shell" => $shell @@ -444,10 +442,9 @@ class Ftps extends ApiCommand implements ResourceEntity Response::standardError('passwordshouldnotbeusername', '', true); } $cryptPassword = Crypt::makeCryptPassword($password, false, true); - $cryptPasswordCompat = Crypt::makeCryptPassword($password, true, true); $stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "` - SET `password` = :password, `password_compat` = :passwordc + SET `password` = :password WHERE `customerid` = :customerid AND `id` = :id "); diff --git a/lib/Froxlor/System/Crypt.php b/lib/Froxlor/System/Crypt.php index 791cd481..f3122f53 100644 --- a/lib/Froxlor/System/Crypt.php +++ b/lib/Froxlor/System/Crypt.php @@ -35,8 +35,13 @@ class Crypt /** * Generates a random password + * + * @param int $length optional, will be read from settings if not given + * @param bool $isSalt optional, default false, do not include special characters + * + * @return string */ - public static function generatePassword(int $length = 0) + public static function generatePassword(int $length = 0, bool $isSalt = false) { $alpha_lower = 'abcdefghijklmnopqrstuvwxyz'; $alpha_upper = strtoupper($alpha_lower); @@ -57,7 +62,7 @@ class Crypt $pw .= mb_substr(self::specialShuffle($numeric), 0, $n); } - if (Settings::Get('panel.password_special_char_required')) { + if (Settings::Get('panel.password_special_char_required') && !$isSalt) { $pw .= mb_substr(self::specialShuffle($special), 0, $n); } @@ -207,21 +212,21 @@ class Crypt * @param string $password * Password to be encrypted * @param bool $htpasswd - * optional whether to generate a SHA1 password for directory protection, if this and $openssl is set, outputs sha1-hash - * @param bool $openssl - * optional generates $htpasswd like strings but for proftpd {algo}base64encoded_hash, if this and $htpasswd is set, outputs sha1-hash + * optional whether to generate a SHA1 password for directory protection + * @param bool $ftpd + * optional generates sha256 password strings for proftpd/pureftpd * * @return string encrypted password */ - public static function makeCryptPassword($password, $htpasswd = false, $openssl = false) + public static function makeCryptPassword(string $password, bool $htpasswd = false, bool $ftpd = false) { - if ($htpasswd || $openssl) { - if ($htpasswd && $openssl) { - // sha1 compatible for pure-ftpd (not encoded) - return sha1($password); + if ($htpasswd || $ftpd) { + if ($ftpd) { + // sha256 compatible for proftpd and pure-ftpd + return crypt($password, '$5$' . self::generatePassword(16, true) . '$'); } - // sha1 hash for either dir-protection or (if openssl=1) for proftpd - return '{SHA' . ($openssl ? '1' : '') . '}' . base64_encode(sha1($password, true)); + // sha1 hash for dir-protection + return '{SHA}' . base64_encode(sha1($password, true)); } // crypt using the specified crypt-algorithm or system default $algo = Settings::Get('system.passwordcryptfunc') !== null ? Settings::Get('system.passwordcryptfunc') : PASSWORD_DEFAULT; diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index c985303b..db899f82 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -4459,7 +4459,7 @@ MYSQLCrypt any # Query to execute in order to fetch the password -MYSQLGetPW SELECT password_compat FROM ftp_users WHERE username="\L" AND login_enabled="y" +MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" # Query to execute in order to fetch the system user name or uid diff --git a/lib/configfiles/bookworm.xml b/lib/configfiles/bookworm.xml index 119b360d..a99fd877 100644 --- a/lib/configfiles/bookworm.xml +++ b/lib/configfiles/bookworm.xml @@ -3098,7 +3098,7 @@ MYSQLCrypt any # Query to execute in order to fetch the password -MYSQLGetPW SELECT password_compat FROM ftp_users WHERE username="\L" AND login_enabled="y" +MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" # Query to execute in order to fetch the system user name or uid diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 7ed156c6..64433043 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -4670,7 +4670,7 @@ MYSQLCrypt any # Query to execute in order to fetch the password -MYSQLGetPW SELECT password_compat FROM ftp_users WHERE username="\L" AND login_enabled="y" +MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" # Query to execute in order to fetch the system user name or uid diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index 85d09bd1..ab76b0b0 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -4661,7 +4661,7 @@ MYSQLCrypt any # Query to execute in order to fetch the password -MYSQLGetPW SELECT password_compat FROM ftp_users WHERE username="\L" AND login_enabled="y" +MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" # Query to execute in order to fetch the system user name or uid diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index c106349c..6831c6ef 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -3876,7 +3876,7 @@ MYSQLCrypt any # Query to execute in order to fetch the password -MYSQLGetPW SELECT password_compat FROM ftp_users WHERE username="\L" AND login_enabled="y" +MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" # Query to execute in order to fetch the system user name or uid diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml index 79b90cb9..ddf594a3 100644 --- a/lib/configfiles/gentoo.xml +++ b/lib/configfiles/gentoo.xml @@ -3577,7 +3577,7 @@ MYSQLUser MYSQLPassword MYSQLDatabase MYSQLCrypt any -MYSQLGetPW SELECT password_compat FROM ftp_users WHERE username="\L" AND login_enabled="y" +MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" MYSQLGetUID SELECT uid FROM ftp_users WHERE username="\L" AND login_enabled="y" MYSQLGetGID SELECT gid FROM ftp_users WHERE username="\L" AND login_enabled="y" MYSQLGetDir SELECT homedir FROM ftp_users WHERE username="\L" AND login_enabled="y" diff --git a/lib/configfiles/jammy.xml b/lib/configfiles/jammy.xml index 60c8faab..5311eefe 100644 --- a/lib/configfiles/jammy.xml +++ b/lib/configfiles/jammy.xml @@ -3876,7 +3876,7 @@ MYSQLCrypt any # Query to execute in order to fetch the password -MYSQLGetPW SELECT password_compat FROM ftp_users WHERE username="\L" AND login_enabled="y" +MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" # Query to execute in order to fetch the system user name or uid