I'm writing a program (WinForms
, C#
) that runs on a Win 7
client machine. It obtains credentials from the user (user id, password, and subdomain name) and uses them to authenticate (via Active Directory
) to other servers to which the program remotely connects. The other servers are on a domain different than the domain the Win 7
client machine is on.
Using the NetworkCredential
, LdapDirectoryIdentifier
, and LdapConnection
classes, I can test the credentials with no more than the user id, password, and subdomain name (See answer for S.O. Why does Active Directory validate last password?).
For example, for the user account ssmith@xyz.gov
, I need only provide ssmith
(user id), the password for ssmith
, and xyz
(the subdomain
). I don't need to provide the top-level domain name
(gov
in this case).
Now, I want to programmatically obtain the top-level domain name
for this user account (gov
in this case). I've examined the properties and methods of the NetworkCredential
, LdapDirectoryIdentifier
, and LdapConnection
classes. I've looked over the other classes in the System.DirectoryServices.Protocols Namespace. I don't see a way to programmatically obtain the top-level domain name
.
Given user id
, password
, and subdomain
name, how can I obtain the top-level domain name
for a user account?
Here is my code. Given a user account of ssmith@xyz.gov, My call looks like this (asterisks represent a SecureString password)
bool result = ValidateCredentials("ssmith","******", "xyz");
Here is my code for the method.
private const int ERROR_LOGON_FAILURE = 0x31;
private bool ValidateCredentials(string username, SecureString ssPassword, string domain)
{
//suports secure string
NetworkCredential credentials = new NetworkCredential(username, ssPassword, domain);
LdapDirectoryIdentifier id = new LdapDirectoryIdentifier(domain);
using (LdapConnection connection = new LdapConnection(id, credentials, AuthType.Kerberos))
{
connection.SessionOptions.Sealing = true;
connection.SessionOptions.Signing = true;
try
{
// The only way to test credentials on a LDAP connection seems to be to attempt a
// Bind operation, which will throw an exception if the credentials are bad
connection.Bind();
}
catch (LdapException lEx)
{
credentials = null;
id = null;
if (ERROR_LOGON_FAILURE == lEx.ErrorCode)
{
return false;
}
throw;
}
}
credentials = null;
id = null;
return true;
}