Example #1
0
 public function testGetGlobalSession()
 {
     $context = \RequestContext::getMain();
     if (!PHPSessionHandler::isInstalled()) {
         PHPSessionHandler::install(SessionManager::singleton());
     }
     $rProp = new \ReflectionProperty(PHPSessionHandler::class, 'instance');
     $rProp->setAccessible(true);
     $handler = \TestingAccessWrapper::newFromObject($rProp->getValue());
     $oldEnable = $handler->enable;
     $reset[] = new \Wikimedia\ScopedCallback(function () use($handler, $oldEnable) {
         if ($handler->enable) {
             session_write_close();
         }
         $handler->enable = $oldEnable;
     });
     $reset[] = TestUtils::setSessionManagerSingleton($this->getManager());
     $handler->enable = true;
     $request = new \FauxRequest();
     $context->setRequest($request);
     $id = $request->getSession()->getId();
     session_id('');
     $session = SessionManager::getGlobalSession();
     $this->assertSame($id, $session->getId());
     session_id('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
     $session = SessionManager::getGlobalSession();
     $this->assertSame('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', $session->getId());
     $this->assertSame('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', $request->getSession()->getId());
     session_write_close();
     $handler->enable = false;
     $request = new \FauxRequest();
     $context->setRequest($request);
     $id = $request->getSession()->getId();
     session_id('');
     $session = SessionManager::getGlobalSession();
     $this->assertSame($id, $session->getId());
     session_id('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
     $session = SessionManager::getGlobalSession();
     $this->assertSame($id, $session->getId());
     $this->assertSame($id, $request->getSession()->getId());
 }
Example #2
0
 public function testClear()
 {
     $session = TestUtils::getDummySession();
     $priv = \TestingAccessWrapper::newFromObject($session);
     $backend = $this->getMock('MediaWiki\\Session\\DummySessionBackend', array('canSetUser', 'setUser', 'save'));
     $backend->expects($this->once())->method('canSetUser')->will($this->returnValue(true));
     $backend->expects($this->once())->method('setUser')->with($this->callback(function ($user) {
         return $user instanceof User && $user->isAnon();
     }));
     $backend->expects($this->once())->method('save');
     $priv->backend = $backend;
     $session->clear();
     $this->assertSame(array(), $backend->data);
     $this->assertTrue($backend->dirty);
     $backend = $this->getMock('MediaWiki\\Session\\DummySessionBackend', array('canSetUser', 'setUser', 'save'));
     $backend->data = array();
     $backend->expects($this->once())->method('canSetUser')->will($this->returnValue(true));
     $backend->expects($this->once())->method('setUser')->with($this->callback(function ($user) {
         return $user instanceof User && $user->isAnon();
     }));
     $backend->expects($this->once())->method('save');
     $priv->backend = $backend;
     $session->clear();
     $this->assertFalse($backend->dirty);
     $backend = $this->getMock('MediaWiki\\Session\\DummySessionBackend', array('canSetUser', 'setUser', 'save'));
     $backend->expects($this->once())->method('canSetUser')->will($this->returnValue(false));
     $backend->expects($this->never())->method('setUser');
     $backend->expects($this->once())->method('save');
     $priv->backend = $backend;
     $session->clear();
     $this->assertSame(array(), $backend->data);
     $this->assertTrue($backend->dirty);
 }
Example #3
0
 public function testGetAllowedUserRights()
 {
     $provider = $this->getMockForAbstractClass('MediaWiki\\Session\\SessionProvider');
     $backend = TestUtils::getDummySessionBackend();
     try {
         $provider->getAllowedUserRights($backend);
         $this->fail('Expected exception not thrown');
     } catch (\InvalidArgumentException $ex) {
         $this->assertSame('Backend\'s provider isn\'t $this', $ex->getMessage());
     }
     \TestingAccessWrapper::newFromObject($backend)->provider = $provider;
     $this->assertNull($provider->getAllowedUserRights($backend));
 }
Example #4
0
 /**
  * Setup SessionManager with a mock session provider
  * @param bool|null $canChangeUser If non-null, canChangeUser will be mocked to return this
  * @param array $methods Additional methods to mock
  * @return array (MediaWiki\Session\SessionProvider, ScopedCallback)
  */
 protected function getMockSessionProvider($canChangeUser = null, array $methods = [])
 {
     if (!$this->config) {
         $this->config = new \HashConfig();
         $this->initializeConfig();
     }
     $this->config->set('ObjectCacheSessionExpiry', 100);
     $methods[] = '__toString';
     $methods[] = 'describe';
     if ($canChangeUser !== null) {
         $methods[] = 'canChangeUser';
     }
     $provider = $this->getMockBuilder('DummySessionProvider')->setMethods($methods)->getMock();
     $provider->expects($this->any())->method('__toString')->will($this->returnValue('MockSessionProvider'));
     $provider->expects($this->any())->method('describe')->will($this->returnValue('MockSessionProvider sessions'));
     if ($canChangeUser !== null) {
         $provider->expects($this->any())->method('canChangeUser')->will($this->returnValue($canChangeUser));
     }
     $this->config->set('SessionProviders', [['factory' => function () use($provider) {
         return $provider;
     }]]);
     $manager = new \MediaWiki\Session\SessionManager(['config' => $this->config, 'logger' => new \Psr\Log\NullLogger(), 'store' => new \HashBagOStuff()]);
     \TestingAccessWrapper::newFromObject($manager)->getProvider((string) $provider);
     $reset = \MediaWiki\Session\TestUtils::setSessionManagerSingleton($manager);
     if ($this->request) {
         $manager->getSessionForRequest($this->request);
     }
     return [$provider, $reset];
 }
 public function testAutoCreateUser()
 {
     global $wgGroupPermissions;
     $that = $this;
     \ObjectCache::$instances[__METHOD__] = new \HashBagOStuff();
     $this->setMwGlobals(array('wgMainCacheType' => __METHOD__));
     $this->stashMwGlobals(array('wgGroupPermissions'));
     $wgGroupPermissions['*']['createaccount'] = true;
     $wgGroupPermissions['*']['autocreateaccount'] = false;
     // Replace the global singleton with one configured for testing
     $manager = $this->getManager();
     $reset = TestUtils::setSessionManagerSingleton($manager);
     $logger = new \TestLogger(true, function ($m) {
         if (substr($m, 0, 15) === 'SessionBackend ') {
             // Don't care.
             return null;
         }
         $m = str_replace('MediaWiki\\Session\\SessionManager::autoCreateUser: '******'', $m);
         $m = preg_replace('/ - from: .*$/', ' - from: XXX', $m);
         return $m;
     });
     $manager->setLogger($logger);
     $session = SessionManager::getGlobalSession();
     // Can't create an already-existing user
     $user = User::newFromName('UTSysop');
     $id = $user->getId();
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame($id, $user->getId());
     $this->assertSame('UTSysop', $user->getName());
     $this->assertSame(array(), $logger->getBuffer());
     $logger->clearBuffer();
     // Sanity check that creation works at all
     $user = User::newFromName('UTSessionAutoCreate1');
     $this->assertSame(0, $user->getId(), 'sanity check');
     $this->assertTrue($manager->autoCreateUser($user));
     $this->assertNotEquals(0, $user->getId());
     $this->assertSame('UTSessionAutoCreate1', $user->getName());
     $this->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate1', User::READ_LATEST));
     $this->assertSame(array(array(LogLevel::INFO, 'creating new user (UTSessionAutoCreate1) - from: XXX')), $logger->getBuffer());
     $logger->clearBuffer();
     // Check lack of permissions
     $wgGroupPermissions['*']['createaccount'] = false;
     $wgGroupPermissions['*']['autocreateaccount'] = false;
     $user = User::newFromName('UTDoesNotExist');
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     $session->clear();
     $this->assertSame(array(array(LogLevel::DEBUG, 'user is blocked from this wiki, blacklisting')), $logger->getBuffer());
     $logger->clearBuffer();
     // Check other permission
     $wgGroupPermissions['*']['createaccount'] = false;
     $wgGroupPermissions['*']['autocreateaccount'] = true;
     $user = User::newFromName('UTSessionAutoCreate2');
     $this->assertSame(0, $user->getId(), 'sanity check');
     $this->assertTrue($manager->autoCreateUser($user));
     $this->assertNotEquals(0, $user->getId());
     $this->assertSame('UTSessionAutoCreate2', $user->getName());
     $this->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate2', User::READ_LATEST));
     $this->assertSame(array(array(LogLevel::INFO, 'creating new user (UTSessionAutoCreate2) - from: XXX')), $logger->getBuffer());
     $logger->clearBuffer();
     // Test account-creation block
     $anon = new User();
     $block = new \Block(array('address' => $anon->getName(), 'user' => $id, 'reason' => __METHOD__, 'expiry' => time() + 100500, 'createAccount' => true));
     $block->insert();
     $this->assertInstanceOf('Block', $anon->isBlockedFromCreateAccount(), 'sanity check');
     $reset2 = new \ScopedCallback(array($block, 'delete'));
     $user = User::newFromName('UTDoesNotExist');
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     \ScopedCallback::consume($reset2);
     $session->clear();
     $this->assertSame(array(array(LogLevel::DEBUG, 'user is blocked from this wiki, blacklisting')), $logger->getBuffer());
     $logger->clearBuffer();
     // Sanity check that creation still works
     $user = User::newFromName('UTSessionAutoCreate3');
     $this->assertSame(0, $user->getId(), 'sanity check');
     $this->assertTrue($manager->autoCreateUser($user));
     $this->assertNotEquals(0, $user->getId());
     $this->assertSame('UTSessionAutoCreate3', $user->getName());
     $this->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate3', User::READ_LATEST));
     $this->assertSame(array(array(LogLevel::INFO, 'creating new user (UTSessionAutoCreate3) - from: XXX')), $logger->getBuffer());
     $logger->clearBuffer();
     // Test prevention by AuthPlugin
     global $wgAuth;
     $oldWgAuth = $wgAuth;
     $mockWgAuth = $this->getMock('AuthPlugin', array('autoCreate'));
     $mockWgAuth->expects($this->once())->method('autoCreate')->will($this->returnValue(false));
     $this->setMwGlobals(array('wgAuth' => $mockWgAuth));
     $user = User::newFromName('UTDoesNotExist');
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     $this->setMwGlobals(array('wgAuth' => $oldWgAuth));
     $session->clear();
     $this->assertSame(array(array(LogLevel::DEBUG, 'denied by AuthPlugin')), $logger->getBuffer());
     $logger->clearBuffer();
     // Test prevention by wfReadOnly()
     $this->setMwGlobals(array('wgReadOnly' => 'Because'));
     $user = User::newFromName('UTDoesNotExist');
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     $this->setMwGlobals(array('wgReadOnly' => false));
     $session->clear();
     $this->assertSame(array(array(LogLevel::DEBUG, 'denied by wfReadOnly()')), $logger->getBuffer());
     $logger->clearBuffer();
     // Test prevention by a previous session
     $session->set('MWSession::AutoCreateBlacklist', 'test');
     $user = User::newFromName('UTDoesNotExist');
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     $session->clear();
     $this->assertSame(array(array(LogLevel::DEBUG, 'blacklisted in session (test)')), $logger->getBuffer());
     $logger->clearBuffer();
     // Test uncreatable name
     $user = User::newFromName('UTDoesNotExist@');
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist@', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     $session->clear();
     $this->assertSame(array(array(LogLevel::DEBUG, 'Invalid username, blacklisting')), $logger->getBuffer());
     $logger->clearBuffer();
     // Test AbortAutoAccount hook
     $mock = $this->getMock(__CLASS__, array('onAbortAutoAccount'));
     $mock->expects($this->once())->method('onAbortAutoAccount')->will($this->returnCallback(function (User $user, &$msg) {
         $msg = 'No way!';
         return false;
     }));
     $this->mergeMwGlobalArrayValue('wgHooks', array('AbortAutoAccount' => array($mock)));
     $user = User::newFromName('UTDoesNotExist');
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     $this->mergeMwGlobalArrayValue('wgHooks', array('AbortAutoAccount' => array()));
     $session->clear();
     $this->assertSame(array(array(LogLevel::DEBUG, 'denied by hook: No way!')), $logger->getBuffer());
     $logger->clearBuffer();
     // Test AbortAutoAccount hook screwing up the name
     $mock = $this->getMock('stdClass', array('onAbortAutoAccount'));
     $mock->expects($this->once())->method('onAbortAutoAccount')->will($this->returnCallback(function (User $user) {
         $user->setName('UTDoesNotExistEither');
     }));
     $this->mergeMwGlobalArrayValue('wgHooks', array('AbortAutoAccount' => array($mock)));
     try {
         $user = User::newFromName('UTDoesNotExist');
         $manager->autoCreateUser($user);
         $this->fail('Expected exception not thrown');
     } catch (\UnexpectedValueException $ex) {
         $this->assertSame('AbortAutoAccount hook tried to change the user name', $ex->getMessage());
     }
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist', $user->getName());
     $this->assertNotSame('UTDoesNotExistEither', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     $this->assertEquals(0, User::idFromName('UTDoesNotExistEither', User::READ_LATEST));
     $this->mergeMwGlobalArrayValue('wgHooks', array('AbortAutoAccount' => array()));
     $session->clear();
     $this->assertSame(array(), $logger->getBuffer());
     $logger->clearBuffer();
     // Test for "exception backoff"
     $user = User::newFromName('UTDoesNotExist');
     $cache = \ObjectCache::getLocalClusterInstance();
     $backoffKey = wfMemcKey('MWSession', 'autocreate-failed', md5($user->getName()));
     $cache->set($backoffKey, 1, 60 * 10);
     $this->assertFalse($manager->autoCreateUser($user));
     $this->assertSame(0, $user->getId());
     $this->assertNotSame('UTDoesNotExist', $user->getName());
     $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST));
     $cache->delete($backoffKey);
     $session->clear();
     $this->assertSame(array(array(LogLevel::DEBUG, 'denied by prior creation attempt failures')), $logger->getBuffer());
     $logger->clearBuffer();
     // Sanity check that creation still works, and test completion hook
     $cb = $this->callback(function (User $user) use($that) {
         $that->assertNotEquals(0, $user->getId());
         $that->assertSame('UTSessionAutoCreate4', $user->getName());
         $that->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate4', User::READ_LATEST));
         return true;
     });
     $mock = $this->getMock('stdClass', array('onAuthPluginAutoCreate', 'onLocalUserCreated'));
     $mock->expects($this->once())->method('onAuthPluginAutoCreate')->with($cb);
     $mock->expects($this->once())->method('onLocalUserCreated')->with($cb, $this->identicalTo(true));
     $this->mergeMwGlobalArrayValue('wgHooks', array('AuthPluginAutoCreate' => array($mock), 'LocalUserCreated' => array($mock)));
     $user = User::newFromName('UTSessionAutoCreate4');
     $this->assertSame(0, $user->getId(), 'sanity check');
     $this->assertTrue($manager->autoCreateUser($user));
     $this->assertNotEquals(0, $user->getId());
     $this->assertSame('UTSessionAutoCreate4', $user->getName());
     $this->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate4', User::READ_LATEST));
     $this->mergeMwGlobalArrayValue('wgHooks', array('AuthPluginAutoCreate' => array(), 'LocalUserCreated' => array()));
     $this->assertSame(array(array(LogLevel::INFO, 'creating new user (UTSessionAutoCreate4) - from: XXX')), $logger->getBuffer());
     $logger->clearBuffer();
 }
 public function testResetIdOfGlobalSession()
 {
     if (!PHPSessionHandler::isInstalled()) {
         PHPSessionHandler::install(SessionManager::singleton());
     }
     if (!PHPSessionHandler::isEnabled()) {
         $rProp = new \ReflectionProperty('MediaWiki\\Session\\PHPSessionHandler', 'instance');
         $rProp->setAccessible(true);
         $handler = \TestingAccessWrapper::newFromObject($rProp->getValue());
         $resetHandler = new \ScopedCallback(function () use($handler) {
             session_write_close();
             $handler->enable = false;
         });
         $handler->enable = true;
     }
     $backend = $this->getBackend(User::newFromName('UTSysop'));
     \TestingAccessWrapper::newFromObject($backend)->usePhpSessionHandling = true;
     TestUtils::setSessionManagerSingleton($this->manager);
     $manager = \TestingAccessWrapper::newFromObject($this->manager);
     $request = \RequestContext::getMain()->getRequest();
     $manager->globalSession = $backend->getSession($request);
     $manager->globalSessionRequest = $request;
     session_id(self::SESSIONID);
     \MediaWiki\quietCall('session_start');
     $backend->resetId();
     $this->assertNotEquals(self::SESSIONID, $backend->getId());
     $this->assertSame($backend->getId(), session_id());
     session_write_close();
     session_id('');
     $this->assertNotSame($backend->getId(), session_id(), 'sanity check');
     $backend->persist();
     $this->assertSame($backend->getId(), session_id());
     session_write_close();
 }
 public function testGetAllowedUserRights()
 {
     $logger = new \TestLogger(true);
     $provider = $this->getProvider();
     $provider->setLogger($logger);
     $backend = TestUtils::getDummySessionBackend();
     $backendPriv = \TestingAccessWrapper::newFromObject($backend);
     try {
         $provider->getAllowedUserRights($backend);
         $this->fail('Expected exception not thrown');
     } catch (\InvalidArgumentException $ex) {
         $this->assertSame('Backend\'s provider isn\'t $this', $ex->getMessage());
     }
     $backendPriv->provider = $provider;
     $backendPriv->providerMetadata = ['rights' => ['foo', 'bar', 'baz']];
     $this->assertSame(['foo', 'bar', 'baz'], $provider->getAllowedUserRights($backend));
     $this->assertSame([], $logger->getBuffer());
     $backendPriv->providerMetadata = ['foo' => 'bar'];
     $this->assertSame([], $provider->getAllowedUserRights($backend));
     $this->assertSame([[LogLevel::DEBUG, 'MediaWiki\\Session\\BotPasswordSessionProvider::getAllowedUserRights: ' . 'No provider metadata, returning no rights allowed']], $logger->getBuffer());
     $logger->clearBuffer();
     $backendPriv->providerMetadata = ['rights' => 'bar'];
     $this->assertSame([], $provider->getAllowedUserRights($backend));
     $this->assertSame([[LogLevel::DEBUG, 'MediaWiki\\Session\\BotPasswordSessionProvider::getAllowedUserRights: ' . 'No provider metadata, returning no rights allowed']], $logger->getBuffer());
     $logger->clearBuffer();
     $backendPriv->providerMetadata = null;
     $this->assertSame([], $provider->getAllowedUserRights($backend));
     $this->assertSame([[LogLevel::DEBUG, 'MediaWiki\\Session\\BotPasswordSessionProvider::getAllowedUserRights: ' . 'No provider metadata, returning no rights allowed']], $logger->getBuffer());
     $logger->clearBuffer();
 }
Example #8
0
 public function testSecrets()
 {
     $logger = new \TestLogger();
     $session = TestUtils::getDummySession(null, -1, $logger);
     // Simple defaulting
     $this->assertEquals('defaulted', $session->getSecret('test', 'defaulted'));
     // Bad encrypted data
     $session->set('test', 'foobar');
     $logger->setCollect(true);
     $this->assertEquals('defaulted', $session->getSecret('test', 'defaulted'));
     $logger->setCollect(false);
     $this->assertSame([[LogLevel::WARNING, 'Invalid sealed-secret format']], $logger->getBuffer());
     $logger->clearBuffer();
     // Tampered data
     $session->setSecret('test', 'foobar');
     $encrypted = $session->get('test');
     $session->set('test', $encrypted . 'x');
     $logger->setCollect(true);
     $this->assertEquals('defaulted', $session->getSecret('test', 'defaulted'));
     $logger->setCollect(false);
     $this->assertSame([[LogLevel::WARNING, 'Sealed secret has been tampered with, aborting.']], $logger->getBuffer());
     $logger->clearBuffer();
     // Unserializable data
     $iv = \MWCryptRand::generate(16, true);
     list($encKey, $hmacKey) = \TestingAccessWrapper::newFromObject($session)->getSecretKeys();
     $ciphertext = openssl_encrypt('foobar', 'aes-256-ctr', $encKey, OPENSSL_RAW_DATA, $iv);
     $sealed = base64_encode($iv) . '.' . base64_encode($ciphertext);
     $hmac = hash_hmac('sha256', $sealed, $hmacKey, true);
     $encrypted = base64_encode($hmac) . '.' . $sealed;
     $session->set('test', $encrypted);
     \MediaWiki\suppressWarnings();
     $this->assertEquals('defaulted', $session->getSecret('test', 'defaulted'));
     \MediaWiki\restoreWarnings();
 }