diff options
author | Maurício Meneghini Fauth <mauricio@fauth.dev> | 2022-09-29 06:45:10 +0300 |
---|---|---|
committer | Maurício Meneghini Fauth <mauricio@fauth.dev> | 2022-09-29 06:45:10 +0300 |
commit | 6a9fe03ff29621beced7cbab4164872cb4cd4384 (patch) | |
tree | d2b4d3df9bff103349f0c77c07558abbedbbe931 /libraries | |
parent | 000bf397a4ae33ea8334917614c70d2cbcea7546 (diff) | |
parent | add68b47e314fb74c6e6c11bafbbed6ed8c74344 (diff) |
Merge branch 'QA_5_2'
Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
Diffstat (limited to 'libraries')
-rw-r--r-- | libraries/classes/Charsets/Collation.php | 1 | ||||
-rw-r--r-- | libraries/classes/Config/ServerConfigChecks.php | 71 | ||||
-rw-r--r-- | libraries/classes/Config/Settings.php | 7 | ||||
-rw-r--r-- | libraries/classes/Controllers/HomeController.php | 14 | ||||
-rw-r--r-- | libraries/classes/Plugins/Auth/AuthenticationCookie.php | 13 | ||||
-rw-r--r-- | libraries/classes/Setup/ConfigGenerator.php | 26 | ||||
-rw-r--r-- | libraries/config.default.php | 7 |
7 files changed, 74 insertions, 65 deletions
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': 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('<br>', $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/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/classes/Controllers/HomeController.php b/libraries/classes/Controllers/HomeController.php index 2b7a30226c..22b3990735 100644 --- a/libraries/classes/Controllers/HomeController.php +++ b/libraries/classes/Controllers/HomeController.php @@ -318,19 +318,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($GLOBALS['cfg']['blowfish_secret'])) { + $encryptionKeyLength = mb_strlen($GLOBALS['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($GLOBALS['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 b4a0b0bfde..c468223232 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationCookie.php +++ b/libraries/classes/Plugins/Auth/AuthenticationCookie.php @@ -592,11 +592,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(); } @@ -605,6 +615,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; diff --git a/libraries/classes/Setup/ConfigGenerator.php b/libraries/classes/Setup/ConfigGenerator.php index 189c8c9260..9d69a5bab1 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 @@ -92,6 +98,12 @@ class ConfigGenerator */ private static function getVarExport($var_name, $var_value, string $eol) { + if ($var_name === 'blowfish_secret') { + $secret = self::getBlowfishSecretKey($var_value); + + return sprintf('$cfg[\'blowfish_secret\'] = \sodium_hex2bin(\'%s\');%s', sodium_bin2hex($secret), $eol); + } + if (! is_array($var_value) || empty($var_value)) { return "\$cfg['" . $var_name . "'] = " . var_export($var_value, true) . ';' . $eol; @@ -197,4 +209,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(); + } } 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'] */ |