Skip to content

Commit

Permalink
* Fixed issue #17301: Survey participants lock out issue
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrieljenik committed May 18, 2021
1 parent cdfaa7a commit 1c44062
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 3 deletions.
2 changes: 2 additions & 0 deletions application/config/config-defaults.php
Expand Up @@ -59,6 +59,8 @@
// If the user enters password incorrectly
$config['maxLoginAttempt'] = 3; // Lock them out after 3 attempts
$config['timeOutTime'] = 60 * 10; // Lock them out for 10 minutes.
$config['loginIpWhitelist'] = []; // Array of regular expressions for IPs that should be excluded from the max login attemps check. Ex: '192.168.0.5|192.168.0.6' or '192.168.0.\d+'
$config['tokenIpWhitelist'] = []; // Array of regular expressions for IPs that should be excluded from the max token validation attemps check. Ex: '192.168.0.5|192.168.0.6' or '192.168.0.\d+'

// Site Settings
$config['printanswershonorsconditions'] = 1; // If set to 1, only relevant answers to questions can be printed by user. If set to 0, also questions not shown are printed
Expand Down
2 changes: 1 addition & 1 deletion application/core/LSUserIdentity.php
Expand Up @@ -55,7 +55,7 @@ public function authenticate()
$result = new LSAuthResult(self::ERROR_NONE);

// Check if the ip is locked out
if (FailedLoginAttempt::model()->isLockedOut()) {
if (FailedLoginAttempt::model()->isLockedOut(FailedLoginAttempt::TYPE_LOGIN)) {
$message = sprintf(gT('You have exceeded the number of maximum login attempts. Please wait %d minutes before trying again.'), App()->getConfig('timeOutTime') / 60);
$result->setError(self::ERROR_IP_LOCKED_OUT, $message);
}
Expand Down
2 changes: 1 addition & 1 deletion application/helpers/frontend_helper.php
Expand Up @@ -1233,7 +1233,7 @@ function finalizeRandomization($fieldmap)
function testIfTokenIsValid(array $subscenarios, array $thissurvey, array $aEnterTokenData, $clienttoken)
{
$FlashError = '';
if (FailedLoginAttempt::model()->isLockedOut()) {
if (FailedLoginAttempt::model()->isLockedOut(FailedLoginAttempt::TYPE_TOKEN)) {
$FlashError = sprintf(gT('You have exceeded the number of maximum token validation attempts. Please wait %d minutes before trying again.'), App()->getConfig('timeOutTime') / 60);
$renderToken = 'main';
} else {
Expand Down
44 changes: 43 additions & 1 deletion application/models/FailedLoginAttempt.php
Expand Up @@ -24,6 +24,9 @@
*/
class FailedLoginAttempt extends LSActiveRecord
{
const TYPE_LOGIN = 'login';
const TYPE_TOKEN = 'token';

/**
* @inheritdoc
* @return FailedLoginAttempt
Expand Down Expand Up @@ -62,12 +65,20 @@ public function deleteAttempts()
/**
* Check if an IP address is allowed to login or not
*
* @param string $attemptType The attempt type ('login' or 'token'). Used to check the white lists.
*
* @return boolean Returns true if the user is blocked
*/
public function isLockedOut()
public function isLockedOut($attemptType = '')
{
$isLockedOut = false;
$ip = substr(App()->getRequest()->getUserHostAddress(), 0, 40);

// Return false if IP is whitelisted
if ($this->isWhitelisted($ip, $attemptType)) {
return false;
}

$criteria = new CDbCriteria;
$criteria->condition = 'number_attempts > :attempts AND ip = :ip';
$criteria->params = array(':attempts' => Yii::app()->getConfig('maxLoginAttempt'), ':ip' => $ip);
Expand Down Expand Up @@ -123,4 +134,35 @@ public function addAttempt()
}
return true;
}

/**
* Returns true if the specified IP is whitelisted
*
* @param string $ip
* @param string $attemptType 'login' or 'token'
*
* @return boolean
*/
private function isWhitelisted($ip, $attemptType)
{
if ($attemptType != self::TYPE_LOGIN && $attemptType != self::TYPE_TOKEN) {
return false;
}

$whiteList = Yii::app()->getConfig($attemptType . 'IpWhitelist');
if (empty($whiteList)) {
return false;
}
if (!is_array($whiteList)) {
$whiteList = [$whiteList];
}
foreach ($whiteList as $whiteListEntry) {
if (!empty($whiteListEntry) && preg_match('/' . str_replace('/', '\/', $whiteListEntry) . '/', $ip, $m)) {
// The IP is whitelisted
return true;
}
}

return false;
}
}

0 comments on commit 1c44062

Please sign in to comment.