diff --git a/libraries/classes/Plugins/Auth/AuthenticationConfig.php b/libraries/classes/Plugins/Auth/AuthenticationConfig.php index 9d53919249..a6727339dd 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationConfig.php +++ b/libraries/classes/Plugins/Auth/AuthenticationConfig.php @@ -26,7 +26,7 @@ class AuthenticationConfig extends AuthenticationPlugin * * @return boolean always true */ - public function auth() + public function showLoginForm() { $response = Response::getInstance(); if ($response->isAjax()) { @@ -44,27 +44,18 @@ class AuthenticationConfig extends AuthenticationPlugin } /** - * Gets advanced authentication settings + * Gets authentication credentials * * @return boolean always true */ - public function authCheck() + public function readCredentials() { if ($GLOBALS['token_provided'] && $GLOBALS['token_mismatch']) { return false; } - return true; - } - - /** - * Set the user and password after last checkings if required - * - * @return boolean always true - */ - public function authSetUser() - { - $this->setSessionAccessTime(); + $this->user = $GLOBALS['cfg']['Server']['user']; + $this->password = $GLOBALS['cfg']['Server']['password']; return true; } @@ -72,10 +63,13 @@ class AuthenticationConfig extends AuthenticationPlugin /** * User is not allowed to login to MySQL -> authentication failed * - * @return boolean always true (no return indeed) + * @param string $failure String describing why authentication has failed + * + * @return void */ - public function authFails() + public function showFailure($failure) { + parent::showFailure($failure); $conn_error = $GLOBALS['dbi']->getError(); if (!$conn_error) { $conn_error = __('Cannot connect: invalid settings.'); @@ -172,7 +166,5 @@ class AuthenticationConfig extends AuthenticationPlugin if (!defined('TESTSUITE')) { exit; } - - return true; } } diff --git a/libraries/classes/Plugins/Auth/AuthenticationCookie.php b/libraries/classes/Plugins/Auth/AuthenticationCookie.php index 29cd4091ee..6af0669f2f 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationCookie.php +++ b/libraries/classes/Plugins/Auth/AuthenticationCookie.php @@ -79,7 +79,7 @@ class AuthenticationCookie extends AuthenticationPlugin * * @return boolean|void */ - public function auth() + public function showLoginForm() { global $conn_error; @@ -100,7 +100,7 @@ class AuthenticationCookie extends AuthenticationPlugin if ($GLOBALS['cfg']['LoginCookieRecall'] && ! empty($GLOBALS['cfg']['blowfish_secret']) ) { - $default_user = $GLOBALS['PHP_AUTH_USER']; + $default_user = $this->user; $default_server = $GLOBALS['pma_auth_server']; $autocomplete = ''; } else { @@ -272,22 +272,22 @@ class AuthenticationCookie extends AuthenticationPlugin } /** - * Gets advanced authentication settings + * Gets authentication credentials * * this function DOES NOT check authentication - it just checks/provides * authentication credentials required to connect to the MySQL server * usually with $GLOBALS['dbi']->connect() * * it returns false if something is missing - which usually leads to - * auth() which displays login form + * showLoginForm() which displays login form * * it returns true if all seems ok which usually leads to auth_set_user() * - * it directly switches to authFails() if user inactivity timeout is reached + * it directly switches to showFailure() if user inactivity timeout is reached * * @return boolean whether we get authentication settings or not */ - public function authCheck() + public function readCredentials() { global $conn_error; @@ -298,7 +298,7 @@ class AuthenticationCookie extends AuthenticationPlugin */ $GLOBALS['pma_auth_server'] = ''; - $GLOBALS['PHP_AUTH_USER'] = $GLOBALS['PHP_AUTH_PW'] = ''; + $this->user = $this->password = ''; $GLOBALS['from_cookie'] = false; if (isset($_REQUEST['pma_username']) && strlen($_REQUEST['pma_username']) > 0) { @@ -349,8 +349,8 @@ class AuthenticationCookie extends AuthenticationPlugin } // The user just logged in - $GLOBALS['PHP_AUTH_USER'] = Core::sanitizeMySQLUser($_REQUEST['pma_username']); - $GLOBALS['PHP_AUTH_PW'] = isset($_REQUEST['pma_password']) ? $_REQUEST['pma_password'] : ''; + $this->user = Core::sanitizeMySQLUser($_REQUEST['pma_username']); + $this->password = isset($_REQUEST['pma_password']) ? $_REQUEST['pma_password'] : ''; if ($GLOBALS['cfg']['AllowArbitraryServer'] && isset($_REQUEST['pma_servername']) ) { @@ -378,19 +378,24 @@ class AuthenticationCookie extends AuthenticationPlugin return true; } - // At the end, try to set the $GLOBALS['PHP_AUTH_USER'] - // and $GLOBALS['PHP_AUTH_PW'] variables from cookies + // At the end, try to set the $this->user + // and $this->password variables from cookies // check cookies if (empty($_COOKIE['pmaUser-' . $GLOBALS['server']])) { return false; } - $GLOBALS['PHP_AUTH_USER'] = $this->cookieDecrypt( + $value = $this->cookieDecrypt( $_COOKIE['pmaUser-' . $GLOBALS['server']], $this->_getEncryptionSecret() ); + if ($value === false) { + return false; + } + + $this->user = $value; // user was never logged in since session start if (empty($_SESSION['browser_access_time'])) { return false; @@ -415,8 +420,7 @@ class AuthenticationCookie extends AuthenticationPlugin Util::cacheUnset('table_priv'); Util::cacheUnset('proc_priv'); - $GLOBALS['no_activity'] = true; - $this->authFails(); + $this->showFailure('no-activity'); if (! defined('TESTSUITE')) { exit; } else { @@ -428,19 +432,20 @@ class AuthenticationCookie extends AuthenticationPlugin if (empty($_COOKIE['pmaAuth-' . $GLOBALS['server']])) { return false; } - - $auth_data = json_decode( - $this->cookieDecrypt( - $_COOKIE['pmaAuth-' . $GLOBALS['server']], - $this->_getSessionEncryptionSecret() - ), - true + $value = $this->cookieDecrypt( + $_COOKIE['pmaAuth-' . $GLOBALS['server']], + $this->_getSessionEncryptionSecret() ); + if ($value === false) { + return false; + } + + $auth_data = json_decode($value, true); if (! is_array($auth_data) || ! isset($auth_data['password'])) { return false; } - $GLOBALS['PHP_AUTH_PW'] = $auth_data['password']; + $this->password = $auth_data['password']; if ($GLOBALS['cfg']['AllowArbitraryServer'] && ! empty($auth_data['server'])) { $GLOBALS['pma_auth_server'] = $auth_data['server']; } @@ -455,7 +460,7 @@ class AuthenticationCookie extends AuthenticationPlugin * * @return boolean always true */ - public function authSetUser() + public function storeCredentials() { global $cfg; @@ -479,13 +484,8 @@ class AuthenticationCookie extends AuthenticationPlugin } unset($tmp_host, $tmp_port, $parts); } - $cfg['Server']['user'] = $GLOBALS['PHP_AUTH_USER']; - $cfg['Server']['password'] = $GLOBALS['PHP_AUTH_PW']; - // Avoid showing the password in phpinfo()'s output - unset($GLOBALS['PHP_AUTH_PW']); - unset($_SERVER['PHP_AUTH_PW']); - $this->setSessionAccessTime(); + return parent::storeCredentials(); } /** @@ -493,19 +493,17 @@ class AuthenticationCookie extends AuthenticationPlugin * * @return void|bool */ - public function storeUserCredentials() + public function rememberCredentials() { - global $cfg; - // Name and password cookies need to be refreshed each time // Duration = one month for username - $this->storeUsernameCookie($cfg['Server']['user']); + $this->storeUsernameCookie($this->user); // Duration = as configured // Do not store password cookie on password change as we will // set the cookie again after password has been changed if (! isset($_POST['change_pw'])) { - $this->storePasswordCookie($cfg['Server']['password']); + $this->storePasswordCookie($this->password); } // Set server cookies if required (once per session) and, in this case, @@ -599,22 +597,26 @@ class AuthenticationCookie extends AuthenticationPlugin /** * User is not allowed to login to MySQL -> authentication failed * - * prepares error message and switches to auth() which display the error + * prepares error message and switches to showLoginForm() which display the error * and the login form * * this function MUST exit/quit the application, - * currently done by call to auth() + * currently done by call to showLoginForm() + * + * @param string $failure String describing why authentication has failed * * @return void */ - public function authFails() + public function showFailure($failure) { global $conn_error; + parent::showFailure($failure); + // Deletes password cookie and displays the login form $GLOBALS['PMA_Config']->removeCookie('pmaAuth-' . $GLOBALS['server']); - $conn_error = $this->getErrorMessage(); + $conn_error = $this->getErrorMessage($failure); $response = Response::getInstance(); @@ -622,7 +624,7 @@ class AuthenticationCookie extends AuthenticationPlugin $response->header('Cache-Control: no-store, no-cache, must-revalidate'); $response->header('Pragma: no-cache'); - $this->auth(); + $this->showLoginForm(); } /** @@ -781,7 +783,7 @@ class AuthenticationCookie extends AuthenticationPlugin * @param string $encdata encrypted data * @param string $secret the secret * - * @return string|bool original data, false on error + * @return string|false original data, false on error */ public function cookieDecrypt($encdata, $secret) { @@ -839,7 +841,7 @@ class AuthenticationCookie extends AuthenticationPlugin * further decryption. I don't think necessary to have one iv * per server so I don't put the server number in the cookie name. * - * @return void + * @return string */ public function createIV() { diff --git a/libraries/classes/Plugins/Auth/AuthenticationHttp.php b/libraries/classes/Plugins/Auth/AuthenticationHttp.php index d58c35c1f8..59dcc98e72 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationHttp.php +++ b/libraries/classes/Plugins/Auth/AuthenticationHttp.php @@ -29,7 +29,7 @@ class AuthenticationHttp extends AuthenticationPlugin * * @return boolean always true (no return indeed) */ - public function auth() + public function showLoginForm() { $response = Response::getInstance(); if ($response->isAjax()) { @@ -100,64 +100,69 @@ class AuthenticationHttp extends AuthenticationPlugin } /** - * Gets advanced authentication settings - * - * @global string $PHP_AUTH_USER the username - * @global string $PHP_AUTH_PW the password + * Gets authentication credentials * * @return boolean whether we get authentication settings or not */ - public function authCheck() + public function readCredentials() { - global $PHP_AUTH_USER, $PHP_AUTH_PW; - // Grabs the $PHP_AUTH_USER variable - if (empty($PHP_AUTH_USER)) { + if (isset($GLOBALS['PHP_AUTH_USER'])) { + $this->user = $GLOBALS['PHP_AUTH_USER']; + } + if (empty($this->user)) { if (Core::getenv('PHP_AUTH_USER')) { - $PHP_AUTH_USER = Core::getenv('PHP_AUTH_USER'); + $this->user = Core::getenv('PHP_AUTH_USER'); } elseif (Core::getenv('REMOTE_USER')) { // CGI, might be encoded, see below - $PHP_AUTH_USER = Core::getenv('REMOTE_USER'); + $this->user = Core::getenv('REMOTE_USER'); } elseif (Core::getenv('REDIRECT_REMOTE_USER')) { // CGI, might be encoded, see below - $PHP_AUTH_USER = Core::getenv('REDIRECT_REMOTE_USER'); + $this->user = Core::getenv('REDIRECT_REMOTE_USER'); } elseif (Core::getenv('AUTH_USER')) { // WebSite Professional - $PHP_AUTH_USER = Core::getenv('AUTH_USER'); + $this->user = Core::getenv('AUTH_USER'); } elseif (Core::getenv('HTTP_AUTHORIZATION')) { // IIS, might be encoded, see below - $PHP_AUTH_USER = Core::getenv('HTTP_AUTHORIZATION'); + $this->user = Core::getenv('HTTP_AUTHORIZATION'); } elseif (Core::getenv('Authorization')) { // FastCGI, might be encoded, see below - $PHP_AUTH_USER = Core::getenv('Authorization'); + $this->user = Core::getenv('Authorization'); } } // Grabs the $PHP_AUTH_PW variable - if (empty($PHP_AUTH_PW)) { + if (isset($GLOBALS['PHP_AUTH_PW'])) { + $this->password = $GLOBALS['PHP_AUTH_PW']; + } + if (empty($this->password)) { if (Core::getenv('PHP_AUTH_PW')) { - $PHP_AUTH_PW = Core::getenv('PHP_AUTH_PW'); + $this->password = Core::getenv('PHP_AUTH_PW'); } elseif (Core::getenv('REMOTE_PASSWORD')) { // Apache/CGI - $PHP_AUTH_PW = Core::getenv('REMOTE_PASSWORD'); + $this->password = Core::getenv('REMOTE_PASSWORD'); } elseif (Core::getenv('AUTH_PASSWORD')) { // WebSite Professional - $PHP_AUTH_PW = Core::getenv('AUTH_PASSWORD'); + $this->password = Core::getenv('AUTH_PASSWORD'); } } // Sanitize empty password login - if (is_null($PHP_AUTH_PW)) { - $PHP_AUTH_PW = ''; + if (is_null($this->password)) { + $this->password = ''; } + // Avoid showing the password in phpinfo()'s output + unset($GLOBALS['PHP_AUTH_PW']); + unset($_SERVER['PHP_AUTH_PW']); + // Decode possibly encoded information (used by IIS/CGI/FastCGI) // (do not use explode() because a user might have a colon in his password - if (strcmp(substr($PHP_AUTH_USER, 0, 6), 'Basic ') == 0) { - $usr_pass = base64_decode(substr($PHP_AUTH_USER, 6)); + if (strcmp(substr($this->user, 0, 6), 'Basic ') == 0) { + $usr_pass = base64_decode(substr($this->user, 6)); if (!empty($usr_pass)) { $colon = strpos($usr_pass, ':'); if ($colon) { - $PHP_AUTH_USER = substr($usr_pass, 0, $colon); - $PHP_AUTH_PW = substr($usr_pass, $colon + 1); + $this->user = substr($usr_pass, 0, $colon); + $this->password = substr($usr_pass, $colon + 1); } unset($colon); } @@ -165,68 +170,40 @@ class AuthenticationHttp extends AuthenticationPlugin } // sanitize username - $PHP_AUTH_USER = Core::sanitizeMySQLUser($PHP_AUTH_USER); + $this->user = Core::sanitizeMySQLUser($this->user); // User logged out -> ensure the new username is not the same $old_usr = isset($_REQUEST['old_usr']) ? $_REQUEST['old_usr'] : ''; if (! empty($old_usr) - && (isset($PHP_AUTH_USER) && hash_equals($old_usr, $PHP_AUTH_USER)) + && (isset($this->user) && hash_equals($old_usr, $this->user)) ) { - $PHP_AUTH_USER = ''; + $this->user = ''; } // Returns whether we get authentication settings or not - if (empty($PHP_AUTH_USER)) { + if (empty($this->user)) { return false; } else { return true; } } - /** - * Set the user and password after last checkings if required - * - * @global array $cfg the valid servers settings - * @global integer $server the id of the current server - * @global string $PHP_AUTH_USER the current username - * @global string $PHP_AUTH_PW the current password - * - * @return boolean always true - */ - public function authSetUser() - { - global $cfg, $server; - global $PHP_AUTH_USER, $PHP_AUTH_PW; - - $cfg['Server']['user'] = $PHP_AUTH_USER; - $cfg['Server']['password'] = $PHP_AUTH_PW; - - // Avoid showing the password in phpinfo()'s output - unset($GLOBALS['PHP_AUTH_PW']); - unset($_SERVER['PHP_AUTH_PW']); - - $this->setSessionAccessTime(); - - return true; - } - /** * User is not allowed to login to MySQL -> authentication failed * - * @return bool true + * @param string $failure String describing why authentication has failed + * + * @return void */ - public function authFails() + public function showFailure($failure) { + parent::showFailure($failure); $error = $GLOBALS['dbi']->getError(); if ($error && $GLOBALS['errno'] != 1045) { Core::fatalError($error); - - return true; + } else { + $this->authForm(); } - - $this->authForm(); - - return true; } /** @@ -236,6 +213,6 @@ class AuthenticationHttp extends AuthenticationPlugin */ public function getLoginFormURL() { - return './index.php?old_usr=' . $GLOBALS['PHP_AUTH_USER']; + return './index.php?old_usr=' . $this->user; } } diff --git a/libraries/classes/Plugins/Auth/AuthenticationSignon.php b/libraries/classes/Plugins/Auth/AuthenticationSignon.php index faa43ab7ae..9391f0b92b 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationSignon.php +++ b/libraries/classes/Plugins/Auth/AuthenticationSignon.php @@ -24,7 +24,7 @@ class AuthenticationSignon extends AuthenticationPlugin * * @return boolean always true (no return indeed) */ - public function auth() + public function showLoginForm() { unset($_SESSION['LAST_SIGNON_URL']); if (empty($GLOBALS['cfg']['Server']['SignonURL'])) { @@ -41,17 +41,12 @@ class AuthenticationSignon extends AuthenticationPlugin } /** - * Gets advanced authentication settings - * - * @global string $PHP_AUTH_USER the username - * @global string $PHP_AUTH_PW the password + * Gets authentication credentials * * @return boolean whether we get authentication settings or not */ - public function authCheck() + public function readCredentials() { - global $PHP_AUTH_USER, $PHP_AUTH_PW; - /* Check if we're using same signon server */ $signon_url = $GLOBALS['cfg']['Server']['SignonURL']; if (isset($_SESSION['LAST_SIGNON_URL']) @@ -91,7 +86,7 @@ class AuthenticationSignon extends AuthenticationPlugin } include $script_name; - list ($PHP_AUTH_USER, $PHP_AUTH_PW) + list ($this->user, $this->password) = get_login_credentials($GLOBALS['cfg']['Server']['user']); } elseif (isset($_COOKIE[$session_name])) { /* Does session exist? */ /* End current session */ @@ -131,10 +126,10 @@ class AuthenticationSignon extends AuthenticationPlugin /* Grab credentials if they exist */ if (isset($_SESSION['PMA_single_signon_user'])) { - $PHP_AUTH_USER = $_SESSION['PMA_single_signon_user']; + $this->user = $_SESSION['PMA_single_signon_user']; } if (isset($_SESSION['PMA_single_signon_password'])) { - $PHP_AUTH_PW = $_SESSION['PMA_single_signon_password']; + $this->password = $_SESSION['PMA_single_signon_password']; } if (isset($_SESSION['PMA_single_signon_host'])) { $single_signon_host = $_SESSION['PMA_single_signon_host']; @@ -193,7 +188,7 @@ class AuthenticationSignon extends AuthenticationPlugin } // Returns whether we get authentication settings or not - if (empty($PHP_AUTH_USER)) { + if (empty($this->user)) { unset($_SESSION['LAST_SIGNON_URL']); return false; @@ -204,33 +199,17 @@ class AuthenticationSignon extends AuthenticationPlugin } } - /** - * Set the user and password after last checkings if required - * - * @global array $cfg the valid servers settings - * @global string $PHP_AUTH_USER the current username - * @global string $PHP_AUTH_PW the current password - * - * @return boolean always true - */ - public function authSetUser() - { - global $cfg; - global $PHP_AUTH_USER, $PHP_AUTH_PW; - - $cfg['Server']['user'] = $PHP_AUTH_USER; - $cfg['Server']['password'] = $PHP_AUTH_PW; - - return true; - } - /** * User is not allowed to login to MySQL -> authentication failed * - * @return boolean always true (no return indeed) + * @param string $failure String describing why authentication has failed + * + * @return void */ - public function authFails() + public function showFailure($failure) { + parent::showFailure($failure); + /* Session name */ $session_name = $GLOBALS['cfg']['Server']['SignonSession']; @@ -247,9 +226,9 @@ class AuthenticationSignon extends AuthenticationPlugin } /* Set error message */ - $_SESSION['PMA_single_signon_error_message'] = $this->getErrorMessage(); + $_SESSION['PMA_single_signon_error_message'] = $this->getErrorMessage($failure); } - $this->auth(); + $this->showLoginForm(); } /** diff --git a/libraries/classes/Plugins/AuthenticationPlugin.php b/libraries/classes/Plugins/AuthenticationPlugin.php index d112c5a487..a153f8f190 100644 --- a/libraries/classes/Plugins/AuthenticationPlugin.php +++ b/libraries/classes/Plugins/AuthenticationPlugin.php @@ -8,7 +8,10 @@ namespace PhpMyAdmin\Plugins; use PhpMyAdmin\Core; +use PhpMyAdmin\IpAllowDeny; +use PhpMyAdmin\Logging; use PhpMyAdmin\Sanitize; +use PhpMyAdmin\Session; use PhpMyAdmin\Url; /** @@ -19,42 +22,71 @@ use PhpMyAdmin\Url; */ abstract class AuthenticationPlugin { + /** + * Username + * + * @var string + */ + public $user = ''; + + /** + * Password + * + * @var string + */ + public $password = ''; + /** * Displays authentication form * * @return boolean */ - abstract public function auth(); + abstract public function showLoginForm(); /** - * Gets advanced authentication settings + * Gets authentication credentials * * @return boolean */ - abstract public function authCheck(); + abstract public function readCredentials(); /** * Set the user and password after last checkings if required * * @return boolean */ - abstract public function authSetUser(); + public function storeCredentials() + { + global $cfg; + + $this->setSessionAccessTime(); + + $cfg['Server']['user'] = $this->user; + $cfg['Server']['password'] = $this->password; + + return true; + } /** * Stores user credentials after successful login. * * @return void */ - public function storeUserCredentials() + public function rememberCredentials() { } /** * User is not allowed to login to MySQL -> authentication failed * - * @return boolean + * @param string $failure String describing why authentication has failed + * + * @return void */ - abstract public function authFails(); + public function showFailure($failure) + { + Logging::logUser($this->user, $failure); + } /** * Perform logout @@ -63,8 +95,6 @@ abstract class AuthenticationPlugin */ public function logOut() { - global $PHP_AUTH_USER, $PHP_AUTH_PW; - /* Obtain redirect URL (before doing logout) */ if (! empty($GLOBALS['cfg']['Server']['LogoutURL'])) { $redirect_url = $GLOBALS['cfg']['Server']['LogoutURL']; @@ -73,8 +103,8 @@ abstract class AuthenticationPlugin } /* Clear credentials */ - $PHP_AUTH_USER = ''; - $PHP_AUTH_PW = ''; + $this->user = ''; + $this->password = ''; /* * Get a logged-in server count in case of LoginCookieDeleteAll is disabled. @@ -121,18 +151,20 @@ abstract class AuthenticationPlugin /** * Returns error message for failed authentication. * + * @param string $failure String describing why authentication has failed + * * @return string */ - public function getErrorMessage() + public function getErrorMessage($failure) { - if (!empty($GLOBALS['login_without_password_is_forbidden'])) { + if ($failure == 'empty-denied') { return __( 'Login without a password is forbidden by configuration' . ' (see AllowNoPassword)' ); - } elseif (!empty($GLOBALS['allowDeny_forbidden'])) { + } elseif ($failure == 'root-denied' || $failure == 'allow-denied') { return __('Access denied!'); - } elseif (!empty($GLOBALS['no_activity'])) { + } elseif ($failure == 'no-activity') { return sprintf( __('No activity within %s seconds; please log in again.'), intval($GLOBALS['cfg']['LoginCookieValidity']) @@ -187,5 +219,82 @@ abstract class AuthenticationPlugin $time = time(); } $_SESSION['browser_access_time'][$guid] = $time; - } + } + + /** + * High level authentication interface + * + * Gets the credentials or shows login form if necessary + * + * @return void + */ + public function authenticate() + { + if (! $this->readCredentials()) { + /* Force generating of new session on login */ + Session::secure(); + $this->showLoginForm(); + } else { + $this->storeCredentials(); + } + + $this->checkRules(); + } + + /** + * Check configuration defined restrictions for authentication + * + * @return void + */ + public function checkRules() + { + global $cfg; + + // Check IP-based Allow/Deny rules as soon as possible to reject the + // user based on mod_access in Apache + if (isset($cfg['Server']['AllowDeny']) + && isset($cfg['Server']['AllowDeny']['order']) + ) { + $allowDeny_forbidden = false; // default + if ($cfg['Server']['AllowDeny']['order'] == 'allow,deny') { + $allowDeny_forbidden = true; + if (IpAllowDeny::allowDeny('allow')) { + $allowDeny_forbidden = false; + } + if (IpAllowDeny::allowDeny('deny')) { + $allowDeny_forbidden = true; + } + } elseif ($cfg['Server']['AllowDeny']['order'] == 'deny,allow') { + if (IpAllowDeny::allowDeny('deny')) { + $allowDeny_forbidden = true; + } + if (IpAllowDeny::allowDeny('allow')) { + $allowDeny_forbidden = false; + } + } elseif ($cfg['Server']['AllowDeny']['order'] == 'explicit') { + if (IpAllowDeny::allowDeny('allow') && ! IpAllowDeny::allowDeny('deny')) { + $allowDeny_forbidden = false; + } else { + $allowDeny_forbidden = true; + } + } // end if ... elseif ... elseif + + // Ejects the user if banished + if ($allowDeny_forbidden) { + $this->showFailure('allow-denied'); + } + } // end if + + // is root allowed? + if (! $cfg['Server']['AllowRoot'] && $cfg['Server']['user'] == 'root') { + $this->showFailure('root-denied'); + } + + // is a login without password allowed? + if (! $cfg['Server']['AllowNoPassword'] + && $cfg['Server']['password'] === '' + ) { + $this->showFailure('empty-denied'); + } + } } diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 34a377715d..8e9e8ee2de 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -36,7 +36,6 @@ use PhpMyAdmin\Core; use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\Database\DatabaseList; use PhpMyAdmin\ErrorHandler; -use PhpMyAdmin\IpAllowDeny; use PhpMyAdmin\LanguageManager; use PhpMyAdmin\Logging; use PhpMyAdmin\Message; @@ -512,65 +511,7 @@ if (! defined('PMA_MINIMUM_COMMON')) { /** @var AuthenticationPlugin $auth_plugin */ $auth_plugin = new $auth_class($plugin_manager); - if (! $auth_plugin->authCheck()) { - /* Force generating of new session on login */ - Session::secure(); - $auth_plugin->auth(); - } else { - $auth_plugin->authSetUser(); - } - - // Check IP-based Allow/Deny rules as soon as possible to reject the - // user based on mod_access in Apache - if (isset($cfg['Server']['AllowDeny']) - && isset($cfg['Server']['AllowDeny']['order']) - ) { - $allowDeny_forbidden = false; // default - if ($cfg['Server']['AllowDeny']['order'] == 'allow,deny') { - $allowDeny_forbidden = true; - if (IpAllowDeny::allowDeny('allow')) { - $allowDeny_forbidden = false; - } - if (IpAllowDeny::allowDeny('deny')) { - $allowDeny_forbidden = true; - } - } elseif ($cfg['Server']['AllowDeny']['order'] == 'deny,allow') { - if (IpAllowDeny::allowDeny('deny')) { - $allowDeny_forbidden = true; - } - if (IpAllowDeny::allowDeny('allow')) { - $allowDeny_forbidden = false; - } - } elseif ($cfg['Server']['AllowDeny']['order'] == 'explicit') { - if (IpAllowDeny::allowDeny('allow') && ! IpAllowDeny::allowDeny('deny')) { - $allowDeny_forbidden = false; - } else { - $allowDeny_forbidden = true; - } - } // end if ... elseif ... elseif - - // Ejects the user if banished - if ($allowDeny_forbidden) { - Logging::logUser($cfg['Server']['user'], 'allow-denied'); - $auth_plugin->authFails(); - } - } // end if - - // is root allowed? - if (! $cfg['Server']['AllowRoot'] && $cfg['Server']['user'] == 'root') { - $allowDeny_forbidden = true; - Logging::logUser($cfg['Server']['user'], 'root-denied'); - $auth_plugin->authFails(); - } - - // is a login without password allowed? - if (! $cfg['Server']['AllowNoPassword'] - && $cfg['Server']['password'] === '' - ) { - $login_without_password_is_forbidden = true; - Logging::logUser($cfg['Server']['user'], 'empty-denied'); - $auth_plugin->authFails(); - } + $auth_plugin->authenticate(); // Try to connect MySQL with the control user profile (will be used to // get the privileges list for the current user but the true user link @@ -588,8 +529,7 @@ if (! defined('PMA_MINIMUM_COMMON')) { $userlink = $GLOBALS['dbi']->connect(DatabaseInterface::CONNECT_USER); if ($userlink === false) { - Logging::logUser($cfg['Server']['user'], 'mysql-denied'); - $GLOBALS['auth_plugin']->authFails(); + $auth_plugin->showFailure('mysql-denied'); } // Set timestamp for the session, if required. @@ -633,7 +573,7 @@ if (! defined('PMA_MINIMUM_COMMON')) { $controllink = $GLOBALS['dbi']->connect(DatabaseInterface::CONNECT_USER); } - $auth_plugin->storeUserCredentials(); + $auth_plugin->rememberCredentials(); /* Log success */ Logging::logUser($cfg['Server']['user']); diff --git a/test/classes/Plugins/Auth/AuthenticationConfigTest.php b/test/classes/Plugins/Auth/AuthenticationConfigTest.php index 27ec8e0c06..3fe0f16e7d 100644 --- a/test/classes/Plugins/Auth/AuthenticationConfigTest.php +++ b/test/classes/Plugins/Auth/AuthenticationConfigTest.php @@ -47,43 +47,47 @@ class AuthenticationConfigTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::auth + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm * * @return void */ public function testAuth() { $this->assertTrue( - $this->object->auth() + $this->object->showLoginForm() ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials * * @return void */ public function testAuthCheck() { + $GLOBALS['cfg']['Server'] = array( + 'user' => 'username', + 'password' => 'password', + ); $this->assertTrue( - $this->object->authCheck() + $this->object->readCredentials() ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authSetUser + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::storeCredentials * * @return void */ public function testAuthSetUser() { $this->assertTrue( - $this->object->authSetUser() + $this->object->storeCredentials() ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authFails + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showFailure * * @return void */ @@ -101,13 +105,9 @@ class AuthenticationConfigTest extends PmaTestCase $GLOBALS['dbi'] = $dbi; ob_start(); - $result = $this->object->authFails(); + $this->object->showFailure(''); $html = ob_get_clean(); - $this->assertTrue( - $result - ); - $this->assertContains( 'You probably did not create a configuration file. You might want ' . 'to use the setup script to create one.', diff --git a/test/classes/Plugins/Auth/AuthenticationCookieTest.php b/test/classes/Plugins/Auth/AuthenticationCookieTest.php index 0b37133ca0..e0e48f46ea 100644 --- a/test/classes/Plugins/Auth/AuthenticationCookieTest.php +++ b/test/classes/Plugins/Auth/AuthenticationCookieTest.php @@ -60,7 +60,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::auth + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm * * @return void * @group medium @@ -87,17 +87,11 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['conn_error'] = true; $this->assertTrue( - $this->object->auth() + $this->object->showLoginForm() ); } - /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::auth - * - * @return void - * @group medium - */ - public function testAuthError() + private function getAuthErrorMockResponse() { $mockResponse = $this->mockResponse(); @@ -106,12 +100,6 @@ class AuthenticationCookieTest extends PmaTestCase ->with() ->will($this->returnValue(false)); - $_REQUEST['old_usr'] = ''; - $GLOBALS['cfg']['LoginCookieRecall'] = true; - $GLOBALS['cfg']['blowfish_secret'] = 'secret'; - $GLOBALS['PHP_AUTH_USER'] = 'pmauser'; - $GLOBALS['pma_auth_server'] = 'localhost'; - // mock footer $mockFooter = $this->getMockBuilder('PhpMyAdmin\Footer') ->disableOriginalConstructor() @@ -165,17 +153,7 @@ class AuthenticationCookieTest extends PmaTestCase ->will($this->returnValue($mockHeader)); $GLOBALS['pmaThemeImage'] = 'test'; - $GLOBALS['conn_error'] = true; - $GLOBALS['cfg']['Lang'] = 'en'; - $GLOBALS['cfg']['AllowArbitraryServer'] = true; $GLOBALS['cfg']['Servers'] = array(1, 2); - $GLOBALS['cfg']['CaptchaLoginPrivateKey'] = ''; - $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; - $GLOBALS['target'] = 'testTarget'; - $GLOBALS['db'] = 'testDb'; - $GLOBALS['table'] = 'testTable'; - - file_put_contents('testlogo_right.png', ''); // mock error handler @@ -194,9 +172,38 @@ class AuthenticationCookieTest extends PmaTestCase ->with(); $GLOBALS['error_handler'] = $mockErrorHandler; + } + + /** + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm + * + * @return void + * @group medium + */ + public function testAuthError() + { + $this->getAuthErrorMockResponse(); + + $_REQUEST['old_usr'] = ''; + $GLOBALS['cfg']['LoginCookieRecall'] = true; + $GLOBALS['cfg']['blowfish_secret'] = 'secret'; + $this->object->user = 'pmauser'; + $GLOBALS['pma_auth_server'] = 'localhost'; + + + $GLOBALS['conn_error'] = true; + $GLOBALS['cfg']['Lang'] = 'en'; + $GLOBALS['cfg']['AllowArbitraryServer'] = true; + $GLOBALS['cfg']['CaptchaLoginPrivateKey'] = ''; + $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; + $GLOBALS['target'] = 'testTarget'; + $GLOBALS['db'] = 'testDb'; + $GLOBALS['table'] = 'testTable'; + + file_put_contents('testlogo_right.png', ''); ob_start(); - $this->object->auth(); + $this->object->showLoginForm(); $result = ob_get_clean(); // assertions @@ -261,7 +268,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::auth + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm * * @return void * @group medium @@ -299,7 +306,7 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['error_handler'] = new ErrorHandler; ob_start(); - $this->object->auth(); + $this->object->showLoginForm(); $result = ob_get_clean(); // assertions @@ -344,7 +351,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::auth with headers + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm with headers * * @return void */ @@ -362,7 +369,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::auth with headers + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm with headers * * @return void */ @@ -382,7 +389,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials * * @return void */ @@ -394,7 +401,7 @@ class AuthenticationCookieTest extends PmaTestCase $_REQUEST['pma_username'] = 'testPMAUser'; $this->assertFalse( - $this->object->authCheck() + $this->object->readCredentials() ); $this->assertEquals( @@ -404,7 +411,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials * * @return void */ @@ -428,7 +435,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials * * @return void */ @@ -454,7 +461,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials * * @return void */ @@ -469,17 +476,17 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['cfg']['AllowArbitraryServer'] = true; $this->assertTrue( - $this->object->authCheck() + $this->object->readCredentials() ); $this->assertEquals( 'testPMAUser', - $GLOBALS['PHP_AUTH_USER'] + $this->object->user ); $this->assertEquals( 'testPMAPSWD', - $GLOBALS['PHP_AUTH_PW'] + $this->object->password ); $this->assertEquals( @@ -493,7 +500,7 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials * * @return void */ @@ -508,12 +515,12 @@ class AuthenticationCookieTest extends PmaTestCase $_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09'); $this->assertFalse( - $this->object->authCheck() + $this->object->readCredentials() ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials * * @return void */ @@ -529,12 +536,12 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['cfg']['LoginCookieValidity'] = 1440; $this->assertFalse( - $this->object->authCheck() + $this->object->readCredentials() ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck (mock blowfish functions reqd) + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials (mock blowfish functions reqd) * * @return void */ @@ -562,17 +569,17 @@ class AuthenticationCookieTest extends PmaTestCase ->will($this->returnValue('testBF')); $this->assertFalse( - $this->object->authCheck() + $this->object->readCredentials() ); $this->assertEquals( 'testBF', - $GLOBALS['PHP_AUTH_USER'] + $this->object->user ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck (mocking blowfish functions) + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials (mocking blowfish functions) * * @return void */ @@ -602,7 +609,7 @@ class AuthenticationCookieTest extends PmaTestCase ->will($this->returnValue('{"password":""}')); $this->assertTrue( - $this->object->authCheck() + $this->object->readCredentials() ); $this->assertTrue( @@ -611,13 +618,13 @@ class AuthenticationCookieTest extends PmaTestCase $this->assertEquals( '', - $GLOBALS['PHP_AUTH_PW'] + $this->object->password ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authCheck (mocking the object itself) + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials (mocking the object itself) * * @return void */ @@ -638,29 +645,30 @@ class AuthenticationCookieTest extends PmaTestCase // mock for blowfish function $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') ->disableOriginalConstructor() - ->setMethods(array('authFails')) + ->setMethods(array('showFailure', 'cookieDecrypt')) ->getMock(); $this->object->expects($this->once()) - ->method('authFails'); + ->method('cookieDecrypt') + ->will($this->returnValue('testBF')); + + + $this->object->expects($this->once()) + ->method('showFailure'); $this->assertFalse( - $this->object->authCheck() - ); - - $this->assertTrue( - $GLOBALS['no_activity'] + $this->object->readCredentials() ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authSetUser + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::storeCredentials * * @return void */ public function testAuthSetUser() { - $GLOBALS['PHP_AUTH_USER'] = 'pmaUser2'; + $this->object->user = 'pmaUser2'; $arr = array( 'host' => 'a', 'port' => 1, @@ -674,22 +682,14 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['cfg']['Servers'][1] = $arr; $GLOBALS['cfg']['AllowArbitraryServer'] = true; $GLOBALS['pma_auth_server'] = 'b 2'; - $GLOBALS['PHP_AUTH_PW'] = $_SERVER['PHP_AUTH_PW'] = 'testPW'; + $this->object->password = 'testPW'; $GLOBALS['server'] = 2; $GLOBALS['cfg']['LoginCookieStore'] = true; $GLOBALS['from_cookie'] = true; - $this->object->authSetUser(); + $this->object->storeCredentials(); - $this->assertFalse( - isset($GLOBALS['PHP_AUTH_PW']) - ); - - $this->assertFalse( - isset($_SERVER['PHP_AUTH_PW']) - ); - - $this->object->storeUserCredentials(); + $this->object->rememberCredentials(); $this->assertTrue( isset($_COOKIE['pmaUser-2']) @@ -710,13 +710,13 @@ class AuthenticationCookieTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authSetUser (check for headers redirect) + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::storeCredentials (check for headers redirect) * * @return void */ public function testAuthSetUserWithHeaders() { - $GLOBALS['PHP_AUTH_USER'] = 'pmaUser2'; + $this->object->user = 'pmaUser2'; $arr = array( 'host' => 'a', 'port' => 1, @@ -731,7 +731,7 @@ class AuthenticationCookieTest extends PmaTestCase $GLOBALS['cfg']['Servers'][1] = $arr; $GLOBALS['cfg']['AllowArbitraryServer'] = true; $GLOBALS['pma_auth_server'] = 'b 2'; - $GLOBALS['PHP_AUTH_PW'] = $_SERVER['PHP_AUTH_PW'] = 'testPW'; + $this->object->password = 'testPW'; $GLOBALS['server'] = 2; $GLOBALS['cfg']['LoginCookieStore'] = true; $GLOBALS['from_cookie'] = false; @@ -741,12 +741,12 @@ class AuthenticationCookieTest extends PmaTestCase $this->stringContains('&server=2&lang=en&collation_connection=utf-8') ); - $this->object->authSetUser(); - $this->object->storeUserCredentials(); + $this->object->storeCredentials(); + $this->object->rememberCredentials(); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::authFails + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showFailure * * @return void */ @@ -754,19 +754,17 @@ class AuthenticationCookieTest extends PmaTestCase { $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $GLOBALS['server'] = 2; $_COOKIE['pmaAuth-2'] = 'pass'; - $GLOBALS['login_without_password_is_forbidden'] = '1'; - $this->mockResponse( array('Cache-Control: no-store, no-cache, must-revalidate'), array('Pragma: no-cache') ); - $this->object->authFails(); + $this->object->showFailure('empty-denied'); $this->assertEquals( $GLOBALS['conn_error'], @@ -780,20 +778,17 @@ class AuthenticationCookieTest extends PmaTestCase { $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $GLOBALS['server'] = 2; $_COOKIE['pmaAuth-2'] = 'pass'; - $GLOBALS['login_without_password_is_forbidden'] = ''; - $GLOBALS['allowDeny_forbidden'] = '1'; - $this->mockResponse( array('Cache-Control: no-store, no-cache, must-revalidate'), array('Pragma: no-cache') ); - $this->object->authFails(); + $this->object->showFailure('allow-denied'); $this->assertEquals( $GLOBALS['conn_error'], @@ -805,21 +800,20 @@ class AuthenticationCookieTest extends PmaTestCase { $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $GLOBALS['server'] = 2; $_COOKIE['pmaAuth-2'] = 'pass'; $GLOBALS['allowDeny_forbidden'] = ''; - $GLOBALS['no_activity'] = '1'; $GLOBALS['cfg']['LoginCookieValidity'] = 10; $this->mockResponse( array('Cache-Control: no-store, no-cache, must-revalidate'), array('Pragma: no-cache') ); - $this->object->authFails(); + $this->object->showFailure('no-activity'); $this->assertEquals( $GLOBALS['conn_error'], @@ -831,7 +825,7 @@ class AuthenticationCookieTest extends PmaTestCase { $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $GLOBALS['server'] = 2; @@ -846,14 +840,13 @@ class AuthenticationCookieTest extends PmaTestCase ->will($this->returnValue(false)); $GLOBALS['dbi'] = $dbi; - $GLOBALS['no_activity'] = ''; $GLOBALS['errno'] = 42; $this->mockResponse( array('Cache-Control: no-store, no-cache, must-revalidate'), array('Pragma: no-cache') ); - $this->object->authFails(); + $this->object->showFailure(''); $this->assertEquals( $GLOBALS['conn_error'], @@ -865,7 +858,7 @@ class AuthenticationCookieTest extends PmaTestCase { $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $dbi = $this->getMockBuilder('PhpMyAdmin\DatabaseInterface') @@ -886,7 +879,7 @@ class AuthenticationCookieTest extends PmaTestCase array('Cache-Control: no-store, no-cache, must-revalidate'), array('Pragma: no-cache') ); - $this->object->authFails(); + $this->object->showFailure(''); $this->assertEquals( $GLOBALS['conn_error'], @@ -1144,4 +1137,201 @@ class AuthenticationCookieTest extends PmaTestCase ), ); } + + /** + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationCookie::authenticate + * + * @return void + */ + public function testAuthenticate() + { + $GLOBALS['cfg']['CaptchaLoginPrivateKey'] = ''; + $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; + $GLOBALS['cfg']['Server']['AllowRoot'] = false; + $GLOBALS['cfg']['Server']['AllowNoPassword'] = false; + $_REQUEST['old_usr'] = ''; + $_REQUEST['pma_username'] = 'testUser'; + $_REQUEST['pma_password'] = 'testPassword'; + + ob_start(); + $this->object->authenticate(); + $result = ob_get_clean(); + + /* Nothing should be printed */ + $this->assertEquals('', $result); + + /* Verify readCredentials worked */ + $this->assertEquals('testUser', $this->object->user); + $this->assertEquals('testPassword', $this->object->password); + + /* Verify storeCredentials worked */ + $this->assertEquals('testUser', $GLOBALS['cfg']['Server']['user']); + $this->assertEquals('testPassword', $GLOBALS['cfg']['Server']['password']); + } + + /** + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationCookie::checkRules + * + * @return void + * + * @dataProvider checkRulesProvider + */ + public function testCheckRules($user, $pass, $ip, $root, $nopass, $rules, $expected) + { + $this->object->user = $user; + $this->object->password = $pass; + $this->object->storeCredentials(); + + $_SERVER['REMOTE_ADDR'] = $ip; + + $GLOBALS['cfg']['Server']['AllowRoot'] = $root; + $GLOBALS['cfg']['Server']['AllowNoPassword'] = $nopass; + $GLOBALS['cfg']['Server']['AllowDeny'] = $rules; + + if (! empty($expected)) { + $this->getAuthErrorMockResponse(); + } + + ob_start(); + $this->object->checkRules(); + $result = ob_get_clean(); + + if (empty($expected)) { + $this->assertEquals($expected, $result); + } else { + $this->assertContains($expected, $result); + } + } + + public function checkRulesProvider() + { + return array( + 'nopass-ok' => array( + 'testUser', + '', + '1.2.3.4', + true, + true, + array(), + '', + ), + 'nopass' => array( + 'testUser', + '', + '1.2.3.4', + true, + false, + array(), + 'Login without a password is forbidden', + ), + 'root-ok' => array( + 'root', + 'root', + '1.2.3.4', + true, + true, + array(), + '', + ), + 'root' => array( + 'root', + 'root', + '1.2.3.4', + false, + true, + array(), + 'Access denied!', + ), + 'rules-deny-allow-ok' => array( + 'root', + 'root', + '1.2.3.4', + true, + true, + array( + 'order' => 'deny,allow', + 'rules' => array( + 'allow root 1.2.3.4', + 'deny % from all', + ), + ), + '', + ), + 'rules-deny-allow-reject' => array( + 'user', + 'root', + '1.2.3.4', + true, + true, + array( + 'order' => 'deny,allow', + 'rules' => array( + 'allow root 1.2.3.4', + 'deny % from all', + ), + ), + 'Access denied!', + ), + 'rules-allow-deny-ok' => array( + 'root', + 'root', + '1.2.3.4', + true, + true, + array( + 'order' => 'allow,deny', + 'rules' => array( + 'deny user from all', + 'allow root 1.2.3.4', + ), + ), + '', + ), + 'rules-allow-deny-reject' => array( + 'user', + 'root', + '1.2.3.4', + true, + true, + array( + 'order' => 'allow,deny', + 'rules' => array( + 'deny user from all', + 'allow root 1.2.3.4', + ), + ), + 'Access denied!', + ), + 'rules-explicit-ok' => array( + 'root', + 'root', + '1.2.3.4', + true, + true, + array( + 'order' => 'explicit', + 'rules' => array( + 'deny user from all', + 'allow root 1.2.3.4', + ), + ), + '', + ), + 'rules-explicit-reject' => array( + 'user', + 'root', + '1.2.3.4', + true, + true, + array( + 'order' => 'explicit', + 'rules' => array( + 'deny user from all', + 'allow root 1.2.3.4', + ), + ), + 'Access denied!', + ), + ); + } } diff --git a/test/classes/Plugins/Auth/AuthenticationHttpTest.php b/test/classes/Plugins/Auth/AuthenticationHttpTest.php index cd70af767f..4eb47772ab 100644 --- a/test/classes/Plugins/Auth/AuthenticationHttpTest.php +++ b/test/classes/Plugins/Auth/AuthenticationHttpTest.php @@ -107,13 +107,13 @@ class AuthenticationHttpTest extends PmaTestCase $this->object->logOut(); } else { $this->assertFalse( - $this->object->auth() + $this->object->showLoginForm() ); } } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationHttp::auth + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationHttp::showLoginForm * * @return void */ @@ -169,7 +169,7 @@ class AuthenticationHttpTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationHttp::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationHttp::readCredentials * * @param string $user test username * @param string $pass test password @@ -181,14 +181,11 @@ class AuthenticationHttpTest extends PmaTestCase * @param string $old_usr value for $_REQUEST['old_usr'] * * @return void - * @dataProvider authCheckProvider + * @dataProvider readCredentialsProvider */ public function testAuthCheck($user, $pass, $userIndex, $passIndex, $expectedReturn, $expectedUser, $expectedPass, $old_usr = '' ) { - $GLOBALS['PHP_AUTH_USER'] = ''; - $GLOBALS['PHP_AUTH_PW'] = ''; - $_SERVER[$userIndex] = $user; $_SERVER[$passIndex] = $pass; @@ -196,17 +193,17 @@ class AuthenticationHttpTest extends PmaTestCase $this->assertEquals( $expectedReturn, - $this->object->authCheck() + $this->object->readCredentials() ); $this->assertEquals( $expectedUser, - $GLOBALS['PHP_AUTH_USER'] + $this->object->user ); $this->assertEquals( $expectedPass, - $GLOBALS['PHP_AUTH_PW'] + $this->object->password ); $_SERVER[$userIndex] = null; @@ -218,7 +215,7 @@ class AuthenticationHttpTest extends PmaTestCase * * @return array Test data */ - public function authCheckProvider() + public function readCredentialsProvider() { return array( array( @@ -271,7 +268,7 @@ class AuthenticationHttpTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationHttp::authSetUser + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationHttp::storeCredentials * * @return void */ @@ -279,13 +276,13 @@ class AuthenticationHttpTest extends PmaTestCase { // case 1 - $GLOBALS['PHP_AUTH_USER'] = 'testUser'; - $GLOBALS['PHP_AUTH_PW'] = 'testPass'; + $this->object->user = 'testUser'; + $this->object->password = 'testPass'; $GLOBALS['server'] = 2; $GLOBALS['cfg']['Server']['user'] = 'testUser'; $this->assertTrue( - $this->object->authSetUser() + $this->object->storeCredentials() ); $this->assertEquals( @@ -298,10 +295,6 @@ class AuthenticationHttpTest extends PmaTestCase $GLOBALS['cfg']['Server']['password'] ); - $this->assertFalse( - isset($GLOBALS['PHP_AUTH_PW']) - ); - $this->assertFalse( isset($_SERVER['PHP_AUTH_PW']) ); @@ -312,8 +305,8 @@ class AuthenticationHttpTest extends PmaTestCase ); // case 2 - $GLOBALS['PHP_AUTH_USER'] = 'testUser'; - $GLOBALS['PHP_AUTH_PW'] = 'testPass'; + $this->object->user = 'testUser'; + $this->object->password = 'testPass'; $GLOBALS['cfg']['Servers'][1] = array( 'host' => 'a', 'user' => 'testUser', @@ -326,7 +319,7 @@ class AuthenticationHttpTest extends PmaTestCase ); $this->assertTrue( - $this->object->authSetUser() + $this->object->storeCredentials() ); $this->assertEquals( @@ -345,8 +338,8 @@ class AuthenticationHttpTest extends PmaTestCase // case 3 $GLOBALS['server'] = 3; - $GLOBALS['PHP_AUTH_USER'] = 'testUser'; - $GLOBALS['PHP_AUTH_PW'] = 'testPass'; + $this->object->user = 'testUser'; + $this->object->password = 'testPass'; $GLOBALS['cfg']['Servers'][1] = array( 'host' => 'a', 'user' => 'testUsers', @@ -359,7 +352,7 @@ class AuthenticationHttpTest extends PmaTestCase ); $this->assertTrue( - $this->object->authSetUser() + $this->object->storeCredentials() ); $this->assertEquals( @@ -407,7 +400,7 @@ class AuthenticationHttpTest extends PmaTestCase $GLOBALS['errno'] = 31; ob_start(); - $this->object->authFails(); + $this->object->showFailure(''); $result = ob_get_clean(); $this->assertContains( @@ -426,14 +419,10 @@ class AuthenticationHttpTest extends PmaTestCase $GLOBALS['cfg']['Server']['host'] = 'host'; $GLOBALS['errno'] = 1045; - $this->assertTrue( - $this->object->authFails() - ); + $this->object->showFailure(''); // case 3 $GLOBALS['errno'] = 1043; - $this->assertTrue( - $this->object->authFails() - ); + $this->object->showFailure(''); } } diff --git a/test/classes/Plugins/Auth/AuthenticationSignonTest.php b/test/classes/Plugins/Auth/AuthenticationSignonTest.php index 529aa7cd26..a421b11d72 100644 --- a/test/classes/Plugins/Auth/AuthenticationSignonTest.php +++ b/test/classes/Plugins/Auth/AuthenticationSignonTest.php @@ -45,7 +45,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::auth + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::showLoginForm * * @return void */ @@ -54,7 +54,7 @@ class AuthenticationSignonTest extends PmaTestCase $GLOBALS['cfg']['Server']['SignonURL'] = ''; ob_start(); - $this->object->auth(); + $this->object->showLoginForm(); $result = ob_get_clean(); $this->assertContains( @@ -64,7 +64,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::auth + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::showLoginForm * * @return void */ @@ -79,7 +79,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::auth + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::showLoginForm * * @return void */ @@ -95,7 +95,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::readCredentials * * @return void */ @@ -105,12 +105,12 @@ class AuthenticationSignonTest extends PmaTestCase $_SESSION['LAST_SIGNON_URL'] = 'https://example.com/SignonDiffURL'; $this->assertFalse( - $this->object->authCheck() + $this->object->readCredentials() ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::readCredentials * * @return void */ @@ -126,17 +126,17 @@ class AuthenticationSignonTest extends PmaTestCase $GLOBALS['cfg']['Server']['user'] = 'user'; $this->assertTrue( - $this->object->authCheck() + $this->object->readCredentials() ); $this->assertEquals( 'user', - $GLOBALS['PHP_AUTH_USER'] + $this->object->user ); $this->assertEquals( 'password', - $GLOBALS['PHP_AUTH_PW'] + $this->object->password ); $this->assertEquals( @@ -146,7 +146,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::readCredentials * * @return void */ @@ -202,7 +202,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authCheck + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::readCredentials * * @return void */ @@ -225,32 +225,32 @@ class AuthenticationSignonTest extends PmaTestCase $_SESSION['PMA_single_signon_token'] = 'pmaToken'; $this->assertTrue( - $this->object->authCheck() + $this->object->readCredentials() ); $this->assertEquals( 'user123', - $GLOBALS['PHP_AUTH_USER'] + $this->object->user ); $this->assertEquals( 'pass123', - $GLOBALS['PHP_AUTH_PW'] + $this->object->password ); } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authSetUser + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::storeCredentials * * @return void */ public function testAuthSetUser() { - $GLOBALS['PHP_AUTH_USER'] = 'testUser123'; - $GLOBALS['PHP_AUTH_PW'] = 'testPass123'; + $this->object->user = 'testUser123'; + $this->object->password = 'testPass123'; $this->assertTrue( - $this->object->authSetUser() + $this->object->storeCredentials() ); $this->assertEquals( @@ -265,7 +265,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authFails + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::showFailure * * @return void */ @@ -276,15 +276,13 @@ class AuthenticationSignonTest extends PmaTestCase $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationSignon') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $this->object->expects($this->exactly(1)) - ->method('auth'); + ->method('showLoginForm'); - $GLOBALS['login_without_password_is_forbidden'] = true; - - $this->object->authFails(); + $this->object->showFailure('empty-denied'); $this->assertEquals( 'Login without a password is forbidden by configuration ' @@ -294,7 +292,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authFails + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::showFailure * * @return void */ @@ -305,16 +303,13 @@ class AuthenticationSignonTest extends PmaTestCase $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationSignon') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $this->object->expects($this->exactly(1)) - ->method('auth'); + ->method('showLoginForm'); - $GLOBALS['login_without_password_is_forbidden'] = null; - $GLOBALS['allowDeny_forbidden'] = true; - - $this->object->authFails(); + $this->object->showFailure('allow-denied'); $this->assertEquals( 'Access denied!', @@ -323,7 +318,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authFails + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::showFailure * * @return void */ @@ -334,17 +329,15 @@ class AuthenticationSignonTest extends PmaTestCase $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationSignon') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $this->object->expects($this->exactly(1)) - ->method('auth'); + ->method('showLoginForm'); - $GLOBALS['allowDeny_forbidden'] = null; - $GLOBALS['no_activity'] = true; $GLOBALS['cfg']['LoginCookieValidity'] = '1440'; - $this->object->authFails(); + $this->object->showFailure('no-activity'); $this->assertEquals( 'No activity within 1440 seconds; please log in again.', @@ -353,7 +346,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authFails + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::showFailure * * @return void */ @@ -364,11 +357,11 @@ class AuthenticationSignonTest extends PmaTestCase $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationSignon') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $this->object->expects($this->exactly(1)) - ->method('auth'); + ->method('showLoginForm'); $dbi = $this->getMockBuilder('PhpMyAdmin\DatabaseInterface') ->disableOriginalConstructor() @@ -379,9 +372,8 @@ class AuthenticationSignonTest extends PmaTestCase ->will($this->returnValue('error<123>')); $GLOBALS['dbi'] = $dbi; - $GLOBALS['no_activity'] = null; - $this->object->authFails(); + $this->object->showFailure(''); $this->assertEquals( 'error<123>', @@ -390,7 +382,7 @@ class AuthenticationSignonTest extends PmaTestCase } /** - * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::authFails + * Test for PhpMyAdmin\Plugins\Auth\AuthenticationSignon::showFailure * * @return void */ @@ -401,11 +393,11 @@ class AuthenticationSignonTest extends PmaTestCase $this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationSignon') ->disableOriginalConstructor() - ->setMethods(array('auth')) + ->setMethods(array('showLoginForm')) ->getMock(); $this->object->expects($this->exactly(1)) - ->method('auth'); + ->method('showLoginForm'); $dbi = $this->getMockBuilder('PhpMyAdmin\DatabaseInterface') ->disableOriginalConstructor() @@ -417,7 +409,7 @@ class AuthenticationSignonTest extends PmaTestCase $GLOBALS['dbi'] = $dbi; - $this->object->authFails(); + $this->object->showFailure(''); $this->assertEquals( 'Cannot log in to the MySQL server',