From 400a1adfde3dd730b040c2c73855a98180802e7c Mon Sep 17 00:00:00 2001 From: Paolo Date: Thu, 21 Mar 2019 15:36:22 +0100 Subject: [PATCH] - Added new entry permission_loginas_personids_blacklist in config file permission.php - Renamed method loginAS to loginASByUID in AuthLib.php - Added new public method loginASByPersonId to AuthLib.php - Renamed method connect to anonymousConnect in LDAPLib - Method LDAPLib->connectUsernamePassword now checks both username and password if they are empty strings - Added new constant LOGINAS_PERSONIDS_BLACKLIST to PermissionLib - Renamed method isEntitledLoginAS to isEntitledLoginASByUID in PermissionLib - Added new public method isEntitledLoginASByPersonId to PermissionLib - Added new private method _inLAPersonIdsBlacklist to PermissionLib --- application/config/permission.php | 7 ++- application/libraries/AuthLib.php | 81 +++++++++++++++++++------ application/libraries/LDAPLib.php | 6 +- application/libraries/PermissionLib.php | 29 ++++++--- 4 files changed, 92 insertions(+), 31 deletions(-) diff --git a/application/config/permission.php b/application/config/permission.php index 9bf5af88c..2fe5b6bba 100644 --- a/application/config/permission.php +++ b/application/config/permission.php @@ -2,11 +2,14 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); -// List of permissions that are allowed to perform loginAs +// List of permissions that are allowed to perform loginAs (empty array to avoid any checks) $config['permission_loginas_allowed'] = array('admin'); -// List of permissions that cannot be gained with loginAs +// List of permissions that cannot be gained with loginAs (empty array to avoid any checks) $config['permission_loginas_blacklist'] = array('admin'); // List of users whose identity cannot be obtained with loginAs $config['permission_loginas_users_blacklist'] = array('_DummyLektor', '_DummyStudent'); + +// List of person ids whose identity cannot be obtained with loginAs +$config['permission_loginas_personids_blacklist'] = array(92); diff --git a/application/libraries/AuthLib.php b/application/libraries/AuthLib.php index 10a36439e..c59933613 100644 --- a/application/libraries/AuthLib.php +++ b/application/libraries/AuthLib.php @@ -54,30 +54,74 @@ class AuthLib } /** - * The logged user is able to get the identity of another user if it is allowed + * The logged user is able, if it is allowed, to get the identity of another user by its given uid */ - public function loginAS($uid) + public function loginASByUID($uid) { $loginAS = error('Not authenticated', AUTH_NOT_AUTHENTICATED); // not authenticated by default - // - A user must be already logged - // - The uid must be NOT an empty string - // - The current user should NOT be already logged as the given uid - if ($this->_isLogged() && !isEmptyString($uid) && $this->getAuthObj()->username != $uid) + // A user must be already logged + if ($this->_isLogged()) { - $this->_ci->load->library('PermissionLib'); // Loads permissions library - - // Checks if the logged user is allowed to obtain the new identity - if ($this->_ci->permissionlib->isEntitledLoginAS($uid)) + // - The uid must be NOT an empty string + // - The current user should NOT be already logged as the given uid + if (!isEmptyString($uid) && $this->getAuthObj()->username != $uid) { - // Create the authentication object with new identity data - $loginAS = $this->_createAuthObjByPerson(array('uid' => $uid)); - if (isSuccess($loginAS)) + $this->_ci->load->library('PermissionLib'); // Loads permissions library + + // Checks if the logged user is allowed to obtain the new identity + if ($this->_ci->permissionlib->isEntitledLoginASByUID($uid)) { - // Store the new authentication object in authentication session - setSessionElement(self::SESSION_NAME, self::SESSION_AUTH_OBJ, getData($loginAS)); + // Create the authentication object with new identity data + $loginAS = $this->_createAuthObjByPerson(array('uid' => $uid)); + if (isSuccess($loginAS)) + { + // Store the new authentication object in authentication session + setSessionElement(self::SESSION_NAME, self::SESSION_AUTH_OBJ, getData($loginAS)); + } } } + else + { + $loginAS = error('The given uid is not valid', AUTH_INVALID_CREDENTIALS); + } + } + + return $loginAS; + } + + /** + * The logged user is able, if it is allowed, to get the identity of another user by its given person id + */ + public function loginASByPersonId($person_id) + { + $loginAS = error('Not authenticated', AUTH_NOT_AUTHENTICATED); // not authenticated by default + + // A user must be already logged + if ($this->_isLogged()) + { + // - The person id must be a number + // - The current user should NOT be already logged as the given person id + if (is_numeric($person_id) && $this->getAuthObj()->person_id != $person_id) + { + $this->_ci->load->library('PermissionLib'); // Loads permissions library + + // Checks if the logged user is allowed to obtain the new identity + if ($this->_ci->permissionlib->isEntitledLoginASByPersonId($person_id)) + { + // Create the authentication object with new identity data + $loginAS = $this->_createAuthObjByPerson(array('person_id' => $person_id)); + if (isSuccess($loginAS)) + { + // Store the new authentication object in authentication session + setSessionElement(self::SESSION_NAME, self::SESSION_AUTH_OBJ, getData($loginAS)); + } + } + } + else + { + $loginAS = error('The given person id is not valid', AUTH_INVALID_CREDENTIALS); + } } return $loginAS; @@ -296,7 +340,8 @@ class AuthLib $hta = error('Not authenticated', AUTH_NOT_AUTHENTICATED); // by default is NOT authenticated // Checks if an HTTP basic authentication is active and checks credentials using LDAP - if (!isset($_SERVER['PHP_AUTH_USER']) || isError($hta = $this->_checkLDAPAuthentication($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']))) + if (!isset($_SERVER['PHP_AUTH_USER']) + || isError($hta = $this->_checkLDAPAuthentication($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']))) { // If NOT send the header to perform an HTTP basic authentication header('WWW-Authenticate: Basic realm="'.AUTH_NAME.'"'); @@ -330,14 +375,14 @@ class AuthLib $this->_ci->load->library('LDAPLib'); // Loads the LDAP library - $ldapConnection = $this->_ci->ldaplib->connect(); // connect! + $ldapConnection = $this->_ci->ldaplib->anonymousConnect(); // connect anonymously! if (isSuccess($ldapConnection)) // connected!! { // Get the user DN from LDAP $userDN = $this->_ci->ldaplib->getUserDN($username); if (isSuccess($userDN)) // got it! { - $this->_ci->ldaplib->close(); // close the previous LDAP connection + $this->_ci->ldaplib->close(); // close the previous LDAP anonymous connection // Connects to LDAP using the last working configuration + the retrieved user DN + the provided password $ldapConnection = $this->_ci->ldaplib->connectUsernamePassword(getData($userDN), $password); diff --git a/application/libraries/LDAPLib.php b/application/libraries/LDAPLib.php index 06c238f85..57c8902b5 100644 --- a/application/libraries/LDAPLib.php +++ b/application/libraries/LDAPLib.php @@ -44,7 +44,7 @@ class LDAPLib * The first that works is used and stored in property _workingConfigArray * The LDAP connection link is stored in _connection */ - public function connect() + public function anonymousConnect() { $connect = error('Did not found a working LDAP configuration'); @@ -67,10 +67,12 @@ class LDAPLib } /** - * Tries to reconnect using the given username and password and the last working configuration + * Tries to connect using the given username and password and the last working configuration with anonymous connection */ public function connectUsernamePassword($username, $password) { + if (isEmptyString($username) || isEmptyString($password)) return error('Wrong username and password'); + return $this->_connect($this->_workingConfigArray, $username, $password); } diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index 791bef87a..f68ea983e 100644 --- a/application/libraries/PermissionLib.php +++ b/application/libraries/PermissionLib.php @@ -45,6 +45,7 @@ class PermissionLib const LOGINAS_ALLOWED = 'permission_loginas_allowed'; const LOGINAS_BLACKLIST = 'permission_loginas_blacklist'; const LOGINAS_USERS_BLACKLIST = 'permission_loginas_users_blacklist'; + const LOGINAS_PERSONIDS_BLACKLIST = 'permission_loginas_personids_blacklist'; private $_ci; // CI instance private static $bb; // benutzerberechtigung @@ -238,11 +239,20 @@ class PermissionLib /** * Checks if it is possible for the logged user to gain the identity of the required user specified by the given uid */ - public function isEntitledLoginAS($uid) + public function isEntitledLoginASByUID($uid) { return !$this->_inLAUsersBlacklist($uid) && !$this->_hasLANotAllowedPermissions($uid) && $this->_hasLAPermissions(); } + /** + * Checks if it is possible for the logged user to gain the identity of the required user specified by the given person id + * NOTE: does NOT check permission for the given user because usually this users do NOT have any uid + */ + public function isEntitledLoginASByPersonId($person_id) + { + return !$this->_inLAPersonIdsBlacklist($person_id) && $this->_hasLAPermissions(); + } + //------------------------------------------------------------------------------------------------------------------ // Private methods @@ -251,16 +261,17 @@ class PermissionLib */ private function _inLAUsersBlacklist($uid) { - // List of users whose identity cannot be obtained with loginAs - $loginASUsersBl = $this->_ci->config->item(self::LOGINAS_USERS_BLACKLIST); - // Given uid in user blacklist? - if (in_array($uid, $loginASUsersBl)) - { - return true; - } + return in_array($uid, $this->_ci->config->item(self::LOGINAS_USERS_BLACKLIST)); + } - return false; + /** + * Checks if the given person id is in the person ids blacklist + */ + private function _inLAPersonIdsBlacklist($person_id) + { + // Given person id in person ids blacklist? + return in_array($person_id, $this->_ci->config->item(self::LOGINAS_PERSONIDS_BLACKLIST)); } /**