Let's start with the LDAP filter. Our goal is to build an LDAP filter that will find exactly what we want and that will be as efficient as possible. A few attributes in Active Directory distinguish
user
objects from other object types that we can use to build a filter:
This will get the job done, but we can do even better than this.
Note: Behavior Change in Windows Server 2003
Windows Server 2003 Active Directory indexes the
objectClass
attribute by default, so this rule really only applies to Windows 2000 Active Directory now. Additionally, the schema administrators for your domain may have already indexed it, so check the schema before making assumptions.
One key difference between
contact
objects and
user
objects in Active Directory is that
user
objects have a
sAMAccountName
attribute that is indexed by default. Thus, we could build a filter like this:
(&(objectCategory=person)(sAMAccountName=*))
This will separate the contacts from the users effectively. However, another approach is available that can find
user
objects directly, and it may be the most efficient technique for Active Directory:
(sAMAccountType=805306368)
Using the
sAMAccountType
attribute with a value of
805306368
accesses
a single-valued, indexed attribute that uniquely defines
user
objects. The only downside here is that this attribute is not well documented, so it may not be recommended by Microsoft. However, in our investigations, it is effective.
One piece of good news is that all of these attributes are included in the global catalog, so we can use all of these filters there as well.
This should provide a foundation to build on for various
user
object searches. We may also wish to combine these filters with other attributes to find different
subsets
of
user
objects matching specific criteria. We will see some examples of that in the rest of this section.
Finding Users in ADAM
Things change a little bit for ADAM, because we don't have things like
sAMAccountName
or
sAMAccountType
on an ADAM user. These attributes are actually from the auxiliary class called
securityPrincipal
. This class happens to be slightly different depending on whether it comes from Active Directory or ADAM. In this case, the
securityPrincipal
class does not contain
sAMAccountName
or related attributes in ADAM.
This means that we need to adjust our filters slightly to find our users in ADAM. It turns out that we can use some other indexed attributes, such as
userPrincipalName
, to find our users. However, since this attribute is not required, we have to be careful and ensure that all of our
user
objects have set a value for
userPrincipalName
.
As mentioned in Chapter 8, ADAM also includes the idea of a
userProxy
object that we often will want to return as well. To do so, we should look for common attributes found on both classes that would filter them for our needs. In this case, we know that both the
user
and
userProxy
classes contain
userPrincipalName
, so it is a good candidate for this purpose. We could use a simple filter such as
(userPrincipalName=*)
if we knew that all of our objects would have a value set for this attribute. However, since not all
user
or
userProxy
objects might have a value set for
userPrincipalName
, we would have to use
objectCategory
to be safe. For example:
((objectCategory=person)(objectCategory=userProxy))
The implications here are that if any other class in the directory also shared the same
objectCategory
of
person
or
userProxy
, they would also be returned. In default ADAM instances, this does not occur, but we should always check with our particular ADAM instance. Now, if we want to separate the two classes and treat them differently, we can use
objectClass
, as the classes are different for each type:
(&(objectClass=user)(objectCategory=person))
(&(objectClass=userProxy)(objectCategory=userProxy))
The first filter will return only
user
objects using
objectCategory
as an index, and the second will return only
userProxy
objects in the same manner. It is important to remember that we can customize ADAM heavily with application-specific classes. We should never rely on the fact that any particular class will be there or even be indexed. As such, these are only guidelines, and we really need to check the particular ADAM instance's schema
ourselves
to determine what is there.
Note: New Versions of ADAM Include the userProxyFull Class
With later versions of ADAM, a new class called
userProxyFull
can be found that essentially mirrors the
user
class with the addition of the
msDSBindProxy
auxiliary class. This means that we cannot use
objectCategory
to distinguish between
user
and
userProxyFull
classes as we can with
userProxy
classes. We must instead rely upon the
objectClass
to distinguish between the two. This is another example of where we need to be cognizant of what our schema is for ADAM.