Search code examples
c#directoryservicesnovell

How would I validate a Username/Password using System.DirectoryServices.Protocol?


First, I cannot use Active Directory, so I cannot use System.DirectoryServices directly. This will be a PC sending a query to a Novell network where only System.DirectoryServices.Protocol is supported.

I am pretty sure that I am down to needing to provide the proper SearchRequest.

This is what I have so far:

private static String _certificatePath;
private static String _server;

private static SearchResponse Query(String user, String pwd, out String error)
{
    SearchResponse result = null;
    error = String.Empty;
    if (File.Exists(_certificatePath))
    {
        var identifier = new LdapDirectoryIdentifier(_server, false, false);
        try
        {
            using (var connection = new LdapConnection(identifier))
            {
                connection.SessionOptions.ProtocolVersion = 3;
                var cert = new X509Certificate();
                cert.Import(_certificatePath, null, X509KeyStorageFlags.DefaultKeySet);
                connection.ClientCertificates.Add(cert);
                connection.AuthType = AuthType.External;
                connection.AutoBind = false;
                var request = new SearchRequest()
                {
                    DistinguishedName = user, //Find this person
                    Filter = "(objectClass=*)", //The type of entry we are looking for
                    Scope = System.DirectoryServices.Protocols.SearchScope.Subtree, //We want all entries below this ou
                };
                result = (SearchResponse)connection.SendRequest(request); //Run the query and get results
            }
        } catch (Exception err)
        {
            error = String.Format("SDSP::Query {0}: {1}", err.GetType(), err.Message);
        }
    }
    else
    {
        error = "The system cannot find the Cryptography Certificate at the path specified in the Application Configuration file.";
    }
    return result;
}

How do I create a SearchRequest to validate a user / pwd combination?

var request = new SearchRequest()
{
    DistinguishedName = user, //Find this person
    Filter = "(objectClass=*)", //The type of entry we are looking for
    Scope = System.DirectoryServices.Protocols.SearchScope.Subtree, //We want all entries below this ou
};

Solution

  • On Windows

    You can append ContextOptions.Negotiate parameter for ValidateCredentials (Username and Password).

    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;
    }
    

    Sources:


    On Novell

    DirectoryEntry and DirectorySearcher are both high level class tools that are wrappers for Active Directory.

    //use the users credentials for the query
    DirectoryEntry root = new DirectoryEntry(
        "LDAP://dc=domain,dc=com", 
        loginUser, 
        loginPassword
        );
    
    //query for the username provided
    DirectorySearcher searcher = new DirectorySearcher(
        root, 
        "(sAMAccountName=" + loginUser + ")"
        );    
    
    //a success means the password was right
    bool success = false; 
    try {
        searcher.FindOne();
        success = true;
    }
    catch {
        success = false;
    }
    

    Referred to the answer.