MediaWiki master
resetAuthenticationThrottle.php
Go to the documentation of this file.
1<?php
28use Wikimedia\IPUtils;
29
30// @codeCoverageIgnoreStart
31require_once __DIR__ . '/Maintenance.php';
32// @codeCoverageIgnoreEnd
33
41
42 public function __construct() {
43 parent::__construct();
44 $this->addDescription( 'Reset login/signup throttling for a specified user and/or IP. '
45 . "\n\n"
46 . 'When resetting signup or temp account, provide the IP. When resetting login (or both), provide '
47 . 'both username (as entered in login screen) and IP. An easy way to obtain them is '
48 . "the 'throttler' log channel." );
49 $this->addOption( 'login', 'Reset login throttle' );
50 $this->addOption( 'signup', 'Reset account creation throttle' );
51 $this->addOption( 'tempaccount', 'Reset temp account creation throttle' );
52 $this->addOption( 'tempaccountnameacquisition', 'Reset temp account name acquisition throttle' );
53 $this->addOption( 'user', 'Username to reset (when using --login)', false, true );
54 $this->addOption( 'ip', 'IP to reset', false, true );
55 }
56
57 public function execute() {
58 $forLogin = (bool)$this->getOption( 'login' );
59 $forSignup = (bool)$this->getOption( 'signup' );
60 $forTempAccount = (bool)$this->getOption( 'tempaccount' );
61 $forTempAccountNameAcquisition = (bool)$this->getOption( 'tempaccountnameacquisition' );
62 $username = $this->getOption( 'user' );
63 $ip = $this->getOption( 'ip' );
64
65 if ( !$forLogin && !$forSignup && !$forTempAccount && !$forTempAccountNameAcquisition ) {
66 $this->fatalError(
67 'At least one of --login, --signup, --tempaccount, or --tempaccountnameacquisition is required!'
68 );
69 } elseif ( $ip === null ) {
70 $this->fatalError( '--ip is required!' );
71 } elseif ( !IPUtils::isValid( $ip ) ) {
72 $this->fatalError( "Not a valid IP: $ip" );
73 }
74
75 if ( $forLogin ) {
76 $this->clearLoginThrottle( $username, $ip );
77 }
78 if ( $forSignup ) {
79 $this->clearSignupThrottle( $ip );
80 }
81 if ( $forTempAccount ) {
83 }
84 if ( $forTempAccountNameAcquisition ) {
86 }
87
88 LoggerFactory::getInstance( 'throttler' )->info( 'Manually cleared {type} throttle', [
89 'type' => implode( ' and ', array_filter( [
90 $forLogin ? 'login' : null,
91 $forSignup ? 'signup' : null,
92 $forTempAccount ? 'tempaccount' : null,
93 $forTempAccountNameAcquisition ? 'tempaccountnameacquisition' : null,
94 ] ) ),
95 'username' => $username,
96 'ipKey' => $ip,
97 ] );
98 }
99
104 protected function clearLoginThrottle( $rawUsername, $ip ) {
105 $this->output( 'Clearing login throttle...' );
106
107 $passwordAttemptThrottle = $this->getConfig()->get( MainConfigNames::PasswordAttemptThrottle );
108 if ( !$passwordAttemptThrottle ) {
109 $this->output( "none set\n" );
110 return;
111 }
112
113 $objectCacheFactory = $this->getServiceContainer()->getInstance()->getObjectCacheFactory();
114
115 $throttler = new Throttler( $passwordAttemptThrottle, [
116 'type' => 'password',
117 'cache' => $objectCacheFactory->getLocalClusterInstance(),
118 ] );
119 if ( $rawUsername !== null ) {
120 $usernames = $this->getServiceContainer()->getAuthManager()
121 ->normalizeUsername( $rawUsername );
122 if ( !$usernames ) {
123 $this->fatalError( "Not a valid username: $rawUsername" );
124 }
125 } else {
126 $usernames = [ null ];
127 }
128 foreach ( $usernames as $username ) {
129 $throttler->clear( $username, $ip );
130 }
131
132 $botPasswordThrottler = new Throttler( $passwordAttemptThrottle, [
133 'type' => 'botpassword',
134 'cache' => $objectCacheFactory->getLocalClusterInstance(),
135 ] );
136 // @phan-suppress-next-line PhanPossiblyUndeclaredVariable T240141
137 $botPasswordThrottler->clear( $username, $ip );
138
139 $this->output( "done\n" );
140 }
141
145 protected function clearSignupThrottle( $ip ) {
146 $this->output( 'Clearing signup throttle...' );
147
148 $accountCreationThrottle = $this->getConfig()->get( MainConfigNames::AccountCreationThrottle );
149 if ( !is_array( $accountCreationThrottle ) ) {
150 $accountCreationThrottle = [ [
151 'count' => $accountCreationThrottle,
152 'seconds' => 86400,
153 ] ];
154 }
155 if ( !$accountCreationThrottle ) {
156 $this->output( "none set\n" );
157 return;
158 }
159 $throttler = new Throttler( $accountCreationThrottle, [
160 'type' => 'acctcreate',
161 'cache' => $this->getServiceContainer()->getObjectCacheFactory()
162 ->getLocalClusterInstance(),
163 ] );
164
165 $throttler->clear( null, $ip );
166
167 $this->output( "done\n" );
168 }
169
170 protected function clearTempAccountCreationThrottle( string $ip ): void {
171 $this->output( 'Clearing temp account creation throttle...' );
172
173 $tempAccountCreationThrottle = $this->getConfig()->get( MainConfigNames::TempAccountCreationThrottle );
174 if ( !$tempAccountCreationThrottle ) {
175 $this->output( "none set\n" );
176 return;
177 }
178 $throttler = new Throttler( $tempAccountCreationThrottle, [
179 'type' => 'tempacctcreate',
180 'cache' => $this->getServiceContainer()->getObjectCacheFactory()
181 ->getLocalClusterInstance(),
182 ] );
183
184 $throttler->clear( null, $ip );
185
186 $this->output( "done\n" );
187 }
188
189 protected function clearTempAccountNameAcquisitionThrottle( string $ip ): void {
190 $this->output( 'Clearing temp account name acquisition throttle...' );
191
192 $tempAccountNameAcquisitionThrottle = $this->getConfig()->get(
193 MainConfigNames::TempAccountNameAcquisitionThrottle
194 );
195 if ( !$tempAccountNameAcquisitionThrottle ) {
196 $this->output( "none set\n" );
197 return;
198 }
199 $throttler = new Throttler( $tempAccountNameAcquisitionThrottle, [
200 'type' => 'tempacctnameacquisition',
201 'cache' => $this->getServiceContainer()->getObjectCacheFactory()
202 ->getLocalClusterInstance(),
203 ] );
204
205 $throttler->clear( null, $ip );
206
207 $this->output( "done\n" );
208 }
209
210}
211
212// @codeCoverageIgnoreStart
213$maintClass = ResetAuthenticationThrottle::class;
214require_once RUN_MAINTENANCE_IF_MAIN;
215// @codeCoverageIgnoreEnd
Create PSR-3 logger objects.
A class containing constants representing the names of configuration variables.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
output( $out, $channel=null)
Throw some output to the user.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
getServiceContainer()
Returns the main service container.
addDescription( $text)
Set the description text.
Reset login/signup throttling for a specified user and/or IP.