Solved

Get all users from Active Directory using PHP, LDAP

Posted on 2013-12-19
4
1,804 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
  • 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 108

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

Join & Write a Comment

Synchronize a new Active Directory domain with an existing Office 365 tenant
These days socially coordinated efforts have turned into a critical requirement for enterprises.
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
This tutorial will walk an individual through the steps necessary to join and promote the first Windows Server 2012 domain controller into an Active Directory environment running on Windows Server 2008. Determine the location of the FSMO roles by lo…

747 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now