views:

32

answers:

1

I have a website which requires users to enter their corporate network username and password. It then looks for that account in Active Directory and gets a list of any email addresses associated with that account.

The problem I am having is that ONE incorrect password is locking out an account. Our domain policy is that an account will lock out after three incorrect entries, so I am assuming that I am doing something wrong in my code. I am not very knowledgeable about Active Directory or .NET DirectoryServices in general, which may be apparent from my code. Here it is:

public ArrayList AuthenticateActiveDirectory(string Domain, string UserName, string Password)
{
    // An error occurs if the username/password combo does not exist.
    // That is how we know it is not a valid entry.
    try
    {
        DirectoryEntry entry = new DirectoryEntry("LDAP://" + Domain, UserName, Password);
        object nativeObject = entry.NativeObject;
        ArrayList emails = new ArrayList();
        DirectorySearcher ds = new DirectorySearcher(entry);
        ds.Filter = "samaccountname=" + UserName;
        ds.PropertiesToLoad.Add("mail");
        SearchResult sr = ds.FindOne();
        if (sr.Properties["mail"] != null)
        {
            for (int email = 0; email < sr.Properties["mail"].Count; email++)
            {
                emails.Add(sr.Properties["mail"][email]);
            }
        }
        return emails;
    }
    catch (DirectoryServicesCOMException) { throw; }
    catch (Exception) { throw; }
}
A: 

I did some searching and found some code (thanks to Ayende Rahien for the solution) to use that just authenticates and doesn't search for emails or anything else. I am using this prior to the other function, and it seems to be working fine. I am guessing that my other code is hitting AD more than once - at least 3 times - which is resulting in the lockout. Here is the code I am using now to just authenticate:

    private bool Authenticate(string domain, string user, string password)
{
    try
    {
        using (DirectoryEntry de = new DirectoryEntry("LDAP://" + domain,
                                              user, password))
        {
            return de.NativeObject != null;
        }
    }
    catch
    {
        return false;
    }
}
MJB
As a side note, a general rule of thumb for password retries is to bump it to 10 or so. This is because various windows components are notorious for silently retrying several times before finally giving the "Access Denied" message. This is also not a real degradation of security as it's almost as unlikely to guess a password in 10 tries as it is 3. Further, such a small limit can lead to highly successful DOS attacks where the attacker is simply trying to prevent others from logging in.
Chris Lively
Thanks, but that is not my call. I don't think our Network Admin will agree to that. Regarding DOS attacks: this site is internal only.
MJB