- $throttleKey = wfMemcKey( 'password-throttle', $wgRequest->getIP(), md5( $username ) );
- $count = $wgPasswordAttemptThrottle['count'];
- $period = $wgPasswordAttemptThrottle['seconds'];
-
- $cache = ObjectCache::getLocalClusterInstance();
- $throttleCount = $cache->get( $throttleKey );
- if ( !$throttleCount ) {
- $cache->add( $throttleKey, 1, $period ); // start counter
- } elseif ( $throttleCount < $count ) {
- $cache->incr( $throttleKey );
- } elseif ( $throttleCount >= $count ) {
- return true;
+ $throttleConfig = $wgPasswordAttemptThrottle;
+ if ( isset( $wgPasswordAttemptThrottle['count'] ) ) {
+ // old style. Convert for backwards compat.
+ $throttleConfig = [ $wgPasswordAttemptThrottle ];
+ }
+ foreach ( $throttleConfig as $index => $specificThrottle ) {
+ if ( isset( $specificThrottle['allIPs'] ) ) {
+ $ip = 'All';
+ } else {
+ $ip = $wgRequest->getIP();
+ }
+ $throttleKey = wfGlobalCacheKey( 'password-throttle',
+ $index, $ip, md5( $username )
+ );
+ $count = $specificThrottle['count'];
+ $period = $specificThrottle['seconds'];
+
+ $cache = ObjectCache::getLocalClusterInstance();
+ $throttleCount = $cache->get( $throttleKey );
+ if ( !$throttleCount ) {
+ $cache->add( $throttleKey, 1, $period ); // start counter
+ } elseif ( $throttleCount < $count ) {
+ $cache->incr( $throttleKey );
+ } elseif ( $throttleCount >= $count ) {
+ $logMsg = 'Login attempt rejected because logins to '
+ . '{acct} from IP {ip} have been throttled for '
+ . '{period} seconds due to {count} failed attempts';
+ // If we are hitting a throttle for >= 50 attempts,
+ // it is much more likely to be an attack than someone
+ // simply forgetting their password, so log it at a
+ // higher level.
+ $level = $count >= 50 ? LogLevel::WARNING : LogLevel::INFO;
+ // It should be noted that once the throttle is hit,
+ // every attempt to login will generate the log message
+ // until the throttle expires, not just the attempt that
+ // puts the throttle over the top.
+ LoggerFactory::getInstance( 'password-throttle' )->log(
+ $level,
+ $logMsg,
+ [
+ 'ip' => $ip,
+ 'period' => $period,
+ 'acct' => $username,
+ 'count' => $count,
+ 'throttleIdentifier' => $index,
+ 'method' => __METHOD__
+ ]
+ );
+
+ return [
+ 'throttleIndex' => $index,
+ 'wait' => $period,
+ 'count' => $count
+ ];
+ }