Пример #1
0
 /**
  * @dataProvider providePasswordTests
  * @covers InvalidPassword::equals
  * @covers InvalidPassword::toString
  */
 public function testInvalidUnequalNormal($shouldMatch, $hash, $password)
 {
     $invalid = $this->passwordFactory->newFromCiphertext(null);
     $normal = $this->passwordFactory->newFromCiphertext($hash);
     $this->assertFalse($invalid->equals($normal));
     $this->assertFalse($normal->equals($invalid));
 }
 public function addDBDataOnce()
 {
     $passwordFactory = new \PasswordFactory();
     $passwordFactory->init(\RequestContext::getMain()->getConfig());
     $passwordHash = $passwordFactory->newFromPlaintext('foobaz');
     $sysop = static::getTestSysop()->getUser();
     $userId = \CentralIdLookup::factory('local')->centralIdFromName($sysop->getName());
     $dbw = wfGetDB(DB_MASTER);
     $dbw->delete('bot_passwords', ['bp_user' => $userId, 'bp_app_id' => 'BotPasswordSessionProvider'], __METHOD__);
     $dbw->insert('bot_passwords', ['bp_user' => $userId, 'bp_app_id' => 'BotPasswordSessionProvider', 'bp_password' => $passwordHash->toString(), 'bp_token' => 'token!', 'bp_restrictions' => '{"IPAddresses":["127.0.0.0/8"]}', 'bp_grants' => '["test"]'], __METHOD__);
 }
 public function addDBData()
 {
     $passwordFactory = new \PasswordFactory();
     $passwordFactory->init(\RequestContext::getMain()->getConfig());
     // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
     $passwordFactory->setDefaultType('A');
     $pwhash = $passwordFactory->newFromPlaintext('foobaz');
     $userId = \CentralIdLookup::factory('local')->centralIdFromName('UTSysop');
     $dbw = wfGetDB(DB_MASTER);
     $dbw->delete('bot_passwords', array('bp_user' => $userId, 'bp_app_id' => 'BotPasswordSessionProvider'), __METHOD__);
     $dbw->insert('bot_passwords', array('bp_user' => $userId, 'bp_app_id' => 'BotPasswordSessionProvider', 'bp_password' => $pwhash->toString(), 'bp_token' => 'token!', 'bp_restrictions' => '{"IPAddresses":["127.0.0.0/8"]}', 'bp_grants' => '["test"]'), __METHOD__);
 }
 public function testTestUserCanAuthenticate()
 {
     $user = $this->getMutableTestUser()->getUser();
     $userName = $user->getName();
     $dbw = wfGetDB(DB_MASTER);
     $provider = $this->getProvider();
     $this->assertFalse($provider->testUserCanAuthenticate('<invalid>'));
     $this->assertFalse($provider->testUserCanAuthenticate('DoesNotExist'));
     $this->assertTrue($provider->testUserCanAuthenticate($userName));
     $lowerInitialUserName = mb_strtolower($userName[0]) . substr($userName, 1);
     $this->assertTrue($provider->testUserCanAuthenticate($lowerInitialUserName));
     $dbw->update('user', ['user_password' => \PasswordFactory::newInvalidPassword()->toString()], ['user_name' => $userName]);
     $this->assertFalse($provider->testUserCanAuthenticate($userName));
     // Really old format
     $dbw->update('user', ['user_password' => '0123456789abcdef0123456789abcdef'], ['user_name' => $userName]);
     $this->assertTrue($provider->testUserCanAuthenticate($userName));
 }
 /**
  * Return an instance with a new, random password
  * @return TemporaryPasswordAuthenticationRequest
  */
 public static function newRandom()
 {
     $config = \ConfigFactory::getDefaultInstance()->makeConfig('main');
     // get the min password length
     $minLength = $config->get('MinimalPasswordLength');
     $policy = $config->get('PasswordPolicy');
     foreach ($policy['policies'] as $p) {
         if (isset($p['MinimalPasswordLength'])) {
             $minLength = max($minLength, $p['MinimalPasswordLength']);
         }
         if (isset($p['MinimalPasswordLengthToLogin'])) {
             $minLength = max($minLength, $p['MinimalPasswordLengthToLogin']);
         }
     }
     $password = \PasswordFactory::generateRandomPasswordString($minLength);
     return new self($password);
 }
Пример #6
0
 public function execute()
 {
     global $wgAuth;
     if (!$wgAuth->allowSetLocalPassword()) {
         $this->error('$wgAuth does not allow local passwords. Aborting.', true);
     }
     $passwordFactory = new PasswordFactory();
     $passwordFactory->init(RequestContext::getMain()->getConfig());
     $typeInfo = $passwordFactory->getTypes();
     $layeredType = $this->getOption('type');
     // Check that type exists and is a layered type
     if (!isset($typeInfo[$layeredType])) {
         $this->error('Undefined password type', true);
     }
     $passObj = $passwordFactory->newFromType($layeredType);
     if (!$passObj instanceof LayeredParameterizedPassword) {
         $this->error('Layered parameterized password type must be used.', true);
     }
     // Extract the first layer type
     $typeConfig = $typeInfo[$layeredType];
     $firstType = $typeConfig['types'][0];
     // Get a list of password types that are applicable
     $dbw = $this->getDB(DB_MASTER);
     $typeCond = 'user_password' . $dbw->buildLike(":{$firstType}:", $dbw->anyString());
     $minUserId = 0;
     do {
         $dbw->begin();
         $res = $dbw->select('user', array('user_id', 'user_name', 'user_password'), array('user_id > ' . $dbw->addQuotes($minUserId), $typeCond), __METHOD__, array('ORDER BY' => 'user_id', 'LIMIT' => $this->mBatchSize, 'LOCK IN SHARE MODE'));
         /** @var User[] $updateUsers */
         $updateUsers = array();
         foreach ($res as $row) {
             if ($this->hasOption('verbose')) {
                 $this->output("Updating password for user {$row->user_name} ({$row->user_id}).\n");
             }
             $user = User::newFromId($row->user_id);
             /** @var ParameterizedPassword $password */
             $password = $passwordFactory->newFromCiphertext($row->user_password);
             /** @var LayeredParameterizedPassword $layeredPassword */
             $layeredPassword = $passwordFactory->newFromType($layeredType);
             $layeredPassword->partialCrypt($password);
             $updateUsers[] = $user;
             $dbw->update('user', array('user_password' => $layeredPassword->toString()), array('user_id' => $row->user_id), __METHOD__);
             $minUserId = $row->user_id;
         }
         $dbw->commit();
         // Clear memcached so old passwords are wiped out
         foreach ($updateUsers as $user) {
             $user->clearSharedCache();
         }
     } while ($res->numRows());
 }
Пример #7
0
 public function execute()
 {
     $userName = $this->getArg(0);
     if (preg_match('/^#\\d+$/', $userName)) {
         $user = User::newFromId(substr($userName, 1));
     } else {
         $user = User::newFromName($userName);
     }
     if (!$user || !$user->getId() || !$user->loadFromId()) {
         $this->error("Error: user '{$userName}' does not exist\n", 1);
     }
     $email = $this->getArg(1);
     if (!Sanitizer::validateEmail($email)) {
         $this->error("Error: email '{$email}' is not valid\n", 1);
     }
     // Code from https://wikitech.wikimedia.org/wiki/Password_reset
     $user->setEmail($email);
     $user->setEmailAuthenticationTimestamp(wfTimestampNow());
     $user->saveSettings();
     // Kick whomever is currently controlling the account off
     $user->setPassword(PasswordFactory::generateRandomPasswordString(128));
 }
 /**
  * Test the account creation API with a valid request. Also
  * make sure the new account can log in and is valid.
  *
  * This test does multiple API requests so it might end up being
  * a bit slow. Raise the default timeout.
  * @group medium
  */
 public function testValid()
 {
     global $wgServer;
     if (!isset($wgServer)) {
         $this->markTestIncomplete('This test needs $wgServer to be set in LocalSettings.php');
     }
     $password = PasswordFactory::generateRandomPasswordString();
     $ret = $this->doApiRequest(array('action' => 'createaccount', 'name' => 'Apitestnew', 'password' => $password, 'email' => '*****@*****.**', 'realname' => 'Test Name'));
     $result = $ret[0];
     $this->assertNotInternalType('bool', $result);
     $this->assertNotInternalType('null', $result['createaccount']);
     // Should first ask for token.
     $a = $result['createaccount'];
     $this->assertEquals('NeedToken', $a['result']);
     $token = $a['token'];
     // Finally create the account
     $ret = $this->doApiRequest(array('action' => 'createaccount', 'name' => 'Apitestnew', 'password' => $password, 'token' => $token, 'email' => '*****@*****.**', 'realname' => 'Test Name'), $ret[2]);
     $result = $ret[0];
     $this->assertNotInternalType('bool', $result);
     $this->assertEquals('Success', $result['createaccount']['result']);
     // Try logging in with the new user.
     $ret = $this->doApiRequest(array('action' => 'login', 'lgname' => 'Apitestnew', 'lgpassword' => $password));
     $result = $ret[0];
     $this->assertNotInternalType('bool', $result);
     $this->assertNotInternalType('null', $result['login']);
     $a = $result['login']['result'];
     $this->assertEquals('NeedToken', $a);
     $token = $result['login']['token'];
     $ret = $this->doApiRequest(array('action' => 'login', 'lgtoken' => $token, 'lgname' => 'Apitestnew', 'lgpassword' => $password), $ret[2]);
     $result = $ret[0];
     $this->assertNotInternalType('bool', $result);
     $a = $result['login']['result'];
     $this->assertEquals('Success', $a);
     // log out to destroy the session
     $ret = $this->doApiRequest(array('action' => 'logout'), $ret[2]);
     $this->assertEquals(array(), $ret[0]);
 }
Пример #9
0
 public function testBotPassword()
 {
     global $wgServer, $wgSessionProviders;
     if (!isset($wgServer)) {
         $this->markTestIncomplete('This test needs $wgServer to be set in LocalSettings.php');
     }
     $this->setMwGlobals(array('wgSessionProviders' => array_merge($wgSessionProviders, array(array('class' => 'MediaWiki\\Session\\BotPasswordSessionProvider', 'args' => array(array('priority' => 40))))), 'wgEnableBotPasswords' => true, 'wgBotPasswordsDatabase' => false, 'wgCentralIdLookupProvider' => 'local', 'wgGrantPermissions' => array('test' => array('read' => true))));
     // Make sure our session provider is present
     $manager = TestingAccessWrapper::newFromObject(MediaWiki\Session\SessionManager::singleton());
     if (!isset($manager->sessionProviders['MediaWiki\\Session\\BotPasswordSessionProvider'])) {
         $tmp = $manager->sessionProviders;
         $manager->sessionProviders = null;
         $manager->sessionProviders = $tmp + $manager->getProviders();
     }
     $this->assertNotNull(MediaWiki\Session\SessionManager::singleton()->getProvider('MediaWiki\\Session\\BotPasswordSessionProvider'), 'sanity check');
     $user = self::$users['sysop'];
     $centralId = CentralIdLookup::factory()->centralIdFromLocalUser($user->getUser());
     $this->assertNotEquals(0, $centralId, 'sanity check');
     $passwordFactory = new PasswordFactory();
     $passwordFactory->init(RequestContext::getMain()->getConfig());
     // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
     $passwordFactory->setDefaultType('A');
     $pwhash = $passwordFactory->newFromPlaintext('foobaz');
     $dbw = wfGetDB(DB_MASTER);
     $dbw->insert('bot_passwords', array('bp_user' => $centralId, 'bp_app_id' => 'foo', 'bp_password' => $pwhash->toString(), 'bp_token' => '', 'bp_restrictions' => MWRestrictions::newDefault()->toJson(), 'bp_grants' => '["test"]'), __METHOD__);
     $lgName = $user->username . BotPassword::getSeparator() . 'foo';
     $ret = $this->doApiRequest(array('action' => 'login', 'lgname' => $lgName, 'lgpassword' => 'foobaz'));
     $result = $ret[0];
     $this->assertNotInternalType('bool', $result);
     $this->assertNotInternalType('null', $result['login']);
     $a = $result['login']['result'];
     $this->assertEquals('NeedToken', $a);
     $token = $result['login']['token'];
     $ret = $this->doApiRequest(array('action' => 'login', 'lgtoken' => $token, 'lgname' => $lgName, 'lgpassword' => 'foobaz'), $ret[2]);
     $result = $ret[0];
     $this->assertNotInternalType('bool', $result);
     $a = $result['login']['result'];
     $this->assertEquals('Success', $a);
 }
Пример #10
0
 private function save(array $data)
 {
     $bp = BotPassword::newUnsaved(['centralId' => $this->userId, 'appId' => $this->par, 'restrictions' => MWRestrictions::newFromJson($data['restrictions']), 'grants' => array_merge(MWGrants::getHiddenGrants(), preg_replace('/^grant-/', '', $data['grants']))]);
     if ($this->operation === 'insert' || !empty($data['resetPassword'])) {
         $this->password = PasswordFactory::generateRandomPasswordString(max(32, $this->getConfig()->get('MinimalPasswordLength')));
         $passwordFactory = new PasswordFactory();
         $passwordFactory->init(RequestContext::getMain()->getConfig());
         $password = $passwordFactory->newFromPlaintext($this->password);
     } else {
         $password = null;
     }
     if ($bp->save($this->operation, $password)) {
         return Status::newGood();
     } else {
         // Messages: botpasswords-insert-failed, botpasswords-update-failed
         return Status::newFatal("botpasswords-{$this->operation}-failed", $this->par);
     }
 }
Пример #11
0
 /**
  * Invalidate all passwords for a user, by central ID
  * @param int $centralId
  * @return bool Whether any passwords were invalidated
  */
 public static function invalidateAllPasswordsForCentralId($centralId)
 {
     global $wgEnableBotPasswords;
     if (!$wgEnableBotPasswords) {
         return false;
     }
     $dbw = self::getDB(DB_MASTER);
     $dbw->update('bot_passwords', array('bp_password' => PasswordFactory::newInvalidPassword()->toString()), array('bp_user' => $centralId), __METHOD__);
     return (bool) $dbw->affectedRows();
 }
Пример #12
0
 /**
  * Set the password on a testing user
  *
  * This assumes we're still using the generic AuthManager config from
  * PHPUnitMaintClass::finalSetup(), and just sets the password in the
  * database directly.
  * @param User $user
  * @param string $password
  */
 public static function setPasswordForUser(User $user, $password)
 {
     if (!$user->getId()) {
         throw new MWException("Passed User has not been added to the database yet!");
     }
     $dbw = wfGetDB(DB_MASTER);
     $row = $dbw->selectRow('user', ['user_password'], ['user_id' => $user->getId()], __METHOD__);
     if (!$row) {
         throw new MWException("Passed User has an ID but is not in the database?");
     }
     $passwordFactory = new PasswordFactory();
     $passwordFactory->init(RequestContext::getMain()->getConfig());
     if (!$passwordFactory->newFromCiphertext($row->user_password)->equals($password)) {
         $passwordHash = $passwordFactory->newFromPlaintext($password);
         $dbw->update('user', ['user_password' => $passwordHash->toString()], ['user_id' => $user->getId()], __METHOD__);
     }
 }
 public function testTestUserCanAuthenticate()
 {
     $dbw = wfGetDB(DB_MASTER);
     $passwordFactory = new \PasswordFactory();
     $passwordFactory->init(\RequestContext::getMain()->getConfig());
     // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
     $passwordFactory->setDefaultType('A');
     $pwhash = $passwordFactory->newFromPlaintext('password')->toString();
     $provider = $this->getProvider();
     $providerPriv = \TestingAccessWrapper::newFromObject($provider);
     $this->assertFalse($provider->testUserCanAuthenticate('<invalid>'));
     $this->assertFalse($provider->testUserCanAuthenticate('DoesNotExist'));
     $dbw->update('user', ['user_newpassword' => \PasswordFactory::newInvalidPassword()->toString(), 'user_newpass_time' => null], ['user_name' => 'UTSysop']);
     $this->assertFalse($provider->testUserCanAuthenticate('UTSysop'));
     $dbw->update('user', ['user_newpassword' => $pwhash, 'user_newpass_time' => null], ['user_name' => 'UTSysop']);
     $this->assertTrue($provider->testUserCanAuthenticate('UTSysop'));
     $this->assertTrue($provider->testUserCanAuthenticate('uTSysop'));
     $dbw->update('user', ['user_newpassword' => $pwhash, 'user_newpass_time' => $dbw->timestamp(time() - 10)], ['user_name' => 'UTSysop']);
     $providerPriv->newPasswordExpiry = 100;
     $this->assertTrue($provider->testUserCanAuthenticate('UTSysop'));
     $providerPriv->newPasswordExpiry = 1;
     $this->assertFalse($provider->testUserCanAuthenticate('UTSysop'));
     $dbw->update('user', ['user_newpassword' => \PasswordFactory::newInvalidPassword()->toString(), 'user_newpass_time' => null], ['user_name' => 'UTSysop']);
 }
Пример #14
0
 /**
  * Returns a (raw, unhashed) random password string.
  * @param Config $config
  * @return string
  */
 public static function generatePassword($config)
 {
     return PasswordFactory::generateRandomPasswordString(max(32, $config->get('MinimalPasswordLength')));
 }
Пример #15
0
 /**
  * @dataProvider provideSave
  * @param string|null $password
  */
 public function testSave($password)
 {
     $passwordFactory = new \PasswordFactory();
     $passwordFactory->init(\RequestContext::getMain()->getConfig());
     $bp = BotPassword::newUnsaved(['centralId' => 42, 'appId' => 'TestSave', 'restrictions' => MWRestrictions::newFromJson('{"IPAddresses":["127.0.0.0/8"]}'), 'grants' => ['test']]);
     $this->assertFalse($bp->isSaved(), 'sanity check');
     $this->assertNull(BotPassword::newFromCentralId(42, 'TestSave', BotPassword::READ_LATEST), 'sanity check');
     $passwordHash = $password ? $passwordFactory->newFromPlaintext($password) : null;
     $this->assertFalse($bp->save('update', $passwordHash));
     $this->assertTrue($bp->save('insert', $passwordHash));
     $bp2 = BotPassword::newFromCentralId(42, 'TestSave', BotPassword::READ_LATEST);
     $this->assertInstanceOf('BotPassword', $bp2);
     $this->assertEquals($bp->getUserCentralId(), $bp2->getUserCentralId());
     $this->assertEquals($bp->getAppId(), $bp2->getAppId());
     $this->assertEquals($bp->getToken(), $bp2->getToken());
     $this->assertEquals($bp->getRestrictions(), $bp2->getRestrictions());
     $this->assertEquals($bp->getGrants(), $bp2->getGrants());
     $pw = TestingAccessWrapper::newFromObject($bp)->getPassword();
     if ($password === null) {
         $this->assertInstanceOf('InvalidPassword', $pw);
     } else {
         $this->assertTrue($pw->equals($password));
     }
     $token = $bp->getToken();
     $this->assertFalse($bp->save('insert'));
     $this->assertTrue($bp->save('update'));
     $this->assertNotEquals($token, $bp->getToken());
     $bp2 = BotPassword::newFromCentralId(42, 'TestSave', BotPassword::READ_LATEST);
     $this->assertInstanceOf('BotPassword', $bp2);
     $this->assertEquals($bp->getToken(), $bp2->getToken());
     $pw = TestingAccessWrapper::newFromObject($bp)->getPassword();
     if ($password === null) {
         $this->assertInstanceOf('InvalidPassword', $pw);
     } else {
         $this->assertTrue($pw->equals($password));
     }
     $passwordHash = $passwordFactory->newFromPlaintext('XXX');
     $token = $bp->getToken();
     $this->assertTrue($bp->save('update', $passwordHash));
     $this->assertNotEquals($token, $bp->getToken());
     $pw = TestingAccessWrapper::newFromObject($bp)->getPassword();
     $this->assertTrue($pw->equals('XXX'));
     $this->assertTrue($bp->delete());
     $this->assertFalse($bp->isSaved());
     $this->assertNull(BotPassword::newFromCentralId(42, 'TestSave', BotPassword::READ_LATEST));
     $this->assertFalse($bp->save('foobar'));
 }
Пример #16
0
 /**
  * @param User $u
  * @param bool $throttle
  * @param string $emailTitle Message name of email title
  * @param string $emailText Message name of email text
  * @return Status
  */
 function mailPasswordInternal($u, $throttle = true, $emailTitle = 'passwordremindertitle', $emailText = 'passwordremindertext')
 {
     global $wgNewPasswordExpiry, $wgMinimalPasswordLength;
     if ($u->getEmail() == '') {
         return Status::newFatal('noemail', $u->getName());
     }
     $ip = $this->getRequest()->getIP();
     if (!$ip) {
         return Status::newFatal('badipaddress');
     }
     $currentUser = $this->getUser();
     Hooks::run('User::mailPasswordInternal', [&$currentUser, &$ip, &$u]);
     $np = PasswordFactory::generateRandomPasswordString($wgMinimalPasswordLength);
     $u->setNewpassword($np, $throttle);
     $u->saveSettings();
     $userLanguage = $u->getOption('language');
     $mainPage = Title::newMainPage();
     $mainPageUrl = $mainPage->getCanonicalURL();
     $m = $this->msg($emailText, $ip, $u->getName(), $np, '<' . $mainPageUrl . '>', round($wgNewPasswordExpiry / 86400))->inLanguage($userLanguage)->text();
     $result = $u->sendMail($this->msg($emailTitle)->inLanguage($userLanguage)->text(), $m);
     return $result;
 }
Пример #17
0
 /**
  * Set the password on a testing user
  *
  * This assumes we're still using the generic AuthManager config from
  * PHPUnitMaintClass::finalSetup(), and just sets the password in the
  * database directly.
  * @param User $user
  * @param string $password
  */
 public static function setPasswordForUser(User $user, $password)
 {
     if (!$user->getId()) {
         throw new MWException("Passed User has not been added to the database yet!");
     }
     $passwordFactory = new PasswordFactory();
     $passwordFactory->init(RequestContext::getMain()->getConfig());
     // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
     $passwordFactory->setDefaultType('A');
     $pwhash = $passwordFactory->newFromPlaintext($password);
     wfGetDB(DB_MASTER)->update('user', array('user_password' => $pwhash->toString()), array('user_id' => $user->getId()), __METHOD__);
 }
Пример #18
0
 /**
  * Process the form.  At this point we know that the user passes all the criteria in
  * userCanExecute(), and if the data array contains 'Username', etc, then Username
  * resets are allowed.
  * @param array $data
  * @throws MWException
  * @throws ThrottledError|PermissionsError
  * @return bool|array
  */
 public function onSubmit(array $data)
 {
     global $wgAuth, $wgMinimalPasswordLength;
     if (isset($data['Domain'])) {
         if ($wgAuth->validDomain($data['Domain'])) {
             $wgAuth->setDomain($data['Domain']);
         } else {
             $wgAuth->setDomain('invaliddomain');
         }
     }
     if (isset($data['Capture']) && !$this->getUser()->isAllowed('passwordreset')) {
         // The user knows they don't have the passwordreset permission,
         // but they tried to spoof the form. That's naughty
         throw new PermissionsError('passwordreset');
     }
     /**
      * @var $firstUser User
      * @var $users User[]
      */
     if (isset($data['Username']) && $data['Username'] !== '') {
         $method = 'username';
         $users = [User::newFromName($data['Username'])];
     } elseif (isset($data['Email']) && $data['Email'] !== '' && Sanitizer::validateEmail($data['Email'])) {
         $method = 'email';
         $res = wfGetDB(DB_SLAVE)->select('user', User::selectFields(), ['user_email' => $data['Email']], __METHOD__);
         if ($res) {
             $users = [];
             foreach ($res as $row) {
                 $users[] = User::newFromRow($row);
             }
         } else {
             // Some sort of database error, probably unreachable
             throw new MWException('Unknown database error in ' . __METHOD__);
         }
     } else {
         // The user didn't supply any data
         return false;
     }
     // Check for hooks (captcha etc), and allow them to modify the users list
     $error = [];
     if (!Hooks::run('SpecialPasswordResetOnSubmit', [&$users, $data, &$error])) {
         return [$error];
     }
     $this->method = $method;
     if (count($users) == 0) {
         if ($method == 'email') {
             // Don't reveal whether or not an email address is in use
             return true;
         } else {
             return ['noname'];
         }
     }
     $firstUser = $users[0];
     if (!$firstUser instanceof User || !$firstUser->getId()) {
         // Don't parse username as wikitext (bug 65501)
         return [['nosuchuser', wfEscapeWikiText($data['Username'])]];
     }
     // Check against the rate limiter
     if ($this->getUser()->pingLimiter('mailpassword')) {
         throw new ThrottledError();
     }
     // Check against password throttle
     foreach ($users as $user) {
         if ($user->isPasswordReminderThrottled()) {
             # Round the time in hours to 3 d.p., in case someone is specifying
             # minutes or seconds.
             return [['throttled-mailpassword', round($this->getConfig()->get('PasswordReminderResendTime'), 3)]];
         }
     }
     // All the users will have the same email address
     if ($firstUser->getEmail() == '') {
         // This won't be reachable from the email route, so safe to expose the username
         return [['noemail', wfEscapeWikiText($firstUser->getName())]];
     }
     // We need to have a valid IP address for the hook, but per bug 18347, we should
     // send the user's name if they're logged in.
     $ip = $this->getRequest()->getIP();
     if (!$ip) {
         return ['badipaddress'];
     }
     $caller = $this->getUser();
     Hooks::run('User::mailPasswordInternal', [&$caller, &$ip, &$firstUser]);
     $username = $caller->getName();
     $msg = IP::isValid($username) ? 'passwordreset-emailtext-ip' : 'passwordreset-emailtext-user';
     // Send in the user's language; which should hopefully be the same
     $userLanguage = $firstUser->getOption('language');
     $passwords = [];
     foreach ($users as $user) {
         $password = PasswordFactory::generateRandomPasswordString($wgMinimalPasswordLength);
         $user->setNewpassword($password);
         $user->saveSettings();
         $passwords[] = $this->msg('passwordreset-emailelement', $user->getName(), $password)->inLanguage($userLanguage)->text();
         // We'll escape the whole thing later
     }
     $passwordBlock = implode("\n\n", $passwords);
     $this->email = $this->msg($msg)->inLanguage($userLanguage);
     $this->email->params($username, $passwordBlock, count($passwords), '<' . Title::newMainPage()->getCanonicalURL() . '>', round($this->getConfig()->get('NewPasswordExpiry') / 86400));
     $title = $this->msg('passwordreset-emailtitle')->inLanguage($userLanguage);
     $this->result = $firstUser->sendMail($title->text(), $this->email->text());
     if (isset($data['Capture']) && $data['Capture']) {
         // Save the user, will be used if an error occurs when sending the email
         $this->firstUser = $firstUser;
     } else {
         // Blank the email if the user is not supposed to see it
         $this->email = null;
     }
     if ($this->result->isGood()) {
         return true;
     } elseif (isset($data['Capture']) && $data['Capture']) {
         // The email didn't send, but maybe they knew that and that's why they captured it
         return true;
     } else {
         // @todo FIXME: The email wasn't sent, but we have already set
         // the password throttle timestamp, so they won't be able to try
         // again until it expires...  :(
         return [['mailerror', $this->result->getMessage()]];
     }
 }
Пример #19
0
 /**
  * Lazily instantiate and return a factory object for making passwords
  *
  * @deprecated since 1.27, create a PasswordFactory directly instead
  * @return PasswordFactory
  */
 public static function getPasswordFactory()
 {
     wfDeprecated(__METHOD__, '1.27');
     $ret = new PasswordFactory();
     $ret->init(RequestContext::getMain()->getConfig());
     return $ret;
 }
Пример #20
0
 public function testInvalidPlaintext()
 {
     $passwordFactory = new PasswordFactory();
     $invalid = $passwordFactory->newFromPlaintext(null);
     $this->assertInstanceOf('InvalidPassword', $invalid);
 }