Identificar si un usuario está en el grupo de administradores locales

Mi problema

Estoy usando las funciones de la API de Windows PInvoked para verificar si un usuario forma parte del grupo de administradores locales. Estoy utilizando GetCurrentProcess , OpenProcessToken , GetTokenInformation y LookupAccountSid para verificar si el usuario es un administrador local.

GetTokenInformation devuelve una estructura TOKEN_GROUPS con una matriz de estructuras SID_AND_ATTRIBUTES . Repaso la colección y comparo los nombres de usuario devueltos por LookupAccountSid .

Mi problema es que, localmente (o más generalmente en nuestro dominio interno), esto funciona como se esperaba. La incorporada \ Administradores se encuentra dentro de la membresía de grupo del token de proceso actual y mi método devuelve verdadero. En otro dominio de otro desarrollador la función devuelve falso.

LookupAccountSid funciona correctamente durante las 2 primeras iteraciones de la estructura TOKEN_GROUPS , devolviendo Ninguno y Todos, y luego se queja TOKEN_GROUPS que “Un parámetro es incorrecto”.

¿Qué haría que solo dos grupos funcionen correctamente?

La estructura TOKEN_GROUPS indica que hay 14 grupos. Supongo que es el SID que no es válido.

Todo lo que he invocado lo he tomado de un ejemplo en el sitio web de PInvoke. La única diferencia es que con LookupAccountSid he cambiado el parámetro Sid de un byte[] a un IntPtr porque SID_AND_ATTRIBUTES también se define con un IntPtr . ¿Esto está bien ya que LookupAccountSid está definido con un PSID?

LookupAccountSid PInvoke

  [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern bool LookupAccountSid( string lpSystemName, IntPtr Sid, StringBuilder lpName, ref uint cchName, StringBuilder ReferencedDomainName, ref uint cchReferencedDomainName, out SID_NAME_USE peUse); 

Donde cae el código

  for (int i = 0; i < usize; i++) { accountCount = 0; domainCount = 0; //Get Sizes LookupAccountSid(null, tokenGroups.Groups[i].SID, null, ref accountCount, null, ref domainCount, out snu); accountName2.EnsureCapacity((int) accountCount); domainName.EnsureCapacity((int) domainCount); if (!LookupAccountSid(null, tokenGroups.Groups[i].SID, accountName2, ref accountCount, domainName, ref domainCount, out snu)) { //Finds its way here after 2 iterations //But only in a different developers domain var error = Marshal.GetLastWin32Error(); _log.InfoFormat("Failed to look up SID's account name. {0}", new Win32Exception(error).Message); continue; } 

Si se necesita más código, hágamelo saber. Cualquier ayuda sería muy apreciada.

Parece que estás intentando duplicar la funcionalidad de NetUserGetLocalGroups . También puede usar NetUserGetInfo con un nivel de información de 1 y verificar el valor de usri1_priv en USER_INFO_1 para USER_PRIV_ADMIN .

No estoy seguro de si NetUserGetLocalGroups sabe acerca de negar SID (si necesita verificar si el proceso actual (no la cuenta del usuario) está en el grupo de administración, debe manejar negar SID)

Si solo necesita compatibilidad con 2000 y versiones posteriores, PInvoke CheckTokenMembership (esa página de MSDN tiene una función de ejemplo IsUserAdmin)

En NT4, necesita obtener una matriz TokenGroups de GetTokenInformation, pero no llama a LookupAccountSid, solo llama a EqualSid en cada elemento y lo compara con un SID de grupo de administradores que crea con AllocateAndInitializeSid (…, SECURITY_BUILTIN_DOMAIN_RID) …