Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ValidateCredentials returns true for unknown user?

I'm seeing some odd behaviour here using PrincipalContext.ValidateCredentials. The set-up is two Active Directory domains in parent/child setup (so we have primary domain company.com and sub-domain development.company.com).

When I validate credentials against the primary domain, ValidateCredentials behaves as expected, returning true for good user/pass pairs, and false for anything else.

However if I validate a user in the sub-domain, ValidateCredentials returns true for both good username/passwords AND invalid users. If I provide a valid user with an invalid password, it correctly returns false.

Now I'm working around it at the moment by doing UserPrincipal.FindByIdentity() first and if the user exists, then calling ValidateCredentials -- but I'd like to understand what's going on.

Another workaround I've looked at is by passing the username through as domain\username as the MSDN entry for ValidateCredentials states:

In each version of this function, the userName string can be in one of a variety of different formats. For a complete list of the acceptable types of formats, see the ADS_NAME_TYPE_ENUM documentation.

...of which this form of username is listed. But this causes ValidateCredentials to always return true, no matter what combination of username and password I pass in.

The pertinent code is:

bool authenticated = false;

// Various options tried for ContextOptions, [etc] inc. explicit username/password to bind to AD with -- no luck.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain, null, ContextOptions.Negotiate, null, null))
{
    log(pc.ConnectedServer + " => " + pc.UserName + " => " + pc.Name + " => " + pc.Container);
    using (var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, username))
    {
        if (user != null)
        {
            log(user.DistinguishedName + "; " + user.DisplayName);
            authenticated = pc.ValidateCredentials(username, password);
        } else {
            log("User not found");
            // Debug only -- is FindByIdentity() needed. This should always return 
            // false, but doesn't.
            authenticated = pc.ValidateCredentials(username, password);
        }
    }
}
return authenticated;

Any and all (sensible) suggestions welcome -- I'm scratching my head over this as it just goes against all expectations.

I ought to add: this is running as myself on my machine, both of which are members of the primary domain. However I've also tried running it in a command prompt on my machine as a user of the sub-domain (runas /user:subdomain\user cmd) with exactly the same results.

like image 975
Chris J Avatar asked Sep 07 '11 15:09

Chris J


2 Answers

Some amount of googling later (not that I've been in and out of google all day trying to find this anyway), I've found the answer.

Put simply, if the Guest account is enabled in the domain, ValidateCredentials will return TRUE for an unknown user. I've just checked the status of the guest user in development.company.com, and sure enough the account is enabled. If I have the guest account disabled, ValidateCredentials correctly returns false.

This is a fairly fundamental gotcha, not sure I'm keen on this behaviour... pity it's not explicitly mentioned on MSDN.

like image 76
Chris J Avatar answered Nov 17 '22 02:11

Chris J


I have used ContextOptions.SimpleBind flag with ValidateCredentials it solved my problem..

Sample code:

    using (var context = new PrincipalContext(ContextType.Domain, "DOMAIN", null))
    {
        bool loginResult = context.ValidateCredentials(username, password, ContextOptions.SimpleBind); // returns false for unknown user
    }
like image 1
Saad Shaikh Avatar answered Nov 17 '22 00:11

Saad Shaikh