/
FailedLoginAttempt.php
185 lines (168 loc) · 5.25 KB
/
FailedLoginAttempt.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<?php if (!defined('BASEPATH')) {
die('No direct script access allowed');
}
/*
* LimeSurvey
* Copyright (C) 2007-2011 The LimeSurvey Project Team / Carsten Schmitz
* All rights reserved.
* License: GNU/GPL License v2 or later, see LICENSE.php
* LimeSurvey is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*
*/
/**
* Class FailedLoginAttempt
*
* @property integer $id
* @property string $ip Ip address
* @property string $last_attempt
* @property integer $number_attempts
*/
class FailedLoginAttempt extends LSActiveRecord
{
const TYPE_LOGIN = 'login';
const TYPE_TOKEN = 'token';
/**
* @inheritdoc
* @return FailedLoginAttempt
*/
public static function model($class = __CLASS__)
{
/** @var self $model */
$model = parent::model($class);
return $model;
}
/** @inheritdoc */
public function primaryKey()
{
return 'id';
}
/** @inheritdoc */
public function tableName()
{
return '{{failed_login_attempts}}';
}
/**
* Deletes all the attempts by IP
*
* @access public
* @return void
*/
public function deleteAttempts()
{
$ip = substr(getIPAddress(), 0, 40);
$this->deleteAllByAttributes(array('ip' => $ip));
}
/**
* 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($attemptType = '')
{
$isLockedOut = false;
$ip = substr(getIPAddress(), 0, 40);
// Return false if IP is whitelisted
if (!empty($attemptType) && $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);
$row = $this->find($criteria);
if ($row != null) {
$lastattempt = strtotime($row->last_attempt);
if (time() > $lastattempt + Yii::app()->getConfig('timeOutTime')) {
$this->deleteAttempts();
} else {
$isLockedOut = true;
}
}
return $isLockedOut;
}
/**
* This function removes obsolete login attempts
* TODO
*/
public function cleanOutOldAttempts()
{
// this where select whole part
//$this->db->where('now() > (last_attempt+'.$this->config->item("timeOutTime").')');
//return $this->db->delete('failed_login_attempts');
}
/**
* Records an failed login-attempt if IP is not already locked out
*
* @access public
* @return true
*/
public function addAttempt()
{
if (!$this->isLockedOut()) {
$timestamp = date("Y-m-d H:i:s");
$ip = substr(getIPAddress(), 0, 40);
$row = $this->findByAttributes(array('ip' => $ip));
if ($row !== null) {
$row->number_attempts = $row->number_attempts + 1;
$row->last_attempt = $timestamp;
$row->save();
} else {
$record = new FailedLoginAttempt;
$record->ip = $ip;
$record->number_attempts = 1;
$record->last_attempt = $timestamp;
$record->save();
}
}
return true;
}
/**
* Returns true if the specified IP is whitelisted
*
* @param string $ip
* @param string $attemptType 'login' or 'token'
*
* @throws InvalidArgumentException if an invalid attempt type is specified
* @return boolean
*/
private function isWhitelisted($ip, $attemptType)
{
// Init
if ($attemptType != self::TYPE_LOGIN && $attemptType != self::TYPE_TOKEN) {
throw new InvalidArgumentException(sprintf("Invalid attempt type: %s", $attemptType));
}
if (empty($ip)) {
return false;
}
$binaryIP = inet_pton($ip);
$whiteList = Yii::app()->getConfig($attemptType . 'IpWhitelist');
if (empty($whiteList)) {
return false;
}
// Validating
$whiteListEntries = preg_split('/\n|,/', $whiteList);
foreach ($whiteListEntries as $whiteListEntry) {
if (empty($whiteListEntry)) {
continue;
}
// Compare directly
if ($whiteListEntry == $ip) {
// The IP is whitelisted
return true;
}
// Compare binary representations
$binaryWhiteListEntry = inet_pton($whiteListEntry);
if ($binaryWhiteListEntry !== false && $binaryWhiteListEntry == $binaryIP) {
// The IP is whitelisted
return true;
}
}
// Not whitelisted
return false;
}
}