Merge "Widgets: Allow titles with name of Object.prototypes"
[lhc/web/wiklou.git] / includes / auth / LocalPasswordPrimaryAuthenticationProvider.php
index bbc6e8d..86a6aae 100644 (file)
@@ -88,22 +88,26 @@ class LocalPasswordPrimaryAuthenticationProvider
                        'user_id', 'user_password', 'user_password_expires',
                ];
 
-               $dbw = wfGetDB( DB_MASTER );
-               $row = $dbw->selectRow(
+               $dbr = wfGetDB( DB_REPLICA );
+               $row = $dbr->selectRow(
                        'user',
                        $fields,
                        [ 'user_name' => $username ],
                        __METHOD__
                );
                if ( !$row ) {
-                       return AuthenticationResponse::newAbstain();
+                       // Do not reveal whether its bad username or
+                       // bad password to prevent username enumeration
+                       // on private wikis. (T134100)
+                       return $this->failResponse( $req );
                }
 
+               $oldRow = clone $row;
                // Check for *really* old password hashes that don't even have a type
                // The old hash format was just an md5 hex hash, with no type information
                if ( preg_match( '/^[0-9a-f]{32}$/', $row->user_password ) ) {
                        if ( $this->config->get( 'PasswordSalt' ) ) {
-                               $row->user_password = ":A:{$row->user_id}:{$row->user_password}";
+                               $row->user_password = ":B:{$row->user_id}:{$row->user_password}";
                        } else {
                                $row->user_password = ":A:{$row->user_password}";
                        }
@@ -131,13 +135,19 @@ class LocalPasswordPrimaryAuthenticationProvider
 
                // @codeCoverageIgnoreStart
                if ( $this->getPasswordFactory()->needsUpdate( $pwhash ) ) {
-                       $pwhash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
-                       $dbw->update(
-                               'user',
-                               [ 'user_password' => $pwhash->toString() ],
-                               [ 'user_id' => $row->user_id ],
-                               __METHOD__
-                       );
+                       $newHash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
+                       \DeferredUpdates::addCallableUpdate( function () use ( $newHash, $oldRow ) {
+                               $dbw = wfGetDB( DB_MASTER );
+                               $dbw->update(
+                                       'user',
+                                       [ 'user_password' => $newHash->toString() ],
+                                       [
+                                               'user_id' => $oldRow->user_id,
+                                               'user_password' => $oldRow->user_password
+                                       ],
+                                       __METHOD__
+                               );
+                       } );
                }
                // @codeCoverageIgnoreEnd
 
@@ -152,8 +162,8 @@ class LocalPasswordPrimaryAuthenticationProvider
                        return false;
                }
 
-               $dbw = wfGetDB( DB_MASTER );
-               $row = $dbw->selectRow(
+               $dbr = wfGetDB( DB_REPLICA );
+               $row = $dbr->selectRow(
                        'user',
                        [ 'user_password' ],
                        [ 'user_name' => $username ],
@@ -235,14 +245,14 @@ class LocalPasswordPrimaryAuthenticationProvider
 
                $pwhash = null;
 
-               if ( $this->loginOnly ) {
-                       $pwhash = $this->getPasswordFactory()->newFromCiphertext( null );
-                       $expiry = null;
-                       // @codeCoverageIgnoreStart
-               } elseif ( get_class( $req ) === PasswordAuthenticationRequest::class ) {
-                       // @codeCoverageIgnoreEnd
-                       $pwhash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
-                       $expiry = $this->getNewPasswordExpiry( $username );
+               if ( get_class( $req ) === PasswordAuthenticationRequest::class ) {
+                       if ( $this->loginOnly ) {
+                               $pwhash = $this->getPasswordFactory()->newFromCiphertext( null );
+                               $expiry = null;
+                       } else {
+                               $pwhash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
+                               $expiry = $this->getNewPasswordExpiry( $username );
+                       }
                }
 
                if ( $pwhash ) {
@@ -290,7 +300,7 @@ class LocalPasswordPrimaryAuthenticationProvider
                                // Nothing we can do besides claim it, because the user isn't in
                                // the DB yet
                                if ( $req->username !== $user->getName() ) {
-                                       $req = clone( $req );
+                                       $req = clone $req;
                                        $req->username = $user->getName();
                                }
                                $ret = AuthenticationResponse::newPass( $req->username );