class ApiLogin extends ApiBase {
/**
- * The amount of time a user must wait after submitting
+ * Time (in seconds) a user must wait after submitting
* a bad login (will be multiplied by the THROTTLE_FACTOR for each bad attempt)
*/
- const THROTTLE_TIME = 10;
+ const THROTTLE_TIME = 1;
/**
* The factor by which the wait-time in between authentication
* attempts is increased every failed attempt.
*/
- const THROTTLE_FACTOR = 1.5;
+ const THROTTLE_FACTOR = 2;
/**
* The maximum number of failed logins after which the wait increase stops.
$val['count'] = 1 + $val['count'];
}
- $delay = ApiLogin::calculateDelay($val);
+ $delay = ApiLogin::calculateDelay($val['count']);
$wgMemc->delete($key);
- $wgMemc->add( $key, $val, $delay );
+ // Cache expiration should be the maximum timeout - to prevent a "try and wait" attack
+ $wgMemc->add( $key, $val, ApiLogin::calculateDelay(ApiLogin::THOTTLE_MAX_COUNT) );
return $delay;
}
$val = $wgMemc->get($this->getMemCacheKey());
- $elapse = (time() - $val['lastReqTime']) / 1000; // in seconds
- $canRetryIn = ApiLogin::calculateDelay($val) - $elapse;
+ $elapse = (time() - $val['lastReqTime']); // in seconds
+ $canRetryIn = ApiLogin::calculateDelay($val['count']) - $elapse;
return $canRetryIn < 0 ? 0 : $canRetryIn;
}
* Based on the number of previously attempted logins, returns
* the delay (in seconds) when the next login attempt will be allowed.
*/
- private static function calculateDelay($val) {
+ private static function calculateDelay($count) {
// Defensive programming
- $count = $val['count'];
+ $count = intval($count);
$count = $count < 1 ? 1 : $count;
$count = $count > self::THOTTLE_MAX_COUNT ? self::THOTTLE_MAX_COUNT : $count;