Finding LDAP nested group membership in PHP

php ldap

I found the solution to the question: "Are a user member of group in a Microsoft LDAP directory tree?". This can be a bit tricky if the user does not have an direct relationship to that group.

Example: if user A is member of group B and group B is an member of group C. How do we find out if user A is a member of group C?

It relies on a fairly weird search filter called '1.2.840.113556.1.4.1941' and as is defined as:

LDAP_MATCHING_RULE_IN_CHAIN: This rule is limited to filters that apply to the DN. This is a special "extended match operator that walks the chain of ancestry in objects all the way to the root until it finds a match.

Source: msdn.microsoft.com Search Filter Syntax

Below is naive demonstration on how to use this filter with PHP and the ldap library.

<?php
/**
 * Recursively search $userDN groups to find if $userDN $groupToFind is in that  
 * group
 * This can be used for verifying if a user have an indirect (nested) member
 * ship in a group.
 * 
 * @param resource $ldapConnection
 * @param string $userDN - e.g: CN=User Name,OU=Users,DC=domain,DC=com
 * @param string $haystackDN - e.g: CN=Finance,OU=Groups,DC=domain,DC=com
 * @return boolean - true if  $userDN is member of $groupToFind 
 */
public function inGroup($ldapConnection, $userDN, $groupToFind) {
    $filter = "(memberof:1.2.840.113556.1.4.1941:=".$groupToFind.")";
    $search = ldap_search($ldapConnection, $userDN, $filter, array("dn"), 1);
    $items = ldap_get_entries($ldapConnection, $search);
    if(!isset($items["count"])) {
        return false;
    }
    return (bool)$items["count"];
}

It's easy when you know how to (sarcasm).