/** * Internally authenticate the login request. * * This may create a local account as a side effect if the * authentication plugin allows transparent local account * creation. * * @public */ function authenticateUserData() { global $wgUser, $wgAuth; if ('' == $this->mName) { return self::NO_NAME; } // XXCHANGED - by Reuben to allow login via Username or Email $u = null; // Check if $this->mName is actually an email address $looksLikeEmail = strpos($this->mName, '@') !== false; if ($looksLikeEmail) { list($u, $count) = WikihowUser::newFromEmailAddress($this->mName); } // Only do the username lookup if it didn't look like an email address // or the email addresses didn't have exactly 1 account attached if (is_null($u)) { $u = User::newFromName($this->mName); // Show error specific to email addresses if there's no username // with an '@' in it either if ($looksLikeEmail) { if ($count < 1) { return self::NO_EMAIL; } elseif ($count > 1) { return self::MULTIPLE_EMAILS; } } if (is_null($u) || !User::isUsableName($u->getName())) { return self::ILLEGAL; } } if (0 == $u->getID()) { global $wgAuth; /** * If the external authentication plugin allows it, * automatically create a new account for users that * are externally defined but have not yet logged in. */ if ($wgAuth->autoCreate() && $wgAuth->userExists($u->getName())) { if ($wgAuth->authenticate($u->getName(), $this->mPassword)) { $u = $this->initUser($u, true); } else { return self::WRONG_PLUGIN_PASS; } } else { return self::NOT_EXISTS; } } else { $u->load(); } // Give general extensions, such as a captcha, a chance to abort logins $abort = self::ABORTED; if (!wfRunHooks('AbortLogin', array($u, $this->mPassword, &$abort))) { return $abort; } if (!$u->checkPassword($this->mPassword)) { if ($u->checkTemporaryPassword($this->mPassword)) { // The e-mailed temporary password should not be used // for actual logins; that's a very sloppy habit, // and insecure if an attacker has a few seconds to // click "search" on someone's open mail reader. // // Allow it to be used only to reset the password // a single time to a new value, which won't be in // the user's e-mail archives. // // For backwards compatibility, we'll still recognize // it at the login form to minimize surprises for // people who have been logging in with a temporary // password for some time. // // As a side-effect, we can authenticate the user's // e-mail address if it's not already done, since // the temporary password was sent via e-mail. // if (!$u->isEmailConfirmed()) { $u->confirmEmail(); } // At this point we just return an appropriate code // indicating that the UI should show a password // reset form; bot interfaces etc will probably just // fail cleanly here. // $retval = self::RESET_PASS; } else { $retval = '' == $this->mPassword ? self::EMPTY_PASS : self::WRONG_PASS; } } else { $wgAuth->updateUser($u); $wgUser = $u; $retval = self::SUCCESS; } wfRunHooks('LoginAuthenticateAudit', array($u, $this->mPassword, $retval)); return $retval; }
/** * @throws PasswordError when cannot set the new password because requirements not met. */ function attemptReset($newpass, $retype) { $looksLikeEmail = strpos($this->mName, '@') !== false; if ($looksLikeEmail) { list($user, $count) = WikihowUser::newFromEmailAddress($this->mName); } else { $user = User::newFromName($this->mName); } if ($user->isAnon()) { throw new PasswordError('no such user'); } if (!$user->checkTemporaryPassword($this->mTemporaryPassword)) { throw new PasswordError(wfMsg('resetpass_bad_temporary')); } if ($newpass !== $retype) { throw new PasswordError(wfMsg('badretype')); } $user->setPassword($newpass); $user->saveSettings(); }
/** * Internally authenticate the login request. * * This may create a local account as a side effect if the * authentication plugin allows transparent local account * creation. * @return int */ public function authenticateUserData() { global $wgUser, $wgAuth; $this->load(); if ($this->mUsername == '') { return self::NO_NAME; } // We require a login token to prevent login CSRF // Handle part of this before incrementing the throttle so // token-less login attempts don't count towards the throttle // but wrong-token attempts do. // Upgrade hack by Gershon Bialer // Removed token verification to get static header login working // XXXXX // If the user doesn't have a login token yet, set one. /*if ( !self::getLoginToken() ) { self::setLoginToken(); return self::NEED_TOKEN; } // If the user didn't pass a login token, tell them we need one if ( !$this->mToken ) { return self::NEED_TOKEN; }*/ $throttleCount = self::incLoginThrottle($this->mUsername); if ($throttleCount === true) { return self::THROTTLED; } // Upgrade hack by Gershon Bialer // Removed token verification to get static header login working // XXXXX // Validate the login token //if ( $this->mToken !== self::getLoginToken() ) { // return self::WRONG_TOKEN; //} // Load the current user now, and check to see if we're logging in as // the same name. This is necessary because loading the current user // (say by calling getName()) calls the UserLoadFromSession hook, which // potentially creates the user in the database. Until we load $wgUser, // checking for user existence using User::newFromName($name)->getId() below // will effectively be using stale data. if ($this->getUser()->getName() === $this->mUsername) { wfDebug(__METHOD__ . ": already logged in as {$this->mUsername}\n"); return self::SUCCESS; } //XXCHANGEDXX - added our login by email logic back [sc] // Check if $this->mName is actually an email address $u = null; $looksLikeEmail = strpos($this->mUsername, '@') !== false; if ($looksLikeEmail) { list($u, $count) = WikihowUser::newFromEmailAddress($this->mUsername); } // Only do the username lookup if it didn't look like an email address // or the email addresses didn't have exactly 1 account attached if (is_null($u)) { $u = User::newFromName($this->mUsername); // Show error specific to email addresses if there's no username // with an '@' in it either if ($looksLikeEmail) { if ($count < 1) { return self::NO_EMAIL; } elseif ($count > 1) { return self::MULTIPLE_EMAILS; } } $u = User::newFromName($this->mUsername); if (!$u instanceof User || !User::isUsableName($u->getName())) { return self::ILLEGAL; } } $isAutoCreated = false; if ($u->getID() == 0) { $status = $this->attemptAutoCreate($u); if ($status !== self::SUCCESS) { return $status; } else { $isAutoCreated = true; } } else { $u->load(); } // Give general extensions, such as a captcha, a chance to abort logins $abort = self::ABORTED; $msg = null; if (!wfRunHooks('AbortLogin', array($u, $this->mPassword, &$abort, &$msg))) { $this->mAbortLoginErrorMsg = $msg; return $abort; } global $wgBlockDisablesLogin; if (!$u->checkPassword($this->mPassword)) { if ($u->checkTemporaryPassword($this->mPassword)) { // The e-mailed temporary password should not be used for actu- // al logins; that's a very sloppy habit, and insecure if an // attacker has a few seconds to click "search" on someone's o- // pen mail reader. // // Allow it to be used only to reset the password a single time // to a new value, which won't be in the user's e-mail ar- // chives. // // For backwards compatibility, we'll still recognize it at the // login form to minimize surprises for people who have been // logging in with a temporary password for some time. // // As a side-effect, we can authenticate the user's e-mail ad- // dress if it's not already done, since the temporary password // was sent via e-mail. if (!$u->isEmailConfirmed()) { $u->confirmEmail(); $u->saveSettings(); } // At this point we just return an appropriate code/ indicating // that the UI should show a password reset form; bot inter- // faces etc will probably just fail cleanly here. $retval = self::RESET_PASS; } else { $retval = $this->mPassword == '' ? self::EMPTY_PASS : self::WRONG_PASS; } } elseif ($wgBlockDisablesLogin && $u->isBlocked()) { // If we've enabled it, make it so that a blocked user cannot login $retval = self::USER_BLOCKED; } else { $wgAuth->updateUser($u); $wgUser = $u; // This should set it for OutputPage and the Skin // which is needed or the personal links will be // wrong. $this->getContext()->setUser($u); // Please reset throttle for successful logins, thanks! if ($throttleCount) { self::clearLoginThrottle($this->mUsername); } if ($isAutoCreated) { // Must be run after $wgUser is set, for correct new user log wfRunHooks('AuthPluginAutoCreate', array($u)); } $retval = self::SUCCESS; } wfRunHooks('LoginAuthenticateAudit', array($u, $this->mPassword, $retval)); return $retval; }
function mailPassword() { global $wgUser, $wgOut, $wgAuth, $wgRequest; $result = array(); if (!$wgAuth->allowPasswordChange()) { $result['error_general'] = wfMsg('resetpass_forbidden'); return $result; } # Check against blocked IPs # fixme -- should we not? if ($wgUser->isBlocked()) { $result['error_general'] = wfMsg('blocked-mailpassword'); return $result; } # Check against the rate limiter if ($wgUser->pingLimiter('mailpassword')) { // Commented out By Gershon Bialer on 12/9/2013 // because they prevented error from showing in the upgrade //$wgOut->disable(); //$wgOut->rateLimited(); $result['error_general'] = "<h4>" . wfMsg('actionthrottled') . "</h4>"; $result['error_general'] .= wfMsg('actionthrottledtext'); return $result; } $name = $wgRequest->getVal('name'); if (!isset($name) || '' == $name) { $result['error_username'] = wfMsg('noname'); return $result; } $name = trim($name); $u = null; // If $name looks like an email address, we look it up by email // address first $looksLikeEmail = strpos($name, '@') !== false; if ($looksLikeEmail) { list($u, $count) = WikihowUser::newFromEmailAddress($name); } if (is_null($u)) { $u = User::newFromName($name); // Show error specific to email addresses if there's no username // with an '@' in it either if ($looksLikeEmail) { if ($count < 1) { $result['error_username'] = wfMsg('noemail_login'); return $result; } elseif ($count > 1) { $result['error_username'] = wfMsg('multipleemails_login'); return $result; } } } if (is_null($u)) { $result['error_username'] = wfMsg('noname'); return $result; } if (0 == $u->getID()) { $result['error_username'] = wfMsg('nosuchuser', $u->getName()); return $result; } $abortError = ''; if (!wfRunHooks('AbortAccountReminder', array($u, &$abortError))) { // Hook point to add extra creation throttles and blocks wfDebug("LoginForm::addNewAccountInternal: a hook blocked creation\n"); $result['error_captcha'] = $abortError; //had a problem with the captcha, need to load a new one $template = new QuickTemplateWrapper(); $template->set('header', ''); wfRunHooks('AccountReminderNewCaptcha', array(&$template)); //hack since templates ECHO the data you want ob_start(); $template->html('header'); $var = ob_get_contents(); ob_end_clean(); //end hack $result['newCaptcha'] = $var; return $result; } # Check against password throttle if ($u->isPasswordReminderThrottled()) { global $wgPasswordReminderResendTime; # Round the time in hours to 3 d.p., in case someone is specifying minutes or seconds. $result['error_general'] = wfMsg('throttled-mailpassword', round($wgPasswordReminderResendTime, 3)); return $result; } $mailResult = $this->mailPasswordInternal($u, true, 'passwordremindertitle', 'passwordremindertext'); if (WikiError::isError($mailResult)) { $result['error_general'] = wfMsg('mailerror', $mailResult->getMessage()); return $result; } else { $result['success'] = wfMsgHtml('passwordsent', $u->getName()); return $result; } }