From 0ed04a6c00423cc5eeffef19558d7598e96fd82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Wed, 30 Mar 2022 22:13:54 -0300 Subject: Remove `trigger_error` calls from `HomeController` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maurício Meneghini Fauth (cherry picked from commit c5611531c03a5c9dfe13510e7fc5b901daa77039) Signed-off-by: Maurício Meneghini Fauth --- libraries/classes/Controllers/HomeController.php | 103 ++++++++++++----------- 1 file changed, 54 insertions(+), 49 deletions(-) (limited to 'libraries') diff --git a/libraries/classes/Controllers/HomeController.php b/libraries/classes/Controllers/HomeController.php index 322ed3702e..998cc3b4ce 100644 --- a/libraries/classes/Controllers/HomeController.php +++ b/libraries/classes/Controllers/HomeController.php @@ -30,10 +30,7 @@ use function ini_get; use function mb_strlen; use function preg_match; use function sprintf; -use function trigger_error; -use const E_USER_NOTICE; -use const E_USER_WARNING; use const PHP_VERSION; use const SODIUM_CRYPTO_SECRETBOX_KEYBYTES; @@ -48,6 +45,12 @@ class HomeController extends AbstractController /** @var DatabaseInterface */ private $dbi; + /** + * @var array> + * @psalm-var list + */ + private $errors = []; + public function __construct( ResponseRenderer $response, Template $template, @@ -241,6 +244,7 @@ class HomeController extends AbstractController 'config_storage_message' => $configStorageMessage ?? '', 'has_theme_manager' => $cfg['ThemeManager'], 'themes' => $this->themeManager->getThemesArray(), + 'errors' => $this->errors, ]); } @@ -256,16 +260,16 @@ class HomeController extends AbstractController */ $gc_time = (int) ini_get('session.gc_maxlifetime'); if ($gc_time < $cfg['LoginCookieValidity']) { - trigger_error( - __( + $this->errors[] = [ + 'message' => __( 'Your PHP parameter [a@https://www.php.net/manual/en/session.' . 'configuration.php#ini.session.gc-maxlifetime@_blank]session.' . 'gc_maxlifetime[/a] is lower than cookie validity configured ' . 'in phpMyAdmin, because of this, your login might expire sooner ' . 'than configured in phpMyAdmin.' ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } } @@ -273,14 +277,14 @@ class HomeController extends AbstractController * Check whether LoginCookieValidity is limited by LoginCookieStore. */ if ($cfg['LoginCookieStore'] != 0 && $cfg['LoginCookieStore'] < $cfg['LoginCookieValidity']) { - trigger_error( - __( + $this->errors[] = [ + 'message' => __( 'Login cookie store is lower than cookie validity configured in ' . 'phpMyAdmin, because of this, your login will expire sooner than ' . 'configured in phpMyAdmin.' ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } /** @@ -292,15 +296,15 @@ class HomeController extends AbstractController && $cfg['Server']['controluser'] === 'pma' && $cfg['Server']['controlpass'] === 'pmapass' ) { - trigger_error( - __( + $this->errors[] = [ + 'message' => __( 'Your server is running with default values for the ' . 'controluser and password (controlpass) and is open to ' . 'intrusion; you really should fix this security weakness' . ' by changing the password for controluser \'pma\'.' ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } /** @@ -308,23 +312,23 @@ class HomeController extends AbstractController */ if (! empty($_SESSION['encryption_key'])) { if (empty($cfg['blowfish_secret'])) { - trigger_error( - __( + $this->errors[] = [ + 'message' => __( 'The configuration file now needs a secret passphrase (blowfish_secret).' ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } elseif (mb_strlen($cfg['blowfish_secret'], '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { - trigger_error( - sprintf( + $this->errors[] = [ + 'message' => sprintf( __( 'The secret passphrase in configuration (blowfish_secret) is not the correct length.' . ' It should be %d bytes long.' ), SODIUM_CRYPTO_SECRETBOX_KEYBYTES ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } } @@ -333,16 +337,16 @@ class HomeController extends AbstractController * production environment. */ if (@file_exists(ROOT_PATH . 'config')) { - trigger_error( - __( + $this->errors[] = [ + 'message' => __( 'Directory [code]config[/code], which is used by the setup script, ' . 'still exists in your phpMyAdmin directory. It is strongly ' . 'recommended to remove it once phpMyAdmin has been configured. ' . 'Otherwise the security of your server may be compromised by ' . 'unauthorized people downloading your configuration.' ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } /** @@ -353,22 +357,22 @@ class HomeController extends AbstractController && ini_get('suhosin.request.max_value_length') && ini_get('suhosin.simulation') == '0' ) { - trigger_error( - sprintf( + $this->errors[] = [ + 'message' => sprintf( __( 'Server running with Suhosin. Please refer to %sdocumentation%s for possible issues.' ), '[doc@faq1-38]', '[/doc]' ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } /* Missing template cache */ if ($this->config->getTempDir('twig') === null) { - trigger_error( - sprintf( + $this->errors[] = [ + 'message' => sprintf( __( 'The $cfg[\'TempDir\'] (%s) is not accessible. ' . 'phpMyAdmin is not able to cache templates and will ' . @@ -376,8 +380,8 @@ class HomeController extends AbstractController ), $this->config->get('TempDir') ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } $this->checkLanguageStats(); @@ -410,12 +414,12 @@ class HomeController extends AbstractController return; } - trigger_error( - 'You are using an incomplete translation, please help to make it ' - . 'better by [a@https://www.phpmyadmin.net/translate/' - . '@_blank]contributing[/a].', - E_USER_NOTICE - ); + $this->errors[] = [ + 'message' => 'You are using an incomplete translation, please help to make it ' + . 'better by [a@https://www.phpmyadmin.net/translate/' + . '@_blank]contributing[/a].', + 'severity' => 'notice', + ]; } private function checkPhpExtensionsRequirements(): void @@ -425,15 +429,15 @@ class HomeController extends AbstractController * to tell user something might be broken without it, see bug #1063149. */ if (! extension_loaded('mbstring')) { - trigger_error( - __( + $this->errors[] = [ + 'message' => __( 'The mbstring PHP extension was not found and you seem to be using' . ' a multibyte charset. Without the mbstring extension phpMyAdmin' . ' is unable to split strings correctly and it may result in' . ' unexpected results.' ), - E_USER_WARNING - ); + 'severity' => 'warning', + ]; } /** @@ -443,12 +447,13 @@ class HomeController extends AbstractController return; } - trigger_error( - __( + $this->errors[] = [ + 'message' => __( 'The curl extension was not found and allow_url_fopen is ' . 'disabled. Due to this some features such as error reporting ' . 'or version check are disabled.' - ) - ); + ), + 'severity' => 'notice', + ]; } } -- cgit v1.2.3 From 5d4884d294ca9b1f069fcacada98f6697f464274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Thu, 15 Sep 2022 13:04:22 -0300 Subject: Update setup page to generate better blowfish_secret keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of generating a printable string, it generates a binary string and converts it to an hexadecimal string. Signed-off-by: Maurício Meneghini Fauth --- libraries/classes/Config/ServerConfigChecks.php | 71 +++++++------------------ libraries/classes/Setup/ConfigGenerator.php | 26 +++++++++ 2 files changed, 46 insertions(+), 51 deletions(-) (limited to 'libraries') diff --git a/libraries/classes/Config/ServerConfigChecks.php b/libraries/classes/Config/ServerConfigChecks.php index 4a8283c742..3420091e94 100644 --- a/libraries/classes/Config/ServerConfigChecks.php +++ b/libraries/classes/Config/ServerConfigChecks.php @@ -11,17 +11,17 @@ use PhpMyAdmin\Core; use PhpMyAdmin\Sanitize; use PhpMyAdmin\Setup\Index as SetupIndex; use PhpMyAdmin\Url; -use PhpMyAdmin\Util; use function __; -use function count; use function function_exists; use function htmlspecialchars; -use function implode; use function ini_get; -use function preg_match; +use function is_string; +use function mb_strlen; +use function sodium_crypto_secretbox_keygen; use function sprintf; -use function strlen; + +use const SODIUM_CRYPTO_SECRETBOX_KEYBYTES; /** * Performs various compatibility, security and consistency checks on current config @@ -247,9 +247,12 @@ class ServerConfigChecks $cookieAuthServer, $blowfishSecretSet ): array { - if ($cookieAuthServer && $blowfishSecret === null) { + if ( + $cookieAuthServer + && (! is_string($blowfishSecret) || mb_strlen($blowfishSecret, '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) + ) { $blowfishSecretSet = true; - $this->cfg->set('blowfish_secret', Util::generateRandom(32)); + $this->cfg->set('blowfish_secret', sodium_crypto_secretbox_keygen()); } return [ @@ -345,55 +348,21 @@ class ServerConfigChecks ): void { // $cfg['blowfish_secret'] // it's required for 'cookie' authentication - if (! $cookieAuthUsed) { - return; - } - - if ($blowfishSecretSet) { - // 'cookie' auth used, blowfish_secret was generated - SetupIndex::messagesSet( - 'notice', - 'blowfish_secret_created', - Descriptions::get('blowfish_secret'), - Sanitize::sanitizeMessage(__( - 'You didn\'t have blowfish secret set and have enabled ' - . '[kbd]cookie[/kbd] authentication, so a key was automatically ' - . 'generated for you. It is used to encrypt cookies; you don\'t need to ' - . 'remember it.' - )) - ); - - return; - } - - $blowfishWarnings = []; - // check length - if (strlen($blowfishSecret) < 32) { - // too short key - $blowfishWarnings[] = __('Key is too short, it should have at least 32 characters.'); - } - - // check used characters - $hasDigits = (bool) preg_match('/\d/', $blowfishSecret); - $hasChars = (bool) preg_match('/\S/', $blowfishSecret); - $hasNonword = (bool) preg_match('/\W/', $blowfishSecret); - if (! $hasDigits || ! $hasChars || ! $hasNonword) { - $blowfishWarnings[] = Sanitize::sanitizeMessage( - __( - 'Key should contain letters, numbers [em]and[/em] special characters.' - ) - ); - } - - if (empty($blowfishWarnings)) { + if (! $cookieAuthUsed || ! $blowfishSecretSet) { return; } + // 'cookie' auth used, blowfish_secret was generated SetupIndex::messagesSet( - 'error', - 'blowfish_warnings' . count($blowfishWarnings), + 'notice', + 'blowfish_secret_created', Descriptions::get('blowfish_secret'), - implode('
', $blowfishWarnings) + Sanitize::sanitizeMessage(__( + 'You didn\'t have blowfish secret set and have enabled ' + . '[kbd]cookie[/kbd] authentication, so a key was automatically ' + . 'generated for you. It is used to encrypt cookies; you don\'t need to ' + . 'remember it.' + )) ); } diff --git a/libraries/classes/Setup/ConfigGenerator.php b/libraries/classes/Setup/ConfigGenerator.php index d252636efa..af5d94a637 100644 --- a/libraries/classes/Setup/ConfigGenerator.php +++ b/libraries/classes/Setup/ConfigGenerator.php @@ -15,12 +15,18 @@ use function count; use function gmdate; use function implode; use function is_array; +use function is_string; +use function mb_strlen; use function preg_replace; +use function sodium_bin2hex; +use function sodium_crypto_secretbox_keygen; +use function sprintf; use function str_contains; use function strtr; use function var_export; use const DATE_RFC1123; +use const SODIUM_CRYPTO_SECRETBOX_KEYBYTES; /** * Config file generation class @@ -94,6 +100,12 @@ class ConfigGenerator */ private static function getVarExport($var_name, $var_value, $crlf) { + if ($var_name === 'blowfish_secret') { + $secret = self::getBlowfishSecretKey($var_value); + + return sprintf('$cfg[\'blowfish_secret\'] = \sodium_hex2bin(\'%s\');%s', sodium_bin2hex($secret), $crlf); + } + if (! is_array($var_value) || empty($var_value)) { return "\$cfg['" . $var_name . "'] = " . var_export($var_value, true) . ';' . $crlf; @@ -199,4 +211,18 @@ class ConfigGenerator return $ret; } + + /** + * @param mixed $key + * + * @psalm-return non-empty-string + */ + private static function getBlowfishSecretKey($key): string + { + if (is_string($key) && mb_strlen($key, '8bit') === SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { + return $key; + } + + return sodium_crypto_secretbox_keygen(); + } } -- cgit v1.2.3 From 700db7e72b2aba5649832e73496743cdfc257fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Thu, 15 Sep 2022 15:28:35 -0300 Subject: Update the docs to reflect the blowfish_secret changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maurício Meneghini Fauth --- libraries/classes/Config/Settings.php | 7 +++---- libraries/config.default.php | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'libraries') diff --git a/libraries/classes/Config/Settings.php b/libraries/classes/Config/Settings.php index c5ee9ede3d..62d344c516 100644 --- a/libraries/classes/Config/Settings.php +++ b/libraries/classes/Config/Settings.php @@ -118,10 +118,9 @@ final class Settings public $AllowThirdPartyFraming; /** - * The 'cookie' auth_type uses AES algorithm to encrypt the password. If - * at least one server configuration uses 'cookie' auth_type, enter here a - * pass phrase that will be used by AES. The maximum length seems to be 46 - * characters. + * The 'cookie' auth_type uses the Sodium extension to encrypt the cookies. If at least one server configuration + * uses 'cookie' auth_type, enter here a generated string of random bytes to be used as an encryption key. The + * encryption key must be 32 bytes long. * * @var string */ diff --git a/libraries/config.default.php b/libraries/config.default.php index 3ecb83faa2..2c3acd51c1 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -100,10 +100,9 @@ $cfg['TranslationWarningThreshold'] = 80; $cfg['AllowThirdPartyFraming'] = false; /** - * The 'cookie' auth_type uses AES algorithm to encrypt the password. If - * at least one server configuration uses 'cookie' auth_type, enter here a - * pass phrase that will be used by AES. The maximum length seems to be 46 - * characters. + * The 'cookie' auth_type uses the Sodium extension to encrypt the cookies. If at least one server configuration + * uses 'cookie' auth_type, enter here a generated string of random bytes to be used as an encryption key. The + * encryption key must be 32 bytes long. * * @global string $cfg['blowfish_secret'] */ -- cgit v1.2.3 From 5d9142674d09379a9e4394779c1e624dd2d6ece5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Fri, 23 Sep 2022 14:32:30 -0300 Subject: Allow longer cookie encryption keys to be used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maurício Meneghini Fauth --- libraries/classes/Controllers/HomeController.php | 14 +++++++++----- libraries/classes/Plugins/Auth/AuthenticationCookie.php | 13 ++++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'libraries') diff --git a/libraries/classes/Controllers/HomeController.php b/libraries/classes/Controllers/HomeController.php index 998cc3b4ce..39235fdc06 100644 --- a/libraries/classes/Controllers/HomeController.php +++ b/libraries/classes/Controllers/HomeController.php @@ -311,19 +311,23 @@ class HomeController extends AbstractController * Check if user does not have defined blowfish secret and it is being used. */ if (! empty($_SESSION['encryption_key'])) { - if (empty($cfg['blowfish_secret'])) { + $encryptionKeyLength = mb_strlen($cfg['blowfish_secret'], '8bit'); + if ($encryptionKeyLength < SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { $this->errors[] = [ 'message' => __( - 'The configuration file now needs a secret passphrase (blowfish_secret).' + 'The configuration file needs a valid key for cookie encryption.' + . ' A temporary key was automatically generated for you.' + . ' Please refer to the [doc@cfg_blowfish_secret]documentation[/doc].' ), 'severity' => 'warning', ]; - } elseif (mb_strlen($cfg['blowfish_secret'], '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { + } elseif ($encryptionKeyLength > SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { $this->errors[] = [ 'message' => sprintf( __( - 'The secret passphrase in configuration (blowfish_secret) is not the correct length.' - . ' It should be %d bytes long.' + 'The cookie encryption key in the configuration file is longer than necessary.' + . ' It should only be %d bytes long.' + . ' Please refer to the [doc@cfg_blowfish_secret]documentation[/doc].' ), SODIUM_CRYPTO_SECRETBOX_KEYBYTES ), diff --git a/libraries/classes/Plugins/Auth/AuthenticationCookie.php b/libraries/classes/Plugins/Auth/AuthenticationCookie.php index 33faf56b34..e083ddf19a 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationCookie.php +++ b/libraries/classes/Plugins/Auth/AuthenticationCookie.php @@ -597,11 +597,21 @@ class AuthenticationCookie extends AuthenticationPlugin */ private function getEncryptionSecret(): string { + /** @var mixed $key */ $key = $GLOBALS['cfg']['blowfish_secret'] ?? null; - if (is_string($key) && mb_strlen($key, '8bit') === SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { + if (! is_string($key)) { + return $this->getSessionEncryptionSecret(); + } + + $length = mb_strlen($key, '8bit'); + if ($length === SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { return $key; } + if ($length > SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { + return mb_substr($key, 0, SODIUM_CRYPTO_SECRETBOX_KEYBYTES, '8bit'); + } + return $this->getSessionEncryptionSecret(); } @@ -610,6 +620,7 @@ class AuthenticationCookie extends AuthenticationPlugin */ private function getSessionEncryptionSecret(): string { + /** @var mixed $key */ $key = $_SESSION['encryption_key'] ?? null; if (is_string($key) && mb_strlen($key, '8bit') === SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { return $key; -- cgit v1.2.3 From 8331b15243096bc1f286a8c20771482fbd20ec4d Mon Sep 17 00:00:00 2001 From: William Desportes Date: Wed, 28 Sep 2022 23:47:45 +0200 Subject: Fix #17736 - Add utf8mb3 as an alias of utf8 on the charset description page Signed-off-by: William Desportes --- libraries/classes/Charsets/Collation.php | 1 + 1 file changed, 1 insertion(+) (limited to 'libraries') diff --git a/libraries/classes/Charsets/Collation.php b/libraries/classes/Charsets/Collation.php index 5215fe561f..74215bd0a9 100644 --- a/libraries/classes/Charsets/Collation.php +++ b/libraries/classes/Charsets/Collation.php @@ -344,6 +344,7 @@ final class Collation // Fall through to other unicode case 'ucs2': case 'utf8': + case 'utf8mb3': case 'utf16': case 'utf16le': case 'utf16be': -- cgit v1.2.3