Merge pull request #1428 from pipoprods/feat/ldap-auth
This commit is contained in:
commit
78c2f122e0
3 changed files with 117 additions and 13 deletions
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Shaarli\Security;
|
namespace Shaarli\Security;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Shaarli\Config\ConfigManager;
|
use Shaarli\Config\ConfigManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,26 +140,86 @@ public function isLoggedIn()
|
||||||
*/
|
*/
|
||||||
public function checkCredentials($remoteIp, $clientIpId, $login, $password)
|
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')) {
|
||||||
if ($login != $this->configManager->get('credentials.login')
|
|
||||||
|| $hash != $this->configManager->get('credentials.hash')
|
|
||||||
) {
|
|
||||||
logm(
|
|
||||||
$this->configManager->get('resource.log'),
|
|
||||||
$remoteIp,
|
|
||||||
'Login failed for user ' . $login
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sessionManager->storeLoginInfo($clientIpId);
|
// Check credentials
|
||||||
|
try {
|
||||||
|
$useLdapLogin = !empty($this->configManager->get('ldap.host'));
|
||||||
|
if ((false === $useLdapLogin && $this->checkCredentialsFromLocalConfig($login, $password))
|
||||||
|
|| (true === $useLdapLogin && $this->checkCredentialsFromLdap($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,
|
||||||
|
'Exception while checking credentials: ' . $exception
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
logm(
|
logm(
|
||||||
$this->configManager->get('resource.log'),
|
$this->configManager->get('resource.log'),
|
||||||
$remoteIp,
|
$remoteIp,
|
||||||
'Login successful'
|
'Login failed for user ' . $login
|
||||||
|
);
|
||||||
|
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) {
|
||||||
|
$resource = ldap_connect($host);
|
||||||
|
|
||||||
|
ldap_set_option($resource, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||||
|
|
||||||
|
return $resource;
|
||||||
|
};
|
||||||
|
$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
|
||||||
);
|
);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -122,6 +122,11 @@ Must be an associative array: `translation domain => translation path`.
|
||||||
- **enable_thumbnails**: Enable or disable thumbnail display.
|
- **enable_thumbnails**: Enable or disable thumbnail display.
|
||||||
- **enable_localcache**: Enable or disable local cache.
|
- **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
|
## Configuration file example
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
@ -223,6 +228,10 @@ Must be an associative array: `translation domain => translation path`.
|
||||||
"extensions": {
|
"extensions": {
|
||||||
"demo": "plugins/demo_plugin/languages/"
|
"demo": "plugins/demo_plugin/languages/"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"host": "ldap://localhost",
|
||||||
|
"dn": "uid=%s,ou=people,dc=example,dc=org"
|
||||||
}
|
}
|
||||||
} ?>
|
} ?>
|
||||||
```
|
```
|
||||||
|
|
|
@ -78,6 +78,7 @@ public function setUp()
|
||||||
'security.ban_after' => 2,
|
'security.ban_after' => 2,
|
||||||
'security.ban_duration' => 3600,
|
'security.ban_duration' => 3600,
|
||||||
'security.trusted_proxies' => [$this->trustedProxy],
|
'security.trusted_proxies' => [$this->trustedProxy],
|
||||||
|
'ldap.host' => '',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->cookie = [];
|
$this->cookie = [];
|
||||||
|
@ -296,4 +297,37 @@ public function testCheckCredentialsGoodLoginAndPassword()
|
||||||
$this->loginManager->checkCredentials('', '', $this->login, $this->password)
|
$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->configManager->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; })
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue