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 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()); }
/** * 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; }
/** * 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__); }
/** * @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')); }
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); }
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); } }
/** * Get the password * @return Password */ protected function getPassword() { list($index, $options) = DBAccessObjectUtils::getDBOptions($this->flags); $db = self::getDB($index); $password = $db->selectField('bot_passwords', 'bp_password', array('bp_user' => $this->centralId, 'bp_app_id' => $this->appId), __METHOD__, $options); if ($password === false) { return PasswordFactory::newInvalidPassword(); } $passwordFactory = new \PasswordFactory(); $passwordFactory->init(\RequestContext::getMain()->getConfig()); try { return $passwordFactory->newFromCiphertext($password); } catch (PasswordError $ex) { return PasswordFactory::newInvalidPassword(); } }
/** * 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']); }