/** * recurse through all groups, adding parent groups to $all_group_dns array. * * @param array $current_group_entries of ldap group entries that are starting point. should include at least 1 entry. * @param array $all_group_dns as array of all groups user is a member of. MIXED CASE VALUES * @param array $tested_group_ids as array of tested group dn, cn, uid, etc. MIXED CASE VALUES * whether these value are dn, cn, uid, etc depends on what attribute members, uniquemember, memberUid contains * whatever attribute is in $this->$tested_group_ids to avoid redundant recursing * @param int $level of recursion * @param int $max_levels as max recursion allowed * * given set of groups entries ($current_group_entries such as it, hr, accounting), * find parent groups (such as staff, people, users) and add them to list of group memberships ($all_group_dns) * * (&(objectClass=[$this->groupObjectClass])(|([$this->groupMembershipsAttr]=groupid1)([$this->groupMembershipsAttr]=groupid2)) * * @return FALSE for error or misconfiguration, otherwise TRUE. results are passed by reference. */ public function groupMembershipsFromEntryRecursive($current_group_entries, &$all_group_dns, &$tested_group_ids, $level, $max_levels) { if (!$this->groupGroupEntryMembershipsConfigured || !is_array($current_group_entries) || count($current_group_entries) == 0) { return FALSE; } if (isset($current_group_entries['count'])) { unset($current_group_entries['count']); } $ors = array(); foreach ($current_group_entries as $i => $group_entry) { if ($this->groupMembershipsAttrMatchingUserAttr == 'dn') { $member_id = $group_entry['dn']; } else { // maybe cn, uid, etc is held $member_id = ldap_servers_get_first_rdn_value_from_dn($group_entry['dn'], $this->groupMembershipsAttrMatchingUserAttr); } if ($member_id && !in_array($member_id, $tested_group_ids)) { $tested_group_ids[] = $member_id; $all_group_dns[] = $group_entry['dn']; // add $group_id (dn, cn, uid) to query $ors[] = $this->groupMembershipsAttr . '=' . ldap_pear_escape_filter_value($member_id); } } if ($level < $max_levels && count($ors)) { $count = count($ors); for ($i = 0; $i < $count; $i = $i + LDAP_SERVER_LDAP_QUERY_CHUNK) { // only 50 or so per query $current_ors = array_slice($ors, $i, LDAP_SERVER_LDAP_QUERY_CHUNK); $or = '(|(' . join(")(", $current_ors) . '))'; // e.g. (|(cn=group1)(cn=group2)) or (|(dn=cn=group1,ou=blah...)(dn=cn=group2,ou=blah...)) $query_for_parent_groups = '(&(objectClass=' . $this->groupObjectClass . ')' . $or . ')'; foreach ($this->basedn as $base_dn) { // need to search on all basedns one at a time $group_entries = $this->search($base_dn, $query_for_parent_groups); // no attributes, just dns needed if ($group_entries !== FALSE) { $this->groupMembershipsFromEntryRecursive($group_entries, $all_group_dns, $tested_group_ids, $level + 1, $max_levels); } } } } return TRUE; }
/** * recurse through all groups, adding parent groups to $all_group_dns array. * * @param array $current_group_entries of ldap group entries that are starting point. should include at least 1 entry. * @param array $all_group_dns as array of all groups user is a member of. MIXED CASE VALUES * @param array $tested_group_ids as array of tested group dn, cn, uid, etc. MIXED CASE VALUES * whether these value are dn, cn, uid, etc depends on what attribute members, uniquemember, memberUid contains * whatever attribute is in $this->$tested_group_ids to avoid redundant recursing * @param int $level of recursion * @param int $max_levels as max recursion allowed * * given set of groups entries ($current_group_entries such as it, hr, accounting), * find parent groups (such as staff, people, users) and add them to list of group memberships ($all_group_dns) * * (&(objectClass=[$this->groupObjectClass])(|([$this->groupMembershipsAttr]=groupid1)([$this->groupMembershipsAttr]=groupid2)) * * @return FALSE for error or misconfiguration, otherwise TRUE. results are passed by reference. */ public function groupMembershipsFromEntryRecursive($current_group_entries, &$all_group_dns, &$tested_group_ids, $level, $max_levels) { if (!$this->groupGroupEntryMembershipsConfigured || !is_array($current_group_entries) || count($current_group_entries) == 0) { return FALSE; } if (isset($current_group_entries['count'])) { unset($current_group_entries['count']); } $ors = array(); foreach ($current_group_entries as $i => $group_entry) { if ($this->groupMembershipsAttrMatchingUserAttr == 'dn') { $member_id = $group_entry['dn']; } else { // maybe cn, uid, etc is held $member_id = ldap_servers_get_first_rdn_value_from_dn($group_entry['dn'], $this->groupMembershipsAttrMatchingUserAttr); if (!$member_id) { if ($this->detailed_watchdog_log) { watchdog('ldap_server', 'group_entry: %ge', array('%ge' => pretty_print_ldap_entry($group_entry))); } // group not identified by simple checks yet! // examine the entry and see if it matches the configured groupObjectClass $goc = $group_entry['objectclass']; // TODO do we need to ensure such entry is there? if (is_array($goc)) { // TODO is it always an array? foreach ($goc as $g) { $g = drupal_strtolower($g); if ($g == $this->groupObjectClass) { // found a group, current user must be member in it - so: if ($this->detailed_watchdog_log) { watchdog('ldap_server', 'adding %mi', array('%mi' => $member_id)); } $member_id = $group_entry['dn']; break; } } } } } if ($member_id && !in_array($member_id, $tested_group_ids)) { $tested_group_ids[] = $member_id; $all_group_dns[] = $group_entry['dn']; // add $group_id (dn, cn, uid) to query $ors[] = $this->groupMembershipsAttr . '=' . ldap_pear_escape_filter_value($member_id); } } if ($level < $max_levels && count($ors)) { $count = count($ors); for ($i = 0; $i < $count; $i = $i + LDAP_SERVER_LDAP_QUERY_CHUNK) { // only 50 or so per query $current_ors = array_slice($ors, $i, LDAP_SERVER_LDAP_QUERY_CHUNK); $or = '(|(' . join(")(", $current_ors) . '))'; // e.g. (|(cn=group1)(cn=group2)) or (|(dn=cn=group1,ou=blah...)(dn=cn=group2,ou=blah...)) $query_for_parent_groups = '(&(objectClass=' . $this->groupObjectClass . ')' . $or . ')'; foreach ($this->basedn as $base_dn) { // need to search on all basedns one at a time $group_entries = $this->search($base_dn, $query_for_parent_groups); // no attributes, just dns needed if ($group_entries !== FALSE) { $this->groupMembershipsFromEntryRecursive($group_entries, $all_group_dns, $tested_group_ids, $level + 1, $max_levels); } } } } return TRUE; }