Пример #1
0
 /**
  * Returns a non-persistent backend that thinks it has at least one session active
  * @param User|null $user
  */
 protected function getBackend(User $user = null)
 {
     if (!$this->config) {
         $this->config = new \HashConfig();
         $this->manager = null;
     }
     if (!$this->store) {
         $this->store = new TestBagOStuff();
         $this->manager = null;
     }
     $logger = new \Psr\Log\NullLogger();
     if (!$this->manager) {
         $this->manager = new SessionManager(array('store' => $this->store, 'logger' => $logger, 'config' => $this->config));
     }
     if (!$this->provider) {
         $this->provider = new \DummySessionProvider();
     }
     $this->provider->setLogger($logger);
     $this->provider->setConfig($this->config);
     $this->provider->setManager($this->manager);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $this->provider, 'id' => self::SESSIONID, 'persisted' => true, 'userInfo' => UserInfo::newFromUser($user ?: new User(), true), 'idIsSafe' => true));
     $id = new SessionId($info->getId());
     $backend = new SessionBackend($id, $info, $this->store, $this->store, $logger, 10);
     $priv = \TestingAccessWrapper::newFromObject($backend);
     $priv->persist = false;
     $priv->requests = array(100 => new \FauxRequest());
     $priv->usePhpSessionHandling = false;
     $manager = \TestingAccessWrapper::newFromObject($this->manager);
     $manager->allSessionBackends = array($backend->getId() => $backend);
     $manager->allSessionIds = array($backend->getId() => $id);
     $manager->sessionProviders = array((string) $this->provider => $this->provider);
     return $backend;
 }
Пример #2
0
 /**
  * @dataProvider provideSecuritySensitiveOperationStatus
  * @param bool $mutableSession
  */
 public function testSecuritySensitiveOperationStatus($mutableSession)
 {
     $this->logger = new \Psr\Log\NullLogger();
     $user = \User::newFromName('UTSysop');
     $provideUser = null;
     $reauth = $mutableSession ? AuthManager::SEC_REAUTH : AuthManager::SEC_FAIL;
     list($provider, $reset) = $this->getMockSessionProvider($mutableSession, ['provideSessionInfo']);
     $provider->expects($this->any())->method('provideSessionInfo')->will($this->returnCallback(function () use($provider, &$provideUser) {
         return new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => \DummySessionProvider::ID, 'persisted' => true, 'userInfo' => UserInfo::newFromUser($provideUser, true)]);
     }));
     $this->initializeManager();
     $this->config->set('ReauthenticateTime', []);
     $this->config->set('AllowSecuritySensitiveOperationIfCannotReauthenticate', []);
     $provideUser = new \User();
     $session = $provider->getManager()->getSessionForRequest($this->request);
     $this->assertSame(0, $session->getUser()->getId(), 'sanity check');
     // Anonymous user => reauth
     $session->set('AuthManager:lastAuthId', 0);
     $session->set('AuthManager:lastAuthTimestamp', time() - 5);
     $this->assertSame($reauth, $this->manager->securitySensitiveOperationStatus('foo'));
     $provideUser = $user;
     $session = $provider->getManager()->getSessionForRequest($this->request);
     $this->assertSame($user->getId(), $session->getUser()->getId(), 'sanity check');
     // Error for no default (only gets thrown for non-anonymous user)
     $session->set('AuthManager:lastAuthId', $user->getId() + 1);
     $session->set('AuthManager:lastAuthTimestamp', time() - 5);
     try {
         $this->manager->securitySensitiveOperationStatus('foo');
         $this->fail('Expected exception not thrown');
     } catch (\UnexpectedValueException $ex) {
         $this->assertSame($mutableSession ? '$wgReauthenticateTime lacks a default' : '$wgAllowSecuritySensitiveOperationIfCannotReauthenticate lacks a default', $ex->getMessage());
     }
     if ($mutableSession) {
         $this->config->set('ReauthenticateTime', ['test' => 100, 'test2' => -1, 'default' => 10]);
         // Mismatched user ID
         $session->set('AuthManager:lastAuthId', $user->getId() + 1);
         $session->set('AuthManager:lastAuthTimestamp', time() - 5);
         $this->assertSame(AuthManager::SEC_REAUTH, $this->manager->securitySensitiveOperationStatus('foo'));
         $this->assertSame(AuthManager::SEC_REAUTH, $this->manager->securitySensitiveOperationStatus('test'));
         $this->assertSame(AuthManager::SEC_OK, $this->manager->securitySensitiveOperationStatus('test2'));
         // Missing time
         $session->set('AuthManager:lastAuthId', $user->getId());
         $session->set('AuthManager:lastAuthTimestamp', null);
         $this->assertSame(AuthManager::SEC_REAUTH, $this->manager->securitySensitiveOperationStatus('foo'));
         $this->assertSame(AuthManager::SEC_REAUTH, $this->manager->securitySensitiveOperationStatus('test'));
         $this->assertSame(AuthManager::SEC_OK, $this->manager->securitySensitiveOperationStatus('test2'));
         // Recent enough to pass
         $session->set('AuthManager:lastAuthTimestamp', time() - 5);
         $this->assertSame(AuthManager::SEC_OK, $this->manager->securitySensitiveOperationStatus('foo'));
         // Not recent enough to pass
         $session->set('AuthManager:lastAuthTimestamp', time() - 20);
         $this->assertSame(AuthManager::SEC_REAUTH, $this->manager->securitySensitiveOperationStatus('foo'));
         // But recent enough for the 'test' operation
         $this->assertSame(AuthManager::SEC_OK, $this->manager->securitySensitiveOperationStatus('test'));
     } else {
         $this->config->set('AllowSecuritySensitiveOperationIfCannotReauthenticate', ['test' => false, 'default' => true]);
         $this->assertEquals(AuthManager::SEC_OK, $this->manager->securitySensitiveOperationStatus('foo'));
         $this->assertEquals(AuthManager::SEC_FAIL, $this->manager->securitySensitiveOperationStatus('test'));
     }
     // Test hook, all three possible values
     foreach ([AuthManager::SEC_OK => AuthManager::SEC_OK, AuthManager::SEC_REAUTH => $reauth, AuthManager::SEC_FAIL => AuthManager::SEC_FAIL] as $hook => $expect) {
         $this->hook('SecuritySensitiveOperationStatus', $this->exactly(2))->with($this->anything(), $this->anything(), $this->callback(function ($s) use($session) {
             return $s->getId() === $session->getId();
         }), $mutableSession ? $this->equalTo(500, 1) : $this->equalTo(-1))->will($this->returnCallback(function (&$v) use($hook) {
             $v = $hook;
             return true;
         }));
         $session->set('AuthManager:lastAuthTimestamp', time() - 500);
         $this->assertEquals($expect, $this->manager->securitySensitiveOperationStatus('test'), "hook {$hook}");
         $this->assertEquals($expect, $this->manager->securitySensitiveOperationStatus('test2'), "hook {$hook}");
         $this->unhook('SecuritySensitiveOperationStatus');
     }
     \ScopedCallback::consume($reset);
 }
 /**
  * @dataProvider providePersistSession
  * @param bool $secure
  * @param bool $remember
  */
 public function testPersistSession($secure, $remember)
 {
     $this->setMwGlobals(array('wgCookieExpiration' => 100, 'wgSecureLogin' => false));
     $provider = $this->getProvider('session');
     $provider->setLogger(new \Psr\Log\NullLogger());
     $priv = \TestingAccessWrapper::newFromObject($provider);
     $priv->sessionCookieOptions = array('prefix' => 'x', 'path' => 'CookiePath', 'domain' => 'CookieDomain', 'secure' => false, 'httpOnly' => true);
     $sessionId = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
     $user = User::newFromName('UTSysop');
     $this->assertFalse($user->requiresHTTPS(), 'sanity check');
     $backend = new SessionBackend(new SessionId($sessionId), new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $sessionId, 'persisted' => true, 'userInfo' => UserInfo::newFromUser($user, true), 'idIsSafe' => true)), new \EmptyBagOStuff(), new \EmptyBagOStuff(), new \Psr\Log\NullLogger(), 10);
     \TestingAccessWrapper::newFromObject($backend)->usePhpSessionHandling = false;
     $backend->setRememberUser($remember);
     $backend->setForceHTTPS($secure);
     // No cookie
     $priv->sessionCookieName = null;
     $request = new \FauxRequest();
     $provider->persistSession($backend, $request);
     $this->assertSame(array(), $request->response()->getCookies());
     // Cookie
     $priv->sessionCookieName = 'session';
     $request = new \FauxRequest();
     $time = time();
     $provider->persistSession($backend, $request);
     $cookie = $request->response()->getCookieData('xsession');
     $this->assertInternalType('array', $cookie);
     if (isset($cookie['expire']) && $cookie['expire'] > 0) {
         // Round expiry so we don't randomly fail if the seconds ticked during the test.
         $cookie['expire'] = round($cookie['expire'] - $time, -2);
     }
     $this->assertEquals(array('value' => $sessionId, 'expire' => null, 'path' => 'CookiePath', 'domain' => 'CookieDomain', 'secure' => $secure, 'httpOnly' => true, 'raw' => false), $cookie);
     $cookie = $request->response()->getCookieData('forceHTTPS');
     if ($secure) {
         $this->assertInternalType('array', $cookie);
         if (isset($cookie['expire']) && $cookie['expire'] > 0) {
             // Round expiry so we don't randomly fail if the seconds ticked during the test.
             $cookie['expire'] = round($cookie['expire'] - $time, -2);
         }
         $this->assertEquals(array('value' => 'true', 'expire' => $remember ? 100 : null, 'path' => 'CookiePath', 'domain' => 'CookieDomain', 'secure' => false, 'httpOnly' => true, 'raw' => false), $cookie);
     } else {
         $this->assertNull($cookie);
     }
     // Headers sent
     $request = $this->getSentRequest();
     $provider->persistSession($backend, $request);
     $this->assertSame(array(), $request->response()->getCookies());
 }
Пример #4
0
 public function testNewFromUser()
 {
     // User that exists
     $user = User::newFromName('UTSysop');
     $userinfo = UserInfo::newFromUser($user);
     $this->assertFalse($userinfo->isAnon());
     $this->assertFalse($userinfo->isVerified());
     $this->assertSame($user->getId(), $userinfo->getId());
     $this->assertSame($user->getName(), $userinfo->getName());
     $this->assertSame($user->getToken(true), $userinfo->getToken());
     $this->assertSame($user, $userinfo->getUser());
     $userinfo2 = $userinfo->verified();
     $this->assertNotSame($userinfo2, $userinfo);
     $this->assertSame("<-:{$user->getId()}:{$user->getName()}>", (string) $userinfo);
     $this->assertFalse($userinfo2->isAnon());
     $this->assertTrue($userinfo2->isVerified());
     $this->assertSame($user->getId(), $userinfo2->getId());
     $this->assertSame($user->getName(), $userinfo2->getName());
     $this->assertSame($user->getToken(true), $userinfo2->getToken());
     $this->assertSame($user, $userinfo2->getUser());
     $this->assertSame($userinfo2, $userinfo2->verified());
     $this->assertSame("<+:{$user->getId()}:{$user->getName()}>", (string) $userinfo2);
     $userinfo = UserInfo::newFromUser($user, true);
     $this->assertTrue($userinfo->isVerified());
     $this->assertSame($userinfo, $userinfo->verified());
     // User name that does not exist should still be non-anon
     $user = User::newFromName('DoesNotExist');
     $this->assertSame(0, $user->getId(), 'sanity check');
     $userinfo = UserInfo::newFromUser($user);
     $this->assertFalse($userinfo->isAnon());
     $this->assertFalse($userinfo->isVerified());
     $this->assertSame($user->getId(), $userinfo->getId());
     $this->assertSame($user->getName(), $userinfo->getName());
     $this->assertSame('', $userinfo->getToken());
     $this->assertSame($user, $userinfo->getUser());
     $userinfo2 = $userinfo->verified();
     $this->assertNotSame($userinfo2, $userinfo);
     $this->assertSame("<-:{$user->getId()}:{$user->getName()}>", (string) $userinfo);
     $this->assertFalse($userinfo2->isAnon());
     $this->assertTrue($userinfo2->isVerified());
     $this->assertSame($user->getId(), $userinfo2->getId());
     $this->assertSame($user->getName(), $userinfo2->getName());
     $this->assertSame('', $userinfo2->getToken());
     $this->assertSame($user, $userinfo2->getUser());
     $this->assertSame($userinfo2, $userinfo2->verified());
     $this->assertSame("<+:{$user->getId()}:{$user->getName()}>", (string) $userinfo2);
     $userinfo = UserInfo::newFromUser($user, true);
     $this->assertTrue($userinfo->isVerified());
     $this->assertSame($userinfo, $userinfo->verified());
     // Anonymous user gives anon
     $userinfo = UserInfo::newFromUser(new User(), false);
     $this->assertTrue($userinfo->isVerified());
     $this->assertSame(0, $userinfo->getId());
     $this->assertSame(null, $userinfo->getName());
 }
 public function testCheckSessionInfo()
 {
     $logger = new \TestLogger(true, function ($m) {
         return preg_replace('/^Session \\[\\d+\\][a-zA-Z0-9_\\\\]+<(?:null|anon|[+-]:\\d+:\\w+)>\\w+: /', 'Session X: ', $m);
     });
     $provider = $this->getProvider();
     $provider->setLogger($logger);
     $user = \User::newFromName('UTSysop');
     $request = $this->getMock('FauxRequest', array('getIP'));
     $request->expects($this->any())->method('getIP')->will($this->returnValue('127.0.0.1'));
     $bp = \BotPassword::newFromUser($user, 'BotPasswordSessionProvider');
     $data = array('provider' => $provider, 'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'userInfo' => UserInfo::newFromUser($user, true), 'persisted' => false, 'metadata' => array('centralId' => $bp->getUserCentralId(), 'appId' => $bp->getAppId(), 'token' => $bp->getToken()));
     $dataMD = $data['metadata'];
     foreach (array_keys($data['metadata']) as $key) {
         $data['metadata'] = $dataMD;
         unset($data['metadata'][$key]);
         $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
         $metadata = $info->getProviderMetadata();
         $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
         $this->assertSame(array(array(LogLevel::INFO, "Session X: Missing metadata: {$key}")), $logger->getBuffer());
         $logger->clearBuffer();
     }
     $data['metadata'] = $dataMD;
     $data['metadata']['appId'] = 'Foobar';
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame(array(array(LogLevel::INFO, "Session X: No BotPassword for {$bp->getUserCentralId()} Foobar")), $logger->getBuffer());
     $logger->clearBuffer();
     $data['metadata'] = $dataMD;
     $data['metadata']['token'] = 'Foobar';
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame(array(array(LogLevel::INFO, 'Session X: BotPassword token check failed')), $logger->getBuffer());
     $logger->clearBuffer();
     $request2 = $this->getMock('FauxRequest', array('getIP'));
     $request2->expects($this->any())->method('getIP')->will($this->returnValue('10.0.0.1'));
     $data['metadata'] = $dataMD;
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request2, $metadata));
     $this->assertSame(array(array(LogLevel::INFO, 'Session X: Restrictions check failed')), $logger->getBuffer());
     $logger->clearBuffer();
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertTrue($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame(array(), $logger->getBuffer());
     $this->assertEquals($dataMD + array('rights' => array('read')), $metadata);
 }
 /**
  * Create a new session for a request
  * @param User $user
  * @param BotPassword $bp
  * @param WebRequest $request
  * @return Session
  */
 public function newSessionForRequest(User $user, BotPassword $bp, WebRequest $request)
 {
     $id = $this->getSessionIdFromCookie($request);
     $info = new SessionInfo(SessionInfo::MAX_PRIORITY, ['provider' => $this, 'id' => $id, 'userInfo' => UserInfo::newFromUser($user, true), 'persisted' => $id !== null, 'metadata' => ['centralId' => $bp->getUserCentralId(), 'appId' => $bp->getAppId(), 'token' => $bp->getToken(), 'rights' => \MWGrants::getGrantRights($bp->getGrants())]]);
     $session = $this->getManager()->getSessionFromInfo($info, $request);
     $session->persist();
     return $session;
 }
 public function testCheckSessionInfo()
 {
     $logger = new \TestLogger(true);
     $provider = $this->getProvider();
     $provider->setLogger($logger);
     $user = static::getTestSysop()->getUser();
     $request = $this->getMock('FauxRequest', ['getIP']);
     $request->expects($this->any())->method('getIP')->will($this->returnValue('127.0.0.1'));
     $bp = \BotPassword::newFromUser($user, 'BotPasswordSessionProvider');
     $data = ['provider' => $provider, 'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'userInfo' => UserInfo::newFromUser($user, true), 'persisted' => false, 'metadata' => ['centralId' => $bp->getUserCentralId(), 'appId' => $bp->getAppId(), 'token' => $bp->getToken()]];
     $dataMD = $data['metadata'];
     foreach (array_keys($data['metadata']) as $key) {
         $data['metadata'] = $dataMD;
         unset($data['metadata'][$key]);
         $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
         $metadata = $info->getProviderMetadata();
         $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
         $this->assertSame([[LogLevel::INFO, 'Session "{session}": Missing metadata: {missing}']], $logger->getBuffer());
         $logger->clearBuffer();
     }
     $data['metadata'] = $dataMD;
     $data['metadata']['appId'] = 'Foobar';
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame([[LogLevel::INFO, 'Session "{session}": No BotPassword for {centralId} {appId}']], $logger->getBuffer());
     $logger->clearBuffer();
     $data['metadata'] = $dataMD;
     $data['metadata']['token'] = 'Foobar';
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame([[LogLevel::INFO, 'Session "{session}": BotPassword token check failed']], $logger->getBuffer());
     $logger->clearBuffer();
     $request2 = $this->getMock('FauxRequest', ['getIP']);
     $request2->expects($this->any())->method('getIP')->will($this->returnValue('10.0.0.1'));
     $data['metadata'] = $dataMD;
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request2, $metadata));
     $this->assertSame([[LogLevel::INFO, 'Session "{session}": Restrictions check failed']], $logger->getBuffer());
     $logger->clearBuffer();
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertTrue($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame([], $logger->getBuffer());
     $this->assertEquals($dataMD + ['rights' => ['read']], $metadata);
 }