• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3357
  • Last Modified:

Get all users from Active Directory using PHP, LDAP

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
Terry Woods
Asked:
Terry Woods
  • 2
4 Solutions
 
Frosty555Commented:
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
 
Frosty555Commented:
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
 
Ray PaseurCommented:
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
 
Terry WoodsIT GuruAuthor Commented:
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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now