2012-06-01 27 views
14

Estoy tratando de utilizar el .NET 3.5 System.DirectoryServices.AccountManagement espacio de nombres para validar las credenciales del usuario contra nuestro servidor LDAP de Active Directory a través de una conexión LDAP encriptada SSL. Aquí está el código de ejemplo:¿Cómo valido los créditos de Active Directory sobre LDAP + SSL?

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:389", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate)) 
{ 
    return pc.ValidateCredentials(_username, _password); 
} 

Este código funciona bien a través de LDAP no seguro (puerto 389), sin embargo prefiero no transmito una combinación usuario/pase en texto claro. Pero cuando cambio a LDAP + SSL (puerto 636), tengo la siguiente excepción:

System.DirectoryServices.Protocols.DirectoryOperationException: The server cannot handle directory requests. 
    at System.DirectoryServices.Protocols.ErrorChecking.CheckAndSetLdapError(Int32 error) 
    at System.DirectoryServices.Protocols.LdapSessionOptions.FastConcurrentBind() 
    at System.DirectoryServices.AccountManagement.CredentialValidator.BindLdap(NetworkCredential creds, ContextOptions contextOptions) 
    at System.DirectoryServices.AccountManagement.CredentialValidator.Validate(String userName, String password) 
    at System.DirectoryServices.AccountManagement.PrincipalContext.ValidateCredentials(String userName, String password) 
    at (my code) 

puerto 636 funciona para otras actividades, tales como la búsqueda de información no contraseña para esa entrada LDAP/AD ...

UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, _username) 

... así que sé que no es la configuración SSL de mi servidor LDAP, ya que funciona a través de SSL para otras operaciones de búsqueda.

¿Alguien ha recibido la llamada ValidateCredentials(...) para trabajar a través de SSL? ¿Puedes explicar cómo? ¿O hay otra/mejor forma de validar de forma segura las credenciales de AD/LDAP?

+0

Aquí hay un artículo de MSDN para solucionar problemas de LDAP sobre SSL: http://support.microsoft.com/kb/938703 – CAbbott

+0

Gracias por el enlace. Pero nuevamente puedo comunicarme a través de LDAPS (puerto 636) bien para todas las demás consultas LDAP que he realizado. Parece algo inusual sobre 'ValidateCredentials()'. Sin embargo, revisaré el artículo con más detalle. –

+0

Las contraseñas deben transmitirse en texto claro -no hash- a través de una conexión segura a un servidor que admita comprobaciones de calidad de contraseñas y cumplimiento de historial de contraseñas a menos que el cliente LDAP proporcione la calidad de contraseña y las comprobaciones del historial; de lo contrario, el servidor no podrá calidad e historia. –

Respuesta

14

Pude validar las credenciales utilizando el espacio de nombres System.DirectoryServices.Protocols, gracias a un compañero de trabajo. Aquí está el código:

// See http://support.microsoft.com/kb/218185 for full list of LDAP error codes 
const int ldapErrorInvalidCredentials = 0x31; 

const string server = "sd.example.com:636"; 
const string domain = "sd.example.com"; 

try 
{ 
    using (var ldapConnection = new LdapConnection(server)) 
    { 
     var networkCredential = new NetworkCredential(_username, _password, domain); 
     ldapConnection.SessionOptions.SecureSocketLayer = true; 
     ldapConnection.AuthType = AuthType.Negotiate; 
     ldapConnection.Bind(networkCredential); 
    } 

    // If the bind succeeds, the credentials are valid 
    return true; 
} 
catch (LdapException ldapException) 
{ 
    // Invalid credentials throw an exception with a specific error code 
    if (ldapException.ErrorCode.Equals(ldapErrorInvalidCredentials)) 
    { 
     return false; 
    } 

    throw; 
} 

No estoy encantada con el uso de un bloque try/catch para controlar decisión a la lógica, pero es lo que funciona. :/

1

Quizás esta es otra forma. No hay nada inusual en validar credenciales. ContextOptions debe establecerse correctamente.

Valor por defecto:

ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing

Añadir SSL:

ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing | ContextOptions.SecureSocketLayer

ContextOptions.Negotiate o ContextOptions.SimpleBind es necesario. O lo que sea que su servidor necesite para realizar la autenticación. ContextOptions solo admite O bit a bit.

Puede probar también establecer ContextOptions directamente de esta manera en el método ValidateCredentials.

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:636", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate | ContextOptions.SecureSocketLayer)) 
{ 
    return pc.ValidateCredentials(_username, _password); 
} 

O

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:636", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate)) 
{ 
    return pc.ValidateCredentials(_username, _password, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer); 
} 
+0

Veo que dice "O lo que sea que su servidor necesite para realizar la autenticación". ¿Cómo puedo saber qué necesita un servidor para la autenticación? Estoy trabajando en un servidor que anteriormente está configurado con algunas opciones, pero no sé qué son ahora. ¿Puedo revisarlos de alguna manera? –

0

Para mí, el método ValidateCredentials funciona bien. El problema, descubrí, estaba en el servidor que aloja el AD (estoy usando AD LDS). Necesitaba asociar el certificado del servidor con la instancia de AD. Entonces, si su instancia se llamaba 'MyAD' (o ActiveDirectoryWebService), tenía que abrir la MMC, ingresar el módulo 'Certificados', seleccionar 'Cuenta de servicio' y luego seleccionar 'MyAD' de la lista. Desde allí, puede agregar el certificado SSL en la tienda personal 'MyAD'. Esto finalmente impulsó el procesamiento SSL.

sospecho, por lo que sé de la LdapConnection método y el hecho de que se omitiera la función de devolución de llamada, que no está validando su certificado de servidor. Es un trabajo complicado y ValidateCredentials lo hace de forma gratuita. Probablemente no es un gran problema, pero un agujero de seguridad sin embargo.

Cuestiones relacionadas