/** * Main execution point */ function execute($par) { global $wgAuth; $this->checkReadOnly(); $request = $this->getRequest(); $this->mUserName = trim($request->getVal('wpName')); $this->mOldpass = $request->getVal('wpPassword'); $this->mNewpass = $request->getVal('wpNewPassword'); $this->mRetype = $request->getVal('wpRetype'); $this->mDomain = $request->getVal('wpDomain'); $this->setHeaders(); $this->outputHeader(); $this->getOutput()->disallowUserJs(); $user = $this->getUser(); if (!$request->wasPosted() && !$user->isLoggedIn()) { $this->error($this->msg('resetpass-no-info')->text()); return; } if ($request->wasPosted() && $request->getBool('wpCancel')) { $this->doReturnTo(); return; } if ($request->wasPosted() && $user->matchEditToken($request->getVal('token'))) { try { if (isset($_SESSION['wsDomain'])) { $this->mDomain = $_SESSION['wsDomain']; } $wgAuth->setDomain($this->mDomain); if (!$wgAuth->allowPasswordChange()) { $this->error($this->msg('resetpass_forbidden')->text()); return; } $this->attemptReset($this->mNewpass, $this->mRetype); $this->getOutput()->addWikiMsg('resetpass_success'); if (!$user->isLoggedIn()) { LoginForm::setLoginToken(); $token = LoginForm::getLoginToken(); $data = array('action' => 'submitlogin', 'wpName' => $this->mUserName, 'wpDomain' => $this->mDomain, 'wpLoginToken' => $token, 'wpPassword' => $this->mNewpass, 'returnto' => $request->getVal('returnto')); if ($request->getCheck('wpRemember')) { $data['wpRemember'] = 1; } $login = new LoginForm(new FauxRequest($data, true)); $login->setContext($this->getContext()); $login->execute(null); } $this->doReturnTo(); } catch (PasswordError $e) { $this->error($e->getMessage()); } } $this->showForm(); }
/** * Executes the log-in attempt using the parameters passed. If * the log-in succeeeds, it attaches a cookie to the session * and outputs the user id, username, and session token. If a * log-in fails, as the result of a bad password, a nonexistent * user, or any other reason, the host is cached with an expiry * and no log-in attempts will be accepted until that expiry * is reached. The expiry is $this->mLoginThrottle. */ public function execute() { $params = $this->extractRequestParams(); $result = array(); // Init session if necessary if (session_id() == '') { wfSetupSession(); } $context = new DerivativeContext($this->getContext()); $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => ''))); $loginForm = new LoginForm(); $loginForm->setContext($context); global $wgCookiePrefix, $wgPasswordAttemptThrottle; $authRes = $loginForm->authenticateUserData(); switch ($authRes) { case LoginForm::SUCCESS: $user = $context->getUser(); $this->getContext()->setUser($user); $user->setOption('rememberpassword', 1); $user->setCookies($this->getRequest()); ApiQueryInfo::resetTokenCache(); // Run hooks. // @todo FIXME: Split back and frontend from this hook. // @todo FIXME: This hook should be placed in the backend $injected_html = ''; wfRunHooks('UserLoginComplete', array(&$user, &$injected_html)); $result['result'] = 'Success'; $result['lguserid'] = intval($user->getId()); $result['lgusername'] = $user->getName(); $result['lgtoken'] = $user->getToken(); $result['cookieprefix'] = $wgCookiePrefix; $result['sessionid'] = session_id(); break; case LoginForm::NEED_TOKEN: $result['result'] = 'NeedToken'; $result['token'] = $loginForm->getLoginToken(); $result['cookieprefix'] = $wgCookiePrefix; $result['sessionid'] = session_id(); break; case LoginForm::WRONG_TOKEN: $result['result'] = 'WrongToken'; break; case LoginForm::NO_NAME: $result['result'] = 'NoName'; break; case LoginForm::ILLEGAL: $result['result'] = 'Illegal'; break; case LoginForm::WRONG_PLUGIN_PASS: $result['result'] = 'WrongPluginPass'; break; case LoginForm::NOT_EXISTS: $result['result'] = 'NotExists'; break; case LoginForm::RESET_PASS: // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin - "The e-mailed temporary password should not be used for actual logins;" // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin - "The e-mailed temporary password should not be used for actual logins;" case LoginForm::WRONG_PASS: $result['result'] = 'WrongPass'; break; case LoginForm::EMPTY_PASS: $result['result'] = 'EmptyPass'; break; case LoginForm::CREATE_BLOCKED: $result['result'] = 'CreateBlocked'; $result['details'] = 'Your IP address is blocked from account creation'; break; case LoginForm::THROTTLED: $result['result'] = 'Throttled'; $result['wait'] = intval($wgPasswordAttemptThrottle['seconds']); break; case LoginForm::USER_BLOCKED: $result['result'] = 'Blocked'; break; case LoginForm::ABORTED: $result['result'] = 'Aborted'; $result['reason'] = $loginForm->mAbortLoginErrorMsg; break; default: ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}"); } $this->getResult()->addValue(null, 'login', $result); }
public function onSuccess() { if ($this->getUser()->isLoggedIn()) { $this->getOutput()->wrapWikiMsg("<div class=\"successbox\">\n\$1\n</div>", 'changepassword-success'); $this->getOutput()->returnToMain(); } else { $request = $this->getRequest(); LoginForm::setLoginToken(); $token = LoginForm::getLoginToken(); $data = array('action' => 'submitlogin', 'wpName' => $this->mUserName, 'wpDomain' => $this->mDomain, 'wpLoginToken' => $token, 'wpPassword' => $request->getVal('wpNewPassword')) + $request->getValues('wpRemember', 'returnto', 'returntoquery'); $login = new LoginForm(new DerivativeRequest($request, $data, true)); $login->setContext($this->getContext()); $login->execute(null); } }
/** * Executes the log-in attempt using the parameters passed. If * the log-in succeeds, it attaches a cookie to the session * and outputs the user id, username, and session token. If a * log-in fails, as the result of a bad password, a nonexistent * user, or any other reason, the host is cached with an expiry * and no log-in attempts will be accepted until that expiry * is reached. The expiry is $this->mLoginThrottle. */ public function execute() { // If we're in a mode that breaks the same-origin policy, no tokens can // be obtained if ($this->lacksSameOriginSecurity()) { $this->getResult()->addValue(null, 'login', array('result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied')); return; } $params = $this->extractRequestParams(); $result = array(); // Init session if necessary if (session_id() == '') { wfSetupSession(); } $context = new DerivativeContext($this->getContext()); $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => ''))); $loginForm = new LoginForm(); $loginForm->setContext($context); $authRes = $loginForm->authenticateUserData(); switch ($authRes) { case LoginForm::SUCCESS: $user = $context->getUser(); $this->getContext()->setUser($user); $user->setCookies($this->getRequest(), null, true); ApiQueryInfo::resetTokenCache(); // Run hooks. // @todo FIXME: Split back and frontend from this hook. // @todo FIXME: This hook should be placed in the backend $injected_html = ''; Hooks::run('UserLoginComplete', array(&$user, &$injected_html)); $result['result'] = 'Success'; $result['lguserid'] = intval($user->getId()); $result['lgusername'] = $user->getName(); $result['lgtoken'] = $user->getToken(); $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = session_id(); break; case LoginForm::NEED_TOKEN: $result['result'] = 'NeedToken'; $result['token'] = $loginForm->getLoginToken(); $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = session_id(); break; case LoginForm::WRONG_TOKEN: $result['result'] = 'WrongToken'; break; case LoginForm::NO_NAME: $result['result'] = 'NoName'; break; case LoginForm::ILLEGAL: $result['result'] = 'Illegal'; break; case LoginForm::WRONG_PLUGIN_PASS: $result['result'] = 'WrongPluginPass'; break; case LoginForm::NOT_EXISTS: $result['result'] = 'NotExists'; break; // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. case LoginForm::RESET_PASS: case LoginForm::WRONG_PASS: $result['result'] = 'WrongPass'; break; case LoginForm::EMPTY_PASS: $result['result'] = 'EmptyPass'; break; case LoginForm::CREATE_BLOCKED: $result['result'] = 'CreateBlocked'; $result['details'] = 'Your IP address is blocked from account creation'; $block = $context->getUser()->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::THROTTLED: $result['result'] = 'Throttled'; $throttle = $this->getConfig()->get('PasswordAttemptThrottle'); $result['wait'] = intval($throttle['seconds']); break; case LoginForm::USER_BLOCKED: $result['result'] = 'Blocked'; $block = User::newFromName($params['name'])->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::ABORTED: $result['result'] = 'Aborted'; $result['reason'] = $loginForm->mAbortLoginErrorMsg; break; default: ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}"); } $this->getResult()->addValue(null, 'login', $result); LoggerFactory::getInstance('authmanager')->info('Login attempt', array('event' => 'login', 'successful' => $authRes === LoginForm::SUCCESS, 'status' => LoginForm::$statusCodes[$authRes])); }
public function execute() { // If we're in a mode that breaks the same-origin policy, no tokens can // be obtained if ($this->lacksSameOriginSecurity()) { $this->dieUsage('Cannot create account when the same-origin policy is not applied', 'aborted'); } // $loginForm->addNewaccountInternal will throw exceptions // if wiki is read only (already handled by api), user is blocked or does not have rights. // Use userCan in order to hit GlobalBlock checks (according to Special:userlogin) $loginTitle = SpecialPage::getTitleFor('Userlogin'); if (!$loginTitle->userCan('createaccount', $this->getUser())) { $this->dieUsage('You do not have the right to create a new account', 'permdenied-createaccount'); } if ($this->getUser()->isBlockedFromCreateAccount()) { $this->dieUsage('You cannot create a new account because you are blocked', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($this->getUser()->getBlock()))); } $params = $this->extractRequestParams(); // Init session if necessary if (session_id() == '') { wfSetupSession(); } if ($params['mailpassword'] && !$params['email']) { $this->dieUsageMsg('noemail'); } if ($params['language'] && !Language::isSupportedLanguage($params['language'])) { $this->dieUsage('Invalid language parameter', 'langinvalid'); } $context = new DerivativeContext($this->getContext()); $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('type' => 'signup', 'uselang' => $params['language'], 'wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpRetype' => $params['password'], 'wpDomain' => $params['domain'], 'wpEmail' => $params['email'], 'wpRealName' => $params['realname'], 'wpCreateaccountToken' => $params['token'], 'wpCreateaccount' => $params['mailpassword'] ? null : '1', 'wpCreateaccountMail' => $params['mailpassword'] ? '1' : null))); $loginForm = new LoginForm(); $loginForm->setContext($context); Hooks::run('AddNewAccountApiForm', array($this, $loginForm)); $loginForm->load(); $status = $loginForm->addNewaccountInternal(); $result = array(); if ($status->isGood()) { // Success! $user = $status->getValue(); if ($params['language']) { $user->setOption('language', $params['language']); } if ($params['mailpassword']) { // If mailpassword was set, disable the password and send an email. $user->setPassword(null); $status->merge($loginForm->mailPasswordInternal($user, false, 'createaccount-title', 'createaccount-text')); } elseif ($this->getConfig()->get('EmailAuthentication') && Sanitizer::validateEmail($user->getEmail())) { // Send out an email authentication message if needed $status->merge($user->sendConfirmationMail()); } // Save settings (including confirmation token) $user->saveSettings(); Hooks::run('AddNewAccount', array($user, $params['mailpassword'])); if ($params['mailpassword']) { $logAction = 'byemail'; } elseif ($this->getUser()->isLoggedIn()) { $logAction = 'create2'; } else { $logAction = 'create'; } $user->addNewUserLogEntry($logAction, (string) $params['reason']); // Add username, id, and token to result. $result['username'] = $user->getName(); $result['userid'] = $user->getId(); $result['token'] = $user->getToken(); } $apiResult = $this->getResult(); if ($status->hasMessage('sessionfailure') || $status->hasMessage('nocookiesfornew')) { // Token was incorrect, so add it to result, but don't throw an exception // since not having the correct token is part of the normal // flow of events. $result['token'] = LoginForm::getCreateaccountToken(); $result['result'] = 'NeedToken'; } elseif (!$status->isOK()) { // There was an error. Die now. $this->dieStatus($status); } elseif (!$status->isGood()) { // Status is not good, but OK. This means warnings. $result['result'] = 'Warning'; // Add any warnings to the result $warnings = $status->getErrorsByType('warning'); if ($warnings) { foreach ($warnings as &$warning) { ApiResult::setIndexedTagName($warning['params'], 'param'); } ApiResult::setIndexedTagName($warnings, 'warning'); $result['warnings'] = $warnings; } } else { // Everything was fine. $result['result'] = 'Success'; } // Give extensions a chance to modify the API result data Hooks::run('AddNewAccountApiResult', array($this, $loginForm, &$result)); $apiResult->addValue(null, 'createaccount', $result); }
public function execute() { // $loginForm->addNewaccountInternal will throw exceptions // if wiki is read only (already handled by api), user is blocked or does not have rights. // Use userCan in order to hit GlobalBlock checks (according to Special:userlogin) $loginTitle = SpecialPage::getTitleFor('Userlogin'); if (!$loginTitle->userCan('createaccount', $this->getUser())) { $this->dieUsage('You do not have the right to create a new account', 'permdenied-createaccount'); } if ($this->getUser()->isBlockedFromCreateAccount()) { $this->dieUsage('You cannot create a new account because you are blocked', 'blocked'); } $params = $this->extractRequestParams(); $result = array(); // Init session if necessary if (session_id() == '') { wfSetupSession(); } if ($params['mailpassword'] && !$params['email']) { $this->dieUsageMsg('noemail'); } $context = new DerivativeContext($this->getContext()); $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('type' => 'signup', 'uselang' => $params['language'], 'wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpRetype' => $params['password'], 'wpDomain' => $params['domain'], 'wpEmail' => $params['email'], 'wpRealName' => $params['realname'], 'wpCreateaccountToken' => $params['token'], 'wpCreateaccount' => $params['mailpassword'] ? null : '1', 'wpCreateaccountMail' => $params['mailpassword'] ? '1' : null))); $loginForm = new LoginForm(); $loginForm->setContext($context); $loginForm->load(); $status = $loginForm->addNewaccountInternal(); $result = array(); if ($status->isGood()) { // Success! $user = $status->getValue(); // If we showed up language selection links, and one was in use, be // smart (and sensible) and save that language as the user's preference global $wgLoginLanguageSelector, $wgEmailAuthentication; if ($wgLoginLanguageSelector && $params['language']) { $user->setOption('language', $params['language']); } if ($params['mailpassword']) { // If mailpassword was set, disable the password and send an email. $user->setPassword(null); $status->merge($loginForm->mailPasswordInternal($user, false, 'createaccount-title', 'createaccount-text')); } elseif ($wgEmailAuthentication && Sanitizer::validateEmail($user->getEmail())) { // Send out an email authentication message if needed $status->merge($user->sendConfirmationMail()); } // Save settings (including confirmation token) $user->saveSettings(); wfRunHooks('AddNewAccount', array($user, $params['mailpassword'])); if ($params['mailpassword']) { $logAction = 'byemail'; } elseif ($this->getUser()->isLoggedIn()) { $logAction = 'create2'; } else { $logAction = 'create'; } $user->addNewUserLogEntry($logAction, (string) $params['reason']); // Add username, id, and token to result. $result['username'] = $user->getName(); $result['userid'] = $user->getId(); $result['token'] = $user->getToken(); } $apiResult = $this->getResult(); if ($status->hasMessage('sessionfailure') || $status->hasMessage('nocookiesfornew')) { // Token was incorrect, so add it to result, but don't throw an exception // since not having the correct token is part of the normal // flow of events. $result['token'] = LoginForm::getCreateaccountToken(); $result['result'] = 'needtoken'; } elseif (!$status->isOK()) { // There was an error. Die now. // Cannot use dieUsageMsg() directly because extensions // might return custom error messages. $errors = $status->getErrorsArray(); if ($errors[0] instanceof Message) { $code = 'aborted'; $desc = $errors[0]; } else { $code = array_shift($errors[0]); $desc = wfMessage($code, $errors[0]); } $this->dieUsage($desc, $code); } elseif (!$status->isGood()) { // Status is not good, but OK. This means warnings. $result['result'] = 'warning'; // Add any warnings to the result $warnings = $status->getErrorsByType('warning'); if ($warnings) { foreach ($warnings as &$warning) { $apiResult->setIndexedTagName($warning['params'], 'param'); } $apiResult->setIndexedTagName($warnings, 'warning'); $result['warnings'] = $warnings; } } else { // Everything was fine. $result['result'] = 'success'; } $apiResult->addValue(null, 'createaccount', $result); }
/** * Executes the log-in attempt using the parameters passed. If * the log-in succeeds, it attaches a cookie to the session * and outputs the user id, username, and session token. If a * log-in fails, as the result of a bad password, a nonexistent * user, or any other reason, the host is cached with an expiry * and no log-in attempts will be accepted until that expiry * is reached. The expiry is $this->mLoginThrottle. */ public function execute() { // If we're in a mode that breaks the same-origin policy, no tokens can // be obtained if ($this->lacksSameOriginSecurity()) { $this->getResult()->addValue(null, 'login', array('result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied')); return; } $params = $this->extractRequestParams(); $result = array(); // Make sure session is persisted $session = MediaWiki\Session\SessionManager::getGlobalSession(); $session->persist(); // Make sure it's possible to log in if (!$session->canSetUser()) { $this->getResult()->addValue(null, 'login', array('result' => 'Aborted', 'reason' => 'Cannot log in when using ' . $session->getProvider()->describe(Language::factory('en')))); return; } $authRes = false; $context = new DerivativeContext($this->getContext()); $loginType = 'N/A'; // Check login token $token = LoginForm::getLoginToken(); if (!$token) { LoginForm::setLoginToken(); $authRes = LoginForm::NEED_TOKEN; } elseif (!$params['token']) { $authRes = LoginForm::NEED_TOKEN; } elseif ($token !== $params['token']) { $authRes = LoginForm::WRONG_TOKEN; } // Try bot passwords if ($authRes === false && $this->getConfig()->get('EnableBotPasswords') && strpos($params['name'], BotPassword::getSeparator()) !== false) { $status = BotPassword::login($params['name'], $params['password'], $this->getRequest()); if ($status->isOk()) { $session = $status->getValue(); $authRes = LoginForm::SUCCESS; $loginType = 'BotPassword'; } else { LoggerFactory::getInstance('authmanager')->info('BotPassword login failed: ' . $status->getWikiText()); } } // Normal login if ($authRes === false) { $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => ''))); $loginForm = new LoginForm(); $loginForm->setContext($context); $authRes = $loginForm->authenticateUserData(); $loginType = 'LoginForm'; } switch ($authRes) { case LoginForm::SUCCESS: $user = $context->getUser(); $this->getContext()->setUser($user); $user->setCookies($this->getRequest(), null, true); ApiQueryInfo::resetTokenCache(); // Run hooks. // @todo FIXME: Split back and frontend from this hook. // @todo FIXME: This hook should be placed in the backend $injected_html = ''; Hooks::run('UserLoginComplete', array(&$user, &$injected_html)); $result['result'] = 'Success'; $result['lguserid'] = intval($user->getId()); $result['lgusername'] = $user->getName(); // @todo: These are deprecated, and should be removed at some // point (1.28 at the earliest, and see T121527). They were ok // when the core cookie-based login was the only thing, but // CentralAuth broke that a while back and // SessionManager/AuthManager are *really* going to break it. $result['lgtoken'] = $user->getToken(); $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = $session->getId(); break; case LoginForm::NEED_TOKEN: $result['result'] = 'NeedToken'; $result['token'] = LoginForm::getLoginToken(); // @todo: See above about deprecation $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = $session->getId(); break; case LoginForm::WRONG_TOKEN: $result['result'] = 'WrongToken'; break; case LoginForm::NO_NAME: $result['result'] = 'NoName'; break; case LoginForm::ILLEGAL: $result['result'] = 'Illegal'; break; case LoginForm::WRONG_PLUGIN_PASS: $result['result'] = 'WrongPluginPass'; break; case LoginForm::NOT_EXISTS: $result['result'] = 'NotExists'; break; // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. case LoginForm::RESET_PASS: case LoginForm::WRONG_PASS: $result['result'] = 'WrongPass'; break; case LoginForm::EMPTY_PASS: $result['result'] = 'EmptyPass'; break; case LoginForm::CREATE_BLOCKED: $result['result'] = 'CreateBlocked'; $result['details'] = 'Your IP address is blocked from account creation'; $block = $context->getUser()->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::THROTTLED: $result['result'] = 'Throttled'; $throttle = $this->getConfig()->get('PasswordAttemptThrottle'); $result['wait'] = intval($throttle['seconds']); break; case LoginForm::USER_BLOCKED: $result['result'] = 'Blocked'; $block = User::newFromName($params['name'])->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::ABORTED: $result['result'] = 'Aborted'; $result['reason'] = $loginForm->mAbortLoginErrorMsg; break; default: ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}"); } $this->getResult()->addValue(null, 'login', $result); LoggerFactory::getInstance('authmanager')->info('Login attempt', array('event' => 'login', 'successful' => $authRes === LoginForm::SUCCESS, 'loginType' => $loginType, 'status' => LoginForm::$statusCodes[$authRes])); }
/** * Main execution point */ function execute( $par ) { global $wgAuth; $this->setHeaders(); $this->outputHeader(); $this->getOutput()->disallowUserJs(); $request = $this->getRequest(); $this->mUserName = trim( $request->getVal( 'wpName' ) ); $this->mOldpass = $request->getVal( 'wpPassword' ); $this->mNewpass = $request->getVal( 'wpNewPassword' ); $this->mRetype = $request->getVal( 'wpRetype' ); $this->mDomain = $request->getVal( 'wpDomain' ); $user = $this->getUser(); if ( !$user->isLoggedIn() && !LoginForm::getLoginToken() ) { LoginForm::setLoginToken(); } if ( !$request->wasPosted() && !$user->isLoggedIn() ) { $this->error( $this->msg( 'resetpass-no-info' )->text() ); return; } if ( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) { $titleObj = Title::newFromText( $request->getVal( 'returnto' ) ); if ( !$titleObj instanceof Title ) { $titleObj = Title::newMainPage(); } $query = $request->getVal( 'returntoquery' ); $this->getOutput()->redirect( $titleObj->getFullURL( $query ) ); return; } $this->checkReadOnly(); $this->checkPermissions(); if ( $request->wasPosted() && $user->matchEditToken( $request->getVal( 'token' ) ) ) { try { $this->mDomain = $wgAuth->getDomain(); if ( !$wgAuth->allowPasswordChange() ) { $this->error( $this->msg( 'resetpass_forbidden' )->text() ); return; } if ( !$user->isLoggedIn() && $request->getVal( 'wpLoginOnChangeToken' ) !== LoginForm::getLoginToken() ) { // Potential CSRF (bug 62497) $this->error( $this->msg( 'sessionfailure' )->text() ); return false; } $this->attemptReset( $this->mNewpass, $this->mRetype ); if ( $user->isLoggedIn() ) { $this->getOutput()->wrapWikiMsg( "<div class=\"successbox\">\n$1\n</div>", 'changepassword-success' ); $this->getOutput()->returnToMain(); } else { LoginForm::setLoginToken(); $token = LoginForm::getLoginToken(); $data = array( 'action' => 'submitlogin', 'wpName' => $this->mUserName, 'wpDomain' => $this->mDomain, 'wpLoginToken' => $token, 'wpPassword' => $request->getVal( 'wpNewPassword' ), ) + $request->getValues( 'wpRemember', 'returnto', 'returntoquery' ); $login = new LoginForm( new DerivativeRequest( $request, $data, true ) ); $login->setContext( $this->getContext() ); $login->execute( null ); } return; } catch ( PasswordError $e ) { $this->error( $e->getMessage() ); } } $this->showForm(); }
/** * Executes the log-in attempt using the parameters passed. If * the log-in succeeds, it attaches a cookie to the session * and outputs the user id, username, and session token. If a * log-in fails, as the result of a bad password, a nonexistent * user, or any other reason, the host is cached with an expiry * and no log-in attempts will be accepted until that expiry * is reached. The expiry is $this->mLoginThrottle. */ public function execute() { // If we're in a mode that breaks the same-origin policy, no tokens can // be obtained if ($this->lacksSameOriginSecurity()) { $this->getResult()->addValue(null, 'login', ['result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied']); return; } $params = $this->extractRequestParams(); $result = []; // Make sure session is persisted $session = MediaWiki\Session\SessionManager::getGlobalSession(); $session->persist(); // Make sure it's possible to log in if (!$session->canSetUser()) { $this->getResult()->addValue(null, 'login', ['result' => 'Aborted', 'reason' => 'Cannot log in when using ' . $session->getProvider()->describe(Language::factory('en'))]); return; } $authRes = false; $context = new DerivativeContext($this->getContext()); $loginType = 'N/A'; // Check login token $token = $session->getToken('', 'login'); if ($token->wasNew() || !$params['token']) { $authRes = 'NeedToken'; } elseif (!$token->match($params['token'])) { $authRes = 'WrongToken'; } // Try bot passwords if ($authRes === false && $this->getConfig()->get('EnableBotPasswords') && strpos($params['name'], BotPassword::getSeparator()) !== false) { $status = BotPassword::login($params['name'], $params['password'], $this->getRequest()); if ($status->isOK()) { $session = $status->getValue(); $authRes = 'Success'; $loginType = 'BotPassword'; } else { $authRes = 'Failed'; $message = $status->getMessage(); LoggerFactory::getInstance('authmanager')->info('BotPassword login failed: ' . $status->getWikiText(false, false, 'en')); } } if ($authRes === false) { if ($this->getConfig()->get('DisableAuthManager')) { // Non-AuthManager login $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), ['wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => ''])); $loginForm = new LoginForm(); $loginForm->setContext($context); $authRes = $loginForm->authenticateUserData(); $loginType = 'LoginForm'; switch ($authRes) { case LoginForm::SUCCESS: $authRes = 'Success'; break; case LoginForm::NEED_TOKEN: $authRes = 'NeedToken'; break; } } else { // Simplified AuthManager login, for backwards compatibility $manager = AuthManager::singleton(); $reqs = AuthenticationRequest::loadRequestsFromSubmission($manager->getAuthenticationRequests(AuthManager::ACTION_LOGIN, $this->getUser()), ['username' => $params['name'], 'password' => $params['password'], 'domain' => $params['domain'], 'rememberMe' => true]); $res = AuthManager::singleton()->beginAuthentication($reqs, 'null:'); switch ($res->status) { case AuthenticationResponse::PASS: if ($this->getConfig()->get('EnableBotPasswords')) { $warn = 'Main-account login via action=login is deprecated and may stop working ' . 'without warning.'; $warn .= ' To continue login with action=login, see [[Special:BotPasswords]].'; $warn .= ' To safely continue using main-account login, see action=clientlogin.'; } else { $warn = 'Login via action=login is deprecated and may stop working without warning.'; $warn .= ' To safely log in, see action=clientlogin.'; } $this->setWarning($warn); $authRes = 'Success'; $loginType = 'AuthManager'; break; case AuthenticationResponse::FAIL: // Hope it's not a PreAuthenticationProvider that failed... $authRes = 'Failed'; $message = $res->message; \MediaWiki\Logger\LoggerFactory::getInstance('authentication')->info(__METHOD__ . ': Authentication failed: ' . $message->plain()); break; default: $authRes = 'Aborted'; break; } } } $result['result'] = $authRes; switch ($authRes) { case 'Success': if ($this->getConfig()->get('DisableAuthManager')) { $user = $context->getUser(); $this->getContext()->setUser($user); $user->setCookies($this->getRequest(), null, true); } else { $user = $session->getUser(); } ApiQueryInfo::resetTokenCache(); // Deprecated hook $injected_html = ''; Hooks::run('UserLoginComplete', [&$user, &$injected_html]); $result['lguserid'] = intval($user->getId()); $result['lgusername'] = $user->getName(); // @todo: These are deprecated, and should be removed at some // point (1.28 at the earliest, and see T121527). They were ok // when the core cookie-based login was the only thing, but // CentralAuth broke that a while back and // SessionManager/AuthManager *really* break it. $result['lgtoken'] = $user->getToken(); $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = $session->getId(); break; case 'NeedToken': $result['token'] = $token->toString(); $this->setWarning('Fetching a token via action=login is deprecated. ' . 'Use action=query&meta=tokens&type=login instead.'); $this->logFeatureUsage('action=login&!lgtoken'); // @todo: See above about deprecation $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = $session->getId(); break; case 'WrongToken': break; case 'Failed': $result['reason'] = $message->useDatabase('false')->inLanguage('en')->text(); break; case 'Aborted': $result['reason'] = 'Authentication requires user interaction, ' . 'which is not supported by action=login.'; if ($this->getConfig()->get('EnableBotPasswords')) { $result['reason'] .= ' To be able to login with action=login, see [[Special:BotPasswords]].'; $result['reason'] .= ' To continue using main-account login, see action=clientlogin.'; } else { $result['reason'] .= ' To log in, see action=clientlogin.'; } break; // Results from LoginForm for when $wgDisableAuthManager is true // Results from LoginForm for when $wgDisableAuthManager is true case LoginForm::WRONG_TOKEN: $result['result'] = 'WrongToken'; break; case LoginForm::NO_NAME: $result['result'] = 'NoName'; break; case LoginForm::ILLEGAL: $result['result'] = 'Illegal'; break; case LoginForm::WRONG_PLUGIN_PASS: $result['result'] = 'WrongPluginPass'; break; case LoginForm::NOT_EXISTS: $result['result'] = 'NotExists'; break; // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. case LoginForm::RESET_PASS: case LoginForm::WRONG_PASS: $result['result'] = 'WrongPass'; break; case LoginForm::EMPTY_PASS: $result['result'] = 'EmptyPass'; break; case LoginForm::CREATE_BLOCKED: $result['result'] = 'CreateBlocked'; $result['details'] = 'Your IP address is blocked from account creation'; $block = $context->getUser()->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::THROTTLED: $result['result'] = 'Throttled'; $result['wait'] = intval($loginForm->mThrottleWait); break; case LoginForm::USER_BLOCKED: $result['result'] = 'Blocked'; $block = User::newFromName($params['name'])->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::ABORTED: $result['result'] = 'Aborted'; $result['reason'] = $loginForm->mAbortLoginErrorMsg; break; default: ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}"); } $this->getResult()->addValue(null, 'login', $result); if ($loginType === 'LoginForm' && isset(LoginForm::$statusCodes[$authRes])) { $authRes = LoginForm::$statusCodes[$authRes]; } LoggerFactory::getInstance('authmanager')->info('Login attempt', ['event' => 'login', 'successful' => $authRes === 'Success', 'loginType' => $loginType, 'status' => $authRes]); }