]>
git.immae.eu Git - github/shaarli/Shaarli.git/blob - application/security/BanManager.php
4 namespace Shaarli\Security
;
11 * Failed login attempts will store the associated IP address.
12 * After N failed attempts, the IP will be prevented from log in for duration D.
13 * Both N and D can be set in the configuration file.
15 * @package Shaarli\Security
19 /** @var array List of allowed proxies IP */
20 protected $trustedProxies;
22 /** @var int Number of allowed failed attempt before the ban */
23 protected $nbAttempts;
25 /** @var int Ban duration in seconds */
26 protected $banDuration;
28 /** @var string Path to the file containing IP bans and failures */
31 /** @var string Path to the log file, used to log bans */
34 /** @var array List of IP with their associated number of failed attempts */
35 protected $failures = [];
37 /** @var array List of banned IP with their associated unban timestamp */
41 * BanManager constructor.
43 * @param array $trustedProxies List of allowed proxies IP
44 * @param int $nbAttempts Number of allowed failed attempt before the ban
45 * @param int $banDuration Ban duration in seconds
46 * @param string $banFile Path to the file containing IP bans and failures
47 * @param string $logFile Path to the log file, used to log bans
49 public function __construct($trustedProxies, $nbAttempts, $banDuration, $banFile, $logFile) {
50 $this->trustedProxies
= $trustedProxies;
51 $this->nbAttempts
= $nbAttempts;
52 $this->banDuration
= $banDuration;
53 $this->banFile
= $banFile;
54 $this->logFile
= $logFile;
59 * Handle a failed login and ban the IP after too many failed attempts
61 * @param array $server The $_SERVER array
63 public function handleFailedAttempt($server)
65 $ip = $this->getIp($server);
66 // the IP is behind a trusted forward proxy, but is not forwarded
67 // in the HTTP headers, so we do nothing
72 // increment the fail count for this IP
73 if (isset($this->failures
[$ip])) {
74 $this->failures
[$ip]++
;
76 $this->failures
[$ip] = 1;
79 if ($this->failures
[$ip] >= $this->nbAttempts
) {
80 $this->bans
[$ip] = time() +
$this->banDuration
;
83 $server['REMOTE_ADDR'],
84 'IP address banned from login: '. $ip
87 $this->writeBanFile();
91 * Remove failed attempts for the provided client.
93 * @param array $server $_SERVER
95 public function clearFailures($server)
97 $ip = $this->getIp($server);
98 // the IP is behind a trusted forward proxy, but is not forwarded
99 // in the HTTP headers, so we do nothing
104 if (isset($this->failures
[$ip])) {
105 unset($this->failures
[$ip]);
107 $this->writeBanFile();
111 * Check whether the client IP is banned or not.
113 * @param array $server $_SERVER
115 * @return bool True if the IP is banned, false otherwise
117 public function isBanned($server)
119 $ip = $this->getIp($server);
120 // the IP is behind a trusted forward proxy, but is not forwarded
121 // in the HTTP headers, so we allow the authentication attempt.
126 // the user is not banned
127 if (! isset($this->bans
[$ip])) {
131 // the user is still banned
132 if ($this->bans
[$ip] > time()) {
136 // the ban has expired, the user can attempt to log in again
137 if (isset($this->failures
[$ip])) {
138 unset($this->failures
[$ip]);
140 unset($this->bans
[$ip]);
141 logm($this->logFile
, $server['REMOTE_ADDR'], 'Ban lifted for: '. $ip);
143 $this->writeBanFile();
148 * Retrieve the IP from $_SERVER.
149 * If the actual IP is behind an allowed reverse proxy,
150 * we try to extract the forwarded IP from HTTP headers.
152 * @param array $server $_SERVER
154 * @return string|bool The IP or false if none could be extracted
156 protected function getIp($server)
158 $ip = $server['REMOTE_ADDR'];
159 if (! in_array($ip, $this->trustedProxies
)) {
162 return getIpAddressFromProxy($server, $this->trustedProxies
);
166 * Read a file containing banned IPs
168 protected function readBanFile()
170 $data = FileUtils
::readFlatDB($this->banFile
);
171 if (isset($data['failures']) && is_array($data['failures'])) {
172 $this->failures
= $data['failures'];
175 if (isset($data['bans']) && is_array($data['bans'])) {
176 $this->bans
= $data['bans'];
181 * Write the banned IPs to a file
183 protected function writeBanFile()
185 return FileUtils
::writeFlatDB(
188 'failures' => $this->failures
,
189 'bans' => $this->bans
,
195 * Get the Failures (for UT purpose).
199 public function getFailures()
201 return $this->failures
;
205 * Get the Bans (for UT purpose).
209 public function getBans()