public function execute($subPage)
 {
     $this->setHeaders();
     $this->loadAuth($subPage);
     $this->outputHeader();
     $status = $this->trySubmit();
     if ($status === false || !$status->isOK()) {
         $this->displayForm($status);
         return;
     }
     /** @var AuthenticationResponse $response */
     $response = $status->getValue();
     if ($response->status === AuthenticationResponse::FAIL) {
         $this->displayForm(StatusValue::newFatal($response->message));
         return;
     }
     $status = StatusValue::newGood();
     $status->warning(wfMessage('unlinkaccounts-success'));
     $this->loadAuth($subPage, null, true);
     // update requests so the unlinked one doesn't show up
     // Reset sessions - if the user unlinked an account because it was compromised,
     // log attackers out from sessions obtained via that account.
     $session = $this->getRequest()->getSession();
     $user = $this->getUser();
     SessionManager::singleton()->invalidateSessionsForUser($user);
     $session->setUser($user);
     $session->resetId();
     $this->displayForm($status);
 }
예제 #2
0
 public function testGetGlobalSession()
 {
     $context = \RequestContext::getMain();
     if (!PHPSessionHandler::isInstalled()) {
         PHPSessionHandler::install(SessionManager::singleton());
     }
     $rProp = new \ReflectionProperty('MediaWiki\\Session\\PHPSessionHandler', 'instance');
     $rProp->setAccessible(true);
     $handler = \TestingAccessWrapper::newFromObject($rProp->getValue());
     $oldEnable = $handler->enable;
     $reset[] = new \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());
 }
예제 #3
0
파일: FauxRequest.php 프로젝트: paladox/2
 /**
  * @param array $data Array of *non*-urlencoded key => value pairs, the
  *   fake GET/POST values
  * @param bool $wasPosted Whether to treat the data as POST
  * @param MediaWiki\\Session\\Session|array|null $session Session, session
  *  data array, or null
  * @param string $protocol 'http' or 'https'
  * @throws MWException
  */
 public function __construct($data = array(), $wasPosted = false, $session = null, $protocol = 'http')
 {
     $this->requestTime = microtime(true);
     if (is_array($data)) {
         $this->data = $data;
     } else {
         throw new MWException("FauxRequest() got bogus data");
     }
     $this->wasPosted = $wasPosted;
     if ($session instanceof MediaWiki\Session\Session) {
         $this->sessionId = $session->getSessionId();
     } elseif (is_array($session)) {
         $mwsession = SessionManager::singleton()->getEmptySession($this);
         $this->sessionId = $mwsession->getSessionId();
         foreach ($session as $key => $value) {
             $mwsession->set($key, $value);
         }
     } elseif ($session !== null) {
         throw new MWException("FauxRequest() got bogus session");
     }
     $this->protocol = $protocol;
 }
예제 #4
0
 public function execute()
 {
     $username = $this->getOption('user');
     $file = $this->getOption('file');
     if ($username === null && $file === null) {
         $this->error('Either --user or --file is required', 1);
     } elseif ($username !== null && $file !== null) {
         $this->error('Cannot use both --user and --file', 1);
     }
     if ($username !== null) {
         $usernames = [$username];
     } else {
         $usernames = is_readable($file) ? file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) : false;
         if ($usernames === false) {
             $this->error("Could not open {$file}", 2);
         }
     }
     $i = 0;
     $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
     $sessionManager = SessionManager::singleton();
     foreach ($usernames as $username) {
         $i++;
         $user = User::newFromName($username);
         try {
             $sessionManager->invalidateSessionsForUser($user);
             if ($user->getId()) {
                 $this->output("Invalidated sessions for user {$username}\n");
             } else {
                 # session invalidation might still work if there is a central identity provider
                 $this->output("Could not find user {$username}, tried to invalidate anyway\n");
             }
         } catch (Exception $e) {
             $this->output("Failed to invalidate sessions for user {$username} | " . str_replace(["\r", "\n"], ' ', $e->getMessage()) . "\n");
         }
         if ($i % $this->mBatchSize) {
             $lbFactory->waitForReplication();
         }
     }
 }
 public function testGetLoginCookieExpiration()
 {
     $config = $this->getConfig();
     $provider = \TestingAccessWrapper::newFromObject(new CookieSessionProvider(['priority' => 10]));
     $provider->setLogger(new \Psr\Log\NullLogger());
     $provider->setConfig($config);
     $provider->setManager(SessionManager::singleton());
     $this->assertSame(200, $provider->getLoginCookieExpiration('Token'));
     $this->assertSame(100, $provider->getLoginCookieExpiration('User'));
     $config->set('ExtendedLoginCookieExpiration', null);
     $this->assertSame(100, $provider->getLoginCookieExpiration('Token'));
     $this->assertSame(100, $provider->getLoginCookieExpiration('User'));
 }
예제 #6
0
 /**
  * Returns true if the request has a persistent session.
  * This does not necessarily mean that the user is logged in!
  *
  * @deprecated since 1.27, use
  *  \\MediaWiki\\Session\\SessionManager::singleton()->getPersistedSessionId()
  *  instead.
  * @return bool
  */
 public function checkSessionCookie()
 {
     wfDeprecated(__METHOD__, '1.27');
     return SessionManager::singleton()->getPersistedSessionId($this) !== null;
 }
예제 #7
0
/**
 * Initialise php session
 *
 * @deprecated since 1.27, use MediaWiki\\Session\\SessionManager instead.
 *  Generally, "using" SessionManager will be calling ->getSessionById() or
 *  ::getGlobalSession() (depending on whether you were passing $sessionId
 *  here), then calling $session->persist().
 * @param bool|string $sessionId
 */
function wfSetupSession($sessionId = false)
{
    wfDeprecated(__FUNCTION__, '1.27');
    // If they're calling this, they probably want our session management even
    // if NO_SESSION was set for Setup.php.
    if (!MediaWiki\Session\PHPSessionHandler::isInstalled()) {
        MediaWiki\Session\PHPSessionHandler::install(SessionManager::singleton());
    }
    if ($sessionId) {
        session_id($sessionId);
    }
    $session = SessionManager::getGlobalSession();
    $session->persist();
    if (session_id() !== $session->getId()) {
        session_id($session->getId());
    }
    MediaWiki\quietCall('session_cache_limiter', 'private, must-revalidate');
    MediaWiki\quietCall('session_start');
}
예제 #8
0
 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();
 }
예제 #9
0
 /**
  * Actually set the password and such
  * @since 1.27 cannot set a password for a user not in the database
  * @param string|null $str New password to set or null to set an invalid
  *  password hash meaning that the user will not be able to log in
  *  through the web interface.
  * @return bool Success
  */
 private function setPasswordInternal($str)
 {
     global $wgDisableAuthManager;
     if ($wgDisableAuthManager) {
         $id = self::idFromName($this->getName(), self::READ_LATEST);
         if ($id == 0) {
             throw new LogicException('Cannot set a password for a user that is not in the database.');
         }
         $passwordFactory = new PasswordFactory();
         $passwordFactory->init(RequestContext::getMain()->getConfig());
         $dbw = wfGetDB(DB_MASTER);
         $dbw->update('user', ['user_password' => $passwordFactory->newFromPlaintext($str)->toString(), 'user_newpassword' => PasswordFactory::newInvalidPassword()->toString(), 'user_newpass_time' => $dbw->timestampOrNull(null)], ['user_id' => $id], __METHOD__);
         // When the main password is changed, invalidate all bot passwords too
         BotPassword::invalidateAllPasswordsForUser($this->getName());
     } else {
         $manager = AuthManager::singleton();
         // If the user doesn't exist yet, fail
         if (!$manager->userExists($this->getName())) {
             throw new LogicException('Cannot set a password for a user that is not in the database.');
         }
         $data = ['username' => $this->getName(), 'password' => $str, 'retype' => $str];
         $reqs = $manager->getAuthenticationRequests(AuthManager::ACTION_CHANGE, $this);
         $reqs = AuthenticationRequest::loadRequestsFromSubmission($reqs, $data);
         foreach ($reqs as $req) {
             $status = $manager->allowsAuthenticationDataChange($req);
             if (!$status->isOk()) {
                 \MediaWiki\Logger\LoggerFactory::getInstance('authentication')->info(__METHOD__ . ': Password change rejected: ' . $status->getWikiText());
                 return false;
             }
         }
         foreach ($reqs as $req) {
             $manager->changeAuthenticationData($req);
         }
         $this->setOption('watchlisttoken', false);
     }
     SessionManager::singleton()->invalidateSessionsForUser($this);
     return true;
 }
예제 #10
0
 /**
  * @param User $user
  * @param bool $useContextLang Use 'uselang' to set the user's language
  */
 private function setDefaultUserOptions(User $user, $useContextLang)
 {
     global $wgContLang;
     \MediaWiki\Session\SessionManager::singleton()->invalidateSessionsForUser($user);
     $lang = $useContextLang ? \RequestContext::getMain()->getLanguage() : $wgContLang;
     $user->setOption('language', $lang->getPreferredVariant());
     if ($wgContLang->hasVariants()) {
         $user->setOption('variant', $wgContLang->getPreferredVariant());
     }
 }
예제 #11
0
파일: User.php 프로젝트: paladox/2
 /**
  * Static factory method for creation of a "system" user from username.
  *
  * A "system" user is an account that's used to attribute logged actions
  * taken by MediaWiki itself, as opposed to a bot or human user. Examples
  * might include the 'Maintenance script' or 'Conversion script' accounts
  * used by various scripts in the maintenance/ directory or accounts such
  * as 'MediaWiki message delivery' used by the MassMessage extension.
  *
  * This can optionally create the user if it doesn't exist, and "steal" the
  * account if it does exist.
  *
  * @param string $name Username
  * @param array $options Options are:
  *  - validate: As for User::getCanonicalName(), default 'valid'
  *  - create: Whether to create the user if it doesn't already exist, default true
  *  - steal: Whether to reset the account's password and email if it
  *    already exists, default false
  * @return User|null
  */
 public static function newSystemUser($name, $options = array())
 {
     $options += array('validate' => 'valid', 'create' => true, 'steal' => false);
     $name = self::getCanonicalName($name, $options['validate']);
     if ($name === false) {
         return null;
     }
     $dbw = wfGetDB(DB_MASTER);
     $row = $dbw->selectRow('user', array_merge(self::selectFields(), array('user_password', 'user_newpassword')), array('user_name' => $name), __METHOD__);
     if (!$row) {
         // No user. Create it?
         return $options['create'] ? self::createNew($name) : null;
     }
     $user = self::newFromRow($row);
     // A user is considered to exist as a non-system user if it has a
     // password set, or a temporary password set, or an email set.
     $passwordFactory = new PasswordFactory();
     $passwordFactory->init(RequestContext::getMain()->getConfig());
     try {
         $password = $passwordFactory->newFromCiphertext($row->user_password);
     } catch (PasswordError $e) {
         wfDebug('Invalid password hash found in database.');
         $password = PasswordFactory::newInvalidPassword();
     }
     try {
         $newpassword = $passwordFactory->newFromCiphertext($row->user_newpassword);
     } catch (PasswordError $e) {
         wfDebug('Invalid password hash found in database.');
         $newpassword = PasswordFactory::newInvalidPassword();
     }
     if (!$password instanceof InvalidPassword || !$newpassword instanceof InvalidPassword || $user->mEmail) {
         // User exists. Steal it?
         if (!$options['steal']) {
             return null;
         }
         $nopass = PasswordFactory::newInvalidPassword()->toString();
         $dbw->update('user', array('user_password' => $nopass, 'user_newpassword' => $nopass, 'user_newpass_time' => null), array('user_id' => $user->getId()), __METHOD__);
         $user->invalidateEmail();
         $user->saveSettings();
     }
     SessionManager::singleton()->preventSessionsForUser($user->getName());
     return $user;
 }
예제 #12
0
 public function resetAuthToken()
 {
     \MediaWiki\Session\SessionManager::singleton()->invalidateSessionsForUser($this->user);
     return true;
 }
예제 #13
0
 /**
  * Check if a session cookie is present.
  *
  * This will not pick up a cookie set during _this_ request, but is meant
  * to ensure that the client is returning the cookie which was set on a
  * previous pass through the system.
  *
  * @private
  * @return bool
  */
 function hasSessionCookie()
 {
     global $wgDisableCookieCheck;
     return $wgDisableCookieCheck || SessionManager::singleton()->getPersistedSessionId($this->getRequest()) !== null;
 }
 protected function success()
 {
     $session = $this->getRequest()->getSession();
     $user = $this->getUser();
     $out = $this->getOutput();
     $returnUrl = $this->getReturnUrl();
     // change user token and update the session
     SessionManager::singleton()->invalidateSessionsForUser($user);
     $session->setUser($user);
     $session->resetId();
     if ($returnUrl) {
         $out->redirect($returnUrl);
     } else {
         // messages used: changecredentials-success removecredentials-success
         $out->wrapWikiMsg("<div class=\"successbox\">\n\$1\n</div>", static::$messagePrefix . '-success');
         $out->returnToMain();
     }
 }
예제 #15
0
 /**
  * Actually add a user to the database.
  * Give it a User object that has been initialised with a name.
  *
  * @param User $u
  * @param bool $autocreate True if this is an autocreation via auth plugin
  * @return Status Status object, with the User object in the value member on success
  * @private
  */
 function initUser($u, $autocreate)
 {
     global $wgAuth;
     $status = $u->addToDatabase();
     if (!$status->isOK()) {
         return $status;
     }
     if ($wgAuth->allowPasswordChange()) {
         $u->setPassword($this->mPassword);
     }
     $u->setEmail($this->mEmail);
     $u->setRealName($this->mRealName);
     SessionManager::singleton()->invalidateSessionsForUser($u);
     Hooks::run('LocalUserCreated', [$u, $autocreate]);
     $oldUser = $u;
     $wgAuth->initUser($u, $autocreate);
     if ($oldUser !== $u) {
         wfWarn(get_class($wgAuth) . '::initUser() replaced the user object');
     }
     $u->saveSettings();
     // Update user count
     DeferredUpdates::addUpdate(new SiteStatsUpdate(0, 0, 0, 0, 1));
     // Watch user's userpage and talk page
     $u->addWatch($u->getUserPage(), User::IGNORE_USER_RIGHTS);
     return Status::newGood($u);
 }
예제 #16
0
 /**
  * Return the session for this request
  * @since 1.27
  * @note For performance, keep the session locally if you will be making
  *  much use of it instead of calling this method repeatedly.
  * @return Session
  */
 public function getSession()
 {
     if ($this->sessionId !== null) {
         $session = SessionManager::singleton()->getSessionById((string) $this->sessionId, true, $this);
         if ($session) {
             return $session;
         }
     }
     $session = SessionManager::singleton()->getSessionForRequest($this);
     $this->sessionId = $session->getSessionId();
     return $session;
 }
예제 #17
0
 public function testSetLoggedOutCookie()
 {
     $provider = \TestingAccessWrapper::newFromObject(new CookieSessionProvider(array('priority' => 1, 'sessionName' => 'MySessionName', 'cookieOptions' => array('prefix' => 'x'))));
     $provider->setLogger(new \Psr\Log\NullLogger());
     $provider->setConfig($this->getConfig());
     $provider->setManager(SessionManager::singleton());
     $t1 = time();
     $t2 = time() - 86400 * 2;
     // Set it
     $request = new \FauxRequest();
     $provider->setLoggedOutCookie($t1, $request);
     $this->assertSame((string) $t1, $request->response()->getCookie('xLoggedOut'));
     // Too old
     $request = new \FauxRequest();
     $provider->setLoggedOutCookie($t2, $request);
     $this->assertSame(null, $request->response()->getCookie('xLoggedOut'));
     // Don't reset if it's already set
     $request = new \FauxRequest();
     $request->setCookies(array('xLoggedOut' => $t1), '');
     $provider->setLoggedOutCookie($t1, $request);
     $this->assertSame(null, $request->response()->getCookie('xLoggedOut'));
 }
예제 #18
0
 /**
  * Get a complete Key header
  *
  * @return string
  */
 public function getKeyHeader()
 {
     $cvCookies = $this->getCacheVaryCookies();
     $cookiesOption = array();
     foreach ($cvCookies as $cookieName) {
         $cookiesOption[] = 'param=' . $cookieName;
     }
     $this->addVaryHeader('Cookie', $cookiesOption);
     foreach (SessionManager::singleton()->getVaryHeaders() as $header => $options) {
         $this->addVaryHeader($header, $options);
     }
     $headers = array();
     foreach ($this->mVaryHeader as $header => $option) {
         $newheader = $header;
         if (is_array($option) && count($option) > 0) {
             $newheader .= ';' . implode(';', $option);
         }
         $headers[] = $newheader;
     }
     $key = 'Key: ' . implode(',', $headers);
     return $key;
 }
예제 #19
0
파일: User.php 프로젝트: paladox/mediawiki
 /**
  * Actually set the password and such
  * @since 1.27 cannot set a password for a user not in the database
  * @param string|null $str New password to set or null to set an invalid
  *  password hash meaning that the user will not be able to log in
  *  through the web interface.
  * @return bool Success
  */
 private function setPasswordInternal($str)
 {
     $manager = AuthManager::singleton();
     // If the user doesn't exist yet, fail
     if (!$manager->userExists($this->getName())) {
         throw new LogicException('Cannot set a password for a user that is not in the database.');
     }
     $status = $this->changeAuthenticationData(['username' => $this->getName(), 'password' => $str, 'retype' => $str]);
     if (!$status->isGood()) {
         \MediaWiki\Logger\LoggerFactory::getInstance('authentication')->info(__METHOD__ . ': Password change rejected: ' . $status->getWikiText(null, null, 'en'));
         return false;
     }
     $this->setOption('watchlisttoken', false);
     SessionManager::singleton()->invalidateSessionsForUser($this);
     return true;
 }