An improved/updated version of this function was posted on 10/19/2011, get it here
PHP function that gets the members of an Active Directory group, and returns the data as an array.
Input for the function: group name, user name, password
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?php
// explode DN into array
function explode_dn($dn, $with_attributes=0)
{
$result = ldap_explode_dn($dn, $with_attributes);
//translate hex code into ascii again
foreach($result as $key => $value) $result[$key] = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $value);
return $result;
}
// get members list from AD
function get_members($group,$user,$password) {
// Active Directory server
$ldap_host = "server.college.school.edu";
// Active Directory DN
$ldap_dn = "OU=Departments,DC=college,DC=school,DC=edu";
// Domain, for purposes of constructing $user
$ldap_usr_dom = "@college.school.edu";
// connect and search ldap
$ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP");
@ldap_bind($ldap, $user . $ldap_usr_dom, $password) or die("Could not bind to LDAP");
$results = ldap_search($ldap,$ldap_dn, "cn=" . $group);
$entries = ldap_get_entries($ldap, $results);
$dirty = 0;
// build array of members for this group, first item is count - skipped using $dirty
foreach($entries[0]['member'] as $member) {
if($dirty == 0) {
$dirty = 1;
} else {
$member_dets = explode_dn($member);
$members[] = str_replace("CN=","",$member_dets[0]);
}
}
return $members;
}
?>
The Manager Group contains:<br />
<?php foreach(get_members("group name","user name","password") as $e) { // replace with your values
echo $e . "<br />";
} ?> |
Related Post: PHP login script using LDAP, verify group membership
Forgive my ignorance, I’m pretty ignorant when it comes to PHP. Is there an easy way I can extract attributes as well as names for this? Instead of the results you would normally get, you would get something like this:
The Manager Group contains:
Joe Smith – 6165551212 – jsmith@globocorp.com
Jane Doe – 6195551234 – jdoe@globocorp.com
Nevermind. As soon as I ask, I figure it out. Thanks
Hi
Please can you explain how you fixed it? to get more than user ID in the outputs?
hanks
Abrahem,
To do this you could:
1. Query all the members of the group
2. For each member of the group, query further details
3. Return the array
Tweaking the code above, you can do this:
<?php // explode DN into array function explode_dn($dn, $with_attributes=0) { $result = ldap_explode_dn($dn, $with_attributes); //translate hex code into ascii again foreach($result as $key => $value) $result[$key] = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $value); return $result; } // get members list from AD function get_members($group,$user,$password) { // Active Directory server $ldap_host = "server.college.school.edu"; // Active Directory DN $ldap_dn = "OU=Departments,DC=college,DC=school,DC=edu"; // Domain, for purposes of constructing $user $ldap_usr_dom = "@college.school.edu"; // connect and search ldap $ldap = ldap_connect($ldap_host); @ldap_bind($ldap, $user . $ldap_usr_dom, $password); $results = ldap_search($ldap,$ldap_dn, "cn=" . $group); $member_list = ldap_get_entries($ldap, $results); // establish variables $dirty = 0; $group_member_details = array(); // build array of members for this group, first item is count - skipped using $dirty foreach($member_list[0]['member'] as $member) { if($dirty == 0) { $dirty = 1; } else { // get member's CN from the result $member_dn = explode_dn($member); $member_cn = str_replace("CN=","",$member_dn[0]); // query individual member for all of their details, filtering on CN $member_search = ldap_search($ldap, $ldap_dn, "(CN=" . $member_cn . ")"); $member_details = ldap_get_entries($ldap, $member_search); $group_member_details[] = array($member_details[0]['sn'][0],$member_details[0]['mail'][0]); } } ldap_close($ldap); return $group_member_details; } ?> The Manager Group contains:<br /> <?php $result = get_members("group name","user name","password"); foreach($result as $e) { echo $e[0] . " - " . $e[1] . "<br />"; } ?>Ideally though, you should consider using a PHP LDAP Class for doing more advanced AD queries
http://www.google.com/search?hl=&q=php+ldap+class
Fantastic work – thanks a lot!
Thanks for this function. I’m having a slight problem with the function in response #5 though.
When I run it against a group in my AD it returns an array with all the members but it’s empty. Like this:
Array ( [0] => Array ( [0] => [1] => ) [1] => Array ( [0] => [1] => ) [2] => Array ( [0] => [1] => ) [3] => Array ( [0] => [1] => ) [4] => Array ( [0] => [1] => ) [5] => Array ( [0] => [1] => )
I have no idea why or how to fix it.
Brig, try print_r($member_list); at line 28 and verify that your first part of the function is working correctly and that the member names are returned
See if the first array value [0] of $member_list is an array of all the members, if this output is different the following foreach loop (line 34) wont work correctly
Afterwards, try a print_r($member_details); in that foreach loop to make sure the second ldap query is working – around line 45
That might give you insight as to where the problem lies
Hi Sam, thanks a lot for you reply.
I just tried your suggestions. If I put print_r($member_list); at line 28 I get the following:
Array ( [count] => 1 [0] => Array ( [objectclass] => Array ( [count] => 2 [0] => top [1] => group ) [0] => objectclass [cn] => Array ( [count] => 1 [0] => IM-All_Users ) [1] => cn [member] => Array ( [count] => 543 [0] => CN=Jocasta Anderson,OU=Users,OU=Company,OU=London,OU=UK,DC=domain,DC=pri [1] => CN=Ian Worrad,OU=Users,OU=Company,OU=London,OU=UK,DC=domain,DC=pri [2] => CN=Beatrix Borsos,OU=Users,OU=Dusseldorf,OU=GERMANY,DC=domain,DC=pri [3] => CN=Max Ali,OU=Users,OU=Company,OU=London,OU=UK,DC=domain,DC=pri [4] => CN=Lauren Mortimer,OU=Users,OU=Company,OU=London,OU=UK,DC=domain,DC=pri [5] => CN=Michelle Brown,OU=Users,OU=Contracts Admin,OU=IT,OU=London,OU=UK,DC=domain,DC=pri [6] => CN=Louise McAleer,OU=Users,OU=Company,OU=London,OU=UK,DC=domain,DC=pri……..
So I get all the users in thr group I’m looking for.
When I try print_r($member_details); at line 45 I get the following:
Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 ) Array ( [count] => 0 )…….
Not sure why it doesn’t pick up the details when I can return all the members.
I really appreciate your help!
Worked it out. The problem is that our users in AD are not all located in a single OU.
When I change
$member_search = ldap_search($ldap, $ldap_dn, “(CN=” . $member_cn . “)”);
on line 43 to
$member_search = ldap_search($ldap, $base_dn, “(CN=” . $member_cn . “)”);
Where $base_dn is the path to one of my user OU’s it starts to work.
Just have to figure out how to query all the OU’s now. If it’s at all possible, I’m not sure yet.
Thanks a lot for this function Sam and your help!
Brig,
Ah yes that’s right
If the OU is different from the group’s OU then the inner ldap query needs to have a different base_dn
Because it’s not that way for my environment, I wasn’t thinking of that situation
To query all the members that could be in multiple OU’s, try leaving it blank (just doing the DC’s) or just putting the outer-most OU (provided that there is one)
Just thought I post the final working solution in case someone would need it in the future.
Slightly modified to output an XML file for our phonesystem.
Not sure how to paste code here so put it up on pastebin: http://pastebin.com/xH67tE6p
Thanks Brig,
I will also post it here
<?php function explode_dn($dn, $with_attributes=0) { $result = ldap_explode_dn($dn, $with_attributes); foreach($result as $key => $value) $result[$key] = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $value); return $result; } function get_members($group,$user,$password) { $ldap_host = "LDAPSERVER"; $ldap_dn = "OU=some_group,OU=some_group,DC=company,DC=com"; $base_dn = "DC=company,DC=com"; $ldap_usr_dom = "@company.com"; $ldap = ldap_connect($ldap_host); ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION,3); ldap_set_option($ldap, LDAP_OPT_REFERRALS,0); ldap_bind($ldap, $user . $ldap_usr_dom, $password); $results = ldap_search($ldap,$ldap_dn, "cn=" . $group); $member_list = ldap_get_entries($ldap, $results); $dirty = 0; $group_member_details = array(); foreach($member_list[0]['member'] as $member) { if($dirty == 0) { $dirty = 1; } else { $member_dn = explode_dn($member); $member_cn = str_replace("CN=","",$member_dn[0]); $member_search = ldap_search($ldap, $base_dn, "(CN=" . $member_cn . ")"); $member_details = ldap_get_entries($ldap, $member_search); $group_member_details[] = array($member_details[0]['givenname'][0],$member_details[0]['sn'][0],$member_details[0]['telephonenumber'][0],$member_details[0]['othertelephone'][0]); } } ldap_close($ldap); return $group_member_details; } // Specify the group from where to get members and a username and password with rights to query it $result = get_members("groupname","username","password"); $xml = simplexml_load_string("<?xml version='1.0'?>\n<AddressBook></AddressBook>"); $version = $xml->addChild('version', '1'); foreach($result as $e) { $contact = $xml->addChild('Contact'); $contact->addChild('FirstName', $e[0]); $contact->addChild('LastName', $e[1]); $phone = $contact->addChild('Phone'); if ($e[3] == '') { $phone->addChild('phonenumber', '0'); } else { $phone->addChild('phonenumber', $e[3]); } $phone->addChild('accountindex', '0'); $phone = $contact->addChild('Phone'); if ($e[2] == '') { $phone->addChild('phonenumber', '0'); } else { $phone->addChild('phonenumber', $e[2]); } $phone->addChild('accountindex', '1'); $contact->addChild('Group', '0'); $contact->addChild('PhotoUrl', 'empty'); } $xml->asXML('phonebook.xml'); ?>How could this be used to display users of an OU as opposed to members of a group?
You just need to change the LDAP search string
In the original example it’s:
You would change this to something like:
You could also provide the $ldap_dn to the OU that you want, and put in a * for your search string to return everything in that OU, like this:
I tried your suggestion.
$results = ldap_search($ldap,$ldap_dn, “ou=” . $group); not working but when I use the $results = ldap_search($ldap,$ldap_dn, “cn=*”); works and I see the outputs through print_r($member_list); But there is a problem.
member in line 34 is an attribut of the group object. The OU dosen’t have this. So second ldap query is empty print_r($member_details); dosen’t show anything.
Hans,
If you want to get everyone in a CN like ‘Users’, you can simplify things a bit:
< ?php // Active Directory server $ldap_host = "ad.host"; // Active Directory DN $ldap_dn = "CN=Users,DC=ad,DC=host"; // Domain, for purposes of constructing $user $ldap_usr_dom = "@ad.host"; // AD user $user = "test"; $password = "password1234!"; // connect and search ldap $ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP"); @ldap_bind($ldap, $user . $ldap_usr_dom, $password) or die("Could not bind to LDAP"); $results = ldap_search($ldap,$ldap_dn, "(&(objectClass=user))"); $entries = ldap_get_entries($ldap, $results); $i = 0; foreach($entries as $u) { if($i != 0) echo $u['samaccountname'][0] . ""; $i++; } ?>Thanks for this function. Fantastic work.
Is it possible to sort the results by ldap_sort or other function?
Hans
Hans,
I haven’t tested this but you should be able to put:
Between lines 26 and 27, so it looks like:
Where ‘cn’ is the parameter you want to sort by.
You could also use PHP functions to sort the output array, see http://www.php.net/manual/en/array.sorting.php for options
Sam thanks for your suggestions and help. I put sort($group_member_details); between lines Line 46 and 47 and the output array was sorted.
The first code works for me if I put a Group name it returns the users in the group. However, I need the last code that you have that gets everyone in a OU like ‘TestUsers’. However, that last code just doesnt seem to work. It does not return anything.
Any ideas why?
See if you are getting any errors:
Make sure error_reporting and display_errors is enabled for your PHP installation
Remove the @ in front of the ldap_bind on line 17
Also verify that your $ldap_dn variable is correctly formed
I am not getting any errors at all. error_reporting is enabled for my PHP installation
I tried removing the @ in front of the ldap_bind on line 17 also no luck.
The $ldap_dn variable is definately correctly formed because its the same one I use for your main code and that works fine. And if I change the password for the account specified, i get a message saying cannot bind. So it definately binds correctly. It Just does not output anything.
Ahmed,
I have tested the code again with my AD installation
I was able to query members of an OU (as well as an OU inside of an OU) with no issues
Using, for example, $ldap_dn = “OU=TestUsers,DC=ad,DC=myserver”;
Verify that your DN is the correct path to the OU you are trying to query
How complex is your OU structure?
Thanks for your reply Sam. It now works great :)
You are correct the issue was with the DN. I used the example you just gave and modified it and it worked. Thanks.
No problem
Glad to hear it.
Hi sam, can you help me?
I cannot retrieve records.
Results: Array ( [count] => 1 [0] => Array ( [objectclass] => Array ( [count] => 2 [0] => top [1] => container ) [0] => objectclass [cn] => Array ( [count] => 1 [0] => Users ) [1] => cn [description] => Array ( [count] => 1 [0] => Default container for upgraded user accounts ) [2] => description [distinguishedname] => Array ( [count] => 1 [0] => CN=Users,DC=sdb,DC=sucden,DC=sp ) [3] => distinguishedname [instancetype] => Array ( [count] => 1 [0] => 4 ) [4] => instancetype [whencreated] => Array ( [count] => 1 [0] => 20090921145941.0Z ) [5] => whencreated [whenchanged] => Array ( [count] => 1 [0] => 20090921145941.0Z ) [6] => whenchanged [usncreated] => Array ( [count] => 1 [0] => 4304 ) [7] => usncreated [usnchanged] => Array ( [count] => 1 [0] => 4304 ) [8] => usnchanged [showinadvancedviewonly] => Array ( [count] => 1 [0] => FALSE ) [9] => showinadvancedviewonly [name] => Array ( [count] => 1 [0] => Users ) [10] => name [objectguid] => Array ( [count] => 1 [0] => ÈÂi%ÇBA«ÌN‚ãó5 ) [11] => objectguid [systemflags] => Array ( [count] => 1 [0] => -1946157056 ) [12] => systemflags [objectcategory] => Array ( [count] => 1 [0] => CN=Container,CN=Schema,CN=Configuration,DC=sdb,DC=sucden,DC=sp ) [13] => objectcategory [iscriticalsystemobject] => Array ( [count] => 1 [0] => TRUE ) [14] => iscriticalsystemobject [count] => 15 [dn] => CN=Users,DC=sdb,DC=sucden,DC=sp ) )CONFIG:
$ldap_host = “SERVER”;
$ldap_dn = “CN=Users,DC=sdb,DC=sucden,DC=sp”;
$base_dn = “DC=sdb,DC=sucden,DC=sp”;
$ldap_usr_dom = “@sdb.sucden.sp”;
Regards.
Hmm, It’s hard to say… did you change anything like the ldap_search string?
Can you post the entire code?
function get_members($group,$user,$password) { $ldap_host = "SERVER"; $ldap_dn = "CN=Users,DC=sdb,DC=sucden,DC=sp"; $base_dn = "DC=sdb,DC=sucden,DC=sp"; $ldap_usr_dom = "@sdb.sucden.sp"; $ldap = ldap_connect($ldap_host); ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION,3); ldap_set_option($ldap, LDAP_OPT_REFERRALS,0); ldap_bind($ldap, $user . $ldap_usr_dom, $password); $results = ldap_search($ldap,$ldap_dn, "cn=" . $group); $member_list = ldap_get_entries($ldap, $results); $dirty = 0; $group_member_details = array(); foreach($member_list[0]['member'] as $member) { if($dirty == 0) { $dirty = 1; } else { $member_dn = explode_dn($member); $member_cn = str_replace("CN=","",$member_dn[0]); $member_search = ldap_search($ldap, $base_dn, "(CN=" . $member_cn . ")"); $member_details = ldap_get_entries($ldap, $member_search); $group_member_details[] = array($member_details[0]['givenname'][0],$member_details[0]['sn'][0],$member_details[0]['telephonenumber'][0],$member_details[0]['othertelephone'][0]); } } ldap_close($ldap); return $group_member_details; } // Specify the group from where to get members and a username and password with rights to query it $result = get_members("Users","joao","XXXXXX"); print_r($result);Joao,
I have rewritten the function, try using the new one: http://samjlevy.com/?p=1460
Hi there.
I am trying to modify your code to return the samaccountname (username) of each user, rather than their canonical name, but not having much luck!
From what i understand, i think i will have to return the list of members as you already have, and then search LDAP again to match the canonical name to the samaccount name, but maybe there is an easier way ?
Thanks,
Dan.
Dan,
Try the improved version of this function I posted a few days ago:
http://samjlevy.com/?p=1460
With it you can specifically request samaccountname or any other user object attribute
Is there is any way i can get the list of all the groups of all the ou’s with PHP
You should be able to tweak the LDAP query to get a list of groups
Try something like (objectcategory=group)(samaccountname=*)