Page 1 of 1

check if user belongs to a certain group

Posted: Thu May 08, 2008 5:24 pm
by zifnabbe
Hi,

Is it possible to find out if a user belongs to a certain group?

Thanks

Posted: Thu May 08, 2008 6:02 pm
by Nico Bendlin
Please define the context of "user".
If you are refferring to the user token of the current thread or current process, you might have a look at IsUserAnAdmin/SHTestTokenMembership/CheckTokenMembership.
(if you need a pre-Win2K emulation of CheckTokenMembership in Delphi: http://www.delphipraxis.net/post730030.html#730030)
If you have to deal with non-elevated admins, you might have a look at IsTokenRestricted/GetTokenInformation(TokenElevationType).

Posted: Thu May 08, 2008 11:09 pm
by zifnabbe
With user I mean the current user account logged into windows.
I would like to know if that user belongs to a certain group (active directory). If so, I allow the user to use a certain application otherwise (s)he may not use it.

Posted: Fri May 16, 2008 5:49 pm
by madshi
Check out NetUserGetGroups and NetGroupGetUsers and related APIs. These also work for ActiveDirectory. You can also use COM objects to access ActiveDirectory. But I find that more complicated than using the "old" APIs.

madSecurity currently does not contain functions to list group users.

Posted: Sun May 18, 2008 3:36 am
by iconic
@Nico: IsUserAnAdminIn() just wraps CheckTokenMembership() and isn't advised to be called directly anymore. In the past I've used IsNTAdmin() API (advpack.dll) to test for admin rights but unfortunately this no longer works correctly under Vista variants. I just compare security identifiers from my current process to the admin group via OpenProcessToken->GetTokenInformation->EqualSID.
This seems to work fine on Windows 2000 - Windows Vista.

--Iconic

Posted: Sun May 18, 2008 4:26 am
by Nico Bendlin
iconic wrote:@Nico: IsUserAnAdminIn() just wraps CheckTokenMembership() and isn't advised to be called directly anymore.
Who gave/gives this advice?
(edit: Well, there is a comment in MSDN now :))

The linked Delphi source emulates the APIs if they are not present.

Posted: Sun May 18, 2008 5:29 am
by iconic
@Nico,
Your emulation seems useful. My unemulated implementation is very similar to the methods that you invoke to check for admin rights. I'm actually very surprised that Microsoft has never "officially" backed an API to check for admin rights definitively. It would be nice to have one reliable API not change from the very first NT release to the current Vista build.

Code: Select all

function UserIsAdmin: BOOL;
const
  SECURITY_BUILTIN_DOMAIN_RID = $00000020;
        DOMAIN_ALIAS_RID_ADMINS = $00000220;
var
              hToken: ULONG;
               ulRet: ULONG;
          lpSIDAdmin: Pointer;
                   i: ULONG;
           sidNtAuth: SID_IDENTIFIER_AUTHORITY;
              TokInf: Array [0..$FF] of ULONG;
               lpGrp: ^_TOKEN_GROUPS;
begin
  result := False;
  ZeroMemory(@sidNtAuth.Value, 6);
  ulRet := 0;
  sidNtAuth.Value[5] := 5;
  lpGrp := @TokInf;
  if not OpenProcessToken(DWORD(-1), TOKEN_READ, hToken) then exit;
  if GetTokenInformation(hToken, TokenGroups, @TokInf, $400, ulRet) and (ulRet > 0) then
  begin
  AllocateAndInitializeSid(sidNtAuth, 2, SECURITY_BUILTIN_DOMAIN_RID,
                           DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, lpSIDAdmin);
  for i := 0 to lpGrp^.GroupCount -1 do
    begin
      result := EqualSID(lpsidAdmin, lpGrp^.Groups[i].SID);
      if (result) then break;
    end;
    FreeSID(lpsidAdmin);
  end;
  CloseHandle(hToken);
end;
Nice work!

--Iconic

Posted: Sun May 18, 2008 12:31 pm
by Nico Bendlin
EqualSID() - without the check if the SID is disabled in the token - will lead to another behaviour than IsUserAnAdmin(). All functions of this kind are intended as an "access check" - but your function will return false positives for "limited" tokens. E.g. in Windows XP [Shift+RMB] on an executable, choose "Run as..." and enable the checkbox to limit the token. Windows XP will just disable the admin SID in the token. In this case your function still returns TRUE. If this is intended (your function is not intended as "access check", but as "group check"), this is the wrong way of doing it - because Windows is free to completely remove the SID from the new token. As I mentioned above, there other functions available to check for "is token limited", "is token un-elevated", and "is the user account in the token a member of group x" (a completely different story).

This has always been a source of confusion, IsUserAnAdmin() and similar do not answer the question "Is the user account included in the token a member of group x?", but they will tell you "Has the token the rights to access an object that is accessible by members of group x?"

Best regards,
Nico Bendlin

Posted: Sun May 18, 2008 1:28 pm
by iconic
True, it's a small access check with no real sanity checks, it's all I really need however for any programs that I am currently developing. If in the future I come across the need to have a more "bullet proof", versatile admin access checking function I will definitely look back at your emulated functions. Your link is much appreciated to the forum and I'm sure others can benefit from this too.

--Iconic

Posted: Tue May 20, 2008 10:20 am
by zifnabbe
thanks for all the advice. I'll check these asap. Right now I'm in the middle of a house move and have very limited access to internet.