phpmyadmin/test/classes/Plugins/Auth/AuthenticationCookieTest.php
William Desportes af100abddf
Add more tests for testCookieDecrypt
Signed-off-by: William Desportes <williamdes@wdes.fr>
2020-01-07 19:07:27 +01:00

1400 lines
39 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* tests for PhpMyAdmin\Plugins\Auth\AuthenticationCookie class
*
* @package PhpMyAdmin-test
*/
declare(strict_types=1);
namespace PhpMyAdmin\Tests\Plugins\Auth;
use PhpMyAdmin\Config;
use PhpMyAdmin\ErrorHandler;
use PhpMyAdmin\Footer;
use PhpMyAdmin\Header;
use PhpMyAdmin\Plugins\Auth\AuthenticationCookie;
use PhpMyAdmin\Tests\PmaTestCase;
use ReflectionException;
use ReflectionMethod;
require_once ROOT_PATH . 'libraries/config.default.php';
/**
* tests for PhpMyAdmin\Plugins\Auth\AuthenticationCookie class
*
* @package PhpMyAdmin-test
*/
class AuthenticationCookieTest extends PmaTestCase
{
/**
* @var AuthenticationCookie
*/
protected $object;
/**
* Configures global environment.
*
* @return void
*/
protected function setUp(): void
{
$GLOBALS['PMA_Config'] = new Config();
$GLOBALS['PMA_Config']->enableBc();
$GLOBALS['server'] = 0;
$GLOBALS['text_dir'] = 'ltr';
$GLOBALS['db'] = 'db';
$GLOBALS['table'] = 'table';
$_POST['pma_password'] = '';
$this->object = new AuthenticationCookie();
$GLOBALS['PMA_PHP_SELF'] = '/phpmyadmin/';
$GLOBALS['cfg']['Server']['DisableIS'] = false;
}
/**
* tearDown for test cases
*
* @return void
*/
protected function tearDown(): void
{
parent::tearDown();
unset($this->object);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm
*
* @return void
* @group medium
*/
public function testAuthErrorAJAX()
{
$mockResponse = $this->mockResponse();
$mockResponse->expects($this->once())
->method('isAjax')
->with()
->will($this->returnValue(true));
$mockResponse->expects($this->once())
->method('setRequestStatus')
->with(false);
$mockResponse->expects($this->once())
->method('addJSON')
->with(
'redirect_flag',
'1'
);
$GLOBALS['conn_error'] = true;
$this->assertTrue(
$this->object->showLoginForm()
);
}
/**
* @return void
*/
private function getAuthErrorMockResponse()
{
$mockResponse = $this->mockResponse();
$mockResponse->expects($this->once())
->method('isAjax')
->with()
->will($this->returnValue(false));
// mock footer
$mockFooter = $this->getMockBuilder('PhpMyAdmin\Footer')
->disableOriginalConstructor()
->setMethods(['setMinimal'])
->getMock();
$mockFooter->expects($this->once())
->method('setMinimal')
->with();
// mock header
$mockHeader = $this->getMockBuilder('PhpMyAdmin\Header')
->disableOriginalConstructor()
->setMethods(
[
'setBodyId',
'setTitle',
'disableMenuAndConsole',
'disableWarnings',
]
)
->getMock();
$mockHeader->expects($this->once())
->method('setBodyId')
->with('loginform');
$mockHeader->expects($this->once())
->method('setTitle')
->with('phpMyAdmin');
$mockHeader->expects($this->once())
->method('disableMenuAndConsole')
->with();
$mockHeader->expects($this->once())
->method('disableWarnings')
->with();
// set mocked headers and footers
$mockResponse->expects($this->once())
->method('getFooter')
->with()
->will($this->returnValue($mockFooter));
$mockResponse->expects($this->once())
->method('getHeader')
->with()
->will($this->returnValue($mockHeader));
$GLOBALS['pmaThemeImage'] = 'test';
$GLOBALS['cfg']['Servers'] = [
1,
2,
];
// mock error handler
$mockErrorHandler = $this->getMockBuilder('PhpMyAdmin\ErrorHandler')
->disableOriginalConstructor()
->setMethods(['hasDisplayErrors', 'dispErrors'])
->getMock();
$mockErrorHandler->expects($this->once())
->method('hasDisplayErrors')
->with()
->will($this->returnValue(true));
$mockErrorHandler->expects($this->once())
->method('dispErrors')
->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';
ob_start();
$this->object->showLoginForm();
$result = ob_get_clean();
// assertions
$this->assertStringContainsString(
' id="imLogo"',
$result
);
$this->assertStringContainsString(
'<div class="error">',
$result
);
$this->assertStringContainsString(
'<form method="post" id="login_form" action="index.php" name="login_form" ' .
'class="disableAjax hide login js-show">',
$result
);
$this->assertStringContainsString(
'<input type="text" name="pma_servername" id="input_servername" ' .
'value="localhost"',
$result
);
$this->assertStringContainsString(
'<input type="text" name="pma_username" id="input_username" ' .
'value="pmauser" size="24" class="textfield">',
$result
);
$this->assertStringContainsString(
'<input type="password" name="pma_password" id="input_password" ' .
'value="" size="24" class="textfield">',
$result
);
$this->assertStringContainsString(
'<select name="server" id="select_server" ' .
'onchange="document.forms[\'login_form\'].' .
'elements[\'pma_servername\'].value = \'\'" >',
$result
);
$this->assertStringContainsString(
'<input type="hidden" name="target" value="testTarget">',
$result
);
$this->assertStringContainsString(
'<input type="hidden" name="db" value="testDb">',
$result
);
$this->assertStringContainsString(
'<input type="hidden" name="table" value="testTable">',
$result
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm
*
* @return void
* @group medium
*/
public function testAuthCaptcha()
{
$mockResponse = $this->mockResponse();
$mockResponse->expects($this->once())
->method('isAjax')
->with()
->will($this->returnValue(false));
$mockResponse->expects($this->once())
->method('getFooter')
->with()
->will($this->returnValue(new Footer()));
$mockResponse->expects($this->once())
->method('getHeader')
->with()
->will($this->returnValue(new Header()));
$_REQUEST['old_usr'] = '';
$GLOBALS['cfg']['LoginCookieRecall'] = false;
$GLOBALS['pmaThemeImage'] = 'test';
$GLOBALS['cfg']['Lang'] = '';
$GLOBALS['cfg']['AllowArbitraryServer'] = false;
$GLOBALS['cfg']['Servers'] = [1];
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = 'testprivkey';
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = 'testpubkey';
$GLOBALS['server'] = 0;
$GLOBALS['error_handler'] = new ErrorHandler();
ob_start();
$this->object->showLoginForm();
$result = ob_get_clean();
// assertions
$this->assertStringContainsString('id="imLogo"', $result);
// Check for language selection if locales are there
$loc = LOCALE_PATH . '/cs/LC_MESSAGES/phpmyadmin.mo';
if (is_readable($loc)) {
$this->assertStringContainsString(
'<select name="lang" class="autosubmit" lang="en" dir="ltr" ' .
'id="sel-lang">',
$result
);
}
$this->assertStringContainsString(
'<form method="post" id="login_form" action="index.php" name="login_form" ' .
'autocomplete="off" class="disableAjax hide login js-show">',
$result
);
$this->assertStringContainsString(
'<input type="hidden" name="server" value="0">',
$result
);
$this->assertStringContainsString(
'<script src="https://www.google.com/recaptcha/api.js?hl=en"'
. ' async defer></script>',
$result
);
$this->assertStringContainsString(
'<input class="btn btn-primary g-recaptcha" data-sitekey="testpubkey"'
. ' data-callback="Functions_recaptchaCallback" value="Go" type="submit" id="input_go">',
$result
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm with headers
*
* @return void
*/
public function testAuthHeader()
{
$GLOBALS['cfg']['LoginCookieDeleteAll'] = false;
$GLOBALS['cfg']['Servers'] = [1];
$this->mockResponse('Location: https://example.com/logout');
$GLOBALS['cfg']['Server']['LogoutURL'] = 'https://example.com/logout';
$GLOBALS['cfg']['Server']['auth_type'] = 'cookie';
$this->object->logOut();
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm with headers
*
* @return void
*/
public function testAuthHeaderPartial()
{
$GLOBALS['PMA_Config']->set('is_https', false);
$GLOBALS['cfg']['LoginCookieDeleteAll'] = false;
$GLOBALS['cfg']['Servers'] = [
1,
2,
3,
];
$GLOBALS['cfg']['Server']['LogoutURL'] = 'https://example.com/logout';
$GLOBALS['cfg']['Server']['auth_type'] = 'cookie';
$_COOKIE['pmaAuth-2'] = '';
$this->mockResponse('Location: /phpmyadmin/index.php?server=2&lang=en');
$this->object->logOut();
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials
*
* @return void
*/
public function testAuthCheckCaptcha()
{
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = 'testprivkey';
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = 'testpubkey';
$_POST["g-recaptcha-response"] = '';
$_POST['pma_username'] = 'testPMAUser';
$this->assertFalse(
$this->object->readCredentials()
);
$this->assertEquals(
'Missing reCAPTCHA verification, maybe it has been blocked by adblock?',
$GLOBALS['conn_error']
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials
*
* @return void
*/
public function testLogoutDelete()
{
$this->mockResponse('Location: /phpmyadmin/index.php');
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
$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';
$this->object->logOut();
$this->assertArrayNotHasKey(
'pmaAuth-0',
$_COOKIE
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials
*
* @return void
*/
public function testLogout()
{
$this->mockResponse('Location: /phpmyadmin/index.php');
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
$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'];
$_COOKIE['pmaAuth-1'] = 'test';
$this->object->logOut();
$this->assertArrayNotHasKey(
'pmaAuth-1',
$_COOKIE
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials
*
* @return void
*/
public function testAuthCheckArbitrary()
{
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = '';
$_REQUEST['old_usr'] = '';
$_POST['pma_username'] = 'testPMAUser';
$_REQUEST['pma_servername'] = 'testPMAServer';
$_POST['pma_password'] = 'testPMAPSWD';
$GLOBALS['cfg']['AllowArbitraryServer'] = true;
$this->assertTrue(
$this->object->readCredentials()
);
$this->assertEquals(
'testPMAUser',
$this->object->user
);
$this->assertEquals(
'testPMAPSWD',
$this->object->password
);
$this->assertEquals(
'testPMAServer',
$GLOBALS['pma_auth_server']
);
$this->assertArrayNotHasKey(
'pmaAuth-1',
$_COOKIE
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials
*
* @return void
*/
public function testAuthCheckInvalidCookie()
{
$GLOBALS['cfg']['AllowArbitraryServer'] = true;
$_REQUEST['pma_servername'] = 'testPMAServer';
$_POST['pma_password'] = 'testPMAPSWD';
$_POST['pma_username'] = '';
$GLOBALS['server'] = 1;
$_COOKIE['pmaUser-1'] = '';
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
$this->assertFalse(
$this->object->readCredentials()
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials
*
* @return void
*/
public function testAuthCheckExpires()
{
$GLOBALS['server'] = 1;
$_COOKIE['pmaServer-1'] = 'pmaServ1';
$_COOKIE['pmaUser-1'] = 'pmaUser1';
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
$_COOKIE['pmaAuth-1'] = '';
$GLOBALS['cfg']['blowfish_secret'] = 'secret';
$_SESSION['last_access_time'] = time() - 1000;
$GLOBALS['cfg']['LoginCookieValidity'] = 1440;
$this->assertFalse(
$this->object->readCredentials()
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials (mock blowfish functions reqd)
*
* @return void
*/
public function testAuthCheckDecryptUser()
{
$GLOBALS['server'] = 1;
$_REQUEST['old_usr'] = '';
$_POST['pma_username'] = '';
$_COOKIE['pmaServer-1'] = 'pmaServ1';
$_COOKIE['pmaUser-1'] = 'pmaUser1';
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
$GLOBALS['cfg']['blowfish_secret'] = 'secret';
$_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')
->disableOriginalConstructor()
->setMethods(['cookieDecrypt'])
->getMock();
$this->object->expects($this->once())
->method('cookieDecrypt')
->will($this->returnValue('testBF'));
$this->assertFalse(
$this->object->readCredentials()
);
$this->assertEquals(
'testBF',
$this->object->user
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials (mocking blowfish functions)
*
* @return void
*/
public function testAuthCheckDecryptPassword()
{
$GLOBALS['server'] = 1;
$_REQUEST['old_usr'] = '';
$_POST['pma_username'] = '';
$_COOKIE['pmaServer-1'] = 'pmaServ1';
$_COOKIE['pmaUser-1'] = 'pmaUser1';
$_COOKIE['pmaAuth-1'] = 'pmaAuth1';
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
$GLOBALS['cfg']['blowfish_secret'] = 'secret';
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
$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')
->disableOriginalConstructor()
->setMethods(['cookieDecrypt'])
->getMock();
$this->object->expects($this->at(1))
->method('cookieDecrypt')
->will($this->returnValue('{"password":""}'));
$this->assertTrue(
$this->object->readCredentials()
);
$this->assertTrue(
$GLOBALS['from_cookie']
);
$this->assertEquals(
'',
$this->object->password
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::readCredentials (mocking the object itself)
*
* @return void
*/
public function testAuthCheckAuthFails()
{
$GLOBALS['server'] = 1;
$_REQUEST['old_usr'] = '';
$_POST['pma_username'] = '';
$_COOKIE['pmaServer-1'] = 'pmaServ1';
$_COOKIE['pmaUser-1'] = 'pmaUser1';
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
$GLOBALS['cfg']['blowfish_secret'] = 'secret';
$_SESSION['last_access_time'] = 1;
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
$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()
->setMethods(['showFailure', 'cookieDecrypt'])
->getMock();
$this->object->expects($this->once())
->method('cookieDecrypt')
->will($this->returnValue('testBF'));
$this->object->expects($this->once())
->method('showFailure');
$this->assertFalse(
$this->object->readCredentials()
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::storeCredentials
*
* @return void
*/
public function testAuthSetUser()
{
$this->object->user = 'pmaUser2';
$arr = [
'host' => 'a',
'port' => 1,
'socket' => true,
'ssl' => true,
'user' => 'pmaUser2',
];
$GLOBALS['cfg']['Server'] = $arr;
$GLOBALS['cfg']['Server']['user'] = 'pmaUser';
$GLOBALS['cfg']['Servers'][1] = $arr;
$GLOBALS['cfg']['AllowArbitraryServer'] = true;
$GLOBALS['pma_auth_server'] = 'b 2';
$this->object->password = 'testPW';
$GLOBALS['server'] = 2;
$GLOBALS['cfg']['LoginCookieStore'] = true;
$GLOBALS['from_cookie'] = true;
$GLOBALS['PMA_Config']->set('is_https', false);
$this->object->storeCredentials();
$this->object->rememberCredentials();
$this->assertArrayHasKey(
'pmaUser-2',
$_COOKIE
);
$this->assertArrayHasKey(
'pmaAuth-2',
$_COOKIE
);
$arr['password'] = 'testPW';
$arr['host'] = 'b';
$arr['port'] = '2';
$this->assertEquals(
$arr,
$GLOBALS['cfg']['Server']
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::storeCredentials (check for headers redirect)
*
* @return void
*/
public function testAuthSetUserWithHeaders()
{
$this->object->user = 'pmaUser2';
$arr = [
'host' => 'a',
'port' => 1,
'socket' => true,
'ssl' => true,
'user' => 'pmaUser2',
];
$GLOBALS['cfg']['Server'] = $arr;
$GLOBALS['cfg']['Server']['host'] = 'b';
$GLOBALS['cfg']['Server']['user'] = 'pmaUser';
$GLOBALS['cfg']['Servers'][1] = $arr;
$GLOBALS['cfg']['AllowArbitraryServer'] = true;
$GLOBALS['pma_auth_server'] = 'b 2';
$this->object->password = 'testPW';
$GLOBALS['server'] = 2;
$GLOBALS['cfg']['LoginCookieStore'] = true;
$GLOBALS['from_cookie'] = false;
$this->mockResponse(
$this->stringContains('&server=2&lang=en')
);
$this->object->storeCredentials();
$this->object->rememberCredentials();
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showFailure
*
* @return void
*/
public function testAuthFailsNoPass()
{
$this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie')
->disableOriginalConstructor()
->setMethods(['showLoginForm'])
->getMock();
$GLOBALS['server'] = 2;
$_COOKIE['pmaAuth-2'] = 'pass';
$this->mockResponse(
['Cache-Control: no-store, no-cache, must-revalidate'],
['Pragma: no-cache']
);
$this->object->showFailure('empty-denied');
$this->assertEquals(
$GLOBALS['conn_error'],
'Login without a password is forbidden by configuration'
. ' (see AllowNoPassword)'
);
}
/**
* @return void
*/
public function testAuthFailsDeny()
{
$this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie')
->disableOriginalConstructor()
->setMethods(['showLoginForm'])
->getMock();
$GLOBALS['server'] = 2;
$_COOKIE['pmaAuth-2'] = 'pass';
$this->mockResponse(
['Cache-Control: no-store, no-cache, must-revalidate'],
['Pragma: no-cache']
);
$this->object->showFailure('allow-denied');
$this->assertEquals(
$GLOBALS['conn_error'],
'Access denied!'
);
}
/**
* @return void
*/
public function testAuthFailsActivity()
{
$this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie')
->disableOriginalConstructor()
->setMethods(['showLoginForm'])
->getMock();
$GLOBALS['server'] = 2;
$_COOKIE['pmaAuth-2'] = 'pass';
$GLOBALS['allowDeny_forbidden'] = '';
$GLOBALS['cfg']['LoginCookieValidity'] = 10;
$this->mockResponse(
['Cache-Control: no-store, no-cache, must-revalidate'],
['Pragma: no-cache']
);
$this->object->showFailure('no-activity');
$this->assertEquals(
$GLOBALS['conn_error'],
'No activity within 10 seconds; please log in again.'
);
}
/**
* @return void
*/
public function testAuthFailsDBI()
{
$this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie')
->disableOriginalConstructor()
->setMethods(['showLoginForm'])
->getMock();
$GLOBALS['server'] = 2;
$_COOKIE['pmaAuth-2'] = 'pass';
$dbi = $this->getMockBuilder('PhpMyAdmin\DatabaseInterface')
->disableOriginalConstructor()
->getMock();
$dbi->expects($this->at(0))
->method('getError')
->will($this->returnValue(false));
$GLOBALS['dbi'] = $dbi;
$GLOBALS['errno'] = 42;
$this->mockResponse(
['Cache-Control: no-store, no-cache, must-revalidate'],
['Pragma: no-cache']
);
$this->object->showFailure('');
$this->assertEquals(
$GLOBALS['conn_error'],
'#42 Cannot log in to the MySQL server'
);
}
/**
* @return void
*/
public function testAuthFailsErrno()
{
$this->object = $this->getMockBuilder('PhpMyAdmin\Plugins\Auth\AuthenticationCookie')
->disableOriginalConstructor()
->setMethods(['showLoginForm'])
->getMock();
$dbi = $this->getMockBuilder('PhpMyAdmin\DatabaseInterface')
->disableOriginalConstructor()
->getMock();
$dbi->expects($this->at(0))
->method('getError')
->will($this->returnValue(false));
$GLOBALS['dbi'] = $dbi;
$GLOBALS['server'] = 2;
$_COOKIE['pmaAuth-2'] = 'pass';
unset($GLOBALS['errno']);
$this->mockResponse(
['Cache-Control: no-store, no-cache, must-revalidate'],
['Pragma: no-cache']
);
$this->object->showFailure('');
$this->assertEquals(
$GLOBALS['conn_error'],
'Cannot log in to the MySQL server'
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::_getEncryptionSecret
*
* @return void
*/
public function testGetEncryptionSecretEmpty()
{
$method = new ReflectionMethod(
'PhpMyAdmin\Plugins\Auth\AuthenticationCookie',
'_getEncryptionSecret'
);
$method->setAccessible(true);
$GLOBALS['cfg']['blowfish_secret'] = '';
$_SESSION['encryption_key'] = '';
$result = $method->invoke($this->object, null);
$this->assertEquals(
$result,
$_SESSION['encryption_key']
);
$this->assertEquals(
32,
strlen($result)
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::_getEncryptionSecret
*
* @return void
*/
public function testGetEncryptionSecretConfigured()
{
$method = new ReflectionMethod(
'PhpMyAdmin\Plugins\Auth\AuthenticationCookie',
'_getEncryptionSecret'
);
$method->setAccessible(true);
$GLOBALS['cfg']['blowfish_secret'] = 'notEmpty';
$result = $method->invoke($this->object, null);
$this->assertEquals(
'notEmpty',
$result
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::cookieEncrypt
*
* @return void
*/
public function testCookieEncrypt()
{
$this->object->setIV('testiv09testiv09');
// works with the openssl extension active or inactive
$this->assertEquals(
'{"iv":"dGVzdGl2MDl0ZXN0aXYwOQ==","mac":"347aa45ae1ade00c980f31129ec2defef18b2bfd","payload":"YDEaxOfP9nD9q\/2pC6hjfQ=="}',
$this->object->cookieEncrypt('data123', 'sec321')
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::cookieEncrypt
*
* @return void
*/
public function testCookieEncryptPHPSecLib()
{
$this->object->setUseOpenSSL(false);
$this->testCookieEncrypt();
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::cookieEncrypt
*
* @return void
*/
public function testCookieEncryptOpenSSL()
{
if (! function_exists('openssl_encrypt')) {
$this->markTestSkipped('openssl not available');
}
$this->object->setUseOpenSSL(true);
$this->testCookieEncrypt();
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::cookieDecrypt
*
* @return void
*/
public function testCookieDecrypt()
{
// works with the openssl extension active or inactive
$this->assertEquals(
'data123',
$this->object->cookieDecrypt(
'{"iv":"dGVzdGl2MDl0ZXN0aXYwOQ==","mac":"347aa45ae1ade00c980f31129ec2defef18b2bfd","payload":"YDEaxOfP9nD9q\/2pC6hjfQ=="}',
'sec321'
)
);
$this->assertEquals(
'root',
$this->object->cookieDecrypt(
'{"iv":"AclJhCM7ryNiuPnw3Y8cXg==","mac":"d0ef75e852bc162e81496e116dc571182cb2cba6","payload":"O4vrt9R1xyzAw7ypvrLmQA=="}',
':Kb1?)c(r{]-{`HW*hOzuufloK(M~!p'
)
);
$this->assertFalse(
$this->object->cookieDecrypt(
'{"iv":"AclJhCM7ryNiuPnw3Y8cXg==","mac":"d0ef75e852bc162e81496e116dc571182cb2cba6","payload":"O4vrt9R1xyzAw7ypvrLmQA=="}',
'aedzoiefpzf,zf1z7ef6ef84'
)
);
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::cookieDecrypt
*
* @return void
*/
public function testCookieDecryptPHPSecLib()
{
$this->object->setUseOpenSSL(false);
$this->testCookieDecrypt();
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::cookieDecrypt
*
* @return void
*/
public function testCookieDecryptOpenSSL()
{
if (! function_exists('openssl_encrypt')) {
$this->markTestSkipped('openssl not available');
}
$this->object->setUseOpenSSL(true);
$this->testCookieDecrypt();
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::cookieDecrypt
*
* @return void
*/
public function testCookieDecryptInvalid()
{
// works with the openssl extension active or inactive
$this->assertEquals(
false,
$this->object->cookieDecrypt(
'{"iv":0,"mac":0,"payload":0}',
'sec321'
)
);
}
/**
* Test for secret splitting using getAESSecret
*
* @param string $secret secret
* @param string $mac mac
* @param string $aes aes
*
* @return void
*
* @dataProvider secretsProvider
*/
public function testMACSecretSplit($secret, $mac, $aes): void
{
$this->assertEquals(
$mac,
$this->object->getMACSecret($secret)
);
}
/**
* Test for secret splitting using getMACSecret and getAESSecret
*
* @param string $secret secret
* @param string $mac mac
* @param string $aes aes
*
* @return void
*
* @dataProvider secretsProvider
*/
public function testAESSecretSplit($secret, $mac, $aes): void
{
$this->assertEquals(
$aes,
$this->object->getAESSecret($secret)
);
}
/**
* @throws ReflectionException
*
* @return void
*/
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'] = '';
$this->object->setIV('testiv09testiv09');
$this->object->handlePasswordChange($newPassword);
$payload = [
'password' => $newPassword,
'server' => 'b 2',
];
$method = new ReflectionMethod(
'PhpMyAdmin\Plugins\Auth\AuthenticationCookie',
'_getSessionEncryptionSecret'
);
$method->setAccessible(true);
$encryptedCookie = $this->object->cookieEncrypt(
json_encode($payload),
$method->invoke($this->object, null)
);
$this->assertEquals(
$_COOKIE['pmaAuth-' . $GLOBALS['server']],
$encryptedCookie
);
}
/**
* Data provider for secrets splitting.
*
* @return array
*/
public function secretsProvider()
{
return [
// Optimal case
[
'1234567890123456abcdefghijklmnop',
'1234567890123456',
'abcdefghijklmnop',
],
// Overlapping secret
[
'12345678901234567',
'1234567890123456',
'2345678901234567',
],
// Short secret
[
'1234567890123456',
'1234567890123451',
'2345678901234562',
],
// Really short secret
[
'12',
'1111111111111111',
'2222222222222222',
],
// Too short secret
[
'1',
'1111111111111111',
'1111111111111111',
],
];
}
/**
* 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'] = '';
$_POST['pma_username'] = 'testUser';
$_POST['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
*
* @param string $user user
* @param string $pass pass
* @param string $ip ip
* @param bool $root root
* @param bool $nopass nopass
* @param array $rules rules
* @param string $expected expected result
*
* @return void
*
* @dataProvider checkRulesProvider
*/
public function testCheckRules($user, $pass, $ip, $root, $nopass, $rules, $expected): void
{
$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->assertStringContainsString($expected, $result);
}
}
/**
* @return array
*/
public function checkRulesProvider()
{
return [
'nopass-ok' => [
'testUser',
'',
'1.2.3.4',
true,
true,
[],
'',
],
'nopass' => [
'testUser',
'',
'1.2.3.4',
true,
false,
[],
'Login without a password is forbidden',
],
'root-ok' => [
'root',
'root',
'1.2.3.4',
true,
true,
[],
'',
],
'root' => [
'root',
'root',
'1.2.3.4',
false,
true,
[],
'Access denied!',
],
'rules-deny-allow-ok' => [
'root',
'root',
'1.2.3.4',
true,
true,
[
'order' => 'deny,allow',
'rules' => [
'allow root 1.2.3.4',
'deny % from all',
],
],
'',
],
'rules-deny-allow-reject' => [
'user',
'root',
'1.2.3.4',
true,
true,
[
'order' => 'deny,allow',
'rules' => [
'allow root 1.2.3.4',
'deny % from all',
],
],
'Access denied!',
],
'rules-allow-deny-ok' => [
'root',
'root',
'1.2.3.4',
true,
true,
[
'order' => 'allow,deny',
'rules' => [
'deny user from all',
'allow root 1.2.3.4',
],
],
'',
],
'rules-allow-deny-reject' => [
'user',
'root',
'1.2.3.4',
true,
true,
[
'order' => 'allow,deny',
'rules' => [
'deny user from all',
'allow root 1.2.3.4',
],
],
'Access denied!',
],
'rules-explicit-ok' => [
'root',
'root',
'1.2.3.4',
true,
true,
[
'order' => 'explicit',
'rules' => [
'deny user from all',
'allow root 1.2.3.4',
],
],
'',
],
'rules-explicit-reject' => [
'user',
'root',
'1.2.3.4',
true,
true,
[
'order' => 'explicit',
'rules' => [
'deny user from all',
'allow root 1.2.3.4',
],
],
'Access denied!',
],
];
}
}