--- html/includes/authentication/ldap.inc.php 2014-11-04 17:14:27.000000000 +0100 +++ html/includes/authentication/ldap.inc.php 2015-02-09 23:11:12.319931939 +0100 @@ -39,6 +39,41 @@ } } +function search_user($ldap_group, $userdn, $depth) +{ + global $ds, $config; + + $compare = ldap_compare($ds, $ldap_group, $config['auth_ldap_groupmemberattr'], $userdn); + + if ($compare === TRUE) + { + return TRUE; + } + elseif (($config['auth_ldap_recursive'] === true) && ($depth < $config['auth_ldap_recursive_maxdepth'])) + { + $depth = $depth + 1; + + $filter = "(&(objectCategory=group)(objectclass=group)(memberOf=". $ldap_group ."))"; + $ldap_search = ldap_search($ds, trim($config['auth_ldap_suffix'], ', '), $filter, array("distinguishedname")); + $ldap_results = ldap_get_entries($ds, $ldap_search); + + array_shift($ldap_results); + + foreach($ldap_results as $element) + { + $result = search_user($element['distinguishedname'][0], $userdn, $depth); + if ($result === TRUE) + { + return TRUE; + } + } + } + else + { + return FALSE; + } +} + // DOCME needs phpdoc block function ldap_init() { @@ -108,8 +143,8 @@ foreach ($config['auth_ldap_group'] as $ldap_group) { print_debug("LDAP[Authenticate][Comparing: " . $ldap_group . "][".$config['auth_ldap_groupmemberattr']."=$userdn]"); - $compare = ldap_compare($ds, $ldap_group, $config['auth_ldap_groupmemberattr'], $userdn); - + $compare = search_user($ldap_group, $userdn, 0); + if ($compare === -1) { print_debug("LDAP[Authenticate][Compare LDAP error: " . ldap_error($ds) . "]"); @@ -120,7 +155,7 @@ // $compare === TRUE print_debug("LDAP[Authenticate][Processing group: $ldap_group][Matched]"); return 1; - } // FIXME does not support nested groups + } } } } @@ -216,8 +251,8 @@ // So, we foreach our locally known groups instead. foreach ($config['auth_ldap_groups'] as $ldap_group => $ldap_group_info) { - $compare = ldap_compare($ds, 'cn=' . $ldap_group . ',' . $config['auth_ldap_groupbase'], $config['auth_ldap_groupmemberattr'], $userdn); - + $compare = search_user('cn=' . $ldap_group . ',' . $config['auth_ldap_groupbase'], $userdn, 0); + if ($compare === -1) { print_debug("LDAP[UserLevel][Compare LDAP error: " . ldap_error($ds) . "]"); @@ -311,14 +346,14 @@ $user_id = ldap_internal_auth_user_id($entries[$i]); $userdn = ($config['auth_ldap_groupmembertype'] == 'fulldn' ? $entries[$i]['dn'] : $username); - print_debug("LDAP[UserList][Compare: " . implode('|',$config['auth_ldap_group']) . "][".$config['auth_ldap_groupmemberattr']."][$userdn]"); foreach ($config['auth_ldap_group'] as $ldap_group) { $authorized = 0; - $compare = ldap_compare($ds, $ldap_group, $config['auth_ldap_groupmemberattr'], $userdn); - + + $compare = search_user($ldap_group, $userdn, 0); + if ($compare === -1) { print_debug("LDAP[UserList][Compare LDAP error: " . ldap_error($ds) . "]"); @@ -330,7 +365,7 @@ print_debug("LDAP[UserList][Authorized: $userdn for group $ldap_group]"); $authorized = 1; break; - } // FIXME does not support nested groups + } } if (!isset($config['auth_ldap_group']) || $authorized) --- includes/defaults.inc.php 2014-11-21 13:33:07.000000000 +0100 +++ includes/defaults.inc.php 2015-02-09 22:48:21.459927476 +0100 @@ -542,6 +542,8 @@ #$config['auth_ldap_ad_domain'] = "ad.yourcorp.com"; // AD domain name (fqdn form), used to determine DCs if server list is unset $config['auth_ldap_port'] = 389; // LDAP server port $config['auth_ldap_starttls'] = 'no'; // Use STARTTLS ('no', 'optional' or 'require') +$config['auth_ldap_recursive'] = TRUE; // Active Directory recursive lookup for nested groups +$config['auth_ldap_recursive_maxdepth'] = 3; // Max depth for recursive lookup $config['auth_ldap_prefix'] = "uid="; $config['auth_ldap_suffix'] = ",ou=People,dc=example,dc=com"; #$config['auth_ldap_group'] = array("cn=observium,ou=groups,dc=example,dc=com");