Have BotPassword::login() call AuthManagerLoginAuthenticateAudit
authorBrad Jorsch <bjorsch@wikimedia.org>
Thu, 10 May 2018 14:01:06 +0000 (10:01 -0400)
committerBrad Jorsch <bjorsch@wikimedia.org>
Tue, 11 Dec 2018 20:33:39 +0000 (15:33 -0500)
To facilitate logging all authentications, even ones not via
AuthManager, BotPassword::login() should call the
AuthManagerLoginAuthenticateAudit hook.

Bug: T194338
Change-Id: I27b75c56e060fcb8f71d84ddc2eb8e1533fef33a

includes/user/BotPassword.php

index 0c4b425..187c0a9 100644 (file)
@@ -18,6 +18,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+use MediaWiki\Auth\AuthenticationResponse;
 use MediaWiki\MediaWikiServices;
 use MediaWiki\Session\BotPasswordSessionProvider;
 use Wikimedia\Rdbms\IMaintainableDatabase;
@@ -458,14 +459,14 @@ class BotPassword implements IDBAccessObject {
                // Split name into name+appId
                $sep = self::getSeparator();
                if ( strpos( $username, $sep ) === false ) {
-                       return Status::newFatal( 'botpasswords-invalid-name', $sep );
+                       return self::loginHook( $username, Status::newFatal( 'botpasswords-invalid-name', $sep ) );
                }
                list( $name, $appId ) = explode( $sep, $username, 2 );
 
                // Find the named user
                $user = User::newFromName( $name );
                if ( !$user || $user->isAnon() ) {
-                       return Status::newFatal( 'nosuchuser', $name );
+                       return self::loginHook( $user ?: $name, Status::newFatal( 'nosuchuser', $name ) );
                }
 
                if ( $user->isLocked() ) {
@@ -482,35 +483,66 @@ class BotPassword implements IDBAccessObject {
                        $result = $throttle->increase( $user->getName(), $request->getIP(), __METHOD__ );
                        if ( $result ) {
                                $msg = wfMessage( 'login-throttled' )->durationParams( $result['wait'] );
-                               return Status::newFatal( $msg );
+                               return self::loginHook( $user, Status::newFatal( $msg ) );
                        }
                }
 
                // Get the bot password
                $bp = self::newFromUser( $user, $appId );
                if ( !$bp ) {
-                       return Status::newFatal( 'botpasswords-not-exist', $name, $appId );
+                       return self::loginHook( $user, Status::newFatal( 'botpasswords-not-exist', $name, $appId ) );
                }
 
                // Check restrictions
                $status = $bp->getRestrictions()->check( $request );
                if ( !$status->isOK() ) {
-                       return Status::newFatal( 'botpasswords-restriction-failed' );
+                       return self::loginHook( $user, Status::newFatal( 'botpasswords-restriction-failed' ) );
                }
 
                // Check the password
                $passwordObj = $bp->getPassword();
                if ( $passwordObj instanceof InvalidPassword ) {
-                       return Status::newFatal( 'botpasswords-needs-reset', $name, $appId );
+                       return self::loginHook( $user, Status::newFatal( 'botpasswords-needs-reset', $name, $appId ) );
                }
                if ( !$passwordObj->equals( $password ) ) {
-                       return Status::newFatal( 'wrongpassword' );
+                       return self::loginHook( $user, Status::newFatal( 'wrongpassword' ) );
                }
 
                // Ok! Create the session.
                if ( $throttle ) {
                        $throttle->clear( $user->getName(), $request->getIP() );
                }
-               return Status::newGood( $provider->newSessionForRequest( $user, $bp, $request ) );
+               return self::loginHook(
+                       $user,
+                       Status::newGood( $provider->newSessionForRequest( $user, $bp, $request ) )
+               );
+       }
+
+       /**
+        * Call AuthManagerLoginAuthenticateAudit
+        *
+        * To facilitate logging all authentications, even ones not via
+        * AuthManager, call the AuthManagerLoginAuthenticateAudit hook.
+        *
+        * @param User|string $user User being logged in
+        * @param Status $status Login status
+        * @return Status The passed-in status
+        */
+       private static function loginHook( $user, Status $status ) {
+               if ( $user instanceof User ) {
+                       $name = $user->getName();
+               } else {
+                       $name = $user;
+                       $user = null;
+               }
+
+               if ( $status->isGood() ) {
+                       $response = AuthenticationResponse::newPass( $name );
+               } else {
+                       $response = AuthenticationResponse::newFail( $status->getMessage() );
+               }
+               Hooks::run( 'AuthManagerLoginAuthenticateAudit', [ $response, $user, $name ] );
+
+               return $status;
        }
 }