phpmyadmin/test/classes/Plugins/Auth/AuthenticationCookieTest.php
Maurício Meneghini Fauth 206199105e Remove useless return type annotations
Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
2020-01-23 13:03:29 -03:00

1383 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
/**
* tests for PhpMyAdmin\Plugins\Auth\AuthenticationCookie class
*/
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;
use function base64_encode;
use function function_exists;
use function is_readable;
use function json_encode;
use function ob_get_clean;
use function ob_start;
use function strlen;
use function time;
/**
* tests for PhpMyAdmin\Plugins\Auth\AuthenticationCookie class
*/
class AuthenticationCookieTest extends PmaTestCase
{
/** @var AuthenticationCookie */
protected $object;
/**
* Configures global environment.
*/
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
*/
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'])
->getMock();
$mockErrorHandler->expects($this->once())
->method('hasDisplayErrors')
->with()
->will($this->returnValue(true));
$GLOBALS['error_handler'] = $mockErrorHandler;
}
/**
* Test for PhpMyAdmin\Plugins\Auth\AuthenticationConfig::showLoginForm
*
* @return void
*
* @group medium
*/
public function testAuthError()
{
$_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['db'] = 'testDb';
$GLOBALS['table'] = 'testTable';
$GLOBALS['cfg']['Servers'] = [1, 2];
$GLOBALS['error_handler'] = new ErrorHandler();
ob_start();
$this->object->showLoginForm();
$result = ob_get_clean();
// assertions
$this->assertStringContainsString(
' id="imLogo"',
$result
);
$this->assertStringContainsString(
'<div class="alert alert-danger" role="alert">',
$result
);
$this->assertStringContainsString(
'<form method="post" id="login_form" action="index.php?route=/" name="login_form" ' .
'class="disableAjax hide login js-show form-horizontal">',
$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 form-control">',
$result
);
$this->assertStringContainsString(
'<input type="password" name="pma_password" id="input_password" ' .
'value="" size="24" class="textfield form-control">',
$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="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 form-control" lang="en" dir="ltr" ' .
'id="sel-lang">',
$result
);
}
$this->assertStringContainsString(
'<form method="post" id="login_form" action="index.php?route=/" name="login_form"' .
' class="disableAjax hide login js-show form-horizontal" autocomplete="off">',
$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?route=/&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?route=/');
$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?route=/');
$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
*
* @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
*
* @dataProvider secretsProvider
*/
public function testAESSecretSplit($secret, $mac, $aes): void
{
$this->assertEquals(
$aes,
$this->object->getAESSecret($secret)
);
}
/**
* @return void
*
* @throws ReflectionException
*/
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
*
* @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!',
],
];
}
}