views:

597

answers:

3

I am trying to figure out whether the current windows user either is local administrator or can use UAC to "attain" that group membership.

What I've come up so far looks like this:

var adminIdentifier = new SecurityIdentifier("S-1-5-32-544");
var current = WindowsIdentity.GetCurrent();
bool isAdmin = current.Groups.Contains(adminIdentifier);
bool canBeAdmin = isAdmin;

if (!isAdmin)
{
    var adminGroupName = adminIdentifier.Translate(typeof(NTAccount)).Value;
    adminGroupName = adminGroupName.Substring(adminGroupName.LastIndexOf('\\'));
    string path = "WinNT://./" + adminGroupName + ",group";

    using (DirectoryEntry groupEntry = new DirectoryEntry(path))
    {
      foreach (object member in (IEnumerable)groupEntry.Invoke("Members"))
      {
        using (DirectoryEntry memberEntry = new DirectoryEntry(member))
        {
              object obVal = memberEntry.Properties["objectSid"].Value;
              SecurityIdentifier sid = null;
              if (null != obVal)
              {
                 sid = new SecurityIdentifier((Byte[])obVal,0);
              }

              canBeAdmin = Equals(current.User, sid);
              if (canBeAdmin)
                break;
        }
     }
   }
 }
 Console.WriteLine(canBeAdmin +" "+isAdmin);

This solution takes a few milliseconds to compute. Much faster than the System.DirectoryServices.AccountManagement based approach I tried before.

There is one last thing that bothers me, though. I have to translate the SecurityIdentifier of the admin group to the name. There ought to be a way to get the DirectoryEntry directly by using the SID. According to Google, this should work:

string path = "LDAP://<SID=" + adminIdentifier.ToString() + ">";

However, this does not seem to work. Any idea how the syntax should look like?

+1  A: 

Have you tried using GetAuthorizationGroups on the UserPrincipal object corresponding to the current user? You may have to check whether the user is directly in the local administrators group or whether the local administrators group contains any of the authorization groups that the user is in if GetAuthorizationGroups doesn't include machine-local groups. I haven't tried this with a machine context so I'm not sure whether you'd need to also search the domain context for the latter match if it doesn't compute the local group membership using domain/global/universal groups when using the machine context.

tvanfosson
GetAuthorizationGroups() yields the same result, unfortunately with the same (lack of) performance.
Sven Künzler
A: 

This should be what you want, unless I misunderstand:

var groupName = adminIdentifier.Translate(typeof(NTAccount)).Value;
Noldorin
My problem statement is probably not clear enough :-)I have: a SecurityIdentifier for a windows group.I need: the DirectoryEntry for that groupCurrently, I have to convert the SID to a name. I would like to get rid of that conversion.
Sven Künzler
+1  A: 

Have you tried WindowsPrincipal.IsInRole ?

WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
wp.IsInRole(new SecurityIdentifier("S-1-5-32-544"));
wp.IsInRole(WindowsBuiltInRole.Administrator);
mathieu
WindowsPrincipal.IsInRole() returns false for the administrator group when running in non-elevated mode. That's why I have to determine group membership in another way.
Sven Künzler