diff --git a/ChangeLog b/ChangeLog index f2e9cd6031..5bf20536f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -49,6 +49,7 @@ phpMyAdmin - ChangeLog - issue #15540 Fixed uncaught TypeError: htmlspecialchars() in NavigationTree 4.9.2 (not yet released) +- issue #14184 Change the cookie name from phpMyAdmin to phpMyAdmin_https for HTTPS - issue #15304 Fix ssl_use php error - issue #14804 Fix undefined index: ssl_* variables - issue #14245 Fix mysql 8.0.3 and above fails on advisor diff --git a/libraries/classes/Config.php b/libraries/classes/Config.php index 29ee2191b2..1dd4a11ce8 100644 --- a/libraries/classes/Config.php +++ b/libraries/classes/Config.php @@ -974,7 +974,7 @@ class Config } // save language - if (isset($_COOKIE['pma_lang']) || isset($_POST['lang'])) { + if ($this->issetCookie('pma_lang') || isset($_POST['lang'])) { if ((! isset($config_data['lang']) && $GLOBALS['lang'] != 'en') || isset($config_data['lang']) @@ -1052,7 +1052,7 @@ class Config */ public function getUserValue(string $cookie_name, $cfg_value) { - $cookie_exists = ! empty($_COOKIE[$cookie_name]); + $cookie_exists = ! empty($this->getCookie($cookie_name)); $prefs_type = $this->get('user_preferences'); if ($prefs_type == 'db') { // permanent user preferences value exists, remove cookie @@ -1060,7 +1060,7 @@ class Config $this->removeCookie($cookie_name); } } elseif ($cookie_exists) { - return $_COOKIE[$cookie_name]; + return $this->getCookie($cookie_name); } // return value from $cfg array return $cfg_value; @@ -1407,20 +1407,22 @@ class Config /** * removes cookie * - * @param string $cookie name of cookie to remove + * @param string $cookieName name of cookie to remove * * @return boolean result of setcookie() */ - public function removeCookie(string $cookie): bool + public function removeCookie(string $cookieName): bool { + $httpCookieName = $this->getCookieName($cookieName); + + if ($this->issetCookie($cookieName)) { + unset($_COOKIE[$httpCookieName]); + } if (defined('TESTSUITE')) { - if (isset($_COOKIE[$cookie])) { - unset($_COOKIE[$cookie]); - } return true; } return setcookie( - $cookie, + $httpCookieName, '', time() - 3600, $this->getRootPath(), @@ -1451,19 +1453,21 @@ class Config if (strlen($value) > 0 && null !== $default && $value === $default ) { // default value is used - if (isset($_COOKIE[$cookie])) { + if ($this->issetCookie($cookie)) { // remove cookie return $this->removeCookie($cookie); } return false; } - if (strlen($value) === 0 && isset($_COOKIE[$cookie])) { + if (strlen($value) === 0 && $this->issetCookie($cookie)) { // remove cookie, value is empty return $this->removeCookie($cookie); } - if (! isset($_COOKIE[$cookie]) || $_COOKIE[$cookie] !== $value) { + $httpCookieName = $this->getCookieName($cookie); + + if (! $this->issetCookie($cookie) || $this->getCookie($cookie) !== $value) { // set cookie with new value /* Calculate cookie validity */ if ($validity === null) { @@ -1476,11 +1480,11 @@ class Config $validity = time() + $validity; } if (defined('TESTSUITE')) { - $_COOKIE[$cookie] = $value; + $_COOKIE[$httpCookieName] = $value; return true; } return setcookie( - $cookie, + $httpCookieName, $value, $validity, $this->getRootPath(), @@ -1494,6 +1498,40 @@ class Config return true; } + /** + * get cookie + * + * @param string $cookieName The name of the cookie to get + * + * @return mixed result of getCookie() + */ + public function getCookie(string $cookieName) + { + return @$_COOKIE[$this->getCookieName($cookieName)]; + } + + /** + * Get the real cookie name + * + * @param string $cookieName The name of the cookie + * @return string + */ + public function getCookieName(string $cookieName): string + { + return $cookieName . ( ($this->isHttps()) ? '_https' : '' ); + } + + /** + * isset cookie + * + * @param string $cookieName The name of the cookie to check + * + * @return bool result of issetCookie() + */ + public function issetCookie(string $cookieName): bool + { + return isset($_COOKIE[$this->getCookieName($cookieName)]); + } /** * Error handler to catch fatal errors when loading configuration diff --git a/libraries/classes/ErrorReport.php b/libraries/classes/ErrorReport.php index 968c750d08..43c7a2b75f 100644 --- a/libraries/classes/ErrorReport.php +++ b/libraries/classes/ErrorReport.php @@ -89,6 +89,9 @@ class ErrorReport */ public function getData(string $exceptionType = 'js'): array { + /** @var Config $PMA_Config */ + global $PMA_Config; + $relParams = $this->relation->getRelationsParam(); // common params for both, php & js exceptions $report = [ @@ -98,7 +101,7 @@ class ErrorReport "user_os" => PMA_USR_OS, "server_software" => $_SERVER['SERVER_SOFTWARE'], "user_agent_string" => $_SERVER['HTTP_USER_AGENT'], - "locale" => $_COOKIE['pma_lang'], + "locale" => $PMA_Config->getCookie('pma_lang'), "configuration_storage" => $relParams['db'] === null ? "disabled" : "enabled", "php_version" => PHP_VERSION, diff --git a/libraries/classes/LanguageManager.php b/libraries/classes/LanguageManager.php index 38c3098595..55fe739aa7 100644 --- a/libraries/classes/LanguageManager.php +++ b/libraries/classes/LanguageManager.php @@ -866,8 +866,8 @@ class LanguageManager } // check previous set language - if (! empty($_COOKIE['pma_lang'])) { - $lang = $this->getLanguage($_COOKIE['pma_lang']); + if (! empty($GLOBALS['PMA_Config']->getCookie('pma_lang'))) { + $lang = $this->getLanguage($GLOBALS['PMA_Config']->getCookie('pma_lang')); if ($lang !== false) { return $lang; } diff --git a/libraries/classes/Plugins/Auth/AuthenticationCookie.php b/libraries/classes/Plugins/Auth/AuthenticationCookie.php index ffd8e463c7..a24f65fd33 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationCookie.php +++ b/libraries/classes/Plugins/Auth/AuthenticationCookie.php @@ -326,12 +326,13 @@ class AuthenticationCookie extends AuthenticationPlugin // and $this->password variables from cookies // check cookies - if (empty($_COOKIE['pmaUser-' . $GLOBALS['server']])) { + $serverCookie = $GLOBALS['PMA_Config']->getCookie('pmaUser-' . $GLOBALS['server']); + if (empty($serverCookie)) { return false; } $value = $this->cookieDecrypt( - $_COOKIE['pmaUser-' . $GLOBALS['server']], + $serverCookie, $this->_getEncryptionSecret() ); @@ -373,11 +374,13 @@ class AuthenticationCookie extends AuthenticationPlugin } // check password cookie - if (empty($_COOKIE['pmaAuth-' . $GLOBALS['server']])) { + $serverCookie = $GLOBALS['PMA_Config']->getCookie('pmaAuth-' . $GLOBALS['server']); + + if (empty($serverCookie)) { return false; } $value = $this->cookieDecrypt( - $_COOKIE['pmaAuth-' . $GLOBALS['server']], + $serverCookie, $this->_getSessionEncryptionSecret() ); if ($value === false) { @@ -859,20 +862,22 @@ class AuthenticationCookie extends AuthenticationPlugin */ public function logOut() { + /** @var Config $PMA_Config */ + global $PMA_Config; + // -> delete password cookie(s) if ($GLOBALS['cfg']['LoginCookieDeleteAll']) { foreach ($GLOBALS['cfg']['Servers'] as $key => $val) { - $GLOBALS['PMA_Config']->removeCookie('pmaAuth-' . $key); - if (isset($_COOKIE['pmaAuth-' . $key])) { - unset($_COOKIE['pmaAuth-' . $key]); + $PMA_Config->removeCookie('pmaAuth-' . $key); + if ($PMA_Config->issetCookie('pmaAuth-' . $key)) { + $PMA_Config->removeCookie('pmaAuth-' . $key); } } } else { - $GLOBALS['PMA_Config']->removeCookie( - 'pmaAuth-' . $GLOBALS['server'] - ); - if (isset($_COOKIE['pmaAuth-' . $GLOBALS['server']])) { - unset($_COOKIE['pmaAuth-' . $GLOBALS['server']]); + $cookieName = 'pmaAuth-' . $GLOBALS['server']; + $PMA_Config->removeCookie($cookieName); + if ($PMA_Config->issetCookie($cookieName)) { + $PMA_Config->removeCookie($cookieName); } } parent::logOut(); diff --git a/libraries/classes/Plugins/AuthenticationPlugin.php b/libraries/classes/Plugins/AuthenticationPlugin.php index 53759e3336..67417e9237 100644 --- a/libraries/classes/Plugins/AuthenticationPlugin.php +++ b/libraries/classes/Plugins/AuthenticationPlugin.php @@ -120,6 +120,9 @@ abstract class AuthenticationPlugin */ public function logOut() { + /** @var Config $PMA_Config */ + global $PMA_Config; + /* Obtain redirect URL (before doing logout) */ if (! empty($GLOBALS['cfg']['Server']['LogoutURL'])) { $redirect_url = $GLOBALS['cfg']['Server']['LogoutURL']; @@ -139,7 +142,7 @@ abstract class AuthenticationPlugin && $GLOBALS['cfg']['Server']['auth_type'] == 'cookie' ) { foreach ($GLOBALS['cfg']['Servers'] as $key => $val) { - if (isset($_COOKIE['pmaAuth-' . $key])) { + if ($PMA_Config->issetCookie('pmaAuth-' . $key)) { $server = $key; } } diff --git a/libraries/classes/Session.php b/libraries/classes/Session.php index 34142e57ed..a3c9323ac3 100644 --- a/libraries/classes/Session.php +++ b/libraries/classes/Session.php @@ -172,12 +172,12 @@ class Session // proxy servers session_cache_limiter('private'); - $session_name = 'phpMyAdmin'; - @session_name($session_name); + $httpCookieName = $config->getCookieName('phpMyAdmin'); + @session_name($httpCookieName); // Restore correct sesion ID (it might have been reset by auto started session - if (isset($_COOKIE['phpMyAdmin'])) { - session_id($_COOKIE['phpMyAdmin']); + if ($config->issetCookie('phpMyAdmin')) { + session_id($config->getCookie('phpMyAdmin')); } // on first start of session we check for errors @@ -189,7 +189,7 @@ class Session if ($session_result !== true || $orig_error_count != $errorHandler->countErrors(false) ) { - setcookie($session_name, '', 1); + setcookie($httpCookieName, '', 1); $errors = $errorHandler->sliceErrors($orig_error_count); self::sessionFailed($errors); } diff --git a/libraries/classes/ThemeManager.php b/libraries/classes/ThemeManager.php index 29c1fe8b48..a994a4f326 100644 --- a/libraries/classes/ThemeManager.php +++ b/libraries/classes/ThemeManager.php @@ -212,9 +212,12 @@ class ThemeManager */ public function getThemeCookie() { + /** @var Config $PMA_Config */ + global $PMA_Config; + $name = $this->getThemeCookieName(); - if (isset($_COOKIE[$name])) { - return $_COOKIE[$name]; + if ($PMA_Config->issetCookie($name)) { + return $PMA_Config->getCookie($name); } return false; diff --git a/libraries/classes/Url.php b/libraries/classes/Url.php index aaa35d9315..fd73f52f09 100644 --- a/libraries/classes/Url.php +++ b/libraries/classes/Url.php @@ -37,6 +37,9 @@ class Url $indent = 0, $skip = [] ) { + /** @var Config $PMA_Config */ + global $PMA_Config; + if (is_array($db)) { $params =& $db; } else { @@ -54,7 +57,7 @@ class Url ) { $params['server'] = $GLOBALS['server']; } - if (empty($_COOKIE['pma_lang']) && ! empty($GLOBALS['lang'])) { + if (empty($PMA_Config->getCookie('pma_lang')) && ! empty($GLOBALS['lang'])) { $params['lang'] = $GLOBALS['lang']; } @@ -199,18 +202,20 @@ class Url */ public static function getCommonRaw($params = [], $divider = '?') { + /** @var Config $PMA_Config */ + global $PMA_Config; $separator = Url::getArgSeparator(); // avoid overwriting when creating navi panel links to servers if (isset($GLOBALS['server']) && $GLOBALS['server'] != $GLOBALS['cfg']['ServerDefault'] && ! isset($params['server']) - && ! $GLOBALS['PMA_Config']->get('is_setup') + && ! $PMA_Config->get('is_setup') ) { $params['server'] = $GLOBALS['server']; } - if (empty($_COOKIE['pma_lang']) && ! empty($GLOBALS['lang'])) { + if (empty($PMA_Config->getCookie('pma_lang')) && ! empty($GLOBALS['lang'])) { $params['lang'] = $GLOBALS['lang']; } diff --git a/libraries/common.inc.php b/libraries/common.inc.php index c96667bef3..99dec96ee9 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -156,7 +156,8 @@ if (isset($_REQUEST['goto']) && Core::checkPageValidity($_REQUEST['goto'])) { $diMigration->setGlobal('goto', $_REQUEST['goto']); $diMigration->setGlobal('url_params', ['goto' => $_REQUEST['goto']]); } else { - unset($_REQUEST['goto'], $_GET['goto'], $_POST['goto'], $_COOKIE['goto']); + $GLOBALS['PMA_Config']->removeCookie('goto'); + unset($_REQUEST['goto'], $_GET['goto'], $_POST['goto']); } /** @@ -166,7 +167,8 @@ if (isset($_REQUEST['goto']) && Core::checkPageValidity($_REQUEST['goto'])) { if (isset($_REQUEST['back']) && Core::checkPageValidity($_REQUEST['back'])) { $diMigration->setGlobal('back', $_REQUEST['back']); } else { - unset($_REQUEST['back'], $_GET['back'], $_POST['back'], $_COOKIE['back']); + $GLOBALS['PMA_Config']->removeCookie('back'); + unset($_REQUEST['back'], $_GET['back'], $_POST['back']); } /** diff --git a/test/classes/ConfigTest.php b/test/classes/ConfigTest.php index 3be28b0457..2614811257 100644 --- a/test/classes/ConfigTest.php +++ b/test/classes/ConfigTest.php @@ -876,6 +876,7 @@ class ConfigTest extends PmaTestCase */ public function testSetCookie() { + $this->object->set('is_https', false); $this->assertFalse( $this->object->setCookie( 'TEST_DEF_COOKIE', diff --git a/test/classes/LanguageTest.php b/test/classes/LanguageTest.php index 108f409385..6216bd70c8 100644 --- a/test/classes/LanguageTest.php +++ b/test/classes/LanguageTest.php @@ -166,6 +166,7 @@ class LanguageTest extends PmaTestCase public function testSelect($lang, $post, $get, $cookie, $accept, $agent, $default, $expect): void { $GLOBALS['PMA_Config']->set('Lang', $lang); + $GLOBALS['PMA_Config']->set('is_https', false); $_POST['lang'] = $post; $_GET['lang'] = $get; $_COOKIE['pma_lang'] = $cookie; diff --git a/test/classes/Plugins/Auth/AuthenticationCookieTest.php b/test/classes/Plugins/Auth/AuthenticationCookieTest.php index 35b737f876..8fa8abc970 100644 --- a/test/classes/Plugins/Auth/AuthenticationCookieTest.php +++ b/test/classes/Plugins/Auth/AuthenticationCookieTest.php @@ -365,6 +365,7 @@ class AuthenticationCookieTest extends PmaTestCase */ public function testAuthHeaderPartial() { + $GLOBALS['PMA_Config']->set('is_https', false); $GLOBALS['cfg']['LoginCookieDeleteAll'] = false; $GLOBALS['cfg']['Servers'] = [ 1, @@ -416,6 +417,7 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; $GLOBALS['cfg']['LoginCookieDeleteAll'] = true; $GLOBALS['PMA_Config']->set('PmaAbsoluteUri', ''); + $GLOBALS['PMA_Config']->set('is_https', false); $GLOBALS['cfg']['Servers'] = [1]; $_COOKIE['pmaAuth-0'] = 'test'; @@ -441,6 +443,7 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; $GLOBALS['cfg']['LoginCookieDeleteAll'] = false; $GLOBALS['PMA_Config']->set('PmaAbsoluteUri', ''); + $GLOBALS['PMA_Config']->set('is_https', false); $GLOBALS['cfg']['Servers'] = [1]; $GLOBALS['server'] = 1; $GLOBALS['cfg']['Server'] = ['auth_type' => 'cookie']; @@ -553,6 +556,7 @@ class AuthenticationCookieTest extends PmaTestCase $_SESSION['last_access_time'] = ''; $GLOBALS['cfg']['CaptchaLoginPrivateKey'] = ''; $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; + $GLOBALS['PMA_Config']->set('is_https', false); // mock for blowfish function $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') @@ -593,6 +597,7 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; $_SESSION['browser_access_time']['default'] = time() - 1000; $GLOBALS['cfg']['LoginCookieValidity'] = 1440; + $GLOBALS['PMA_Config']->set('is_https', false); // mock for blowfish function $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') @@ -637,6 +642,8 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; $GLOBALS['cfg']['LoginCookieValidity'] = 0; $_SESSION['browser_access_time']['default'] = -1; + $GLOBALS['PMA_Config']->set('is_https', false); + // mock for blowfish function $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') ->disableOriginalConstructor() @@ -680,6 +687,7 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['server'] = 2; $GLOBALS['cfg']['LoginCookieStore'] = true; $GLOBALS['from_cookie'] = true; + $GLOBALS['PMA_Config']->set('is_https', false); $this->object->storeCredentials(); @@ -1089,6 +1097,7 @@ class AuthenticationCookieTest extends PmaTestCase public function testPasswordChange() { $newPassword = 'PMAPASSWD2'; + $GLOBALS['PMA_Config']->set('is_https', false); $GLOBALS['cfg']['AllowArbitraryServer'] = true; $GLOBALS['pma_auth_server'] = 'b 2'; $_SESSION['encryption_key'] = '';