Merge #15273 - Fix HTTPS/HTTP cookie separation issue

Fixes: #14184
Pull-request: #15273

Signed-off-by: William Desportes <williamdes@wdes.fr>
This commit is contained in:
William Desportes 2019-11-03 15:26:17 +01:00
commit 21695cfeb7
No known key found for this signature in database
GPG Key ID: 90A0EF1B8251A889
13 changed files with 110 additions and 42 deletions

View File

@ -44,6 +44,7 @@ if (ini_get('session.upload_progress.enabled')) {
define('SESSIONUPLOAD', serialize($sessionupload));
session_write_close();
// The cookie name is not good anymore since PR #15273
session_name('phpMyAdmin');
session_id($_COOKIE['phpMyAdmin']);
}

View File

@ -987,7 +987,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'])
@ -1061,7 +1061,7 @@ class Config
*/
public function getUserValue($cookie_name, $cfg_value)
{
$cookie_exists = isset($_COOKIE) && !empty($_COOKIE[$cookie_name]);
$cookie_exists = isset($_COOKIE) && !empty($this->getCookie($cookie_name));
$prefs_type = $this->get('user_preferences');
if ($prefs_type == 'db') {
// permanent user preferences value exists, remove cookie
@ -1069,7 +1069,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;
@ -1528,20 +1528,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($cookie)
public function removeCookie($cookieName)
{
$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(),
@ -1568,19 +1570,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) {
@ -1593,11 +1597,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(),
@ -1611,6 +1615,37 @@ class Config
return true;
}
/**
* get cookie
*
* @param string $cookieName The name of the cookie to get
*
* @return mixed result of getCookie()
*/
public function getCookie($cookieName) {
return @$_COOKIE[$this->getCookieName($cookieName)];
}
/**
* Get the real cookie name
*
* @param string $cookieName The name of the cookie
* @return string
*/
public function getCookieName($cookieName) {
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($cookieName) {
return isset($_COOKIE[$this->getCookieName($cookieName)]);
}
/**
* Error handler to catch fatal errors when loading configuration

View File

@ -72,6 +72,9 @@ class ErrorReport
*/
public function getData($exceptionType = 'js')
{
/** @var Config $PMA_Config */
global $PMA_Config;
$relParams = $this->relation->getRelationsParam();
// common params for both, php & js exceptions
$report = [
@ -81,7 +84,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" =>
is_null($relParams['db']) ? "disabled" : "enabled",
"php_version" => phpversion()

View File

@ -864,8 +864,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;
}

View File

@ -357,12 +357,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()
);
@ -404,11 +405,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) {
@ -868,20 +871,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();

View File

@ -100,6 +100,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'];
@ -119,7 +122,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;
}
}

View File

@ -175,12 +175,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
@ -192,7 +192,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);
}

View File

@ -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;

View File

@ -33,6 +33,9 @@ class Url
public static function getHiddenInputs($db = '', $table = '',
$indent = 0, $skip = array()
) {
/** @var Config $PMA_Config */
global $PMA_Config;
if (is_array($db)) {
$params =& $db;
$_indent = empty($table) ? $indent : $table;
@ -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'];
}
@ -198,18 +201,20 @@ class Url
*/
public static function getCommonRaw($params = array(), $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'];
}

View File

@ -152,7 +152,8 @@ if (Core::checkPageValidity($_REQUEST['goto'])) {
$GLOBALS['goto'] = $_REQUEST['goto'];
$GLOBALS['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']);
}
/**
@ -162,7 +163,8 @@ if (Core::checkPageValidity($_REQUEST['goto'])) {
if (Core::checkPageValidity($_REQUEST['back'])) {
$GLOBALS['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']);
}
/**

View File

@ -863,6 +863,7 @@ class ConfigTest extends PmaTestCase
*/
public function testSetCookie()
{
$this->object->set('is_https', false);
$this->assertFalse(
$this->object->setCookie(
'TEST_DEF_COOKIE',

View File

@ -159,6 +159,7 @@ class LanguageTest extends PmaTestCase
public function testSelect($lang, $post, $get, $cookie, $accept, $agent, $default, $expect)
{
$GLOBALS['PMA_Config']->set('Lang', $lang);
$GLOBALS['PMA_Config']->set('is_https', false);
$_POST['lang'] = $post;
$_GET['lang'] = $get;
$_COOKIE['pma_lang'] = $cookie;

View File

@ -366,6 +366,7 @@ class AuthenticationCookieTest extends PmaTestCase
*/
public function testAuthHeaderPartial()
{
$GLOBALS['PMA_Config']->set('is_https', false);
$GLOBALS['cfg']['LoginCookieDeleteAll'] = false;
$GLOBALS['cfg']['Servers'] = array(1, 2, 3);
$GLOBALS['cfg']['Server']['LogoutURL'] = 'https://example.com/logout';
@ -413,6 +414,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'] = array(1);
$_COOKIE['pmaAuth-0'] = 'test';
@ -438,6 +440,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'] = array(1);
$GLOBALS['server'] = 1;
$GLOBALS['cfg']['Server'] = array('auth_type' => 'cookie');
@ -550,6 +553,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')
@ -590,6 +594,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')
@ -635,6 +640,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()
@ -678,6 +685,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();
@ -1064,6 +1072,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'] = '';