Está en la página 1de 11

How To: ¿Como

44

saber si el usuario
actual es
administrador del
dominio?
Lluis Franco
HOW TO: ¿COMO SABER SI EL USUARIO ACTUAL ES ADMINISTRADOR
DEL DOMINIO?
Nivel: Intermedio
por Lluis Franco

Esta es una cuestión que suscita dudas muy a menudo en todo tipo de foros de
desarrolladores, ya que se trata de una necesidad muy común en las aplicaciones de gestión de
escritorio.

Cuando desarrollamos una aplicación podremos mostrar/ocultar/permitir/revocar ciertas


acciones, u opciones sabiendo a qué grupos pertenece el usuario actual que está ejecutando la
aplicación. Por ejemplo, yo acostumbro a tener un botón en la barra de estado de mis
aplicaciones que permite cambiar la cadena de conexión de la base de datos, y evidentemente,
solo está visible cuando el usuario pertenece al grupo “Administradores” o “Administradores
del dominio”.

Método IsInRole de WindowsPrincipal


Para conseguir este objetivo, el objeto WindowsPrincipal dispone de un método IsInRole, que
nos dirá si un usuario pertenece a un grupo determinado. Además este método tiene varias
sobrecargas, de modo que podemos usarlo pasando el RID (Relative Identifier), SID (Security
Identifier), el nombre e incluso una constante basada en la enumeración WindowsBuiltInRole.
En la Tabla A podemos ver los posibles valores de esta enumeración, y en la Tabla B los valores
de los RID bien conocidos (ver al final del documento).

De este modo para saber si nuestro usuario es administrador local, basta con hacer esto:

WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());


return wp.IsInRole(WindowsBuiltInRole.Administrator);

A partir del usuario que ejecuta nuestra aplicación (válido también en caso de que se haga
suplantación de usuario), creamos un objeto Principal e invocamos al método pasándole el
grupo contra el que deseamos validar. ¿A qué es sencillo?

Nota: Por motivos de rendimiento, para determinar la función del usuario se recomienda
utilizar la sobrecarga de IsInRole(SecurityIdentifier) como sobrecarga preferible.

El problema de esta enumeración es que como su nombre indica, sólo contempla los grupos
locales. Así que si queremos saber si pertenece a un grupo del dominio parece que tendremos
que buscar el SID del grupo, o el nombre, y “hardcodearlo” –introducirlo a mano- en nuestra
aplicación.

¿Feo verdad? Pues la verdad es que si, muy feo… vamos a investigar un poco más, a ver si
encontramos otra forma.
Identificadores de seguridad: SID

Existe una enumeración llamada WellKnownSidType, que devuelve los SID (Security Identifiers,
identificadores de seguridad) más utilizados.

Los SID son valores únicos de longitud variable que se usan para identificar una entidad
principal de seguridad (usuario) o un grupo de seguridad en sistemas operativos Windows. Los
SID conocidos son un grupo de estos identificadores que representan a usuarios o grupos
comunes y cuyos valores permanecen constantes en todos los sistemas operativos. Si quieres
profundizar en estos elementos y su composición puedes hacerlo en este artículo de la
Wikipedia (inglés).

En la Tabla C, al final, se muestra la lista de los SID conocidos. Verás que hay muchos usuarios y
grupos comunes, y entre ellos ¡BINGO!, está también el SID del grupo de administradores del
dominio (en rojo, AccountDomainAdminSid), y parece que por lo tanto ya podemos volver a
probar el método IsInRole:

WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());

SecurityIdentifier sid =
new SecurityIdentifier(WellKnownSidType.AccountDomainAdminsSid, null);

return wp.IsInRole(sid);

¡Ooops! Nuestro gozo en un pozo. Se produce un error:

Figura 1.- Excepción al intentar usar un nulo como segundo argumento

Se necesita especificar el segundo argumento en el constructor del SID de grupo, y por lo tanto
no funciona. El error habla de un AccountDomainSid. ¿Y qué es esto?

DomainSid
Según la documentación del constructor debe proporcionarse el SID del dominio para que éste
ueda devolver algunos identificadores WellKnownSidType, entre los cuales está el de que nos
interesa de los administradores del dominio.

Dicho de otro modo, o sabemos el SID de nuestro dominio o todo lo anterior no vale para
nada… :-(

¿Y cómo podemos saber el SID de dominio? Después de buscar un ratito, lo único que he
encontrado es una utilidad de consola llamada PsGetSid, que forma parte de las PSTools del
inefable Mark Russinovich. Basta descargar esta utilidad y ejecutarla desde la consola de este
modo para saber el SID de nuestro dominio (el nombre de dominio en formato
“microsoft.com” o “net.volvo.com”):

Figura 2.- La utilidad PsGetSid en funcionamiento

Sin embargo tener que hacer esto y usar el identificador “hardcodeado” en el código no sería
tampoco de gran ayuda. Así que vamos a probar si podemos recuperar esta propiedad del
esquema de Directorio Activo mediante un DirectoryEntry. Para ello utilizaremos la clase
Domain:

Domain d = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain,


getDomainName()));

using (DirectoryEntry de = d.GetDirectoryEntry())


{
byte[] domSid = (byte[])de.Properties["objectSid"].Value;
string sdomainSid = sIDtoString(domSid);
Console.WriteLine(sdomainSid);
}

//El código anterior hace uso de estos dos métodos adicionales:

//Obtiene el nombre del dominio actual


public static string getDomainName()
{
return IPGlobalProperties.GetIPGlobalProperties().DomainName;
}

//Transforma el array de bits del SID en su representación textual


public static string sIDtoString(byte[] sidBinary)
{
SecurityIdentifier sid = new SecurityIdentifier(sidBinary, 0);
return sid.ToString();
}
En el código anterior obtenemos dentro de la variable sdomainSid, que se muestra por
consola, el valor del SID de nuestro dominio, que era lo que buscábamos :-)

Poniéndolo todo junto


Como resumen final y con el ánimo de dar un código listo para usar, vamos a encapsular todo
lo explicado dentro de un método extensor de la clase WindowsIdentity de modo que
podamos usarlo con mucha facilidad:

using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Net.NetworkInformation;
using System.Security.Principal;

namespace Alpha.Code
{
public static class SecurityExtensions
{
public static bool IsDomainAdmin (this WindowsIdentity identity)
{
Domain d = Domain.GetDomain(new
DirectoryContext(DirectoryContextType.Domain, getDomainName()));
using (DirectoryEntry de = d.GetDirectoryEntry())
{
byte[] bdomSid = (byte[])de.Properties["objectSid"].Value;
string sdomainSid = sIDtoString(bdomSid);
WindowsPrincipal wp = new WindowsPrincipal(identity);
SecurityIdentifier dsid = new SecurityIdentifier(sdomainSid);
SecurityIdentifier dasid = new SecurityIdentifier(
WellKnownSidType.AccountDomainAdminsSid, dsid);
return wp.IsInRole(dasid);
}
}

public static string getDomainName()


{
return IPGlobalProperties.GetIPGlobalProperties().DomainName;
}

public static string sIDtoString(byte[] sidBinary)


{
SecurityIdentifier sid = new SecurityIdentifier(sidBinary, 0);
return sid.ToString();
}
}
}

Y ahora la forma de usarlo sería tan sencilla como hacer algo así:

if (WindowsIdentity.GetCurrent().IsDomainAdmin())
{
//Acciones a realizar si el usuario es administrador de dominio...
}
APÉNDICE: TABLAS

Tabla A.- Miembros de la enumeración WindowsBuiltInRole para usar con IsInRole

Nombre Descripción
AccountOperator Los operadores de cuentas administran las cuentas de los usuarios de un
equipo o dominio.
Administrator Los administradores tienen acceso completo y sin restricciones al equipo o
dominio.
BackupOperator Los operadores de copia de seguridad pueden reemplazar las restricciones
de seguridad con el único propósito de hacer copias de seguridad de los
archivos o de restaurarlas.

Guest Los invitados tienen más restricciones que los usuarios.


PowerUser Los usuarios avanzados poseen la mayoría de los permisos administrativos,
con algunas restricciones. De este modo, los usuarios avanzados pueden
ejecutar aplicaciones heredadas, además de aplicaciones certificadas.

PrintOperator Los operadores de impresión pueden tomar el control de una impresora.

Replicator Los replicadores permiten la duplicación de archivos en un dominio.

SystemOperator Los operadores del sistema administran un equipo en particular.

User Los usuarios no pueden realizar cambios accidentales o intencionados en


todo el sistema. En consecuencia, pueden ejecutar aplicaciones
certificadas, pero no la mayoría de las aplicaciones heredadas.

Tabla B.- Identificadores de recursos bien conocidos (RID) para usar con IsInRole

Entidad conocida RID Tipo


Domain Administrator 500 User
Domain Guest 501 User
Domain KRBTGT 502 User
Domain Admins 512 Group
Domain Users 513 Group
Domain Guests 514 Group
Domain Computers 515 Group
Domain Controllers 516 Group
Domain Certificate Admins 517 Group
Domain Schema Admins 518 Group
Domain Enterprise Admins 519 Group
Domain Policy Admins 520 Group
Builtin Admins 544 Alias
Builtin users 545 Alias
Builtin Guests 546 Alias
Builtin Power Users 547 Alias
Builtin Account Operators 548 Alias
Builtin System Operators 549 Alias
Builtin Print Operators 550 Alias
Builtin Backup Operators 551 Alias
Builtin Replicator 552 Alias
Builtin RAS Servers 553 Alias

Tabla C.- Miembros de la enumeración WellKnownSidType

Nombre Descripción
NullSid Indica un SID null.
WorldSid Indica un SID que coincide con todos.
LocalSid Indica un SID local.
CreatorOwnerSid Indica un SID que coincide con el propietario o
creador de un objeto.
CreatorGroupSid Indica un SID que coincide con el grupo de
creadores de un objeto.
CreatorOwnerServerSid Indica un SID de Creator Owner Server.
CreatorGroupServerSid Indica un SID de servidor de grupo de creadores.
NTAuthoritySid Indica un SID para la autoridad de Windows NT.
DialupSid Indica un SID para una cuenta de acceso
telefónico.
NetworkSid Indica un SID para una cuenta de red. Este SID se
agrega al proceso de un símbolo (token) cuando
inicia sesión a través de una red.
BatchSid Indica un SID para un proceso por lotes. Este SID
se agrega al proceso de un símbolo (token) cuando
inicia sesión como un trabajo por lotes.
InteractiveSid Indica un SID para una cuenta interactiva. Este SID
se agrega al proceso de un símbolo (token) cuando
inicia sesión interactivamente.
ServiceSid Indica un SID para un servicio. Este SID se agrega al
proceso de un símbolo (token) cuando inicia
sesión como servicio.
AnonymousSid Indica un SID para la cuenta anónima.
ProxySid Indica un SID de servidor proxy.
EnterpriseControllersSid Indica un SID para un controlador de empresa.
SelfSid Indica un SID para sí mismo.
AuthenticatedUserSid Indica un SID para un usuario autenticado.
RestrictedCodeSid Indica un SID para código restringido.
TerminalServerSid Indica un SID que coincide con una cuenta de
Terminal Server.
RemoteLogonIdSid Indica un SID que coincide con inicios de sesión
remotos.
LogonIdsSid Indica un SID que coincide con identificadores de
inicio de sesión.
LocalSystemSid Indica un SID que coincide con el sistema local.
LocalServiceSid Indica un SID que coincide con un servicio local.
NetworkServiceSid Indica un SID que coincide con un servicio de red.

BuiltinDomainSid Indica un SID que coincide con la cuenta de


dominio.
BuiltinAdministratorsSid Indica un SID que coincide con la cuenta de
administrador.
BuiltinUsersSid Indica un SID que coincide con las cuentas de
usuario integradas.
BuiltinGuestsSid Indica un SID que coincide con la cuenta de
invitado.
BuiltinPowerUsersSid Indica un SID que coincide con el grupo de
usuarios avanzados.
BuiltinAccountOperatorsSid Indica un SID que coincide con la cuenta de
operadores de cuentas.
BuiltinSystemOperatorsSid Indica un SID que coincide con el grupo de
operadores de sistema.
BuiltinPrintOperatorsSid Indica un SID que coincide con el grupo de
operadores de impresión.
BuiltinBackupOperatorsSid Indica un SID que coincide con el grupo de
operadores de copias de seguridad.
BuiltinReplicatorSid Indica un SID que coincide con la cuenta del
replicador.
BuiltinPreWindows2000CompatibleAccessSid Indica un SID que coincide con cuentas
compatibles con versiones anteriores a Windows
2000.
BuiltinRemoteDesktopUsersSid Indica un SID que coincide con usuarios de
escritorio remoto.
BuiltinNetworkConfigurationOperatorsSid Indica un SID que coincide con el grupo de
operadores de red.
AccountAdministratorSid Indica un SID que coincide con el grupo de
administradores de cuenta.
AccountGuestSid Indica un SID que coincide con el grupo de
invitados de cuenta.
AccountKrbtgtSid Indica un SID que coincide con el grupo de destino
Kerberos de la cuenta.
AccountDomainAdminsSid Indica un SID que coincide con el grupo de
administradores de dominio de cuenta.
AccountDomainUsersSid Indica un SID que coincide con el grupo de
usuarios de dominio de cuenta.
AccountDomainGuestsSid Indica un SID que coincide con el grupo de
invitados de dominio de cuenta.
AccountComputersSid Indica un SID que coincide con el grupo de equipos
de cuenta.
AccountControllersSid Indica un SID que coincide con el grupo de
controladores de cuenta.
AccountCertAdminsSid Indica un SID que coincide con el grupo de
administradores de certificado.
AccountSchemaAdminsSid Indica un SID que coincide con el grupo de
administradores de esquema.
AccountEnterpriseAdminsSid Indica un SID que coincide con el grupo de
administradores de empresa.
AccountPolicyAdminsSid Indica un SID que coincide con el grupo de
administradores de directivas.
AccountRasAndIasServersSid Indica un SID que coincide con la cuenta de
servidor RAS e IAS.
NtlmAuthenticationSid Indica un SID presente cuando el paquete de
autenticación NTLM de Microsoft autenticó el
cliente.
DigestAuthenticationSid Indica un SID presente cuando el paquete de
autenticación implícita de Microsoft autenticó el
cliente.
SChannelAuthenticationSid Indica un SID presente cuando el paquete de
autenticación de canal seguro (SSL/TLS) autenticó
el cliente.
ThisOrganizationSid Indica un SID presente cuando el usuario se
autenticó desde el bosque o a través de una
confianza que no tiene habilitada la opción de
autenticación selectiva. Si este SID está presente,
OtherOrganizationSid no puede estarlo.
OtherOrganizationSid Indica un SID presente cuando el usuario se
autenticó en un bosque con la opción de
autenticación selectiva habilitada. Si este SID está
presente, ThisOrganizationSid no puede estarlo.

BuiltinIncomingForestTrustBuildersSid Indica un SID que permite a un usuario crear


relaciones de confianza de bosque de entrada. Se
agrega al símbolo (token) de los usuarios que son
miembros del grupo integrado de Creadores de
confianza de bosque de entrada en el dominio raíz
del bosque.

BuiltinPerformanceMonitoringUsersSid Indica un SID que coincide con el grupo de


usuarios que tiene acceso remoto para programar
un registro de contadores de rendimiento en este
equipo.
BuiltinPerformanceLoggingUsersSid Indica un SID que coincide con el grupo de
usuarios que tiene acceso remoto para supervisar
el equipo.
BuiltinAuthorizationAccessSid Indica un SID que coincide con el grupo de acceso
de autorización de Windows.
WinBuiltinTerminalServerLicenseServersSid Indica un SID que está presente en un servidor que
puede emitir licencias de Terminal Server.
MaxDefined Indica el SID máximo definido en la enumeración
WellKnownSidType.

Acerca del autor


Lluís Franco es autor de campusMVP. Es gestor de proyectos y desarrollador en ‘Fimarge Societat
Gestora de Patrimonis’, situada en Andorra. Desde 1994, ha estado principalmente trabajando en el
desarrollo de aplicaciones sobre plataformas Windows. Está especializado en desarrollos financieros con
SQL Server, Visual Basic y C#. Blog: http://geeks.ms/blogs/lfranco

Acerca de campusMVP
CampusMVP te ofrece la mejor formación en tecnología Microsoft a través de nuestros cursos online y
nuestros libros especializados, impartidos y escritos por conocidos MVP de Microsoft. Visita nuestra
página y prueba nuestros cursos y libros gratuitamente. www-campusmvp.com

Reconocimiento - NoComercial - CompartirIgual (by-nc-sa):


No se permite un uso comercial de este documento ni de las posibles obras derivadas, la
distribución de las cuales se debe hacer con una licencia igual a la que regula esta obra original. Se
debe citar la fuente.