Index: ldapgroups.inc
===================================================================
--- ldapgroups.inc	(revision 348)
+++ ldapgroups.inc	(revision 349)
@@ -77,10 +77,9 @@
  */
 function _ldapgroups_detect_groups($user) {
   global $_ldapgroups_ldap;
-
   // Nothing to do if the user is not LDAP authentified
   // or there are no groups configured.
-  if (!(_ldapgroups_ldap_info($user, 'ldapgroups_in_dn') || _ldapgroups_ldap_info($user, 'ldapgroups_in_attr') || _ldapgroups_ldap_info($user, 'ldapgroups_as_entries')))
+  if (!(_ldapgroups_ldap_info($user, 'ldapgroups_in_dn') || _ldapgroups_ldap_info($user, 'ldapgroups_in_attr') || _ldapgroups_ldap_info($user, 'ldapgroups_as_entries') || (bool) module_implements('detect_ldapgroups')))
     return FALSE;
 
   // First try to connect with the stored user's DN and password.
@@ -134,11 +133,38 @@
     }
   }
 
+  // Strategy 4: Custom strategies defined in hooks
+  $hook_groups = module_invoke_all('detect_ldapgroups', $_ldapgroups_ldap, $user);
   $_ldapgroups_ldap->disconnect();
-  return array_unique(array_merge($dn_groups, $attrib_groups, $entries_groups));
+  return array_unique(array_merge($dn_groups, $attrib_groups, $entries_groups, $hook_groups));
 }
 
 /**
+ * Find groups the user is in in LDAP.
+ *
+ * This hook allows modules to provide groups a user is in.
+ * Useful for awkward LDAP layouts that can't be catered by the 3 provided
+ * strategies.
+ *
+ * @param $ldap
+ *   An open LDAPInterface
+ * @param $user
+ *   The user objects. $user->ldap_dn will be of particular interest.
+ * @return
+ *   Array of groupnames the user is in.
+ */
+
+function hook_detect_ldapgroups($ldap, $user) {
+  $rv = array();
+  $gid = $ldap->retrieveAttribute($user->ldap_dn, 'gidNumber');
+  $gid = int($gid);
+  $entries = $ldap->search('ou=Group,dc=example,dc=com', "(gidNumber=$gid)");
+  foreach ($entries as $entry)
+    $rv[] = $entry['dn'];
+  return $rv;
+}
+
+/**
  * Grant a user with a role.
  *
  * @param $user
