I was testing something in my lab: I created an account, and then added a deny ACL to the domain, applying to that and all descendant objects, denying full control. However, I found that using adfind as the denied account, I was still able to list users (but some properties were hidden)!
I found that when applying a deny full control ACL only to the user caused the user to be hidden. However, the inherited permissions are shown and appear to deny everything.
Why is the inherited ACL not sufficient to prevent user listing?
The platform in this case is windows server 2008 R2.
Users can view all child objects of a container unless they have been denied the permission on the container to view child objects.
Controlling Object Visibility
http://msdn.microsoft.com/en-us/library/windows/desktop/ms675746%28v=vs.85%29.aspx
"Active Directory Domain Services provide the ability to hide objects from users who have been denied certain rights. If an object is hidden, an application that is running with a user's credentials will not be able to enumerate or bind to the object.
"If a user is granted the ADS_RIGHT_ACTRL_DS_LIST access control right on a container, the user can view any of the child objects of the container. Likewise, if a user is denied the ADS_RIGHT_ACTRL_DS_LIST access control right on a container, the user cannot view any of the child objects of the container. This allows the contents of entire containers to be hidden."
It turns out that explicit allow ACLs take precedence over inherited deny ACLs, and there are explicit ACLs on every object for authenticated users. Alas; the only way to do this is to either strip the authenticated users permission on anything that needs hiding, or add an explicit ACL to every such object.
This makes it prohibitively difficult to deny a user access to enumerate anything in the domain, alas.
I know that this is old but maybe my answer will help point those who need it in the right direction (I'm going through the same thing now with a company that already had an implemented AD environment).
The built-in Authenticated Users group will be granted the ability to read attributes of Active Directory objects and that will take precedence over an explicit DENY permission inherited from a parent OU / Container. It is all based on the way that AD is originally constructed and how the permission structure is designed when the forest/domain is created. Read this article for more information:
Hiding Data in Active Directory
And this one from the same series (on how to do it)...
Hiding Data in Active Directory, Part 3: Enabling List Object Mode in a Forest
Basically, you can enable List Object Mode by changing the dsHeuristics bit via ADSIedit (change the 3rd bit from 0 to 1). Then get rid of Authenticated Users (so that it isn't automatically applied to AD objects). Then your DENY permissions will take precedence. However, changing this will cause AD to require more time to evaluate permissions so be sure this is what you want to do. For "average" domains, the delay is negligible.
CAUTION: Also, be double sure that this is what you want to do (and I recommend doing this when you first build the domain, not after it is in use). Unless you do this up-front when the domain is first created, you will likely break group policies, apps that query AD, etc. This type of thing should be planned out and implemented on a domain up-front so that you ensure proper permissions are in-place for applications to work at the time they are deployed. It all depends how granular you want to get but it can easily break everything if you implement it on a domain that is already in production.