2 namespace Shaarli\Security
;
4 require_once 'tests/utils/FakeConfigManager.php';
5 use \PHPUnit\Framework\TestCase
;
8 * Test coverage for LoginManager
10 class LoginManagerTest
extends TestCase
12 protected $configManager = null;
13 protected $loginManager = null;
14 protected $banFile = 'sandbox/ipbans.php';
15 protected $logFile = 'sandbox/shaarli.log';
16 protected $globals = [];
17 protected $ipAddr = '127.0.0.1';
18 protected $server = [];
19 protected $trustedProxy = '10.1.1.100';
21 /** @var string User login */
22 protected $login = 'johndoe';
24 /** @var string User password */
25 protected $password = 'IC4nHazL0g1n?';
27 /** @var string Hash of the salted user password */
28 protected $passwordHash = '';
30 /** @var string Salt used by hash functions */
31 protected $salt = '669e24fa9c5a59a613f98e8e38327384504a4af2';
34 * Prepare or reset test resources
36 public function setUp()
38 if (file_exists($this->banFile
)) {
39 unlink($this->banFile
);
42 $this->passwordHash
= sha1($this->password
. $this->login
. $this->salt
);
44 $this->configManager
= new \
FakeConfigManager([
45 'credentials.login' => $this->login
,
46 'credentials.hash' => $this->passwordHash
,
47 'credentials.salt' => $this->salt
,
48 'resource.ban_file' => $this->banFile
,
49 'resource.log' => $this->logFile
,
50 'security.ban_after' => 4,
51 'security.ban_duration' => 3600,
52 'security.trusted_proxies' => [$this->trustedProxy
],
55 $this->globals
= &$GLOBALS;
56 unset($this->globals
['IPBANS']);
58 $this->loginManager
= new LoginManager($this->globals
, $this->configManager
, null);
59 $this->server
['REMOTE_ADDR'] = $this->ipAddr
;
65 public function tearDown()
67 unset($this->globals
['IPBANS']);
71 * Instantiate a LoginManager and load ban records
73 public function testReadBanFile()
77 "<?php\n\$GLOBALS['IPBANS']=array('FAILURES' => array('127.0.0.1' => 99));\n?>"
79 new LoginManager($this->globals
, $this->configManager
, null);
80 $this->assertEquals(99, $this->globals
['IPBANS']['FAILURES']['127.0.0.1']);
84 * Record a failed login attempt
86 public function testHandleFailedLogin()
88 $this->loginManager
->handleFailedLogin($this->server
);
89 $this->assertEquals(1, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
91 $this->loginManager
->handleFailedLogin($this->server
);
92 $this->assertEquals(2, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
96 * Record a failed login attempt - IP behind a trusted proxy
98 public function testHandleFailedLoginBehindTrustedProxy()
101 'REMOTE_ADDR' => $this->trustedProxy
,
102 'HTTP_X_FORWARDED_FOR' => $this->ipAddr
,
104 $this->loginManager
->handleFailedLogin($server);
105 $this->assertEquals(1, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
107 $this->loginManager
->handleFailedLogin($server);
108 $this->assertEquals(2, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
112 * Record a failed login attempt - IP behind a trusted proxy but not forwarded
114 public function testHandleFailedLoginBehindTrustedProxyNoIp()
117 'REMOTE_ADDR' => $this->trustedProxy
,
119 $this->loginManager
->handleFailedLogin($server);
120 $this->assertFalse(isset($this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]));
122 $this->loginManager
->handleFailedLogin($server);
123 $this->assertFalse(isset($this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]));
127 * Record a failed login attempt and ban the IP after too many failures
129 public function testHandleFailedLoginBanIp()
131 $this->loginManager
->handleFailedLogin($this->server
);
132 $this->assertEquals(1, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
133 $this->assertTrue($this->loginManager
->canLogin($this->server
));
135 $this->loginManager
->handleFailedLogin($this->server
);
136 $this->assertEquals(2, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
137 $this->assertTrue($this->loginManager
->canLogin($this->server
));
139 $this->loginManager
->handleFailedLogin($this->server
);
140 $this->assertEquals(3, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
141 $this->assertTrue($this->loginManager
->canLogin($this->server
));
143 $this->loginManager
->handleFailedLogin($this->server
);
144 $this->assertEquals(4, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
145 $this->assertFalse($this->loginManager
->canLogin($this->server
));
147 // handleFailedLogin is not supposed to be called at this point:
148 // - no login form should be displayed once an IP has been banned
149 // - yet this could happen when using custom templates / scripts
150 $this->loginManager
->handleFailedLogin($this->server
);
151 $this->assertEquals(5, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
152 $this->assertFalse($this->loginManager
->canLogin($this->server
));
158 public function testHandleSuccessfulLogin()
160 $this->assertTrue($this->loginManager
->canLogin($this->server
));
162 $this->loginManager
->handleSuccessfulLogin($this->server
);
163 $this->assertTrue($this->loginManager
->canLogin($this->server
));
167 * Erase failure records after successfully logging in from this IP
169 public function testHandleSuccessfulLoginAfterFailure()
171 $this->loginManager
->handleFailedLogin($this->server
);
172 $this->loginManager
->handleFailedLogin($this->server
);
173 $this->assertEquals(2, $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]);
174 $this->assertTrue($this->loginManager
->canLogin($this->server
));
176 $this->loginManager
->handleSuccessfulLogin($this->server
);
177 $this->assertTrue($this->loginManager
->canLogin($this->server
));
178 $this->assertFalse(isset($this->globals
['IPBANS']['FAILURES'][$this->ipAddr
]));
179 $this->assertFalse(isset($this->globals
['IPBANS']['BANS'][$this->ipAddr
]));
183 * The IP is not banned
185 public function testCanLoginIpNotBanned()
187 $this->assertTrue($this->loginManager
->canLogin($this->server
));
193 public function testCanLoginIpBanned()
195 // ban the IP for an hour
196 $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
] = 10;
197 $this->globals
['IPBANS']['BANS'][$this->ipAddr
] = time() +
3600;
199 $this->assertFalse($this->loginManager
->canLogin($this->server
));
203 * The IP is banned, and the ban duration is over
205 public function testCanLoginIpBanExpired()
207 // ban the IP for an hour
208 $this->globals
['IPBANS']['FAILURES'][$this->ipAddr
] = 10;
209 $this->globals
['IPBANS']['BANS'][$this->ipAddr
] = time() +
3600;
210 $this->assertFalse($this->loginManager
->canLogin($this->server
));
213 $this->globals
['IPBANS']['BANS'][$this->ipAddr
] = time() - 3600;
214 $this->assertTrue($this->loginManager
->canLogin($this->server
));
218 * Generate a token depending on the user credentials and client IP
220 public function testGenerateStaySignedInToken()
222 $ipAddress = '10.1.47.179';
223 $this->loginManager
->generateStaySignedInToken($ipAddress);
226 sha1($this->passwordHash
. $ipAddress . $this->salt
),
227 $this->loginManager
->getStaySignedInToken()