views:

221

answers:

2

I have a problem with C# accessing AD objects. The goal of the code is to retrieve a users's groups. We have 2 domains involved - the domain where the application and many users reside, plus a trusted domain that also contains users so the code must be able to get groups from both domains.

I am using a DirectorySearcher object and filtering it based on the user SID. It's packaged into a DLL to be used by applications. The application currently uses the same code and it works, but when it calls the DLL, the DLL won't return anything from AD. It cannot retrieve any users from the FindOne() call.

We ran into a similar problem when using a search for users before when we only had 1 domain involved, but found a workaround - we could open the user object directly, and didn't search for the object. Now that we have a second domain involved, we have to use the user's SID, and we can't just open the object.

The DLL works in one test environment, but will not work in 2 other test environments. What could be causing this type of behavior? Is this a problem with the DLL? AD Security? Application security? How do we determine if the user has access to search?

Alternatively (if we can't find a solution to this problem), how else can I get a user's groups based on their SID without using a search?

+2  A: 

Are you on .NET 3.5 ? The AD stuff for group and user management ("principal management") has been improved quite a bit in 3.5.

There's a new System.DirectoryServices.AccountManagement namespace which is extremely helpful - read all about it here on MSDN Magazine in an article by Ethan Wilansky and Joe Kaplan.

The .NET 3.5 stuff finally allows you to get the user's groups easily, programmatically, and include the user's primary group and any nested group memberships.

If you are on .NET 3.5, you can use code like this:

using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
    using(p = Principal.FindByIdentity(ctx, "yourUserName"))
    {
        var groups = p.GetGroups();

        using (groups)
        {
            foreach (Principal group in groups)
            {
                Console.WriteLine(group.SamAccountName + "-" + group.DisplayName);
            }
        }
    }
}

S.AD.AM also includes new methods on the "Principal" class to find principals (users, groups, computers) by a variety of search criteria, e.g. by name, SID, GUID:

FindByIdentity contains two overloads, both of which take a PrincipalContext and value to find. For the value, you can specify any of the supported identity types: SamAccountName, Name, UserPrincipalName, DistinguishedName, Sid, or Guid.

Pretty neat, eh? :-)

Marc

marc_s
God damn, that's awesome. This is way better than the old way to get user/group information
Alan
It is indeed ! Time to upgrade to .NET 3.5 ?? :-)
marc_s
That sounds like it will be great... once we upgrade to 3.5! The application is still at 2.0... so we are too.
The Application may be .NET 2.0, but does the assembly have to be? I bereeve a .NET 2.0 application can call a .NET 3.5 assembly.
Alan
A: 

Generically speaking, using a DLL won't change how System.DirectoryServices works. I've used a plugin assembly approach to searching AD, and it works the same as running the actual assembly itself.

There are several questions (which you should ask yourself) that might shed some light:

  1. Are the test environments the same? Same functional domain level (Win2000, Win2003, etc), same trust setups?
  2. Is the machine running the code domain joined (ie are you supplying credentials when creating the DirectoryEntry object)? 1 .Does the account you use to search the domain have the cross domain trust.
  3. Are your domains setup as a Parent/Child relationship?
  4. What happens if you search domains via sAMAccountName or UPN?
  5. Do you have your DirectorySearch parameters set to automatically search other domains?

There are a couple ways to debug this.

If FindOne is not returning anything (and no exception is being thrown) then it's telling you that FindOne is not finding any results that match your criteria.

Or, FindOne is throwing an exception (usually a ComException), and you can use the comexception errorcode to lookup what is happening.

You can fire up WireShark, disable, Sealing and Secure bind, and sniff the packets from your application. You will see the LDAP responses to your search.

Alan
No exceptions are being thrown - it just returns 0 groupsThe two that fail are likely set up the same. All 3 env are at 2003 functional level. We can't search on sAMAccountName either - that's the problem we had originally until we changed the code and didn't search anymore.
Same WindowsIdentity current name between the app and the DLL too