How to validate LDAP path against Active Directory - c#

How to validate LDAP path? I have three textboxes, where I am allowing user to enter LDAP Path, username and password. I am able to validate username and password, but when it comes to validating LDAP path, it works initially, but after sometime, it allows invalid path as well.
Valid LDAP path:
192.168.12.12:565
Invalid LDAP path:
gfg192.168.12.12:565fgfgf
and the user is able to get list of users using invalid path.
I have tried LdapConnection, using Directory Entry and using PrincipalContext :
LdapConnection connection = new LdapConnection(txtLDAPPath.Text.Trim());
NetworkCredential credential = new NetworkCredential(txtADUserName.Text.Trim(), password);
connection.Credential = credential;
connection.Bind();
using (DirectoryEntry entry = new DirectoryEntry())
{
entry.Username = txtADUserName.Text.Trim();
entry.Password = password;
entry.Path = txtLDAPPath.Text;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(&(objectClass=user)(objectCategory=person)(!userAccountControl:1.2.840.113556.1.4.803:=2))";
object obj = entry.NativeObject;
SearchResult resultCol = search.FindOne();
}
PrincipalContext ctx = new PrincipalContext(ContextType.Domain,"Domain");
bool Validate= ctx.ValidateCredentials(txtADUserName.Text, password);

The only way I found out is via using System.DirectoryServices.DirectorySearcher.FindOne() method
var paths = new[]
{
new { Path = "LDAP://192.168.1.1:389/OU=Users,OU=Administration,DC=ac-qa,DC=aaaa,DC=se", Filter = "(&(objectClass=user))" }, //OK! returns the first entry
new { Path = "LDAP://192.168.1.1:389/OU=Users,OU=Administration,DC=ac-qa,DC=aaaa,DC=se", Filter = "this is wrong" }, //ERROR! the exeption message: "The this is wrong search filter is invalid."
new { Path = "the wrong path", Filter = "(&(objectClass=user))" }, //ERROR! the exeption message: "Unspecified error"
new { Path = "LDAP://192.168.1.1:389/OU=Test_OrgUnit,DC=ac-qa,DC=aaaa,DC=se", Filter = "(&(objectClass=user))" }, //OK! This is a valid path without any entry inside. result = null
};
foreach (var item in paths)
{
DirectoryEntry entry = new DirectoryEntry(item.Path, Login, Password);
DirectorySearcher search = new DirectorySearcher(entry, item.Filter);
try
{
SearchResult result = search.FindOne();
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}

Related

C# Search Active Directory error

I am pretty new to using C# and this is my second time using it with active directory. I keep getting the error: Object reference not set to an instance of an object. Below is my code. I know that my null reference is in the line var result = searcher.FindOne(); I am unsure of what I need to do to fix this.
static void Main(string[] args)
{
List<string> userList = new List<string>();
try
{
string[] newUsers = { List of users is here ex: jsmith#xyz.com, bsmith#xyz.com, ... };
PrincipalContext AD = new PrincipalContext(ContextType.Domain, "xyz.com");
UserPrincipal u = new UserPrincipal(AD);
PrincipalSearcher search = new PrincipalSearcher(u);
DirectorySearcher searcher = new DirectorySearcher();
foreach (string x in newUsers)
{
searcher.Filter = string.Format("(&(objectCategory=person)(anr={0}))", x);
var result = searcher.FindOne();
userList.Add(string.Format("{0} {1}", result.Properties["DisplayName"][0].ToString(), result.Properties["Company"][0].ToString()));
search.Dispose();
}
foreach(string y in userList)
{
Console.WriteLine(y);
}
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
File.WriteAllLines(file location, userList);
}
Your problem is that you're declaring PrincipalSearcher and DirectorySearcher, yet you're only populating the PrincipalSearcher with UserPrincipal object.
...
UserPrincipal u = new UserPrincipal(AD);
PrincipalSearcher search = new PrincipalSearcher(u);
...
However, your DirectorySearcher object searcher is empty.
DirectorySearcher searcher = new DirectorySearcher();
In foreach loop you're searching for one user using DirectorySearcher object not PrincipalSearcher:
var result = searcher.FindOne();
The above line will always return null. You need to populate DirectorySearcher.
DirectorySearcher searcher = new DirectorySearcher(/*need a DirectoryEntry*/);
I would suggest you take full advantage of UserPrincipal class. It seems that you want to search for users in Active Directory and you know their UserPrincipal names.
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "yourdomain.com"))
{
string [] newUsers; //need to declare list of new users
foreach (string user in newUsers)
{
using (UserPrincipal newUser = UserPrincipal.FindByIdentity(ctx, IdentityType.UserPrincipalName, user))
{
if (newUser != null)
{
//do what you need to do
//newUser will contain all info on a particular user
}
}
}
}
As several commenters have noted, your code is not handling the situation where no user is found by DirectorySearcher.FindOne - and, as noted in the MSDN documentation, FindOne returns null if no user is found:
If more than one entry is found during the search, only the first entry is returned. If no entries are found to match the search criteria, a null reference (Nothing in Visual Basic) is returned.
So you'll need to handle the case where the user you're looking for isn't there:
foreach (string x in newUsers)
{
Console.WriteLine("looking for user {0}", x);
searcher.Filter = string.Format("(&(objectCategory=person)(anr={0}))", x);
var result = searcher.FindOne();
if (result == null)
{
userList.Add(String.Format("user {0} not found!", x));
}
else
{
userList.Add(string.Format("{0} {1}", result.Properties["DisplayName"][0].ToString(), result.Properties["Company"][0].ToString()));
}
search.Dispose();
}

Active Directory reading user attributes

I am trying to let my winform system to authonticate using username of the person in active directory. i am using now the following code. But the result is null !!
private static string LDAP_Connection = "corp.mycompany.global";
private static string LDAP_Path = "LDAP://OU=USERS,OU=BT,OU=EC,OU=tres,DC=corp,DC=company,DC=global";
static DirectoryEntry createDirectoryEntry()
{
// create and return new LDAP connection with desired settings
DirectoryEntry ldapConnection = new DirectoryEntry(LDAP_Connection);
ldapConnection.Path = LDAP_Path;
ldapConnection.AuthenticationType = AuthenticationTypes.Secure;
return ldapConnection;
}
public static void RetreiveUserInfoAdvanced()
{
try
{
// create LDAP connection object
DirectoryEntry myLdapConnection = createDirectoryEntry();
// create search object which operates on LDAP connection object
// and set search object to only find the user specified
DirectorySearcher search = new DirectorySearcher(myLdapConnection);
//search.Filter = "(mail =" + _userlogin + ")";
search.Filter = "mail = a.ghew#mycompany.com";
// create results objects from search object
//SearchResult result = search.FindOne();
string[] requiredProperties = new string[] { "cn", "mail" };
foreach (String property in requiredProperties)
search.PropertiesToLoad.Add(property);
SearchResult result = search.FindOne();
if (result != null)
{
foreach (String property in requiredProperties)
foreach (Object myCollection in result.Properties[property])
Console.WriteLine(String.Format("{0,-20} : {1}", property, myCollection.ToString()));
}
}
}
i used Ad Explorer with the same data, everything is find an working fine and i can reach the required data. But from my system can't.
I don't have your AD environment, but I did the following in a similar configuration:
DirectorySearcher search = new DirectorySearcher(myLdapConnection);
search.Filter = "(mail=a.ghew#mycompany.com)";
search.SearchScope = SearchScope.Subtree;
Give that a go? Basically remove your whitespace in the filter expression and ensure you have traversal enabled.

Active directory listing groups - LdapConnection works, PrincipalContext does not

Creating a web service which talks to Active Directory to verify users and determine which groups they belong to.
I started out with the verification process, and got this working:
public bool AuthenticateAdUser(string username, string password)
{
//in the real code, these come from config
string domain = "TestDomain";
string server = 666.666.666.666;
string authType = "Basic";
string useSsl = "false";
AuthType atype = (AuthType)Enum.Parse(typeof(AuthType), authType);
using (var ldapConnection = new LdapConnection(server))
{
var networkCredential = new NetworkCredential(username, password, domain);
ldapConnection.SessionOptions.SecureSocketLayer = Convert.ToBoolean(useSsl);
ldapConnection.AutoBind = false;
ldapConnection.AuthType = atype;
ldapConnection.Bind(networkCredential);
}
// If the bind succeeds, the credentials are valid
return true;
}
However, I'm not clear on how I can use that LdapConnection object to work with groups. The documentation and examples suggest you use PrinicpalContext for that purpose. So I tried this.
string domain = "TestDomain";
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
{
using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(pc, username).GetGroups(pc))
{
src.ToList().ForEach(sr => result.Add(sr.SamAccountName));
}
}
This fails, claiming it can't contact the Active Directory server. Using a DNS style name ("TestDomain.local") doesn't seem to help.
This does at least spin up a network principal:
string server = "666.666.666.666";
using (PrincipalContext pc = new PrincipalContext(ContextType.Machine, server))
{
using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(pc, username).GetGroups(pc))
{
src.ToList().ForEach(sr => result.Add(sr.SamAccountName));
}
}
But when you try and do anything with it, it fails with "Network path not found".
Any ideas on why the Principal won't work, or how I can use the LdapConnection to query groups?

An Operations Error Occured When trying to retrieve data from active directory

I'm trying to get the manager name from the active directory but am receiving the error "An operations error occured" when it throws the exception.
Code is below:
public override void ItemAdding(SPItemEventProperties properties)
{
base.ItemAdding(properties);
try
{
var requester = properties.Web.CurrentUser;
properties.AfterProperties["Requester"] = requester;
//Get the manager name from the active directory
var domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
DirectoryEntry dir = new DirectoryEntry("LDAP://" + domain);
//Exeception occurs on this line below.
string managerName = dir.Properties["Manager"].Value.ToString();
properties.AfterProperties["Manager"] = managerName;
}
catch(Exception ex)
{
}
}
Edit
Was able to get this figured out using the code below:
try
{
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, Environment.UserName);
string samAccountName = "";
if (user != null)
{
// do something here....
samAccountName = user.SamAccountName;
}
//Get the manager name from the active directory
var domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
using(DirectoryEntry dir = new DirectoryEntry("LDAP://" + domain))
{
using (DirectorySearcher ds = new DirectorySearcher(dir, "samAccountName=" + samAccountName))
{
SearchResult result = ds.FindOne();
string managerName = result.Properties["manager"][0].ToString();
}
}
}
catch (Exception ex)
{
var message = ex.Message;
}
You are trying to access the Manager from the domain, not from requester.
In a winform I would do it like this assuming that requester == samAccountName:
try
{
//Get the manager name from the active directory
var domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
using (DirectoryEntry dir = new DirectoryEntry("LDAP://" + domain))
{
using (DirectorySearcher ds = new DirectorySearcher(dir, "samAccountName=" + requster))
{
SearchResult sr = ds.FindOne();
//Exeception occurs on this line below, if the attribute is not set.
string managerName = sr.Properties["Manager"][0].ToString();
}
}
}
catch (Exception ex)
{
}

LDAP path problems

I am working with LDAP and I am new to this.
Is there a way to get the domain when you only know the username, password, servername
I am trying to do this:
string ldapPath = "LDAP://serverName";
string uid = username;
string password = pwd;
string qry = String.Format("(uid={0})", uid);
string adsPath = String.Empty;
try
{
DirectoryEntry nRoot = new DirectoryEntry(ldapPath, null, null, AuthenticationTypes.Anonymous);
DirectorySearcher ds = new DirectorySearcher(nRoot, qry);
SearchResult sr = ds.FindOne();
if (sr != null)
{
// we want to retrieve the DN like this: "uid=myuser,ou=People,dc=findlay,dc=edu
ldapPath = sr.Path; //update where we will bind next
}
This does not work unless I change
string ldapPath = "LDAP://serverName";
to
string ldapPath = "LDAP://serverName/DC=mydomain,DC=com";
Any help..??
Thanks
Edit rootDSE
string defaultNamingContext;
using (DirectoryEntry rootDSE = new DirectoryEntry("LDAP://serverName/rootDSE", null, null, AuthenticationTypes.Anonymous))
{
defaultNamingContext = rootDSE.Properties["rootDomainNamingContext"].Value.ToString();
}
I too feel this is the solution but it is currently not working for me.. please help!
RootDSE is not server-bound - try this:
string defaultNamingContext;
using (DirectoryEntry rootDSE = new DirectoryEntry("LDAP://rootDSE", null, null, AuthenticationTypes.Anonymous))
{
defaultNamingContext = rootDSE.Properties["defaultNamingContext"].Value.ToString();
}
Or if you're on .NET 3.5 and newer, you could use PrincipalContext instead, which can be constructed without any path - it will just pick up the default domain you're connected to:
PrincipalContext context = new PrincipalContext(ContextType.Domain);
You should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here (that's .NET 3.5 and newer):
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
If :
using (DirectoryEntry rootDSE = new DirectoryEntry("LDAP://serverName/DC=mydomain,DC=com")
{
...
}
works, have you try (without being anonymous):
string defaultNamingContext;
using (DirectoryEntry rootDSE = new DirectoryEntry("LDAP://serverName/rootDSE")
{
defaultNamingContext = rootDSE.Properties["rootDomainNamingContext"].Value.ToString();
}
or
using (DirectoryEntry rootDSE = new DirectoryEntry("LDAP://serverName/rootDSE", user, password)
{
defaultNamingContext = rootDSE.Properties["rootDomainNamingContext"].Value.ToString();
}
It works for me, from a computer not in the domain.
you can try like this
// Method call
string netBiosName = GetNetBiosName(LDAP://CN=Partitions,CN=Configuration,DC=<DomainName>,DC=<local|com>, "<userName"", "<password>");
// Method call
// Method Definition
private string GetNetBiosName(string ldapUrl, string userName, string password)
{
string netbiosName = string.Empty;
DirectoryEntry dirEntry = new DirectoryEntry(ldapUrl,userName, password);
DirectorySearcher searcher = new DirectorySearcher(dirEntry);
searcher.Filter = "netbiosname=*";
searcher.PropertiesToLoad.Add("cn");
SearchResultCollection results = searcher.FindAll();
if (results.Count > 0)
{
ResultPropertyValueCollection rpvc = results[0].Properties["CN"];
netbiosName = rpvc[0].ToString();
}
return netbiosName;
}
pls take a look at this link for more info
You should be able to get the domain by just calling RootDse.

Categories

Resources