From a55cd86a4c3cc66037784c15b55cc81de69b3c20 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 23 Oct 2022 20:43:21 +0200 Subject: [PATCH 01/11] adjust button styles in ssl- and dns-editor; don't show notice about pcntl when using --no-fork Signed-off-by: Michael Kaufmann --- dns_editor.php | 4 ++-- lib/Froxlor/Cron/Traffic/TrafficCron.php | 2 +- ssl_editor.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dns_editor.php b/dns_editor.php index 84b62e34..112e5195 100644 --- a/dns_editor.php +++ b/dns_editor.php @@ -125,7 +125,7 @@ UI::view('user/dns-editor.html.twig', [ 'listing' => Listing::format($collection, $dns_list_data, 'dns_list', ['domain_id' => $domain_id]), 'actions_links' => [ [ - 'class' => 'btn-secondary', + 'class' => 'btn-outline-secondary', 'href' => $linker->getLink([ 'section' => 'domains', 'page' => 'domains', @@ -136,7 +136,7 @@ UI::view('user/dns-editor.html.twig', [ 'icon' => 'fa-solid fa-pen' ], [ - 'class' => 'btn-secondary', + 'class' => 'btn-outline-primary', 'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains']), 'label' => lng('menue.domains.domains'), 'icon' => 'fa-solid fa-globe' diff --git a/lib/Froxlor/Cron/Traffic/TrafficCron.php b/lib/Froxlor/Cron/Traffic/TrafficCron.php index 9d8a872e..cb79996b 100644 --- a/lib/Froxlor/Cron/Traffic/TrafficCron.php +++ b/lib/Froxlor/Cron/Traffic/TrafficCron.php @@ -78,7 +78,7 @@ class TrafficCron extends FroxlorCron // Fork failed return 1; } - } else { + } else if (!defined('CRON_NOFORK_FLAG')) { if (extension_loaded('pcntl')) { $msg = "PHP compiled with pcntl but pcntl_fork function is not available."; } else { diff --git a/ssl_editor.php b/ssl_editor.php index 21871190..d4b7bab3 100644 --- a/ssl_editor.php +++ b/ssl_editor.php @@ -97,7 +97,7 @@ if ($action == '' || $action == 'view') { 'editid' => $id, 'actions_links' => [ [ - 'class' => 'btn-secondary', + 'class' => 'btn-outline-secondary', 'href' => $linker->getLink([ 'section' => 'domains', 'page' => 'domains', From 1f69ab7e3fc221909e3d0f159ab563434581adbf Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 24 Oct 2022 14:25:53 +0200 Subject: [PATCH 02/11] fix keep-current-password when editing mysql-server Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/MysqlServer.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/Froxlor/Api/Commands/MysqlServer.php b/lib/Froxlor/Api/Commands/MysqlServer.php index 6ae319d1..42405825 100644 --- a/lib/Froxlor/Api/Commands/MysqlServer.php +++ b/lib/Froxlor/Api/Commands/MysqlServer.php @@ -131,7 +131,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity require Froxlor::getInstallDir() . "/lib/userdata.inc.php"; // le format - if (isset($sql['root_user']) && isset($sql['root_password']) &&!is_array($sql_root)) { + if (isset($sql['root_user']) && isset($sql['root_password']) && !is_array($sql_root)) { $sql_root = array( 0 => array( 'caption' => 'Default', @@ -377,7 +377,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity $mysql_ca = $this->getParam('mysql_ca', true, $result['ssl']['caFile'] ?? ''); $mysql_verifycert = $this->getBoolParam('mysql_verifycert', true, $result['ssl']['verifyServerCertificate'] ?? 0); $privileged_user = $this->getParam('privileged_user', true, $result['user']); - $privileged_password = $this->getParam('privileged_password', true, $result['password']); + $privileged_password = $this->getParam('privileged_password', true, ''); $description = $this->getParam('description', true, $result['caption']); $allow_all_customers = $this->getParam('allow_all_customers', true, 0); $test_connection = $this->getParam('test_connection', true, 1); @@ -397,6 +397,11 @@ class MysqlServer extends ApiCommand implements ResourceEntity $privileged_password = Validate::validate($privileged_password, 'password', '', '', [], true); $description = Validate::validate(trim($description), 'description', Validate::REGEX_DESC_TEXT, '', [], true); + // keep old password? + if (empty($privileged_password)) { + $privileged_password = $result['password']; + } + if ($mysql_host != $result['host']) { // check whether the server is in use by any customer $result_ms = $this->databasesOnServer(true, $dbserver); From 3acc5457b2ca94807a38c0987ff798c64c320e06 Mon Sep 17 00:00:00 2001 From: envoyr Date: Tue, 25 Oct 2022 13:00:04 +0200 Subject: [PATCH 03/11] fix darkmode search, textarea, progress bars and list groups --- templates/Froxlor/src/scss/components/_search.scss | 2 +- templates/Froxlor/src/scss/variables/_dark.scss | 8 ++++++++ templates/Froxlor/src/scss/variables/_main.scss | 3 +++ templates/Froxlor/user/dns-editor.html.twig | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/templates/Froxlor/src/scss/components/_search.scss b/templates/Froxlor/src/scss/components/_search.scss index b16ba530..520891d0 100644 --- a/templates/Froxlor/src/scss/components/_search.scss +++ b/templates/Froxlor/src/scss/components/_search.scss @@ -20,7 +20,7 @@ width: 70vh; max-height: 50vh; - background: #fff; + background: $search-bg; border: $border-color solid 1px; border-radius: 0 0 $border-radius $border-radius; diff --git a/templates/Froxlor/src/scss/variables/_dark.scss b/templates/Froxlor/src/scss/variables/_dark.scss index f0765b25..de2fd249 100644 --- a/templates/Froxlor/src/scss/variables/_dark.scss +++ b/templates/Froxlor/src/scss/variables/_dark.scss @@ -20,6 +20,8 @@ $nav-link-color: $body-color; // List groups $list-group-bg: $gray-800; $list-group-color: $body-color; +$list-group-hover-bg: $gray-700; +$list-group-action-color: $body-color; // Navbar $navbar-bg: $gray-800; @@ -51,3 +53,9 @@ $modal-content-bg: $gray-800; $input-bg: $gray-900; $input-border-color: $black; $input-group-addon-bg: $gray-800; + +// Progress bar +$progress-bg: $gray-900; + +// Search +$search-bg: $gray-800; diff --git a/templates/Froxlor/src/scss/variables/_main.scss b/templates/Froxlor/src/scss/variables/_main.scss index 0bd42f27..667acfe0 100644 --- a/templates/Froxlor/src/scss/variables/_main.scss +++ b/templates/Froxlor/src/scss/variables/_main.scss @@ -80,3 +80,6 @@ $card-border-width: 0; $heading-bg: $navbar-bg; $heading-color: $body-color; $heading-border-color: #dee2e6; + +// Search +$search-bg: $navbar-bg; diff --git a/templates/Froxlor/user/dns-editor.html.twig b/templates/Froxlor/user/dns-editor.html.twig index ec0df31a..dea6e69b 100644 --- a/templates/Froxlor/user/dns-editor.html.twig +++ b/templates/Froxlor/user/dns-editor.html.twig @@ -25,7 +25,7 @@ {% if zonefile is not empty %}
- +
{% endif %} From 34d55833339dd7d2265ae4b809073837cba69ff5 Mon Sep 17 00:00:00 2001 From: envoyr Date: Tue, 25 Oct 2022 13:37:33 +0200 Subject: [PATCH 04/11] display better exception for traffic results if admin has no customers --- admin_traffic.php | 3 +++ lib/Froxlor/Api/ApiCommand.php | 2 +- lng/de.lng.php | 1 + lng/en.lng.php | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/admin_traffic.php b/admin_traffic.php index 2060fe18..352bdc74 100644 --- a/admin_traffic.php +++ b/admin_traffic.php @@ -37,6 +37,9 @@ if ($page == 'overview' || $page == 'customers') { try { $context = Traffic::getCustomerStats($userinfo, $range); } catch (Exception $e) { + if ($e->getCode() === 405) { + Response::dynamicError(lng('traffic.nocustomers')); + } Response::dynamicError($e->getMessage()); } diff --git a/lib/Froxlor/Api/ApiCommand.php b/lib/Froxlor/Api/ApiCommand.php index ca530273..35130a4d 100644 --- a/lib/Froxlor/Api/ApiCommand.php +++ b/lib/Froxlor/Api/ApiCommand.php @@ -470,7 +470,7 @@ abstract class ApiCommand extends ApiParameter * * @param string $customer_hide_option * optional, when called as customer, some options might be hidden due to the - * panel.customer_hide_options ettings + * panel.customer_hide_options settings * * @return array * @throws Exception diff --git a/lng/de.lng.php b/lng/de.lng.php index 272f4a54..ac447272 100644 --- a/lng/de.lng.php +++ b/lng/de.lng.php @@ -2117,6 +2117,7 @@ Vielen Dank, Ihr Administrator', 'http' => 'HTTP', 'ftp' => 'FTP', 'mail' => 'Mail', + 'nocustomers' => 'Es wird mindestens ein Kunde benötigt um die Traffic Statistiken anzuzeigen.', ], 'translator' => '', 'update' => [ diff --git a/lng/en.lng.php b/lng/en.lng.php index 7d440122..18436845 100644 --- a/lng/en.lng.php +++ b/lng/en.lng.php @@ -2243,6 +2243,7 @@ Yours sincerely, your administrator', 'http' => 'HTTP', 'ftp' => 'FTP', 'mail' => 'Mail', + 'nocustomers' => 'You need at least one customer to view the traffic reports.', ], 'translator' => '', 'update' => [ From afde51ecf65b6de8b958d1d854cffe5e9e2c4d74 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 27 Oct 2022 14:14:16 +0200 Subject: [PATCH 05/11] email validation check input before display Signed-off-by: Michael Kaufmann --- index.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index 4f4fa6ac..902d9cbb 100644 --- a/index.php +++ b/index.php @@ -120,7 +120,6 @@ if ($action == '2fa_entercode') { ]); exit(); } elseif ($action == 'login') { - $languages = Language::getLanguages(); if (isset($_POST['send']) && $_POST['send'] == 'send') { $loginname = Validate::validate($_POST['loginname'], 'loginname'); $password = Validate::validate($_POST['password'], 'password'); @@ -358,7 +357,11 @@ if ($action == '2fa_entercode') { break; case 4: $cmail = isset($_GET['customermail']) ? $_GET['customermail'] : 'unknown'; - $message = str_replace('%s', $cmail, lng('error.errorsendingmail')); + if (!Validate::validateEmail($cmail)) { + $message = lng('error.errorsendingmail', ['invalid.address']); + } else { + $message = lng('error.errorsendingmail', [$cmail]); + } break; case 5: $message = lng('error.user_banned'); From 7cb5135725ebeb905c621083002956e037ca5569 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 27 Oct 2022 14:20:07 +0200 Subject: [PATCH 06/11] secure userinput when adding/editing admins/customers Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Admins.php | 4 ++-- lib/Froxlor/Api/Commands/Customers.php | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Admins.php b/lib/Froxlor/Api/Commands/Admins.php index 8c2b516e..a2ed4b76 100644 --- a/lib/Froxlor/Api/Commands/Admins.php +++ b/lib/Froxlor/Api/Commands/Admins.php @@ -245,7 +245,7 @@ class Admins extends ApiCommand implements ResourceEntity $ipaddress = $this->getParam('ipaddress', true, -1); // validation - $name = Validate::validate($name, 'name', '', '', [], true); + $name = Validate::validate($name, 'name', Validate::REGEX_DESC_TEXT, '', [], true); $idna_convert = new IdnaWrapper(); $email = $idna_convert->encode(Validate::validate($email, 'email', '', '', [], true)); $def_language = Validate::validate($def_language, 'default language', '', '', [], true); @@ -581,7 +581,7 @@ class Admins extends ApiCommand implements ResourceEntity } // validation - $name = Validate::validate($name, 'name', '', '', [], true); + $name = Validate::validate($name, 'name', Validate::REGEX_DESC_TEXT, '', [], true); $idna_convert = new IdnaWrapper(); $email = $idna_convert->encode(Validate::validate($email, 'email', '', '', [], true)); $def_language = Validate::validate($def_language, 'default language', '', '', [], true); diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 82789b24..23160048 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -361,12 +361,12 @@ class Customers extends ApiCommand implements ResourceEntity } // validation - $name = Validate::validate($name, 'name', '', '', [], true); - $firstname = Validate::validate($firstname, 'first name', '', '', [], true); - $company = Validate::validate($company, 'company', '', '', [], true); - $street = Validate::validate($street, 'street', '', '', [], true); + $name = Validate::validate($name, 'name', Validate::REGEX_DESC_TEXT, '', [], true); + $firstname = Validate::validate($firstname, 'first name', Validate::REGEX_DESC_TEXT, '', [], true); + $company = Validate::validate($company, 'company', Validate::REGEX_DESC_TEXT, '', [], true); + $street = Validate::validate($street, 'street', Validate::REGEX_DESC_TEXT, '', [], true); $zipcode = Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', [], true); - $city = Validate::validate($city, 'city', '', '', [], true); + $city = Validate::validate($city, 'city', Validate::REGEX_DESC_TEXT, '', [], true); $phone = Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', [], true); $fax = Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', [], true); $idna_convert = new IdnaWrapper(); @@ -1080,12 +1080,12 @@ class Customers extends ApiCommand implements ResourceEntity // validation if ($this->isAdmin()) { $idna_convert = new IdnaWrapper(); - $name = Validate::validate($name, 'name', '', '', [], true); - $firstname = Validate::validate($firstname, 'first name', '', '', [], true); - $company = Validate::validate($company, 'company', '', '', [], true); - $street = Validate::validate($street, 'street', '', '', [], true); + $name = Validate::validate($name, 'name', Validate::REGEX_DESC_TEXT, '', [], true); + $firstname = Validate::validate($firstname, 'first name', Validate::REGEX_DESC_TEXT, '', [], true); + $company = Validate::validate($company, 'company', Validate::REGEX_DESC_TEXT, '', [], true); + $street = Validate::validate($street, 'street', Validate::REGEX_DESC_TEXT, '', [], true); $zipcode = Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', [], true); - $city = Validate::validate($city, 'city', '', '', [], true); + $city = Validate::validate($city, 'city', Validate::REGEX_DESC_TEXT, '', [], true); $phone = Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', [], true); $fax = Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', [], true); $email = $idna_convert->encode(Validate::validate($email, 'email', '', '', [], true)); From 85e3b6af0ead2e3b234bd00c25e29a6d683fdd11 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 27 Oct 2022 14:21:09 +0200 Subject: [PATCH 07/11] add installation command for cron in case it's somehow not present on the system Signed-off-by: Michael Kaufmann --- lib/configfiles/bionic.xml | 1 + lib/configfiles/bookworm.xml | 1 + lib/configfiles/bullseye.xml | 1 + lib/configfiles/buster.xml | 1 + lib/configfiles/focal.xml | 1 + lib/configfiles/gentoo.xml | 1 + lib/configfiles/jammy.xml | 1 + 7 files changed, 7 insertions(+) diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index acfd215d..eaa141a8 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -4683,6 +4683,7 @@ aliases: files + bin/froxlor-cli froxlor:cron --run-task 99]]> diff --git a/lib/configfiles/bookworm.xml b/lib/configfiles/bookworm.xml index 54b20ecc..270ebe32 100644 --- a/lib/configfiles/bookworm.xml +++ b/lib/configfiles/bookworm.xml @@ -3322,6 +3322,7 @@ aliases: files + bin/froxlor-cli froxlor:cron --run-task 99]]> diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index ba4b885a..5d436a04 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -4894,6 +4894,7 @@ aliases: files + bin/froxlor-cli froxlor:cron --run-task 99]]> diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index 3b6d50ca..25e62da4 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -4885,6 +4885,7 @@ aliases: files + bin/froxlor-cli froxlor:cron --run-task 99]]> diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index 68a9da90..f89d8adf 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -4108,6 +4108,7 @@ aliases: files + bin/froxlor-cli froxlor:cron --run-task 99]]> diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml index 2e4c4069..d77f3b6b 100644 --- a/lib/configfiles/gentoo.xml +++ b/lib/configfiles/gentoo.xml @@ -3910,6 +3910,7 @@ aliases: files + bin/froxlor-cli froxlor:cron --run-task 99]]> diff --git a/lib/configfiles/jammy.xml b/lib/configfiles/jammy.xml index a6ea5e30..86389836 100644 --- a/lib/configfiles/jammy.xml +++ b/lib/configfiles/jammy.xml @@ -4108,6 +4108,7 @@ aliases: files + bin/froxlor-cli froxlor:cron --run-task 99]]> From 1f43f5d514fcf58ee5f4e6bc0ef7466d15f96eb6 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 30 Oct 2022 11:11:12 +0100 Subject: [PATCH 08/11] pure-ftpd compatible password hashes for ftp users Signed-off-by: Michael Kaufmann --- install/froxlor.sql.php | 7 ++++--- install/updates/froxlor/update_2.x.inc.php | 8 ++++++++ lib/Froxlor/Api/Commands/Ftps.php | 12 ++++++++---- lib/Froxlor/System/Crypt.php | 19 +++++++++---------- lib/configfiles/bionic.xml | 22 +++++++++++++++++++++- lib/configfiles/bookworm.xml | 22 +++++++++++++++++++++- lib/configfiles/bullseye.xml | 22 +++++++++++++++++++++- lib/configfiles/buster.xml | 22 +++++++++++++++++++++- lib/configfiles/focal.xml | 22 +++++++++++++++++++++- lib/configfiles/gentoo.xml | 19 ++++++++++++++++--- lib/configfiles/jammy.xml | 22 +++++++++++++++++++++- 11 files changed, 171 insertions(+), 26 deletions(-) diff --git a/install/froxlor.sql.php b/install/froxlor.sql.php index 140dcf45..c51e1c5e 100644 --- a/install/froxlor.sql.php +++ b/install/froxlor.sql.php @@ -42,7 +42,8 @@ CREATE TABLE `ftp_users` ( `username` varchar(255) NOT NULL, `uid` int(5) NOT NULL default '0', `gid` int(5) NOT NULL default '0', - `password` varchar(128) NOT NULL, + `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', @@ -65,8 +66,8 @@ CREATE TABLE `mail_users` ( `id` int(11) NOT NULL auto_increment, `email` varchar(255) NOT NULL default '', `username` varchar(255) NOT NULL default '', - `password` varchar(128) NOT NULL default '', - `password_enc` varchar(128) NOT NULL default '', + `password` varchar(255) NOT NULL default '', + `password_enc` varchar(255) NOT NULL default '', `uid` int(11) NOT NULL default '0', `gid` int(11) NOT NULL default '0', `homedir` varchar(255) NOT NULL default '', diff --git a/install/updates/froxlor/update_2.x.inc.php b/install/updates/froxlor/update_2.x.inc.php index 61844be3..fceeeaf1 100644 --- a/install/updates/froxlor/update_2.x.inc.php +++ b/install/updates/froxlor/update_2.x.inc.php @@ -68,6 +68,14 @@ if (Froxlor::isFroxlorVersion('0.10.38')) { Database::query($sql); // new customer allowed_mysqlserver field 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 '';"); Update::lastStepStatus(0); Update::showUpdateStep("Checking for multiple mysql-servers to allow acccess to customers for existing databases"); diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 76826087..99e2e4d6 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -173,15 +173,17 @@ 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`, `homedir`, `login_enabled`, `uid`, `gid`, `shell`) - VALUES (:customerid, :username, :description, :password, :homedir, 'y', :guid, :guid, :shell)"); + (`customerid`, `username`, `description`, `password`, `password_compat`, `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 @@ -442,16 +444,18 @@ 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 + SET `password` = :password, `password_compat` = :passwordc WHERE `customerid` = :customerid AND `id` = :id "); Database::pexecute($stmt, [ "customerid" => $customer['customerid'], "id" => $id, - "password" => $cryptPassword + "password" => $cryptPassword, + "passwordc" => $cryptPasswordCompat ], true, true); $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ftp-account password for '" . $result['username'] . "'"); } diff --git a/lib/Froxlor/System/Crypt.php b/lib/Froxlor/System/Crypt.php index ebe00c86..791cd481 100644 --- a/lib/Froxlor/System/Crypt.php +++ b/lib/Froxlor/System/Crypt.php @@ -207,24 +207,23 @@ class Crypt * @param string $password * Password to be encrypted * @param bool $htpasswd - * optional whether to generate a SHA1 password for directory protection + * 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 - * - * @return string encrypted password) - * - * 0 - default crypt (depends on system configuration) - * 1 - MD5 $1$ - * 2 - BLOWFISH $2y$07$ - * 3 - SHA-256 $5$ (default) - * 4 - SHA-512 $6$ + * optional generates $htpasswd like strings but for proftpd {algo}base64encoded_hash, if this and $htpasswd is set, outputs sha1-hash * + * @return string encrypted password */ public static function makeCryptPassword($password, $htpasswd = false, $openssl = false) { if ($htpasswd || $openssl) { + if ($htpasswd && $openssl) { + // sha1 compatible for pure-ftpd (not encoded) + return sha1($password); + } + // sha1 hash for either dir-protection or (if openssl=1) for proftpd return '{SHA' . ($openssl ? '1' : '') . '}' . 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; return password_hash($password, $algo); } diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index eaa141a8..c985303b 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -4333,6 +4333,26 @@ TLSVerifyClient off + + " +openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 3072 +chmod 0600 /etc/ssl/private/pure-ftpd.pem /etc/ssl/private/pure-ftpd-dhparams.pem +]]> + + + + + + + + + + + + " +openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 3072 +chmod 0600 /etc/ssl/private/pure-ftpd.pem /etc/ssl/private/pure-ftpd-dhparams.pem +]]> + + + + + + + + + + + + " +openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 3072 +chmod 0600 /etc/ssl/private/pure-ftpd.pem /etc/ssl/private/pure-ftpd-dhparams.pem +]]> + + + + + + + + + + + + " +openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 3072 +chmod 0600 /etc/ssl/private/pure-ftpd.pem /etc/ssl/private/pure-ftpd-dhparams.pem +]]> + + + + + + + + + + + + " +openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 3072 +chmod 0600 /etc/ssl/private/pure-ftpd.pem /etc/ssl/private/pure-ftpd-dhparams.pem +]]> + + + + + + + + + + > /etc/portage/package.use/froxlor]]> + + " +openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 3072 +chmod 0600 /etc/ssl/private/pure-ftpd.pem /etc/ssl/private/pure-ftpd-dhparams.pem +]]> + + + + + + @@ -3563,8 +3576,8 @@ MYSQLSocket /var/run/mysqld/mysqld.sock MYSQLUser MYSQLPassword MYSQLDatabase -MYSQLCrypt Crypt -MYSQLGetPW SELECT password FROM ftp_users WHERE username="\L" AND login_enabled="y" +MYSQLCrypt any +MYSQLGetPW SELECT password_compat 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 86389836..60c8faab 100644 --- a/lib/configfiles/jammy.xml +++ b/lib/configfiles/jammy.xml @@ -3750,6 +3750,26 @@ TLSVerifyClient off + + " +openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 3072 +chmod 0600 /etc/ssl/private/pure-ftpd.pem /etc/ssl/private/pure-ftpd-dhparams.pem +]]> + + + + + + + + + + Date: Sun, 30 Oct 2022 14:22:25 +0100 Subject: [PATCH 09/11] 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 From e86f093d31e27ca64f5fe416006e234892bded38 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 30 Oct 2022 14:31:21 +0100 Subject: [PATCH 10/11] forgot to remove leftover prepared statement variable in Ftps.add() Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Ftps.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 67950a73..e0a7d013 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -176,7 +176,7 @@ class Ftps extends ApiCommand implements ResourceEntity $stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_USERS . "` (`customerid`, `username`, `description`, `password`, `homedir`, `login_enabled`, `uid`, `gid`, `shell`) - VALUES (:customerid, :username, :description, :password, :passwordc, :homedir, 'y', :guid, :guid, :shell)"); + VALUES (:customerid, :username, :description, :password, :homedir, 'y', :guid, :guid, :shell)"); $params = [ "customerid" => $customer['customerid'], "username" => $username, From 19284cad00eae6ed7dcc5db45f4cbded301d5294 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 30 Oct 2022 15:06:07 +0100 Subject: [PATCH 11/11] forgot to remove leftover variable in Ftps.update() Signed-off-by: Michael Kaufmann --- lib/Froxlor/Api/Commands/Ftps.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index e0a7d013..76826087 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -451,8 +451,7 @@ class Ftps extends ApiCommand implements ResourceEntity Database::pexecute($stmt, [ "customerid" => $customer['customerid'], "id" => $id, - "password" => $cryptPassword, - "passwordc" => $cryptPasswordCompat + "password" => $cryptPassword ], true, true); $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated ftp-account password for '" . $result['username'] . "'"); }