How to see what groups a user is a member of?

Hi,

I'm trying to write a PHP script that authenticates a user by checking entered info against user credentials in LDAP. After a user is authenticated, I want to see what groups that user is a member of.

I have the authentication working great, no problems there at all. The problem I'm running into is trying to get what groups that user is a member of.

After some searching on the internet, I found there is a handy-dandy LDAP attribute called "memberof" that contains exactly what I need. However, this attribute is not available in Leopard server.

Does anybody know how to enable the memberof attribute in Leopard Server? If not, maybe you have other suggestions to fetch the data I need?

The machine in question is an Intel Xserve running OSX Leopard Server 10.5.5

Thanks!

Mac OS X (10.5.1)

Posted on Dec 11, 2008 10:13 AM

Reply
9 replies

Dec 11, 2008 10:41 AM in response to Kabukiman

This is a script that I wrote based on LDAPSearch. I will also include a separate posting of functions based on dseditgroup.


<?php
//
// An assortment of functions for quering LDAP.
//
// Global variables:
// $Server - Name of the LDAP server to be queried.
// $Base - Search base for the LDAP server.
// $LDAPsearch - Fundamental command string component of the ldapsearch command to be used in the search.
//
// Member functions:
//
// GetLDAPelement($string)
// GetAppleGroupName($groupid)
// GetAppleGroupUID($groupname)
// GetAppleNestGroupUIDs($groupname)
// GetLDAPGroupMembership($groupname)
// IsLDAPGroupMember($username,$groupname)
// TestLDAPGroupMembership($username,$groupname,&$stack)
// LDAPTest()
//

global $Server;
global $Base;
global $LDAPsearch;
global $debug;

//$debug=1;

$Server="ldap.server.local";
$Base="dc=dc=me,dc=edu";
$LDAPsearch="/usr/bin/ldapsearch -LLL -x -h $Server -b \"cn=groups,${Base}\"";

function GetLDAPelement($string)
{
// LDAP returns its results with the form:
// <fieldname> : <value>
// We are interested in the value of the field, so we can strip off everything before the ":"
// and trim off leading and trailing empty space.

global $debug;

if( $debug) echo "Input string = $string\n";
$result=trim(substr($string,strpos($string,':')+1));
if( $debug) echo "Result string = $result\n";
return $result;
}

function GetAppleGroupName($groupid)
{
global $Server;
global $Base;
global $LDAPsearch;

$command="${LDAPsearch} \"(apple-generateduid=$groupid)\" cn | grep \"cn:\" ";
exec ($command,$result);
return GetLDAPelement($result[0]);

}

function GetAppleGroupUID($groupname)
{
//
// return the apple-generateduid for the specified $groupname.
//
global $Server;
global $Base;
global $LDAPsearch;

$command="$LDAPsearch \"(cn=$groupname)\" apple-generateduid | grep \"apple-generateduid:\" ";
exec ($command,$result);

return GetLDAPelement($result[0]);
}

function GetAppleNestGroupUIDs($groupname)
{
//
// Return the apple-group-nestedgroups given $groupname.
// A $groupname may belong to 0 or more nested groups.
//
global $Server;
global $Base;
global $LDAPsearch;

$command="$LDAPsearch \"(cn=$groupname)\" apple-group-nestedgroup | grep \"apple-group-nestedgroup:\" ";
exec ($command,$result);
for($i=0;$i<count($result);$i++)
{
$result[$i]=GetLDAPelement($result[$i]);
}

return $result;
}

function GetAppleSubGroupNames($groupid)
{
//
// Given a nested $groupid, return the names of the groups that have the same $groupid.
//
global $Server;
global $Base;
global $LDAPsearch;

$command="$LDAPsearch \"(apple-group-nestedgroup=$groupid)\" cn |grep \"cn:\"";
exec($command,$result);
for($i=0;$i<count($result);$i++)
{
$result[$i]=GetLDAPelement($result[$i]);
}
return($result);
}

function GetLDAPGroupMembership($groupname)
{
//
// Given $groupname, return the users that are direct members of the group.
// Nested groups are NOT checked. It only checks the "memberUid" elements of $groupname.
//
global $Server;
global $Base;
global $LDAPsearch;

$command="$LDAPsearch \"(cn=$groupname)\" memberUid | grep \"memberUid:\" ";

exec ($command,$result);

for($i=0;$i<count($result);$i++)
{
if( $debug) echo "Searching $result[$i]\n";

$result[$i]=GetLDAPelement($result[$i]);
}

return $result;
}

function IsLDAPGroupMember($username,$groupname)
{
//
// Determine if a $username is a member of a $groupname. Nested groups are checked.
//
$stack=array();
return TestLDAPGroupMembership($username,$groupname,$stack);
}

function TestLDAPGroupMembership($username,$groupname,&$stack)
{
// This is an internal function to be used as the "engine" of IsLDAPGroupMember().
//
// Test to see if $username is a direct or nested member of $groupname.
// The &$stack is passed by reference, and keeps managing the stack of ${groupname}s that
// have already been tested. This is necessary to make the function recursive without having
// infinite looping due to doubly nested groups.
//
global $debug;

// See if we have already searched this $groupname for the $username. If we have,
// we did not find it the last time, so we will not find it this time. We can stop here.
if( array_search($groupname,$stack)) return false;

if( $debug)echo "Searching for user $username in group $groupname.\n";

$result=GetLDAPGroupMembership($groupname);

if( $debug)echo "Searching direct membership.\n";

// If we find $username in the list of $result, $username IS a group member! We are Done!
if( array_search($username,$result)) return true;

// Add this $groupname to the $stack of groups that have been directly searched.
array_push($stack,$groupname);

if( $debug)echo "Searching sub groups\n";

$groupid=GetAppleNestGroupUIDs($groupname);

if( $debug)echo "Detected ".count($groupid)." groups.\n";

for($group=0;$group<count($groupid);$group++)
{
if( $debug)echo "Group id = $groupid[$group]\n";

$mastername=GetAppleGroupName($groupid[$group]);
if( $debug)echo "Master group name = $mastername\n";

if(TestLDAPGroupMembership($username,$mastername,$stack)) return true;
}
// If we have ended up here, no username was a match!
return false;
}

function LDAPTest()
{
echo "Group Membership test in nested group.\n";

if( IsLDAPGroupMember("root","user"))
{
echo "root is a member of user!\n";
}
else
{
echo "root is NOT a member of user!\n";
}
}
?>

Dec 11, 2008 10:43 AM in response to Kabukiman

Here are a set of php scripts to test group membership based on the dseditgroup command:

<?php

function TestGroupMembership($username,$group)
{
//$debug=1;
//$command="dseditgroup -o checkmember -m ${username} -n /LDAPv3/ares.math.uco
nn.edu ${group}|cut -d\ -f 1";
$command="dseditgroup -o checkmember -m ${username} ${group}|cut -d\ -f 1";
$status=exec($command);
if( $debug) echo "Status = $status\n";

$membership=$status=="yes";
if($debug)echo $membership;
return ($membership);
}

function getGroups($user)
{
$string="id ". $user;
$result=exec($string);

$loc=strpos($result,"groups=");
$groups=substr($result,$loc);

$start=strpos($groups,"=")+1;
$groups=substr($groups,$start);

$count=0;
while(strlen($groups) > 0)
{
$end=strpos($groups,",");
if( $end==0) $end=strlen($groups);
$thisgroup=substr($groups,0,$end);
$thisgid=(int)(substr($thisgroup,0,strpos($thisgroup,"(")));
$start=strpos($thisgroup,"(")+1;
$last=strpos($thisgroup,")");
$length=$last-$start;
$groupname=substr($thisgroup,strpos($thisgroup,"(")+1,$length);
$group[$count]=array("gid"=>$thisgid,"name"=>$groupname);

$groups=substr($groups,$end+1);
$count++;
}
return $group;
}

function isGroupMember($groupName,$groups)
{
$nelements=sizeof($groups);

for($i=0;$i<$nelements;$i++)
{
$element=$groups[$i];
$gid=current($element);
$name=next($element);
if( strcasecmp($groupName,$name) == 0)
{
return True;
}
}
return False;
}

function getGID($groupName,$groups)
{
$nelements=sizeof($groups);
if( $debug) echo "Number of groups read = $nelements<P>\n";

for($i=0;$i<$nelements;$i++)
{
$element=$groups[$i];
$gid=current($element);
$name=next($element);
if( strcasecmp($groupName,$name) == 0)
{
return $gid;
}
}
return False;
}

function PrintGroups($groups)
{
$nelements=sizeof($groups);
if( $debug) echo "Group Membership = $nelements<P>\n";

for($i=0;$i<$nelements;$i++)
{
$element=$groups[$i];
$gid=current($element);
$name=next($element);
echo "GID = $gid, NAME = $name<BR>\n";
}
}
?>

Dec 11, 2008 8:41 PM in response to Kabukiman

Hi,
I am using a filter with ldap_search to retrieve the groups associated with a user identified by shortname. In my case I am using Net/ldap in Ruby but I think the same applies for the PHP function ldap_search at
http://us2.php.net/manual/en/function.ldap-search.php as Camelot pointed to. My filter is

group_filter = Net::LDAP::Filter.eq( "apple-group-realname", "*") & Net::LDAP::Filter.eq( "memberuid", shortname)

It is a combination search criteria to search any attribute of apple_group-realname for an associated attribute memberuid with value shortname. The result is returned as an array along with a status message.

HTH,
Harry

Dec 16, 2008 8:01 AM in response to Al Kirkus

That seemed to do the trick, thank you! Before, I had it sort of rigged together with a series of searches looking for memberUid's in each group. So it would run like this:

Search group 1: is the user here?
Search group 2: is the user here?
Search group 3: is the user here?

Less than elegant. With your, help, I was able to make it work like this:

<?php
$user = $_POST["user"];
$groupsdn = "cn=groups,dc=ldap,dc=mydomain,dc=com";
$conn = ldap_connect('myserver');
$groups = "(&(objectClass=posixGroup)(memberUid=$user))";
$want = array ('cn');
$gres = ldap_search($conn, $groupsdn, $groups, $want);
$ginfo = ldap getentries($conn, $gres);
?>

Works like a charm, thank you!

(edit: looks like apple's message board doesn't want to display my square brackets and converted them to slashes on my second line)

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

How to see what groups a user is a member of?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.