diff --git a/config/authentication.ini.in b/config/authentication.ini.in index 71d9e4402..2a2d2a969 100644 --- a/config/authentication.ini.in +++ b/config/authentication.ini.in @@ -18,6 +18,10 @@ backend = ldap resource = internal_ldap user_class = @ldap_user_objectclass@ user_name_attribute = @ldap_attribute_username@ +group_base_dn = @ldap_group_base_dn@ +group_attribute = @ldap_group_attribute@ +group_member_attribute = @ldap_group_member_attribute@ +group_class = @ldap_group_class@ [internal_db_authentication] @internal_auth_disabled@ diff --git a/library/Icinga/Authentication/Backend/LdapUserBackend.php b/library/Icinga/Authentication/Backend/LdapUserBackend.php index 23a79781d..247f63853 100644 --- a/library/Icinga/Authentication/Backend/LdapUserBackend.php +++ b/library/Icinga/Authentication/Backend/LdapUserBackend.php @@ -4,6 +4,7 @@ namespace Icinga\Authentication\Backend; +use Icinga\Logger\Logger; use Icinga\User; use Icinga\Authentication\UserBackend; use Icinga\Protocol\Ldap\Connection; @@ -23,11 +24,14 @@ class LdapUserBackend extends UserBackend protected $userNameAttribute; - public function __construct(Connection $conn, $userClass, $userNameAttribute) + protected $groupOptions; + + public function __construct(Connection $conn, $userClass, $userNameAttribute, $groupOptions = null) { $this->conn = $conn; $this->userClass = $userClass; $this->userNameAttribute = $userNameAttribute; + $this->groupOptions = $groupOptions; } /** @@ -83,6 +87,41 @@ class LdapUserBackend extends UserBackend } } + /** + * Retrieve the user groups + * + * @param string $dn + * + * @return array|null + */ + public function getGroups($dn) + { + if (empty($this->groupOptions)) { + return null; + } + + $q = $this->conn->select() + ->setBase($this->groupOptions['group_base_dn']) + ->from( + $this->groupOptions['group_class'], + array($this->groupOptions['group_attribute']) + ) + ->where( + $this->groupOptions['group_member_attribute'], + $dn + ); + + $result = $this->conn->fetchAll($q); + + $groups = array(); + + foreach ($result as $group) { + $groups[] = $group->{$this->groupOptions['group_attribute']}; + } + + return $groups; + } + /** * Test whether the given user exists * @@ -127,10 +166,15 @@ class LdapUserBackend extends UserBackend return false; } try { - return $this->conn->testCredentials( - $this->conn->fetchDN($this->createQuery($user->getUsername())), + $userDn = $this->conn->fetchDN($this->createQuery($user->getUsername())); + $authenticated = $this->conn->testCredentials( + $userDn, $password ); + if ($authenticated) { + $user->setGroups($this->getGroups($userDn)); + } + return $authenticated; } catch (LdapException $e) { // Error during authentication of this specific user throw new AuthenticationException( @@ -160,4 +204,3 @@ class LdapUserBackend extends UserBackend ); } } - diff --git a/library/Icinga/Authentication/UserBackend.php b/library/Icinga/Authentication/UserBackend.php index 9e7abd62a..b475e9135 100644 --- a/library/Icinga/Authentication/UserBackend.php +++ b/library/Icinga/Authentication/UserBackend.php @@ -93,26 +93,34 @@ abstract class UserBackend implements Countable $backend = new DbUserBackend($resource); break; case 'msldap': + self::checkLdapConfiguration($name, $backendConfig); + $groupOptions = array( + 'group_base_dn' => $backendConfig->group_base_dn, + 'group_attribute' => $backendConfig->group_attribute, + 'group_member_attribute' => $backendConfig->group_member_attribute, + 'group_class' => $backendConfig->group_class + ); $backend = new LdapUserBackend( $resource, $backendConfig->get('user_class', 'user'), - $backendConfig->get('user_name_attribute', 'sAMAccountName') + $backendConfig->get('user_name_attribute', 'sAMAccountName'), + $groupOptions ); break; case 'ldap': - if (($userClass = $backendConfig->user_class) === null) { - throw new ConfigurationError( - 'Authentication configuration for backend "%s" is missing the user_class directive', - $name - ); - } - if (($userNameAttribute = $backendConfig->user_name_attribute) === null) { - throw new ConfigurationError( - 'Authentication configuration for backend "%s" is missing the user_name_attribute directive', - $name - ); - } - $backend = new LdapUserBackend($resource, $userClass, $userNameAttribute); + self::checkLdapConfiguration($name, $backendConfig); + $groupOptions = array( + 'group_base_dn' => $backendConfig->group_base_dn, + 'group_attribute' => $backendConfig->group_attribute, + 'group_member_attribute' => $backendConfig->group_member_attribute, + 'group_class' => $backendConfig->group_class + ); + $backend = new LdapUserBackend( + $resource, + $backendConfig->user_class, + $backendConfig->user_name_attribute, + $groupOptions + ); break; default: throw new ConfigurationError( @@ -144,4 +152,52 @@ abstract class UserBackend implements Countable * @return bool */ abstract public function authenticate(User $user, $password); + + /** + * Checks the ldap configuration + * + * @param $name + * @param Zend_Config $backendConfig + * + * @throws \Icinga\Exception\ConfigurationError + */ + protected static function checkLdapConfiguration($name, Zend_Config $backendConfig) + { + if ($backendConfig->user_class === null) { + throw new ConfigurationError( + 'Authentication configuration for backend "%s" is missing the user_class directive', + $name + ); + } + if ($backendConfig->user_name_attribute === null) { + throw new ConfigurationError( + 'Authentication configuration for backend "%s" is missing the user_name_attribute directive', + $name + ); + } + if ($backendConfig->group_base_dn === null) { + throw new ConfigurationError( + 'Authentication configuration for backend "%s" is missing the group_base_dn directive', + $name + ); + } + if ($backendConfig->group_attribute === null) { + throw new ConfigurationError( + 'Authentication configuration for backend "%s" is missing the group_attribute directive', + $name + ); + } + if ($backendConfig->group_member_attribute === null) { + throw new ConfigurationError( + 'Authentication configuration for backend "%s" is missing the group_member_attribute directive', + $name + ); + } + if ($backendConfig->group_class === null) { + throw new ConfigurationError( + 'Authentication configuration for backend "%s" is missing the group_class directive', + $name + ); + } + } }