From 1f28d43a70a927a9cd2877bda606d1e89437587a Mon Sep 17 00:00:00 2001 From: Etienne Pallier Date: Wed, 13 Feb 2019 15:22:39 +0100 Subject: [PATCH] Bugfix LDAP anonyme et refactorisation --- README.md | 7 ++++--- UPDATE | 1 + src/Model/Table/LdapConnectionsTable.php | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 125 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index d33e3e3..31a8024 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,12 @@ Logiciel testé et validé sur les configurations suivantes : VERSION ACTUELLE -Date: 12/02/2019 -Version: 2.10.8 +Date: 13/02/2019 +Version: 2.10.9 Author: EP - Bugfix LDAP anonyme se faisait sans vérifier le mot de passe utilisateur !!! + Bugfix LDAP anonyme et refactorisation + LDAP anonyme se faisait sans vérifier le mot de passe utilisateur !!! IMPORTANT: - Pour connaitre la version actuelle, taper "./VERSION" - Pour mettre à jour le code, utiliser ./UPDATE depuis la racine du projet (ne plus se contenter de faire "git pull") diff --git a/UPDATE b/UPDATE index da06d53..3e7ec66 100644 --- a/UPDATE +++ b/UPDATE @@ -2,3 +2,4 @@ cd install/ ./update.sh + diff --git a/src/Model/Table/LdapConnectionsTable.php b/src/Model/Table/LdapConnectionsTable.php index 2cfbcd1..df63fc3 100755 --- a/src/Model/Table/LdapConnectionsTable.php +++ b/src/Model/Table/LdapConnectionsTable.php @@ -173,12 +173,16 @@ class LdapConnectionsTable extends AppTable '); } + // REAL or FAKE LDAP public function getAllLdapUsers() { try { if ($this->checkConfiguration()) { + // REAL LDAP if ($this->LDAP_USED) { + $res = $this->searchLdap($this->filter, []); + /* $ldapConnection = ldap_connect($this->host, $this->port); ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3); @@ -189,7 +193,9 @@ class LdapConnectionsTable extends AppTable $results = ldap_search($ldapConnection, $this->baseDn, $this->filter); $res = ldap_get_entries($ldapConnection, $results); - } + */ + } + // FAKE LDAP else { $res = $this->fakeLDAPUsers; @@ -199,19 +205,25 @@ class LdapConnectionsTable extends AppTable } catch (Exception $e) {} return false; } + + // REAL LDAP only /* - * @param unknown $userName (= login) * @param string $ldapConnection * @param string $filter * @param array $just_these - * @return $info = ldap search result (user attributes) or FALSE + * @param string $userName (= login) => for FAKE LDAP only + * @return $res = ldap search result (1 user or all users attributes) or FALSE */ - public function getUserAttributes($userName, $ldapConnection='', $filter='', $just_these=[]) + //public function getUserAttributes($userName, $ldapConnection='', $filter='', $just_these=[]) + //public function getUserAttributes($ldapConnection='', $filter='', $just_these=[], $userName=NULL) + public function getLdapUsersAttributes($ldapConnection, $filter='', $just_these=[]) { try { if ($this->checkConfiguration()) { - if ($this->LDAP_USED) { + + // LDAP mode + //if ($this->LDAP_USED) { /* (EP) Fonction ldap_search ($link_identifier, $base_dn, $filter, array $attributes = null, $attrsonly = null, $sizelimit = null, $timelimit = null, $deref = null) Concernant le paramètre $attributes (ici, $just_these) : @@ -230,13 +242,21 @@ class LdapConnectionsTable extends AppTable Quand on n'utilise pas $just_these, la fonction ldap_search() retourne TOUS les attributs disponibles, donc c'est le comportement qu'on veut ici. */ + + //$search = $this->getUserAttributes($ldapConnection, $filter, $just_these, $user_login); + //$results = ldap_search($ldapConnection, $this->baseDn, $this->filter); + $results = ldap_search($ldapConnection, $this->baseDn, $filter, $just_these) or die("Could not search to LDAP server response was: " . ldap_error($ldapConnection) ); - $info = ldap_get_entries($ldapConnection, $results); + $res = ldap_get_entries($ldapConnection, $results); //echo $info["count"]." entries returned\n"; - return $info; - } - else return array( $this->getFakeLdapUser($userName) ); + return $res; + //} + + // FAKE LDAP mode + //else return array( $this->getFakeLdapUser($userName) ); + //else return $this->fakeLDAPUsers; + } } catch (Exception $e) { echo 'Exception LDAP : ', $e->getMessage(), "\n"; @@ -244,7 +264,8 @@ class LdapConnectionsTable extends AppTable return false; } - + + public function getAuthenticationType() { return $this->authenticationType; @@ -266,20 +287,29 @@ class LdapConnectionsTable extends AppTable public function getListUsers() { $u = $this->getAllLdapUsers(); + //debug($u); $utilisateurs = []; + // (EP) Refactorisation pour éviter code redondant ci-dessous, c'était pourtant pas compliqué, poil dans la main... + $nb_users = $this->LDAP_USED ? $u['count'] : sizeof($u)-1; + for ($i = 0; $i < $nb_users; $i ++) + // $utilisateurs["Pallier Etienne"] = "Pallier Etienne" + $utilisateurs[ $u[$i]['sn'][0].' '.$u[$i]['givenname'][0] ] = $u[$i]['sn'][0].' '.$u[$i]['givenname'][0]; + /* if ($this->LDAP_USED) { for ($i = 0; $i < $u['count']; $i ++) { - $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = $u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]; + $utilisateurs[ $u[$i]['sn'][0].' '.$u[$i]['givenname'][0] ] = $u[$i]['sn'][0].' '.$u[$i]['givenname'][0]; } } else { for ($i = 0; $i < sizeof($u) - 1; $i ++) { - $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = $u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]; + $utilisateurs[ $u[$i]['sn'][0].' '.$u[$i]['givenname'][0] ] = $u[$i]['sn'][0].' '.$u[$i]['givenname'][0]; } } - + */ + //debug($utilisateurs); return $utilisateurs; } + /** * Return a list of login ofUsers with key = username & value = login @@ -352,13 +382,67 @@ class LdapConnectionsTable extends AppTable ]; } + + // TODO: implement + // REAL LDAP only + private function checkAndFetchUserFromDB($user_login, $user_password) { + // By default, user is not in DB + return FALSE; + } + + + // REAL LDAP only + private function searchLdap($filter, $just_these, $user_login=NULL, $user_password=NULL) { + + // CONNEXION + $ldapConnection = ldap_connect($this->host, $this->port) + or die("Could not connect to $this->host (port $this->port)"); + + if ($ldapConnection) { + + // OPTIONS + ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3); + + // BINDING + + // - Authentified + if ($this->ldap_authentified) + $ldapbind = ldap_bind($ldapConnection, $this->bindDn, $this->bindPass); // or die("Could not bind to LDAP server.". ldap_error($ldapConnection) ); + + // - Anonymous + // En cas de LDAP anonyme, binding quand même pour vérifier le mot de passe de l'utilisateur. + // Sans cette ligne, on passe avec n'importe quel password !!! + else { + $ldapbind = TRUE; + debug("log, pass= " . $user_login . ' ' . $user_password); + if ($user_login && $user_password) $ldapbind = ldap_bind($ldapConnection, $this->authenticationType.'='.$user_login, $user_password); + debug("ldapbind " . $ldapbind); + } + + // SEARCH + if ($ldapbind) { + //$search = $this->getLdapUserAttributes($ldapConnection, $filter, $just_these, $user_login); + $search = $this->getLdapUsersAttributes($ldapConnection, $filter, $just_these); + if ($search === false) die("Could not get user attributes from LDAP server, response was: " . ldap_error($ldapConnection) ); + //return $search[0]; + return $search; + } + + } + + // Il y a eu un pb, utilisateur non reconnu + return FALSE; + + } + - private function checkAndGetLdapUser($user_login, $user_password) { + // REAL LDAP only + private function checkAndFetchUserFromLdap($user_login, $user_password) { // Set LDAP parameters // - Liste des attributs à récupérer dans le ldap (vide = TOUS les attributs) $just_these = []; // TODO: vérifier si cette ligne est bien utile ou pas... (avant on faisait ça) - //if ($this->ldap_authentified) $just_these = array("cn"); + if (! $this->ldap_authentified) $just_these = array("cn"); /* Examples : * @@ -381,6 +465,10 @@ class LdapConnectionsTable extends AppTable //TODO: optimisation, refactoriser si comportement général //$binddn .= ','.$this->baseDn; + $res = $this->searchLdap($filter, $just_these, $user_login, $user_password); + if ($res != FALSE) return $res[0]; + + /* // CONNEXION $ldapConnection = ldap_connect($this->host, $this->port) or die("Could not connect to $this->host (port $this->port)"); @@ -406,12 +494,19 @@ class LdapConnectionsTable extends AppTable } } + */ // Il y a eu un pb, utilisateur non reconnu return FALSE; } + // TODO: implement + private function saveNewUserInDB($user_fetched) { + // SAVE new user in DB + return TRUE; + } + /* * @param string $user_login @@ -427,7 +522,16 @@ class LdapConnectionsTable extends AppTable if ($this->LDAP_USED) { // No connexion allowed without password if (strlen(trim($user_password)) == 0) return FALSE; - return $this->checkAndGetLdapUser($user_login, $user_password); + + // 1) Search user in CACHE (DB) + $user_fetched = $this->checkAndFetchUserFromDB($user_login, $user_password); + if ($user_fetched === FALSE) { + // 2) If not CACHED, search user in LDAP + $user_fetched = $this->checkAndFetchUserFromLdap($user_login, $user_password); + // CACHE the new user in DB for next time + if ($user_fetched != FALSE) $this->saveNewUserInDB($user_fetched); + } + return $user_fetched; // Noter que $user_fetched peut etre egal a FALSE (si pas trouvé) } // We are not using LDAP (so, use FAKE LDAP instead) -- libgit2 0.21.2