0

I have a single domain (my.local) with 2 domain controllers:

  • 192.168.3.63 - DC1
  • 192.168.3.64 - DC2 (primary DC)

I'm testing request to find if user is a member of a group. Here's a query filter:

(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))

And If I use "Active Directory Users and Computers" (ADUaC) snap-in on both controllers I get the same result:

enter image description here

But when I run dsquery, I get no results:

C:\Users\admin>dsquery * domainroot -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))" 
C:\Users\admin>

What is more interesting is that if I specify the -s paramter, dsquery returns the results, BUT only when I pass another DC, not the one from which I run dsquery

On DC1 (192.168.3.63): notice the change in behavior depending on the -s switch

C:\Users\admin>dsquery * domainroot -s 192.168.3.63 -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
C:\Users\admin>
C:\Users\admin>dsquery * domainroot -s 192.168.3.64 -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
"CN=adtest2,CN=Users,DC=my,DC=local"
C:\Users\admin>

On DC2 (192.168.3.64):

C:\Users\admin>dsquery * domainroot -s 192.168.3.63 -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
"CN=adtest2,CN=Users,DC=my,DC=local"
C:\Users\admin>
C:\Users\admin>dsquery * domainroot -s 192.168.3.64 -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
C:\Users\admin>

I tried dsquery to run with domainroot, forestroot and "DC=my,DC=local" - with no effect. I also tried to specify -scope subtree, but this is the default BTW.

  • Why dsquery without specifying DC always fails to find user and ADUaC alays succeeds?
  • Why dsquery returns result only from a different DC, but on from current DC when -s switch is specified?
  • What can/should I chage in order to make dsquery work consistently?
mistika
  • 111
  • 3

1 Answers1

0

This is not going to be a full answer, because it'd take too long to validate and I don't know the nuts and bolts, but I expect it pertains to the specific query that includes 1.2.840.113556.1.4.1941.

This is the LDAP_MATCHING_RULE_IN_CHAIN OID, and it is specific to Active Directory LDAP. If you specify forestroot, you're hitting the GC. For domainroot, it's obviously the domain root. I think the issue here is that this method is not a traditional search for objects by traversing the structure recursively. Such if you're doing a match by name.

LDAP_MATCHING_RULE_IN_CHAIN is a AD-specific "shortcut" method - kind of like a stored proc in SQL. So to use it, you need to bind to an LDAP server (a DC) that offers that specific feature at the protocol level. Just like being able to view a database table is easy, but to use a stored proc, you need to be using SQL features.

You can see what I mean by this by running LDP.exe and binding to a DC - when you do the bind, the DC will list the LDAP features it supports under SupportedControl. With these, they often have sub-controls that can be further queried and I think LDAP_MATCHING_RULE_IN_CHAIN could be one of those.

Remember that the GUI is doing a lot of work for you under the hood. It's not pure LDAP that it's giving you - there are DLLs and .NET hooks that it uses to retrieve data and format it in a friendly way.

So to make your query more consistent, you need to bind to a specific DC to access the LDAP_MATCHING_RULE_IN_CHAIN protocol method, since you're not just "browsing" through the directory. I don't see an example of you using the -d [domain DNS name] switch. This will bind to any available DC in the site/domain.

dsquery user -name *test -d mydomain.org

Lastly, and to make your life much easier, using an LDAP query like that is actually quite unusual for DSQuery. The whole point of it is that's supposed to be a friendly(er) "wrapper" to LDAP, a little like the GUI. It has some "helpers" to make queries easier and format data.

The usual way to get the groups a user is a member of is the following, if you want the group samAccountNames.

dsquery user -samid %USERNAME% | dsget user -memberof | dsget group -samid

If you only want the group DNs, just leave off | dsget group -samid.

This article is quite a nice introduction on the tool - I recommend you read it for good tips on the usual syntax and methods.

These days, I recommend you start getting to grips with AD Powershell. Powershell is really more flexible, although dsquery still has a few tricks.

LeeM
  • 1,388
  • 9
  • 14
  • The original problem raised from our product. We use LDAP the check if a user is a member of a particular group. The application is written in .Net, and it usually works except of one of our customers. I captured LDAP traffic and found that DC (or whatever server it is) returns the empty result set for the query, meanwhile ADUC returns the required user with the same query. Then I tried dsquery to understand what is wrong, but I faced the problem that it returns inconsistent results even in our domain depending on from which DC and to wich DC you make a query. – mistika Sep 17 '20 at 13:46
  • I'd recommend using ldp.exe for troubleshooting pure ldap. You can do the same queries as your product without worrying about application layer interpretation. And bind to individual DCs to see if your results vary. You want to do a proper bind to for that recursive "memberof" query. Another monitoring option is to use the domain controller precompiled log/report in Perfmon. It runs for 5 mins, you do your queries in your product (and also via ldp.exe?) There's a detailed report on ldap query efficiency etc there - esp timeouts. Dcdiag for repl issues. Maybe paging, if it's a big result? – LeeM Sep 18 '20 at 17:58