Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions resources/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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"],
Expand Down
127 changes: 71 additions & 56 deletions resources/lib/UnityLDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ class UnityLDAP extends ldapConn
);

// string vars for OUs
private $STR_BASEOU;
private $STR_USEROU;
private $STR_GROUPOU;
private $STR_PIGROUPOU;
private $STR_ORGGROUPOU;
private $STR_ADMINGROUP;

// Instance vars for various ldapEntry objects
private $baseOU;
private $userOU;
private $groupOU;
private $pi_groupOU;
Expand All @@ -49,6 +51,7 @@ public function __construct(
$dn,
$pass,
$custom_user_mappings,
$base_dn,
$user_ou,
$group_ou,
$pigroup_ou,
Expand All @@ -59,13 +62,15 @@ 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;
$this->STR_ORGGROUPOU = $orggroup_ou;
$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);
Expand Down Expand Up @@ -119,103 +124,113 @@ public function getDefUserShell()
//
// ID Number selection functions
//
public function getNextUIDNumber($UnitySQL)
public function getNextUIDNumber($uid, $UnitySQL)
{
$id_nums_in_use = $this->getIDNumsInUse();
$custom_id_mappings = $this->getCustomIDMappings();
$custom_mapped_id = $this->getCustomMappedID($uid, $id_nums_in_use, $custom_id_mappings);
if (!is_null($custom_mapped_id)) {
return $custom_mapped_id;
}
$max_uid = $UnitySQL->getSiteVar('MAX_UID');
$new_uid = $max_uid + 1;

while ($this->IDNumInUse($new_uid)) {
while ($this->IDNumInUse($new_uid, $id_nums_in_use)) {
$new_uid++;
}

$UnitySQL->updateSiteVar('MAX_UID', $new_uid);

return $new_uid;
}

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;
}

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)
{
// id reserved for debian packages
if (($id >= 100 && $id <= 999) || ($id >= 60000 && $id <= 64999)) {
// reserved for debian packages
if (($id_num >= 100 && $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")
),
array_map(
fn($x) => $x[1],
$this->getCustomIDMappings(),
),
);
}

public function getUnassignedID($uid, $UnitySQL)
private function getCustomIDMappings()
{
$netid = strtok($uid, "_"); // extract netid
// scrape all files in custom folder
$output = [];
$dir = new \DirectoryIterator($this->custom_mappings_path);
foreach ($dir as $fileinfo) {
if ($fileinfo->getExtension() == "csv") {
// found csv file
$handle = fopen($fileinfo->getPathname(), "r");
while (($data = fgetcsv($handle, 1000, ",")) !== false) {
$netid_match = $data[0];
$uid_match = $data[1];

if ($uid == $netid_match || $netid == $netid_match) {
// found a match
if (!$this->IDNumInUse($uid_match)) {
return $uid_match;
}
}
}
if (!$fileinfo->getExtension() == "csv") {
UnitySite::errorLog(
"warning",
"file in custom mappings directory does not have the .csv extension so it is ignored."
);
continue;
}
$handle = fopen($fileinfo->getPathname(), "r");
while (($data = fgetcsv($handle, 1000, ",")) !== false) {
array_merge($output, $data);
}
}
return $output;
}

// didn't find anything from existing mappings, use next available
$next_uid = $this->getNextUIDNumber($UnitySQL);

return $next_uid;
private function getCustomMappedID($uid, $id_nums_in_use, $custom_id_mappings)
{
$netid = strtok($uid, "_");
foreach ($custom_id_mappings as [$match, $uidnumber]) {
if (($uid != $match) || ($netid != $match)) {
continue;
}
if ($this->IDNumInUse($uidnumber, $id_nums_in_use)) {
UnitySite::errorLog(
"warning",
"user '$uid' has a custom mapping for ID $uidnumber but it's already in use!"
);
return null;
} else {
return $uidnumber;
}
}
return null;
}

//
Expand Down
2 changes: 1 addition & 1 deletion resources/lib/UnityUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function init($send_mail = true)
// Create LDAP group
//
$ldapGroupEntry = $this->getLDAPGroup();
$id = $this->LDAP->getUnassignedID($this->getUID(), $this->SQL);
$id = $this->LDAP->getNextUIDNumber($this->getUID(), $this->SQL);

if (!$ldapGroupEntry->exists()) {
$ldapGroupEntry->setAttribute("objectclass", UnityLDAP::POSIX_GROUP_CLASS);
Expand Down