Skip to content

Commit

Permalink
ldap authentication, fixes shaarli#1343
Browse files Browse the repository at this point in the history
  • Loading branch information
pipoprods committed Mar 2, 2020
1 parent 810f0f6 commit cc2ded5
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 9 deletions.
64 changes: 55 additions & 9 deletions application/security/LoginManager.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Shaarli\Security;

use Exception;
use Shaarli\Config\ConfigManager;

/**
Expand Down Expand Up @@ -139,26 +140,71 @@ public function isLoggedIn()
*/
public function checkCredentials($remoteIp, $clientIpId, $login, $password)
{
$hash = sha1($password . $login . $this->configManager->get('credentials.salt'));
// Check login matches config
if ($login != $this->configManager->get('credentials.login')) {
return false;
}

if ($login != $this->configManager->get('credentials.login')
|| $hash != $this->configManager->get('credentials.hash')
) {
// Check credentials
try {
if (($this->configManager->get('ldap.host') != "" && $this->checkCredentialsFromLdap($login, $password))
|| ($this->configManager->get('ldap.host') == "" && $this->checkCredentialsFromLocalConfig($login, $password))) {
$this->sessionManager->storeLoginInfo($clientIpId);
logm(
$this->configManager->get('resource.log'),
$remoteIp,
'Login successful'
);
return true;
}
}
catch(Exception $exception) {
logm(
$this->configManager->get('resource.log'),
$remoteIp,
'Login failed for user ' . $login
'Exception while checking credentials: ' . $exception
);
return false;
}

$this->sessionManager->storeLoginInfo($clientIpId);
logm(
$this->configManager->get('resource.log'),
$remoteIp,
'Login successful'
'Login failed for user ' . $login
);
return true;
return false;
}


/**
* Check user credentials from local config
*
* @param string $login Username
* @param string $password Password
*
* @return bool true if the provided credentials are valid, false otherwise
*/
public function checkCredentialsFromLocalConfig($login, $password) {
$hash = sha1($password . $login . $this->configManager->get('credentials.salt'));

return $login == $this->configManager->get('credentials.login')
&& $hash == $this->configManager->get('credentials.hash');
}

/**
* Check user credentials are valid through LDAP bind
*
* @param string $remoteIp Remote client IP address
* @param string $clientIpId Client IP address identifier
* @param string $login Username
* @param string $password Password
*
* @return bool true if the provided credentials are valid, false otherwise
*/
public function checkCredentialsFromLdap($login, $password, $connect = null, $bind = null)
{
$connect = $connect ?? function($host) { return ldap_connect($host); };
$bind = $bind ?? function($handle, $dn, $password) { return ldap_bind($handle, $dn, $password); };
return $bind($connect($this->configManager->get('ldap.host')), sprintf($this->configManager->get('ldap.dn'), $login), $password);
}

/**
Expand Down
9 changes: 9 additions & 0 deletions doc/md/Shaarli-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ Must be an associative array: `translation domain => translation path`.
- **enable_thumbnails**: Enable or disable thumbnail display.
- **enable_localcache**: Enable or disable local cache.

### LDAP

- **host**: LDAP host used for user authentication
- **dn**: user DN template (`sprintf` format, `%s` being replaced by user login)

## Configuration file example

```json
Expand Down Expand Up @@ -223,6 +228,10 @@ Must be an associative array: `translation domain => translation path`.
"extensions": {
"demo": "plugins/demo_plugin/languages/"
}
},
"ldap": {
"host": "ldap://localhost",
"dn": "uid=%s,ou=people,dc=example,dc=org"
}
} ?>
```
Expand Down
34 changes: 34 additions & 0 deletions tests/security/LoginManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public function setUp()
'security.ban_after' => 2,
'security.ban_duration' => 3600,
'security.trusted_proxies' => [$this->trustedProxy],
'ldap.host' => '',
]);

$this->cookie = [];
Expand Down Expand Up @@ -296,4 +297,37 @@ public function testCheckCredentialsGoodLoginAndPassword()
$this->loginManager->checkCredentials('', '', $this->login, $this->password)
);
}

/**
* Check user credentials through LDAP - server unreachable
*/
public function testCheckCredentialsFromUnreachableLdap()
{
$this->configManager->set('ldap.host', 'dummy');
$this->assertFalse(
$this->loginManager->checkCredentials('', '', $this->login, $this->password)
);
}

/**
* Check user credentials through LDAP - wrong login and password supplied
*/
public function testCheckCredentialsFromLdapWrongLoginAndPassword()
{
$this->coddnfigManager->set('ldap.host', 'dummy');
$this->assertFalse(
$this->loginManager->checkCredentialsFromLdap($this->login, $this->password, function() { return null; }, function() { return false; })
);
}

/**
* Check user credentials through LDAP - correct login and password supplied
*/
public function testCheckCredentialsFromLdapGoodLoginAndPassword()
{
$this->configManager->set('ldap.host', 'dummy');
$this->assertTrue(
$this->loginManager->checkCredentialsFromLdap($this->login, $this->password, function() { return null; }, function() { return true; })
);
}
}

1 comment on commit cc2ded5

@Jaxom99
Copy link

@Jaxom99 Jaxom99 commented on cc2ded5 May 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, nice. How would you test that bit ?
Might be interesting along with this issue !

Please sign in to comment.