I recently mentioned the beauty of Phantom Root and how you can use it to search all of the NCs on a DC in a single fell swoop. This works great but I stumbled upon a slight oddity. I am discussing it with the MSFT DS Dev team as there is some debate/question on exactly what the behavior should be. Whatever the decision, I do classify the current behaviour as odd at a minimum and the more I think about it the more I think the current behaviour is incorrect.
So what is the oddity?
If you query a DC that happens to be a Global Catalog and you specify the base that is within a naming context that is only read-only on the DC (i.e. a Domain that the DC doesn’t host) then instead of the query running on that DC, a referral will be returned to redirect you to a DC of the domain specified. This doesn’t happen when querying the GC port on the same though obviously.
So lets give a couple of examples. These examples have the following constants:
The forest design is
dc=root,dc=com
cn=configuration
cn=schema
dc=child1
There are two domain controllers that are GCs; DC1 is a DC for root.com and a GC, DC2 is a DC for child1.root.com and is also a GC.
You can use phantom root to query with multiple bases and the two GCs will give different results for some of those bases. I don’t believe that is correct as it belies underlying implementation when GCs are all supposed to be created equal. There are other examples of this especially around linked attributes but having that problem in one area doesn’t validate it as ok in another.
Scenario 1
Search Base: “” (null base)
Filter : objectclass=*
Result: Correct
Both GCs will return identical results. Will return all objects in forest.
Scenario 2
Search Base: dc=com
Filter : objectclass=*
Result: Correct
Both GCs will return identical results. Will return all objects in forest.
Scenario 3
Search Base: dc=root,dc=com
Filter : objectclass=*
Result: Incorrect (IMO)
GCs will return different results. DC1 will return all objects in forest. DC2 will return a referral.
Scenario 4
Search Base: dc=child1,dc=root,dc=com
Filter : objectclass=*
Result: Incorrect (IMO)
GCs will return different results. DC1 will return a referral. DC2 will return all objects in forest.
Scenario 5
Search Base: cn=configuration,dc=root,dc=com
Filter : objectclass=*
Result: Correct
GCs will return identical results. Will return all objects in config and schema NCs
Scenario 6
Search Base: cn=users,dc=root,dc=com (or any other container in root.com domain)
Filter : objectclass=*
Result: Incorrect (IMO)
Same as Scenario 3
Scenario 7
Search Base: cn=users,dc=child1,dc=root,dc=com (or any other container in child1.root.com domain)
Filter : objectclass=*
Result: Incorrect (IMO)
Same as Scenario 4
The answer to this could be a simple “so query the GC port then…”. There are reasons why this may not be feasible. One example is that maybe you are working through a reverse proxy or through router ACLs and only port 389 is available. Maybe you are porting an application that is designed from the ground up to only use port 389 and you want to minimize the changes but still need to query any of the partitions directly and you don’t want the overhead of referrals. etc etc etc
One messy issue that could come up when you have multiple DCs for root.com or you have a single DC for root.com but it isn’t a GC and you initially are using a child1.root.com GC for all of your queries and you happen to specify dc=root,dc=com for a base (it is the root domain, this wouldn’t be unusual) and you get a redirection like
REFERRAL: ldap://root.com/dc=root,dc=com
which could take you to ANY root.com DC in the root.com domain including one that isn’t a GC. So say you hit a non-GC DC, the query is executed there and since it isn’t a GC, none of the child1.root.com objects are returned. Referrals are usually handled in the background with no outward visible signs of the referral so many people would be quite shocked if they were expecting some child1.root.com objects to be returned and in fact none were… They would likely have to do a network query to even start to crack the problem or worse, have the app vendor try to figure it out.
I do really hope that MSFT either changes this behaviour or adds some sort of additional control that allows you to disable the referral from being returned and just forces the search. Since these aren’t continuation referrals you cannot block them with the currently available server side referral blocking mechanisms like you can with continuation referrals. In fact, continuation referrals are already disabled when you use Phantom Root.
joe
We have twice run across an issue which we eventually traced to ldap referrals. One thing you didn’t mention in your blog was whether or not you saw any kind of delay in the query response. We have an app that has no option for handling referrals, but we discovered that the ‘Nix ldapsearch tool can ignore referrals, and it shows the referrals that are not followed.
In a query to port 389, we see the referrals, but our query immediately returns data. However, when the same query is done to 636 (ldaps), it seems that there’s a problem with the referrals: the command hangs for at least 2 minutes even though it returned data because it’s waiting for the referrals to complete. Letting the command complete, it comes up with an error that indicates that it could not connect to whatever server the referral is directed to.
We are running AD 2000, but I suspect this behaviour is the same in AD 2003.
I was just wondering if you ever followed up on the issue you saw, since you mentioned that you were talking to the DS Dev Team.
Thanks.
— Rob —