aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSébastien NOBILI <code@pipoprods.org>2020-03-02 17:08:19 +0100
committerSébastien NOBILI <code@pipoprods.org>2020-03-02 17:13:18 +0100
commitcc2ded54e12e3f3140b895067af086cd71cc5dc6 (patch)
tree5e95c4b5b6d7eadef25cbb503167e8f89608162d
parent810f0f6c96b6d26e22164027185c5996b425816c (diff)
downloadShaarli-cc2ded54e12e3f3140b895067af086cd71cc5dc6.tar.gz
Shaarli-cc2ded54e12e3f3140b895067af086cd71cc5dc6.tar.zst
Shaarli-cc2ded54e12e3f3140b895067af086cd71cc5dc6.zip
ldap authentication, fixes shaarli/Shaarli#1343
-rw-r--r--application/security/LoginManager.php64
-rw-r--r--doc/md/Shaarli-configuration.md9
-rw-r--r--tests/security/LoginManagerTest.php34
3 files changed, 98 insertions, 9 deletions
diff --git a/application/security/LoginManager.php b/application/security/LoginManager.php
index 0b0ce0b1..2cea3f10 100644
--- a/application/security/LoginManager.php
+++ b/application/security/LoginManager.php
@@ -1,6 +1,7 @@
1<?php 1<?php
2namespace Shaarli\Security; 2namespace Shaarli\Security;
3 3
4use Exception;
4use Shaarli\Config\ConfigManager; 5use Shaarli\Config\ConfigManager;
5 6
6/** 7/**
@@ -139,26 +140,71 @@ class LoginManager
139 */ 140 */
140 public function checkCredentials($remoteIp, $clientIpId, $login, $password) 141 public function checkCredentials($remoteIp, $clientIpId, $login, $password)
141 { 142 {
142 $hash = sha1($password . $login . $this->configManager->get('credentials.salt')); 143 // Check login matches config
144 if ($login != $this->configManager->get('credentials.login')) {
145 return false;
146 }
143 147
144 if ($login != $this->configManager->get('credentials.login') 148 // Check credentials
145 || $hash != $this->configManager->get('credentials.hash') 149 try {
146 ) { 150 if (($this->configManager->get('ldap.host') != "" && $this->checkCredentialsFromLdap($login, $password))
151 || ($this->configManager->get('ldap.host') == "" && $this->checkCredentialsFromLocalConfig($login, $password))) {
152 $this->sessionManager->storeLoginInfo($clientIpId);
153 logm(
154 $this->configManager->get('resource.log'),
155 $remoteIp,
156 'Login successful'
157 );
158 return true;
159 }
160 }
161 catch(Exception $exception) {
147 logm( 162 logm(
148 $this->configManager->get('resource.log'), 163 $this->configManager->get('resource.log'),
149 $remoteIp, 164 $remoteIp,
150 'Login failed for user ' . $login 165 'Exception while checking credentials: ' . $exception
151 ); 166 );
152 return false;
153 } 167 }
154 168
155 $this->sessionManager->storeLoginInfo($clientIpId);
156 logm( 169 logm(
157 $this->configManager->get('resource.log'), 170 $this->configManager->get('resource.log'),
158 $remoteIp, 171 $remoteIp,
159 'Login successful' 172 'Login failed for user ' . $login
160 ); 173 );
161 return true; 174 return false;
175 }
176
177
178 /**
179 * Check user credentials from local config
180 *
181 * @param string $login Username
182 * @param string $password Password
183 *
184 * @return bool true if the provided credentials are valid, false otherwise
185 */
186 public function checkCredentialsFromLocalConfig($login, $password) {
187 $hash = sha1($password . $login . $this->configManager->get('credentials.salt'));
188
189 return $login == $this->configManager->get('credentials.login')
190 && $hash == $this->configManager->get('credentials.hash');
191 }
192
193 /**
194 * Check user credentials are valid through LDAP bind
195 *
196 * @param string $remoteIp Remote client IP address
197 * @param string $clientIpId Client IP address identifier
198 * @param string $login Username
199 * @param string $password Password
200 *
201 * @return bool true if the provided credentials are valid, false otherwise
202 */
203 public function checkCredentialsFromLdap($login, $password, $connect = null, $bind = null)
204 {
205 $connect = $connect ?? function($host) { return ldap_connect($host); };
206 $bind = $bind ?? function($handle, $dn, $password) { return ldap_bind($handle, $dn, $password); };
207 return $bind($connect($this->configManager->get('ldap.host')), sprintf($this->configManager->get('ldap.dn'), $login), $password);
162 } 208 }
163 209
164 /** 210 /**
diff --git a/doc/md/Shaarli-configuration.md b/doc/md/Shaarli-configuration.md
index 664e36dd..2462e20e 100644
--- a/doc/md/Shaarli-configuration.md
+++ b/doc/md/Shaarli-configuration.md
@@ -122,6 +122,11 @@ Must be an associative array: `translation domain => translation path`.
122- **enable_thumbnails**: Enable or disable thumbnail display. 122- **enable_thumbnails**: Enable or disable thumbnail display.
123- **enable_localcache**: Enable or disable local cache. 123- **enable_localcache**: Enable or disable local cache.
124 124
125### LDAP
126
127- **host**: LDAP host used for user authentication
128- **dn**: user DN template (`sprintf` format, `%s` being replaced by user login)
129
125## Configuration file example 130## Configuration file example
126 131
127```json 132```json
@@ -223,6 +228,10 @@ Must be an associative array: `translation domain => translation path`.
223 "extensions": { 228 "extensions": {
224 "demo": "plugins/demo_plugin/languages/" 229 "demo": "plugins/demo_plugin/languages/"
225 } 230 }
231 },
232 "ldap": {
233 "host": "ldap://localhost",
234 "dn": "uid=%s,ou=people,dc=example,dc=org"
226 } 235 }
227} ?> 236} ?>
228``` 237```
diff --git a/tests/security/LoginManagerTest.php b/tests/security/LoginManagerTest.php
index eef0f22a..f2d78802 100644
--- a/tests/security/LoginManagerTest.php
+++ b/tests/security/LoginManagerTest.php
@@ -78,6 +78,7 @@ class LoginManagerTest extends TestCase
78 'security.ban_after' => 2, 78 'security.ban_after' => 2,
79 'security.ban_duration' => 3600, 79 'security.ban_duration' => 3600,
80 'security.trusted_proxies' => [$this->trustedProxy], 80 'security.trusted_proxies' => [$this->trustedProxy],
81 'ldap.host' => '',
81 ]); 82 ]);
82 83
83 $this->cookie = []; 84 $this->cookie = [];
@@ -296,4 +297,37 @@ class LoginManagerTest extends TestCase
296 $this->loginManager->checkCredentials('', '', $this->login, $this->password) 297 $this->loginManager->checkCredentials('', '', $this->login, $this->password)
297 ); 298 );
298 } 299 }
300
301 /**
302 * Check user credentials through LDAP - server unreachable
303 */
304 public function testCheckCredentialsFromUnreachableLdap()
305 {
306 $this->configManager->set('ldap.host', 'dummy');
307 $this->assertFalse(
308 $this->loginManager->checkCredentials('', '', $this->login, $this->password)
309 );
310 }
311
312 /**
313 * Check user credentials through LDAP - wrong login and password supplied
314 */
315 public function testCheckCredentialsFromLdapWrongLoginAndPassword()
316 {
317 $this->coddnfigManager->set('ldap.host', 'dummy');
318 $this->assertFalse(
319 $this->loginManager->checkCredentialsFromLdap($this->login, $this->password, function() { return null; }, function() { return false; })
320 );
321 }
322
323 /**
324 * Check user credentials through LDAP - correct login and password supplied
325 */
326 public function testCheckCredentialsFromLdapGoodLoginAndPassword()
327 {
328 $this->configManager->set('ldap.host', 'dummy');
329 $this->assertTrue(
330 $this->loginManager->checkCredentialsFromLdap($this->login, $this->password, function() { return null; }, function() { return true; })
331 );
332 }
299} 333}