From 2767d6846e236929d168525304d977dc0f0b7d8f Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Tue, 17 Jun 2025 11:08:48 -0400 Subject: [PATCH] check for conflicts across entire LDAP tree --- resources/init.php | 2 +- resources/lib/UnityLDAP.php | 64 +++++++++++++++++-------------------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/resources/init.php b/resources/init.php index e2d85bd3..cc8e8db2 100644 --- a/resources/init.php +++ b/resources/init.php @@ -45,6 +45,7 @@ $CONFIG["ldap"]["user"], $CONFIG["ldap"]["pass"], __DIR__ . "/../deployment/custom_user_mappings", + $CONFIG["ldap"]["basedn"], $CONFIG["ldap"]["user_ou"], $CONFIG["ldap"]["group_ou"], $CONFIG["ldap"]["pigroup_ou"], @@ -55,7 +56,6 @@ ); $GLOBALS["ldapconn"] = $LDAP; } - // Creates SQL service $SQL = new UnitySQL( $CONFIG["sql"]["host"], diff --git a/resources/lib/UnityLDAP.php b/resources/lib/UnityLDAP.php index 37a938e9..c35298d1 100644 --- a/resources/lib/UnityLDAP.php +++ b/resources/lib/UnityLDAP.php @@ -26,6 +26,7 @@ class UnityLDAP extends ldapConn ); // string vars for OUs + private $STR_BASEOU; private $STR_USEROU; private $STR_GROUPOU; private $STR_PIGROUPOU; @@ -33,6 +34,7 @@ class UnityLDAP extends ldapConn private $STR_ADMINGROUP; // Instance vars for various ldapEntry objects + private $baseOU; private $userOU; private $groupOU; private $pi_groupOU; @@ -49,6 +51,7 @@ public function __construct( $dn, $pass, $custom_user_mappings, + $base_dn, $user_ou, $group_ou, $pigroup_ou, @@ -59,6 +62,7 @@ public function __construct( ) { parent::__construct($host, $dn, $pass); + $this->STR_BASEOU = $base_dn; $this->STR_USEROU = $user_ou; $this->STR_GROUPOU = $group_ou; $this->STR_PIGROUPOU = $pigroup_ou; @@ -66,6 +70,7 @@ public function __construct( $this->STR_ADMINGROUP = $admin_group; // Get Global Entries + $this->baseOU = $this->getEntry($base_dn); $this->userOU = $this->getEntry($user_ou); $this->groupOU = $this->getEntry($group_ou); $this->pi_groupOU = $this->getEntry($pigroup_ou); @@ -123,13 +128,11 @@ public function getNextUIDNumber($UnitySQL) { $max_uid = $UnitySQL->getSiteVar('MAX_UID'); $new_uid = $max_uid + 1; - - while ($this->IDNumInUse($new_uid)) { + $id_nums_in_use = $this->getIDNumsInUse(); + while ($this->IDNumInUse($new_uid, $id_nums_in_use)) { $new_uid++; } - $UnitySQL->updateSiteVar('MAX_UID', $new_uid); - return $new_uid; } @@ -137,13 +140,11 @@ public function getNextPiGIDNumber($UnitySQL) { $max_pigid = $UnitySQL->getSiteVar('MAX_PIGID'); $new_pigid = $max_pigid + 1; - - while ($this->IDNumInUse($new_pigid)) { + $id_nums_in_use = $this->getIDNumsInUse(); + while ($this->IDNumInUse($new_pigid, $id_nums_in_use)) { $new_pigid++; } - $UnitySQL->updateSiteVar('MAX_PIGID', $new_pigid); - return $new_pigid; } @@ -151,47 +152,42 @@ public function getNextOrgGIDNumber($UnitySQL) { $max_gid = $UnitySQL->getSiteVar('MAX_GID'); $new_gid = $max_gid + 1; - - while ($this->IDNumInUse($new_gid)) { + $id_nums_in_use = $this->getIDNumsInUse(); + while ($this->IDNumInUse($new_gid, $id_nums_in_use)) { $new_gid++; } - $UnitySQL->updateSiteVar('MAX_GID', $new_gid); - return $new_gid; } - private function IDNumInUse($id) + private function IDNumInUse($id_num, $id_nums_in_use) { // 0-99 are probably going to be used for local system accounts instead of LDAP accounts // 100-999, 60000-64999 are reserved for debian packages - if (($id <= 999) || ($id >= 60000 && $id <= 64999)) { + if (($id_num <= 999) || ($id_num >= 60000 && $id_num <= 64999)) { return true; } - $users = $this->userOU->getChildrenArray([], true); - foreach ($users as $user) { - if ($user["uidnumber"][0] == $id) { - return true; - } - } - $pi_groups = $this->pi_groupOU->getChildrenArray(["gidnumber"], true); - foreach ($pi_groups as $pi_group) { - if ($pi_group["gidnumber"][0] == $id) { - return true; - } - } - $groups = $this->groupOU->getChildrenArray(["gidnumber"], true); - foreach ($groups as $group) { - if ($group["gidnumber"][0] == $id) { - return true; - } - } + return in_array($id_num, $id_nums_in_use); + } - return false; + private function getIDNumsInUse() + { + return array_merge( + // search entire LDAP tree, not just for entries created by portal + array_map( + fn($x) => intval($x["uidnumber"][0]), + $this->baseOU->getChildrenArray(["uidnumber"], true, "objectClass=posixAccount") + ), + array_map( + fn($x) => intval($x["gidnumber"][0]), + $this->baseOU->getChildrenArray(["gidnumber"], true, "objectClass=posixGroup") + ), + ); } public function getUnassignedID($uid, $UnitySQL) { + $id_nums_in_use = $this->getIDNumsInUse(); $netid = strtok($uid, "_"); // extract netid // scrape all files in custom folder $dir = new \DirectoryIterator($this->custom_mappings_path); @@ -205,7 +201,7 @@ public function getUnassignedID($uid, $UnitySQL) if ($uid == $netid_match || $netid == $netid_match) { // found a match - if (!$this->IDNumInUse($uid_match)) { + if (!$this->IDNumInUse($uid_match, $id_nums_in_use)) { return $uid_match; } }