Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why UserPrincipal.Enabled returns different values?

I am trying to determine if a user account in AD is enabled. For this I use the following code:

string domain = "my domain";
string group = "my security group";
string ou = "my OU";

//init context
using (var cnt= new PrincipalContext(ContextType.Domain, domain))
{
    //find the necessary security group
    using (GroupPrincipal mainGroup 
              = GroupPrincipal.FindByIdentity(cnt, IdentityType.Guid, group))
    {
        if (mainGroup != null)
        {
            //get the group's members
            foreach (var user in mainGroup.GetMembers()
                                   .OfType<UserPrincipal>()
                                   .Where(u => u.DistinguishedName.Contains(ou)))
            {
                //ensure that all the info about the account is loaded
                //by using FindByIdentity as opposed to GetMembers
                var tmpUser= UserPrincipal.FindByIdentity(cnt, 
                                                          user.SamAccountName);
                //actually I could use `user` variable, 
                //as it gave the same result as `tmpUser`.

                //print the account info
                Console.WriteLine(tmpUser.Name + "\t" + 
                                  tmpUser.Enabled.HasValue + "\t" + 
                                  tmpUser.Enabled.Value);                    
            }
        }
    }
}

The problem is, when I run this code under an administrative account, I get the real result, while when I run it under a non-priviledged account, user.Enabled returns false for some of the accounts, while it should be true.

The only similar q&a I managed to find are

  1. UserPrincipal.Enabled returns False for accounts that are in fact enabled?
  2. Everything in Active Directory via C#.NET 3.5 (Using System.DirectoryServices.AccountManagement)

which do not help here.

Why is that so? What are my options to get this info under a non-priviledged account?


Here is another approach: How to determine if user account is enabled or disabled:

private bool IsActive(DirectoryEntry de)
{
    if (de.NativeGuid == null) 
        return false;

    int flags = (int)de.Properties["userAccountControl"].Value;

    if (!Convert.ToBoolean(flags & 0x0002)) 
        return true; 
    else 
        return false;
}

Same approach is described in Active Directory Objects and C#.

However when running under an unpriviledged user account, userAccountControl attribute is null and it's not possible to determine the state of the account.


The workaround here is to use PrincipalContext Constructor, specifying the credentials of a user with enough priviledges to access AD.

It stays unclear to me, why the unpriviledged user had access to AD at all, and couldn't get values of some certain account attributes. Probably this has nothing to do with C#, and should be configured in AD...

like image 748
horgh Avatar asked May 15 '13 02:05

horgh


1 Answers

You'll need to delegate permissions in Active Directory for the accounts that will be performing the AD queries. This is what I had to do for my applications to work (though we are performing other administrative tasks on user accounts).

Check Here for instructions on how to delegate permissions(or see blockquote below).

You may referred the following procedure to run the delegation:

  • Start the delegation of control wizard by performing the following steps:
    • Open Active Directory Users and Computers.
    • In the console tree, double click the domain node.
    • In the details menu, right click the organizational unit, click delegate control, and click next.
    • Select the users or group to which you want to delegate common administrative tasks. To do so, perform the following steps:
    • On the Users or Groups page, click Add.
    • In the select Users, computers or Groups, write the names of the users and groups to which you have to delegate control of the organizational unit, click OK. And click next.
    • Assign common tasks to delegate. To do so perform the following common tasks.
    • On the tasks to delgate page, click delegate the following common tasks.
    • On the tasks to delegate page, select the tasks you want to delegate, and click OK. Click Finish

For Example: To delegate administrator to move user/computer objects, you can use advance mode in AD User and Computer and run delegation. It should have write privilege in both OU for the object moving. For writing new values, the administrators account should have delegated values on the user account (Full privilege in specific OU as well.

Something else worth looking into is if the accounts have the userAccountControl attribute. I've heard that accounts missing this attribute may not report correctly. In most scenarios this attribute should be set to NormalAccount.

like image 54
Tyler Jennings Avatar answered Nov 13 '22 23:11

Tyler Jennings