LDAPS DirectorySearcher.FindOne throws exception - c#

I am trying to validate a user using a secured LDAP query. My code throws an exception while calling
SearchResult result = search.FindOne;
Complete code:
public bool IsValidUser(object username)
{
isValidUser = false;
try
{
DirectoryEntry AD = new DirectoryEntry("LDAP://office:636/", "myaccount", "mypassword");
AD.AuthenticationType = AuthenticationTypes.SecureSocketsLayer;
DirectorySearcher search = new DirectorySearcher(AD);
search.SearchRoot = AD;
search.SearchScope = SearchScope.Subtree;
if (username == DBNull.Value == false & username != "")
{
search.Filter = "(&(objectClass=user) (sAMAccountName=" + username + "))";
SearchResult result = search.FindOne();
if ((result == null))
isValidUser = false;
else
isValidUser = true;
}
else
isValidUser = false;
}
catch (Exception ex)
{
// log(ex);
}
return isValidUser;
}
If I do not provide port number 636, it will work fine but I do not think then the LDAP is done under secured network.

Maybe it can help someone (or future me) - the domain controller can get corrupted sometimes, if it does it makes it impossible to use secure port 636, try to change to non secure port 389 to see if that's the case.
See also: "The server is not operational" domain controller configuration error when you configure a server by using Server Manager

Related

Validating Active Directory username and password

private static bool ValidateUser(string userName, string password, string ldapPath)
{
DirectoryEntry directoryEntry = new DirectoryEntry(ldapPath, userName, password, AuthenticationTypes.ReadonlyServer);
try
{
object obj = directoryEntry.NativeObject;
if (obj.IsNotNullRef())
{
return true;
}
}
catch (Exception ex)
{
//error handling
}
finally
{
directoryEntry.Dispose();
}
return false;
}
I have the sample snippet above that validates an active directory username & password successfully if the domain NETBIOS and DNS match.
However, if the Domain name (NETBIOS) is not matching the DNS entry of the domain, i.e when the NETBIOS & DNS have been registered differently, the code doesn't return true even when you provide a valid UserName and Password.
How can i work around this issue?
EDIT:
The sample input is just standard, a userName, password & a domain URL
Example that returns True:
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://abcd1.xyz1.xx1.org", "abcd1\\stacktrace1", "xxxx", AuthenticationTypes.ReadonlyServer);
Example that returns false:
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://abcd2.xyz2.xx2.org", "abcd2\\stacktrace2", "xxxx", AuthenticationTypes.ReadonlyServer);
The only difference between the 2 examples is that, in example 1, the Domain name (NETBIOS) is matching with the DNS entry while in example 2, NETBIOS & DNS have been registered differently.
Refer following method:
public void AuthenticateUser(string userName, string password)
{
DirectoryUserAuthenticationResponse response = new DirectoryUserAuthenticationResponse();
try
{
// Creating Principal Context.
using (var principalContext = GetPrincipalContext())
{
try
{
// Getting user identity and validating user against active provider.
var aUser = UserPrincipal.FindByIdentity(principalContext, GetIdentitytype(), userName);
if (aUser != null)
{
// To check user account is locked out or not
if (aUser.IsAccountLockedOut())
throw new Exception("UserAccountLockedOut");
// To check user account is disabled or not.
if (aUser.Enabled == false)
throw new Exception("UserAccountDisabled");
// To check user change password on next logon.
if (aUser.LastPasswordSet == null)
throw new Exception("changePassword");
//To check password expiration
if (aUser.LastPasswordSet != null && aUser.PasswordNeverExpires == false)
{
DirectoryEntry rootDSE = new DirectoryEntry("LDAP://" + _directoryServerInfo.IPAddress, userName, password);
try
{
// Bind to the ADsobject to force authentication
object nativeobject = rootDSE.Name;
}
catch (DirectoryServicesCOMException cex)
{
string errorCode = cex.ExtendedErrorMessage.Substring(cex.ExtendedErrorMessage.IndexOf("data", 1));
errorCode = errorCode.Substring(5, 3);
//The commented code below fails to parse properly and throws an exception
// int exErrorCode = int.Parse(errorCode);
int exErrorCode = int.Parse(Regex.Match(errorCode, #"\d+").Value);
if (exErrorCode == (int)PWDFlags.Account_Expired)
throw new Exception("AccountExpired");
if (exErrorCode == (int)PWDFlags.Password_Expiration)
throw new Exception("PasswordExpired");
}
}
// validate the credentials by using principal context method.
var isAuthenticated = principalContext.ValidateCredentials(userName, password);
if (!isAuthenticated)
{
throw new Exception("Invalid your name and passowrd");
}
}
else
throw new Exception("InvalidUsernamePassword");
}
catch (DirectoryServicesCOMException cex)
{
string errorCode = cex.ExtendedErrorMessage.Substring(cex.ExtendedErrorMessage.IndexOf("data", 1));
errorCode = errorCode.Substring(5, 3);
//The commented code below fails to parse properly and throws an exception
// int exErrorCode = int.Parse(errorCode);
int exErrorCode = int.Parse(Regex.Match(errorCode, #"\d+").Value);
if (exErrorCode == (int)PWDFlags.Account_Expired)
throw new Exception("AdminACCExpire");
if (exErrorCode == (int)PWDFlags.Password_Expiration)
throw new Exception("AdminPWDExprire");
else
{
//Else any exception
}
}
}
}
catch (Exception)
{
throw;
}
}
private PrincipalContext GetPrincipalContext()
{
// Creating Principal Context.
PrincipalContext principalContext = null;
string serveraddress = _directoryServerInfo.IPAddress;//+":"+_defdirectoryport ;
if (string.IsNullOrEmpty(_directoryfilterouname))
{
principalContext = new PrincipalContext(ContextType.Domain, serveraddress, _directoryAdminUserId, _directoryAdminPassword);
//principalContext = new PrincipalContext(ContextType.Domain, _directoryServerInfo.IPAddress , _directoryAdminUserId, _directoryAdminPassword);
}
else
{
//string domainComponents = GetDomainComponents();
principalContext = new PrincipalContext(ContextType.Domain, serveraddress, _directoryfilterouname, _directoryAdminUserId, _directoryAdminPassword);
}
//// _directoryServerInfo.HostName = //((System.DirectoryServices.AccountManagement.ADStoreCtx)(principalContext.QueryCtx)).DnsDomainName;
return principalContext;
}

Windows authentication with SharePoint Web Services via SOAP

I am trying to authenticate my SharePoint service t retrieve SPList Items :
private Cookie AuthenticateFBASite(string AuthenticationSiteURL, string UserName, string Password, NetworkCredential nc2)
{
Cookie CurrentSiteCookie = null;
using (Authentication.Authentication authSvc = new Authentication.Authentication())
{
authSvc.Url = AuthenticationSiteURL + "/_vti_bin/authentication.asmx";
authSvc.CookieContainer = new System.Net.CookieContainer(); //create a new cookie container
//set the FBA login information
authSvc.AllowAutoRedirect = true;
authSvc.PreAuthenticate = true;
authSvc.Credentials = nc2;
Authentication.LoginResult result = authSvc.Login(UserName, Password);
if (result.ErrorCode == Authentication.LoginErrorCode.NoError)
{
try
{
CookieCollection cookies = authSvc.CookieContainer.GetCookies(new Uri(AuthenticationSiteURL));
CurrentSiteCookie = cookies[result.CookieName];
return CurrentSiteCookie;
}
catch (System.Exception ex)
{
//Console.WriteLine("Exception occured while calling lists.asmx" + ex.Message);
return CurrentSiteCookie;
}
}
else if (result.ErrorCode == Authentication.LoginErrorCode.PasswordNotMatch)
{
return CurrentSiteCookie;
}
else
return CurrentSiteCookie;
}
}
and it was working fine till today i try to use it again but it return me an eror cookies[result.CookieName] is null , and this only happens on my machine not other machine .
#Eslan May i knw fom where your are calling this code ? from webpart or app or console application ? I suspect its authentication mode issue.

Check if the User is valid user on Domain - Active Directory

A lot of people posted about this but could not get anything to work. I am trying to get the user's username and password on an Asp.net form (the same username and password which the user uses to login to their computer on a domain).
I am using the PrincipalContext to validate the user.
Although I provide valid username and password, but pc.ValidateCredentials always returns false.
This is the first time I am doing User Authentication through Active Directory and have no idea what else do I require to successfully validate a user from Active Directory.
Do I need to provide information in the Container and Name properties on the PrincipalContext Object as it appears to be null.
Currently I am running this code from local machine which is on domain.
Do you have the correct domain? Maybe it is called different than 'DOMAIN', try this one:
private bool Authenticate(string user, string password)
{
using ( var context = new PrincipalContext(ContextType.Domain, Environment.UserDomainName) ) {
return context.ValidateCredentials(user.Trim(), password.Trim());
}
}
Please use below function
private bool AuthenticateAD(string userName, string password, string domain, out string message)
{
message = "";
DirectoryEntry entry = new
DirectoryEntry("LDAP://" + domain, userName, password);
try
{
object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + userName + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (null == result)
{
return false;
}
}
catch (Exception ex)
{
message = ex.Message;
return false;
//throw new Exception("Error authenticating user. " + ex.Message);
}
return true;
}

Unkown name exception while creating virtual directory with DirectoryServices

I'm trying to create a virtual directory on a remote server using DirectoryServices by cloning the settings of another virtual directory, but I get a COMException: Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME)) when invoking AppCreate.
This is the code I've written (simplified with most of tests removed):
public bool CreateVirtualDirectory(string serverName, string primaryVirtualDirectoryName, string virtualDirectoryName, MyUser user)
{
try
{
DirectoryEntry directoryEntry = null;
if (user != null)
directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root", user.UserName, user.Password, AuthenticationTypes.Secure | AuthenticationTypes.Sealing);
else
directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root");
DirectoryEntry primaryVirtualDirectory = directoryEntry.Children.Find(primaryVirtualDirectoryName, directoryEntry.SchemaClassName);
DirectoryEntry virtualDirectory = directoryEntry.Children.Add(virtualDirectoryName, directoryEntry.SchemaClassName);
virtualDirectory.CommitChanges();
virtualDirectory.Properties["Path"].Value = primaryVirtualDirectory.Properties["Path"].Value;
virtualDirectory.Properties["AppFriendlyName"][0] = virtualDirectoryName;
if (primaryVirtualDirectory.Properties["UNCUserName"] != null && primaryVirtualDirectory.Properties["UNCUserName"].Value != null && primaryVirtualDirectory.Properties["UNCUserName"].Value.ToString().Length > 0)
{
// IIS6 of IIS7
virtualDirectory.Properties["AuthNTLM"][0] = true;
virtualDirectory.Properties["UNCUserName"].Value = primaryVirtualDirectory.Properties["UNCUserName"].Value;
virtualDirectory.Properties["UNCPassword"].Value = primaryVirtualDirectory.Properties["UNCPassword"].Value;
}
else
{
// Older versions
virtualDirectory.Properties["AuthFlags"][0] = 5; // MD_AUTH_ANONYMOUS | MD_AUTH_NT
virtualDirectory.Properties["AnonymousUserName"].Value = primaryVirtualDirectory.Properties["AnonymousUserName"].Value;
virtualDirectory.Properties["AnonymousUserPass"].Value = primaryVirtualDirectory.Properties["AnonymousUserPass"].Value;
}
virtualDirectory.Properties["AccessRead"][0] = true;
virtualDirectory.Properties["AccessExecute"][0] = true;
virtualDirectory.Properties["AccessWrite"][0] = false;
virtualDirectory.Properties["AccessScript"][0] = true;
virtualDirectory.Properties["EnableDefaultDoc"][0] = true;
virtualDirectory.Properties["EnableDirBrowsing"][0] = false;
if (primaryVirtualDirectory.Properties["AppPoolId"] != null && primaryVirtualDirectory.Properties["AppPoolId"].Value != null && primaryVirtualDirectory.Properties["AppPoolId"].Value.ToString().Length > 0)
virtualDirectory.Properties["AppPoolId"].Value = primaryVirtualDirectory.Properties["AppPoolId"].Value;
virtualDirectory.Properties["ScriptMaps"].Value = primaryVirtualDirectory.Properties["ScriptMaps"].Value;
// I Tried adding these 3 lines but I keeo getting the same exception
// virtualDirectory.CommitChanges();
// virtualDirectory.Invoke("SetInfo");
// virtualDirectory.CommitChanges();
virtualDirectory.Invoke("AppCreate", true);
// I tried this instead but I still get the same exception
// virtualDirectory.Invoke("AppCreate2", 0);
virtualDirectory.CommitChanges();
return true;
}
catch (Exception exception)
{
return false;
}
}
I tried some variations (see comments in the code) using AppCreate2 instead of AppCreate or calling a CommitChanges and/or invoking SetInfo before the AppCreate, but all lead to the same exception.
The user credentials I'm using has adminstrator rights on the remote server. In fact if I copy the program to the remote server and run it there with the same credentials (I logged in with the same user on the remote server), using 'localhost' as servername and the user variable = null, it works without throwing the exception, so it must have something to do with the remote execution.
The remote server is a Windows Server 2003 R2 SP2 (32bit), the machine running this program is a Windows 7 Professional (64 bit).
Does anyone have any ideas ?

LDAP cache without network connection

We have a program running on different computers in our network, and this program needs to login with an specific administrator account to execute some tasks.
Our supplier wrote the below code to check whether the user is a local admin or not.
The question is:
If the admin user has logged in the computer before, will the credentials be saved in the cache so the below code would work even without a network connection?
If so, how can we force those credentials to be saved?
Else, is there any alternative so we can login with the credentials from the cache?
static bool UserExists(string domain, string username, string password)
{
if (System.Environment.GetEnvironmentVariable("UserDomain") != null)
{
if (string.Compare(System.Environment.GetEnvironmentVariable("UserDomain"), domain, true) != 0)
{
return false;
}
}
string filter = string.Format("(&(ObjectClass={0})(sAMAccountName={1}))", "person", username);
string[] properties = new string[] { "fullname" };
using (DirectoryEntry adRoot = new DirectoryEntry("LDAP://" + domain, null, null, AuthenticationTypes.Secure))
using (DirectorySearcher searcher = new DirectorySearcher(adRoot))
{
adRoot.Username = username;
adRoot.Password = password;
searcher.SearchScope = SearchScope.Subtree;
searcher.ReferralChasing = ReferralChasingOption.All;
searcher.PropertiesToLoad.AddRange(properties);
searcher.Filter = filter;
if (searcher.FindOne() != null)
{
// If you want to see the user details: searcher.FindOne().GetDirectoryEntry();
return true;
}
}
return false;
}
Thanks in advance

Categories

Resources