API: fixed bad login throttling bug (i hope)
authorYuri Astrakhan <yurik@users.mediawiki.org>
Thu, 9 Aug 2007 09:53:05 +0000 (09:53 +0000)
committerYuri Astrakhan <yurik@users.mediawiki.org>
Thu, 9 Aug 2007 09:53:05 +0000 (09:53 +0000)
includes/api/ApiLogin.php

index 10c31d0..d62fbfb 100644 (file)
@@ -37,16 +37,16 @@ if (!defined('MEDIAWIKI')) {
 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. 
@@ -160,10 +160,11 @@ class ApiLogin extends ApiBase {
                        $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;
        }
@@ -178,8 +179,8 @@ class ApiLogin extends ApiBase {
                
                $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;
        }
@@ -188,9 +189,9 @@ class ApiLogin extends ApiBase {
         * 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;