Hi all,

I am working with Drupal 7.16 and the latest LDAP 7.x-2.x-dev.

My LDAP environment is composed of a virtual machine with Mountain Lion and LDAP, fresh install, 1 user (uid=crystaltest,cn=users,dc=vmserver,dc=private) and 2 groups (cn=testgroup,cn=groups,dc=vmserver,dc=private and cn=workgroup,cn=groups,dc=vmserver,dc=private). The user belongs to both groups.

What I need to do: set a role (student) to the user (crystaltest) if this user is part of a specific group (testgroup). Below is my problem in details, please forgive me if it is useless/too much.

What I could achieve:

  • Server binding and associated tests
  • Authentication and associated tests
  • Group configuration and associated tests

What I am struggling with:

  • Authorization: map Drupal roles with LDAP group

Mapping in Authorization settings:

cn=testgroup,cd=vmserver,cd=private|student

Group configuration in Server settings:

User attribute held in "LDAP Group Entry Attribute Holding..."
uid

If this is set to a different attribute name, the groups are not found.

When performing drupal role authorization test watchdog shows me this message:

Notice: Undefined variable: filtered_ldap_authorizations in _ldap_authorizations_user_authorizations() (line 272 of /sites/all/modules/ldap/ldap_authorization/ldap_authorization.inc).

Warning: array_keys() expects parameter 1 to be array, null given in _ldap_authorizations_user_authorizations() (line 272 of /Applications/MAMP/htdocs/druedu/trunk/sites/all/modules/ldap/ldap_authorization/ldap_authorization.inc).

Warning: join() [function.join]: Invalid arguments passed in _ldap_authorizations_user_authorizations() (line 272 of /Applications/MAMP/htdocs/druedu/trunk/sites/all/modules/ldap/ldap_authorization/ldap_authorization.inc).

Notice: Undefined variable: filtered_ldap_authorizations in _ldap_authorizations_user_authorizations() (line 283 of /Applications/MAMP/htdocs/druedu/trunk/sites/all/modules/ldap/ldap_authorization/ldap_authorization.inc).

Notice: Undefined variable: filtered_ldap_authorizations in _ldap_authorizations_user_authorizations() (line 297 of /Applications/MAMP/htdocs/druedu/trunk/sites/all/modules/ldap/ldap_authorization/ldap_authorization.inc).

I am not sure if it can be useful, but digging the code, after dpm some variables, I notice that $group_entries is empty in groupUserMembershipsFromEntry after groupMembershipsFromEntryResursive is called (in LdapServer.class.php, line 1593). Before the call of this function, groups are found by the module.

Going deeper in function calls, I noticed that when ldap_servers_get_first_rdn_value_from_dn is called in the function groupMembershipsFromEntryResursive, the $member_id returned is FALSE.

In ldap_servers_get_first_rdn_value_from_dn (line 829 of ldap_servers.module), the values of $dn and $rdn are respectively:

cn=workgroup,cn=groups,dc=vmserver,dc=private
uid
cn=testgroup,cn=groups,dc=vmserver,dc=private
uid

uid corresponds to the setting: User attribute held in "LDAP Group Entry Attribute Holding...". According to the output, I should set this configuration to cn - however in this case $group_entries in LdapServer.class.php line 1590 is empty after the search function is called:

$group_entries = $this->search($base_dn, $group_query, array());

So depending on the settings of "LDAP Group Entry Attribute Holding...", either the group entries are not found by the LDAP query (when using cn), or are removed later on by ldap_servers_get_first_rdn_value_from_dn (when using uid).

Could you please help me?

Attached is my LDAP configuration according to the directions given in the Help module.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

johnbarclay’s picture

Category: support » bug

Thanks for all the details. They are helpful and appreciated. I see a typo:

cn=testgroup,cd=vmserver,cd=private|student

should be:

cn=workgroup,cn=groups,dc=vmserver,dc=private|student if your group's dn is: cn=testgroup,cd=vmserver,cd=private

For initial testing, since you have a small ldap, I would just turn off the mappings and let it create roles like: cn=testgroup,cn=groups,dc=vmserver,dc=private
cn=workgroup,cn=groups,dc=vmserver,dc=private
and see if that works. The do the mapping/filtering.

The errors and empty results should all be better handled, so I'm marking this as a bug.

crystal_alexandre_froger’s picture

Wow, thank you for this quick reply!

Trying this out right now, feedback in a minute.

crystal_alexandre_froger’s picture

FileSize
110.78 KB

So the group dns are:
cn=testgroup,cn=groups,dc=vmserver,dc=private
cn=workgroup,cn=groups,dc=vmserver,dc=private

No more luck by disabling mapping of fixing the typo in the configuration - the roles are not created (this config is turn on).

Attached a screenshot of the test result page.

johnbarclay’s picture

I committed a fix for "Notice: Undefined variable: filtered_ldap_authorizations". That is not your problem though. I suspect this is a bug.

Have you tried the test form: admin/config/people/ldap/authorization/test/drupal_role ?

crystal_alexandre_froger’s picture

Yes - the result was in the screenshot attached - AUTHORIZATION IDS is empty.

My settings for authorization:

I. BASICS
LDAP Server used in drupal role configuration. *
Selected - vmserver.private
Ticked - Enable this configuration
Unticked - Only apply the following LDAP to drupal role configuration to users authenticated via LDAP. On uncommon reason for disabling this is when you are using Drupal authentication, but want to leverage LDAP for authorization; for this to work the Drupal username still has to map to an LDAP entry.

II. LDAP TO DRUPAL ROLE MAPPING AND FILTERING
All empty/unticked, as recommended

PART III. EVEN MORE SETTINGS.
All ticked

johnbarclay’s picture

Try checking "Only apply the following LDAP to drupal role configuration to users authenticated via LDAP" and do the test again. Thats the only thing that sticks out and that might be where the bug is.

crystal_alexandre_froger’s picture

Well, still the same result - nothing in AUTHORIZATION IDS column...

crystal_alexandre_froger’s picture

I found where I am losing the groups to test: in groupMembershipsFromEntryResursive, the member_id can not be found, therefore AUTHORIZATION IDS becomes empty.
There are some things I don't understand with this function. I have put some comments in the code below, to follow my understanding:

 public function groupMembershipsFromEntryResursive($current_group_entries, &$all_group_dns, &$tested_group_ids, $level, $max_levels) {

//Making sure we can go further - testing the variables we need
    if (!$this->groupGroupEntryMembershipsConfigured || !is_array($current_group_entries) || count($current_group_entries) == 0) {
      return FALSE;
    }
//Remove useless count entry because we want to loop a groups array
    if (isset($current_group_entries['count'])) {
      unset($current_group_entries['count']);
    };

//Conditions init for the LDAP query
    $ors = array();
//For each of the groups found, determine the dns matching our settings and alter the LDAP query
    foreach ($current_group_entries as $i => $group_entry) {
//This is this part I am not sure to understand...
//How a dn of a group can hold the member ids? (example $group_entry['dn'] = 'cn=testgroup,cn=groups,dc=vmserver,dc=private')
      if ($this->groupMembershipsAttrMatchingUserAttr == 'dn') {
        $member_id = $group_entry['dn'];
      }
//Same here, and actually the condition executed with my settings: in my case, groups have a membershipuid attribute, mutli-value. How the $group_entry['dn'] can contain the ids? Don't we need to loop somewhere? (example $group_entry['dn'] = 'cn=testgroup,cn=groups,dc=vmserver,dc=private', with membershipuid = testuser1,testuser2,...)
      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 . '=' . $member_id;
      }
    }

    if (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);
        //dpm("current_ors $i," . LDAP_SERVER_LDAP_QUERY_CHUNK); dpm($current_ors);
        $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 . ')';


        // debug('query_for_parent_groups'); debug($query_for_parent_groups);
        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  && $level < $max_levels) {
            $this->groupMembershipsFromEntryResursive($group_entries, $all_group_dns, $tested_group_ids, $level + 1, $max_levels);
          }
        }
      }
    }
  }

Does it help to see where could be the issue?

crystal_alexandre_froger’s picture

By the way, I found a small thing in this function: * @return FALSE for error or misconfiguration, otherwise TRUE. results are passed by reference.
It never returns TRUE in the code...

crystal_alexandre_froger’s picture

I am not sure about the side effects... But if change this:

      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 . '=' . $member_id;
      }

to this:

      if ($member_id && !in_array($member_id, $tested_group_ids)) {
        $tested_group_ids[] = $member_id;
        // add $group_id (dn, cn, uid) to query
        $ors[] =  $this->groupMembershipsAttr . '=' . $member_id;
      }
    $all_group_dns[] = $group_entry['dn'];

Then the role attribution works.

crystal_alexandre_froger’s picture

The side effect id that the array $all_group_dns would contain duplicates.

I do that instead:

      if(!in_array($group_entry['dn'], $all_group_dns)) {;
        $all_group_dns[] = $group_entry['dn'];
      }
crystal_alexandre_froger’s picture

Status: Active » Closed (duplicate)

I prefer to close this issue since I found other problems, which are also related (OG, nested groups, etc...), and maybe a beginning of solution. See http://drupal.org/node/1839144