From a41c655afe3fbe5e67f9aabbbbeecb1a074dde34 Mon Sep 17 00:00:00 2001 From: Kevin Duret Date: Wed, 21 Sep 2022 10:38:28 +0200 Subject: [PATCH 1/4] add debug and avoid ldap failures --- www/class/centreonContactgroup.class.php | 239 ++++++++++++----------- www/class/centreonLDAP.class.php | 58 ++++-- 2 files changed, 169 insertions(+), 128 deletions(-) diff --git a/www/class/centreonContactgroup.class.php b/www/class/centreonContactgroup.class.php index 9c297811ed3..4c8b55aa0f3 100644 --- a/www/class/centreonContactgroup.class.php +++ b/www/class/centreonContactgroup.class.php @@ -117,7 +117,11 @@ public function getLdapContactgroups($filter = '') $ldapRes = $this->db->query($query); while ($ldapRow = $ldapRes->fetch()) { $ldap = new CentreonLDAP($this->db, null, $ldapRow['ar_id']); - $ldap->connect(null, $ldapRow['ar_id']); + $isConnectedToLdap = $ldap->connect(); + if ($isConnectedToLdap === false) { + continue; + } + $ldapGroups = $ldap->listOfGroups(); foreach ($ldapGroups as $ldapGroup) { @@ -253,13 +257,17 @@ public function insertLdapGroup(string $cgName): ?int return $ldapGroupId; } - $ldap = new CentreonLDAP($this->db, null, $arId); - $ldap->connect(); - $ldapDn = $ldap->findGroupDn($cgName); - // Reset ldap build cache time $this->db->query('UPDATE options SET `value` = 0 WHERE `key` = "ldap_last_acl_update"'); + $ldap = new CentreonLDAP($this->db, null, $arId); + $isConnectedToLdap = $ldap->connect(); + if ($isConnectedToLdap === false) { + return null; + } + + $ldapDn = $ldap->findGroupDn($cgName); + if ($ldapDn !== false) { $this->insertLdapGroupByNameAndDn($arId, $cgName, $ldapDn); return $this->findLdapGroupIdByDn($arId, $ldapDn); @@ -382,133 +390,134 @@ public function syncWithLdap() while ($ldapRow = $ldapRes->fetch()) { $ldapConn = new CentreonLDAP($this->db, null, $ldapRow['ar_id']); $connectionResult = $ldapConn->connect(); - if (false != $connectionResult) { - $res = $this->db->prepare( - "SELECT cg_id, cg_name, cg_ldap_dn FROM contactgroup " . - "WHERE cg_type = 'ldap' AND ar_id = :arId" - ); - $res->bindValue(':arId', $ldapRow['ar_id'], \PDO::PARAM_INT); - $res->execute(); - - // insert groups from ldap into centreon - $registeredGroupsFromDB = $res->fetchAll(); - $registeredGroups = []; - foreach ($registeredGroupsFromDB as $registeredGroupFromDB) { - $registeredGroups[] = $registeredGroupFromDB['cg_name']; - } + if ($connectionResult === false) { + $msg[] = "Unable to connect to LDAP server."; + continue; + } - $ldapGroups = $ldapConn->listOfGroups(); + $res = $this->db->prepare( + "SELECT cg_id, cg_name, cg_ldap_dn FROM contactgroup " . + "WHERE cg_type = 'ldap' AND ar_id = :arId" + ); + $res->bindValue(':arId', $ldapRow['ar_id'], \PDO::PARAM_INT); + $res->execute(); + + // insert groups from ldap into centreon + $registeredGroupsFromDB = $res->fetchAll(); + $registeredGroups = []; + foreach ($registeredGroupsFromDB as $registeredGroupFromDB) { + $registeredGroups[] = $registeredGroupFromDB['cg_name']; + } - foreach ($ldapGroups as $ldapGroup) { - if (!in_array($ldapGroup['name'], $registeredGroups)) { - $this->insertLdapGroupByNameAndDn( - (int) $ldapRow['ar_id'], - $ldapGroup['name'], - $ldapGroup['dn'] - ); - } + $ldapGroups = $ldapConn->listOfGroups(); + + foreach ($ldapGroups as $ldapGroup) { + if (!in_array($ldapGroup['name'], $registeredGroups)) { + $this->insertLdapGroupByNameAndDn( + (int) $ldapRow['ar_id'], + $ldapGroup['name'], + $ldapGroup['dn'] + ); } + } - $res = $this->db->prepare( - "SELECT cg_id, cg_name, cg_ldap_dn FROM contactgroup " . - "WHERE cg_type = 'ldap' AND ar_id = :arId" - ); - $res->bindValue(':arId', $ldapRow['ar_id'], \PDO::PARAM_INT); - $res->execute(); + $res = $this->db->prepare( + "SELECT cg_id, cg_name, cg_ldap_dn FROM contactgroup " . + "WHERE cg_type = 'ldap' AND ar_id = :arId" + ); + $res->bindValue(':arId', $ldapRow['ar_id'], \PDO::PARAM_INT); + $res->execute(); - $this->db->beginTransaction(); - try { - while ($row = $res->fetch()) { - // Test is the group has not been moved or deleted in ldap - if ((empty($row['cg_ldap_dn']) || false === $ldapConn->getEntry($row['cg_ldap_dn'])) - && ldap_errno($ldapConn->getDs()) != 3 - ) { - $dn = $ldapConn->findGroupDn($row['cg_name']); - if (false === $dn && ldap_errno($ldapConn->getDs()) != 3) { - // Delete the ldap group in contactgroup - try { - $stmt = $this->db->prepare( - "DELETE FROM contactgroup WHERE cg_id = :cgId" - ); - $stmt->bindValue('cgId', $row['cg_id'], \PDO::PARAM_INT); - $stmt->execute(); - } catch (\PDOException $e) { - $msg[] = "Error processing delete contactgroup request of ldap group : " . - $row['cg_name']; - throw $e; - } - continue; - } else { // Update the ldap group dn in contactgroup - try { - $updateDnStatement = $this->db->prepare( - "UPDATE contactgroup SET cg_ldap_dn = :cg_dn WHERE cg_id = :cg_id" - ); - $updateDnStatement->bindValue(':cg_dn', $dn, \PDO::PARAM_STR); - $updateDnStatement->bindValue(':cg_id', $row['cg_id'], \PDO::PARAM_INT); - $updateDnStatement->execute(); - $row['cg_ldap_dn'] = $dn; - } catch (\PDOException $e) { - $msg[] = "Error processing update contactgroup request of ldap group : " . - $row['cg_name']; - throw $e; - } + $this->db->beginTransaction(); + try { + while ($row = $res->fetch()) { + // Test is the group has not been moved or deleted in ldap + if ((empty($row['cg_ldap_dn']) || false === $ldapConn->getEntry($row['cg_ldap_dn'])) + && ldap_errno($ldapConn->getDs()) != 3 + ) { + $dn = $ldapConn->findGroupDn($row['cg_name']); + if (false === $dn && ldap_errno($ldapConn->getDs()) != 3) { + // Delete the ldap group in contactgroup + try { + $stmt = $this->db->prepare( + "DELETE FROM contactgroup WHERE cg_id = :cgId" + ); + $stmt->bindValue('cgId', $row['cg_id'], \PDO::PARAM_INT); + $stmt->execute(); + } catch (\PDOException $e) { + $msg[] = "Error processing delete contactgroup request of ldap group : " . + $row['cg_name']; + throw $e; + } + continue; + } else { // Update the ldap group dn in contactgroup + try { + $updateDnStatement = $this->db->prepare( + "UPDATE contactgroup SET cg_ldap_dn = :cg_dn WHERE cg_id = :cg_id" + ); + $updateDnStatement->bindValue(':cg_dn', $dn, \PDO::PARAM_STR); + $updateDnStatement->bindValue(':cg_id', $row['cg_id'], \PDO::PARAM_INT); + $updateDnStatement->execute(); + $row['cg_ldap_dn'] = $dn; + } catch (\PDOException $e) { + $msg[] = "Error processing update contactgroup request of ldap group : " . + $row['cg_name']; + throw $e; } } - $members = $ldapConn->listUserForGroup($row['cg_ldap_dn']); + } + $members = $ldapConn->listUserForGroup($row['cg_ldap_dn']); - // Refresh Users Groups. - $deleteStmt = $this->db->prepare( - "DELETE FROM contactgroup_contact_relation - WHERE contactgroup_cg_id = :cgId" - ); - $deleteStmt->bindValue(':cgId', $row['cg_id'], \PDO::PARAM_INT); - $deleteStmt->execute(); - $contactDns = ''; - foreach ($members as $member) { - $contactDns .= $this->db->quote($member) . ','; + // Refresh Users Groups. + $deleteStmt = $this->db->prepare( + "DELETE FROM contactgroup_contact_relation + WHERE contactgroup_cg_id = :cgId" + ); + $deleteStmt->bindValue(':cgId', $row['cg_id'], \PDO::PARAM_INT); + $deleteStmt->execute(); + $contactDns = ''; + foreach ($members as $member) { + $contactDns .= $this->db->quote($member) . ','; + } + $contactDns = rtrim($contactDns, ","); + + if ($contactDns !== '') { + try { + $resContact = $this->db->query( + "SELECT contact_id FROM contact WHERE contact_ldap_dn IN (" . $contactDns . ")" + ); + } catch (\PDOException $e) { + $msg[] = "Error in getting contact id from members."; + throw $e; + continue; } - $contactDns = rtrim($contactDns, ","); - - if ($contactDns !== '') { + while ($rowContact = $resContact->fetch()) { try { - $resContact = $this->db->query( - "SELECT contact_id FROM contact WHERE contact_ldap_dn IN (" . $contactDns . ")" + $insertStmt = $this->db->prepare( + "INSERT INTO contactgroup_contact_relation + (contactgroup_cg_id, contact_contact_id) + VALUES (:cgId, :contactId)" ); + $insertStmt->bindValue(':cgId', $row['cg_id'], \PDO::PARAM_INT); + $insertStmt->bindValue(':contactId', $rowContact['contact_id'], \PDO::PARAM_INT); + $insertStmt->execute(); } catch (\PDOException $e) { - $msg[] = "Error in getting contact id from members."; + $msg[] = "Error insert relation between contactgroup " . $row['cg_id'] . + " and contact " . $rowContact['contact_id']; throw $e; - continue; - } - while ($rowContact = $resContact->fetch()) { - try { - $insertStmt = $this->db->prepare( - "INSERT INTO contactgroup_contact_relation - (contactgroup_cg_id, contact_contact_id) - VALUES (:cgId, :contactId)" - ); - $insertStmt->bindValue(':cgId', $row['cg_id'], \PDO::PARAM_INT); - $insertStmt->bindValue(':contactId', $rowContact['contact_id'], \PDO::PARAM_INT); - $insertStmt->execute(); - } catch (\PDOException $e) { - $msg[] = "Error insert relation between contactgroup " . $row['cg_id'] . - " and contact " . $rowContact['contact_id']; - throw $e; - } } } } - $updateTime = $this->db->prepare( - "UPDATE `options` SET `value` = :currentTime - WHERE `key` = 'ldap_last_acl_update'" - ); - $updateTime->bindValue(':currentTime', time(), \PDO::PARAM_INT); - $updateTime->execute(); - $this->db->commit(); - } catch (\PDOException $e) { - $this->db->rollBack(); } - } else { - $msg[] = "Unable to connect to LDAP server."; + $updateTime = $this->db->prepare( + "UPDATE `options` SET `value` = :currentTime + WHERE `key` = 'ldap_last_acl_update'" + ); + $updateTime->bindValue(':currentTime', time(), \PDO::PARAM_INT); + $updateTime->execute(); + $this->db->commit(); + } catch (\PDOException $e) { + $this->db->rollBack(); } } return $msg; diff --git a/www/class/centreonLDAP.class.php b/www/class/centreonLDAP.class.php index d8dd7d18c93..f9a7c70e7d8 100644 --- a/www/class/centreonLDAP.class.php +++ b/www/class/centreonLDAP.class.php @@ -198,6 +198,10 @@ public function connect(): bool $this->debug('LDAP Connect : trying url : ' . $url); $this->setErrorHandler(); $this->ds = ldap_connect($url); + if (!$this->ds instanceof \LDAP\Connection) { + $this->debug('LDAP Connection failed to : ' . $url); + continue; + } ldap_set_option($this->ds, LDAP_OPT_REFERRALS, 0); $protocol_version = 3; if (isset($ldap['info']['protocol_version'])) { @@ -323,6 +327,10 @@ public function findGroupDn($group) $this->setErrorHandler(); $filter = preg_replace('/%s/', $this->replaceFilter($group), $this->groupSearchInfo['filter']); $result = ldap_search($this->ds, $this->groupSearchInfo['base_search'], $filter); + if ($result === false) { + $this->debug("LDAP Search : cannot retrieve group DN of " . $group); + return false; + } $entries = ldap_get_entries($this->ds, $result); restore_error_handler(); if ($entries['count'] === 0) { @@ -346,6 +354,9 @@ public function listOfGroups($pattern = '*'): array $filter = preg_replace('/%s/', $pattern, $this->groupSearchInfo['filter']); $result = @ldap_search($this->ds, $this->groupSearchInfo['base_search'], $filter); if (false === $result) { + $this->debug( + "LDAP Search : cannot retrieve list of groups using filter " . $this->groupSearchInfo['filter'] + ); restore_error_handler(); return []; } @@ -379,6 +390,12 @@ public function listOfUsers($pattern = '*'): array $this->setErrorHandler(); $filter = preg_replace('/%s/', $pattern, $this->userSearchInfo['filter']); $result = ldap_search($this->ds, $this->userSearchInfo['base_search'], $filter); + if ($result === false) { + $this->debug( + "LDAP Search : cannot retrieve list of users using filter " . $this->groupSearchInfo['filter'] + ); + return []; + } $entries = ldap_get_entries($this->ds, $result); $nbEntries = $entries['count']; $list = array(); @@ -404,6 +421,9 @@ public function getEntry($dn, $attr = []) } $result = ldap_read($this->ds, $dn, '(objectClass=*)', $attr); if ($result === false) { + $this->debug( + "LDAP Search : cannot retrieve entry with DN " . $dn + ); restore_error_handler(); return false; } @@ -447,6 +467,9 @@ public function listGroupsForUser($userdn): array '(' . $this->groupSearchInfo['member'] . '=' . $this->replaceFilter($userdn) . '))'; $result = @ldap_search($this->ds, $this->groupSearchInfo['base_search'], $filter); if (false === $result) { + $this->debug( + "LDAP Search : cannot list groups of user " . $userdn + ); restore_error_handler(); return array(); } @@ -484,6 +507,9 @@ public function listUserForGroup($groupdn): array $result = @ldap_search($this->ds, $this->userSearchInfo['base_search'], $filter); if (false === $result) { + $this->debug( + "LDAP Search : cannot list users of group " . $groupdn + ); restore_error_handler(); return array(); } @@ -501,6 +527,9 @@ public function listUserForGroup($groupdn): array $result = @ldap_search($this->ds, $this->groupSearchInfo['base_search'], $filter); if (false === $result) { + $this->debug( + "LDAP Search : cannot list users of group " . $groupdn + ); restore_error_handler(); return array(); } @@ -794,21 +823,24 @@ private function debug($msg): void */ private function errorLdapHandler($errno, $errstr, $errfile, $errline): bool { - if ($errno === 2 && ldap_errno($this->ds) === 4) { - /* - Silencing : 'size limit exceeded' warnings in the logs - As the $searchLimit value needs to be consistent with the ldap server's configuration and - as the size limit error thrown is not related with the results. - ldap_errno : 4 = LDAP_SIZELIMIT_EXCEEDED - $errno : 2 = PHP_WARNING - */ - $this->debug("LDAP Error : Size limit exceeded error. This error was not added to php log. " - . "Kindly, check your LDAP server's configuration and your Centreon's LDAP parameters."); - return true; + if ($this->ds instanceof \LDAP\Connection) { + if ($errno === 2&& ldap_errno($this->ds) === 4) { + /* + Silencing : 'size limit exceeded' warnings in the logs + As the $searchLimit value needs to be consistent with the ldap server's configuration and + as the size limit error thrown is not related with the results. + ldap_errno : 4 = LDAP_SIZELIMIT_EXCEEDED + $errno : 2 = PHP_WARNING + */ + $this->debug("LDAP Error : Size limit exceeded error. This error was not added to php log. " + . "Kindly, check your LDAP server's configuration and your Centreon's LDAP parameters."); + return true; + } + + // throwing all errors + $this->debug("LDAP Error : " . ldap_error($this->ds)); } - // throwing all errors - $this->debug("LDAP Error : " . ldap_error($this->ds)); return false; } From 429937a558b4459c0155673db4460d8962932dab Mon Sep 17 00:00:00 2001 From: Kevin Duret Date: Wed, 21 Sep 2022 13:29:59 +0200 Subject: [PATCH 2/4] linting --- www/class/centreonContactgroup.class.php | 4 +++- www/class/centreonLDAP.class.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/www/class/centreonContactgroup.class.php b/www/class/centreonContactgroup.class.php index 4c8b55aa0f3..506b6c00926 100644 --- a/www/class/centreonContactgroup.class.php +++ b/www/class/centreonContactgroup.class.php @@ -432,7 +432,9 @@ public function syncWithLdap() try { while ($row = $res->fetch()) { // Test is the group has not been moved or deleted in ldap - if ((empty($row['cg_ldap_dn']) || false === $ldapConn->getEntry($row['cg_ldap_dn'])) + if ( + (empty($row['cg_ldap_dn']) || false === $ldapConn->getEntry($row['cg_ldap_dn'])) + && $ldapConn->getDs() instanceof \LDAP\Connection && ldap_errno($ldapConn->getDs()) != 3 ) { $dn = $ldapConn->findGroupDn($row['cg_name']); diff --git a/www/class/centreonLDAP.class.php b/www/class/centreonLDAP.class.php index f9a7c70e7d8..0349e4718fa 100644 --- a/www/class/centreonLDAP.class.php +++ b/www/class/centreonLDAP.class.php @@ -824,7 +824,7 @@ private function debug($msg): void private function errorLdapHandler($errno, $errstr, $errfile, $errline): bool { if ($this->ds instanceof \LDAP\Connection) { - if ($errno === 2&& ldap_errno($this->ds) === 4) { + if ($errno === 2 && ldap_errno($this->ds) === 4) { /* Silencing : 'size limit exceeded' warnings in the logs As the $searchLimit value needs to be consistent with the ldap server's configuration and From bc4119b93869aff693c383ad8ff6e75fb4086889 Mon Sep 17 00:00:00 2001 From: Kevin Duret Date: Thu, 22 Sep 2022 09:55:20 +0200 Subject: [PATCH 3/4] Apply suggestions from code review --- www/class/centreonLDAP.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/class/centreonLDAP.class.php b/www/class/centreonLDAP.class.php index 0349e4718fa..f3ec8876d0a 100644 --- a/www/class/centreonLDAP.class.php +++ b/www/class/centreonLDAP.class.php @@ -198,7 +198,7 @@ public function connect(): bool $this->debug('LDAP Connect : trying url : ' . $url); $this->setErrorHandler(); $this->ds = ldap_connect($url); - if (!$this->ds instanceof \LDAP\Connection) { + if (!$this->ds instanceof \LDAP\Connection) { $this->debug('LDAP Connection failed to : ' . $url); continue; } @@ -823,7 +823,7 @@ private function debug($msg): void */ private function errorLdapHandler($errno, $errstr, $errfile, $errline): bool { - if ($this->ds instanceof \LDAP\Connection) { + if ($this->ds instanceof \LDAP\Connection) { if ($errno === 2 && ldap_errno($this->ds) === 4) { /* Silencing : 'size limit exceeded' warnings in the logs From 287ce29b7ebaed294ee8cbb14f816578fff3d8c7 Mon Sep 17 00:00:00 2001 From: Kevin Duret Date: Mon, 17 Oct 2022 13:28:29 +0200 Subject: [PATCH 4/4] move to resource type --- www/class/centreonContactgroup.class.php | 2 +- www/class/centreonLDAP.class.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/www/class/centreonContactgroup.class.php b/www/class/centreonContactgroup.class.php index 506b6c00926..a9c7fab5f0c 100644 --- a/www/class/centreonContactgroup.class.php +++ b/www/class/centreonContactgroup.class.php @@ -434,7 +434,7 @@ public function syncWithLdap() // Test is the group has not been moved or deleted in ldap if ( (empty($row['cg_ldap_dn']) || false === $ldapConn->getEntry($row['cg_ldap_dn'])) - && $ldapConn->getDs() instanceof \LDAP\Connection + && is_resource($ldapConn->getDs()) && ldap_errno($ldapConn->getDs()) != 3 ) { $dn = $ldapConn->findGroupDn($row['cg_name']); diff --git a/www/class/centreonLDAP.class.php b/www/class/centreonLDAP.class.php index f3ec8876d0a..256c63cc04f 100644 --- a/www/class/centreonLDAP.class.php +++ b/www/class/centreonLDAP.class.php @@ -198,7 +198,7 @@ public function connect(): bool $this->debug('LDAP Connect : trying url : ' . $url); $this->setErrorHandler(); $this->ds = ldap_connect($url); - if (!$this->ds instanceof \LDAP\Connection) { + if (!is_resource($this->ds)) { $this->debug('LDAP Connection failed to : ' . $url); continue; } @@ -267,7 +267,7 @@ public function rebind(): bool /** * Send back the ldap resource * - * @return \LDAP\Connection|resource + * @return resource */ public function getDs() { @@ -823,7 +823,7 @@ private function debug($msg): void */ private function errorLdapHandler($errno, $errstr, $errfile, $errline): bool { - if ($this->ds instanceof \LDAP\Connection) { + if (is_resource($this->ds)) { if ($errno === 2 && ldap_errno($this->ds) === 4) { /* Silencing : 'size limit exceeded' warnings in the logs