Solved

Get all users from Active Directory using PHP, LDAP

Posted on 2013-12-19
4
2,531 Views
Last Modified: 2015-05-06
I'm modifying some PHP code that previously pulled all staff details from LDAP to now pull the data from Active Directory.

The code (for Active Directory) does an ldap_bind and connect, then it looks like this:
			$filter = "(&(objectCategory=person)(objectClass=user)(sn=$search*))";
			$dn = 'DC=acmeco,DC=global';
			$ldap_data = ldap_get_entries($con, ldap_search($con, $dn, $filter));

Open in new window


This works, but unfortunately also picks up some non-staff records. I've tried altering the filter to various values to exclude the non-staff records, but with no luck. In particular, I thought that filtering on "distinguishedname" (to look for OU=Users) might work, but the only thing I could get to match was the entire string for just one user (nothing using a wildcard).

How can I filter out the non-staff? Thanks!

I tried this filter, but it returns nothing:
			$filter = "(&(objectCategory=person)(objectClass=user)(distinguishedname=*OU=Users*)(sn=$search*))";

Open in new window


Staff data looks like this (only partly shown, to reduce sanitisation effort):
    [0] => Array
        (
            [objectclass] => Array
                (
                    [count] => 4
                    [0] => top
                    [1] => person
                    [2] => organizationalPerson
                    [3] => user
                )

            [0] => objectclass
            [cn] => Array
                (
                    [count] => 1
                    [0] => Joe Bloggs
                )

            [1] => cn
            [sn] => Array
                (
                    [count] => 1
                    [0] => Bloggs
                )

            [2] => sn
            [c] => Array
                (
                    [count] => 1
                    [0] => AU
                )

            [3] => c
            [l] => Array
                (
                    [count] => 1
                    [0] => Melbourne
                )

            [4] => l
            [st] => Array
                (
                    [count] => 1
                    [0] => Victoria
                )

            [5] => st
            [title] => Array
                (
                    [count] => 1
                    [0] => Project Manager
                )

            [6] => title
            [postalcode] => Array
                (
                    [count] => 1
                    [0] => VIC 3000
                )

            [7] => postalcode
            [physicaldeliveryofficename] => Array
                (
                    [count] => 1
                    [0] => Melbourne
                )

            [8] => physicaldeliveryofficename
            [givenname] => Array
                (
                    [count] => 1
                    [0] => Joe
                )

            [9] => givenname
            [distinguishedname] => Array
                (
                    [count] => 1
                    [0] => CN=Joe Bloggs,OU=MB,OU=Users,OU=NS,OU=AU,DC=acmeco,DC=global
                )

            [10] => distinguishedname

Open in new window


And some non-user records, looking like this (just a part of it):
    [113] => Array
        (
            [objectclass] => Array
                (
                    [count] => 4
                    [0] => top
                    [1] => person
                    [2] => organizationalPerson
                    [3] => user
                )

            [0] => objectclass
            [cn] => Array
                (
                    [count] => 1
                    [0] => Service App Pool 1
                )

            [1] => cn
            [sn] => Array
                (
                    [count] => 1
                    [0] => App Pool 1
                )

            [2] => sn
            [givenname] => Array
                (
                    [count] => 1
                    [0] => Service
                )

            [3] => givenname
            [distinguishedname] => Array
                (
                    [count] => 1
                    [0] => CN=Service App Pool 1,OU=SharePoint Administration,OU=Services,DC=acmeco,DC=global
                )

            [4] => distinguishedname

Open in new window

0
Comment
Question by:Terry Woods
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 31

Assisted Solution

by:Frosty555
Frosty555 earned 334 total points
ID: 39731085
You need to craft a suitable LDAP filter, and search only the relevant portion of your directory.

Your filter looks fine. It will search for user accounts, and you can optionally filter based on the username based on the $search variable.

The problem is your service accounts ARE user accounts - there's no technical difference between the "Service App Pool 1" user, and the "Joe Bloggs" user, except perhaps their location in the directory.

I don't know what the exact structure of your directory is, but looking at the results you posted in your question, it looks like your Users are all under this container:

So why not change your base DN to be that, instead of searching the entire directory:

$dn = 'OU=Users,OU=NS,OU=AU,DC=acmeco,DC=global';

This way, results are only returned for objects inside that particular OU.
0
 
LVL 31

Accepted Solution

by:
Frosty555 earned 334 total points
ID: 39731094
Also I find it's very useful to use an LDAP Browser program to actually browse your directory, craft your ldap search queries etc. and test them so that you can see what the actual results of your queries are SUPPOSED to be, before putting it into PHP.

This helps you iron out syntactical or logical errors in your LDAP search filters.

I used Softerra LDAP Browser, which you can get for free:

http://www.softerra.com/download.htm

The free edition provides read-only access to your directory which is exactly what you want, and it has a very nice graphical interface to help you craft your LDAP queries, test them, and browse and explore your directory, determine the proper distinguished names for various objects etc.

In my network, I had an OpenFire server which shows user accounts from active directory. I wanted it to show only staff user accounts, and ONLY those accounts who were members of a specific security group, "Openfire Users", which was located in a particular place in my directory. Also, I wanted to exclude users who have been disabled.

For that, I used this filter:

(&(objectClass=organizationalPerson)(memberOf=CN=Openfire Users,OU=Security Groups,OU=MyBusiness,DC=mycompany,DC=local)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))

Open in new window

0
 
LVL 110

Assisted Solution

by:Ray Paseur
Ray Paseur earned 166 total points
ID: 39731728
Are you open to filtering this in PHP after the active directory information is acquired?  If so we might be able to create a filter function that would look at givenname->distinguishedname[0] and look for OU=Users.  To do that I would need to see the var_dump() output of the active directory listing.  Var_dump() has more information than print_r().
0
 
LVL 35

Assisted Solution

by:Terry Woods
Terry Woods earned 0 total points
ID: 39735117
I have previously used (and can use) a different free LDAP Browser (it's pretty old; looks like you can still get it here), though I haven't worked much with LDAP and have generally struggled through without spending much time trying to understand the general concepts.

It shows a structure like:
OU=StuffIDoNotWant (there's lots of these)
OU=AU (this is a country; there's more than one)
  OU=NS (this is the region)
    OU=MoreStuffIDoNotWant (there's 3 or 4 like this, at this level)
    OU=Users (only users are in this branch of the tree)
      OU=AS (this corresponds to an office)
        CN=John Doe

Open in new window

There are many offices across multiple countries, and I'm interested in getting all the users from all offices in one or all countries. Adding only "OU=Users," to the base DN I have above doesn't work and returns zero results. I can get the users for one office by adding OU=AU,OU=NS,OU=Users,OU=AS to the base DN, but that's not much good.

In the meantime, I've looked at ways to filter out the non-user records based on data that they tend to have missing (eg email and country), which seems to mostly be ok. I'm not sure that it can be completely reliable though.
0

Featured Post

MS Dynamics Made Instantly Simpler

Make Your Microsoft Dynamics Investment Count  & Drastically Decrease Training Time by Providing Intuitive Step-By-Step WalkThru Tutorials.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Auditing domain password hashes is a commonly overlooked but critical requirement to ensuring secure passwords practices are followed. Methods exist to extract hashes directly for a live domain however this article describes a process to extract u…
A hard and fast method for reducing Active Directory Administrators members.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question