LDAP path problems - c#

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.

Related

Retrieve E-mail address of altRecipient attribute of a user in AD

Am currently working on a Webforms Webapplication in C# and need to import the value of email address of the altRecipient attribute in Active Directory. I've been struggling with this for days now and can't seem to get it right.
The 'altRecipient' attribute returns a path//: that leads to the DistinguishedName. So i get something like this CN=edward-audi,OU=AUe,OU=daimler Mail,DC=diamler,DC=net.The returned value is the CN and the email address i need, is within the CN specifically where OU=daimler Mail. Am not sure if am doing the right thing. Maybe my approach is totally wrong.
SearchResultCollection result;
DirectorySearcher search = new DirectorySearcher("LDAP://DC=mycompany,DC=net")
{
SearchScope = SearchScope.Subtree,
Filter = "(&(objectCategory=user)(sAMAccountName=*" + UserName + "*))"
};
result = search.FindAll();
foreach (SearchResult sr in result)
{
dr = table.NewRow();
DirectoryEntry de = sr.GetDirectoryEntry();
if (de.Properties["altRecipient"].Value != null && de.Properties["altRecipient"].Value.ToString() != string.Empty)
{
string userID = de.Properties["sAMAccountName"].Value.ToString();
string Domain = "domain.net";
PrincipalContext pc = new PrincipalContext(ContextType.Domain, Domain);
UserPrincipal up = UserPrincipal.FindByIdentity(pc, userID);
if (up != null)
{
string userPrincipal = up.ToString();
de = up.GetUnderlyingObject() as DirectoryEntry;
string altRecepientCN = de.Properties["altRecipient"].Value.ToString();
UserPrincipal altRecepientValue = UserPrincipal.FindByIdentity(pc, altRecepientCN);
}
}
}

Connecting to LDAP server throws NullReferenceException

I am trying to connect to the online test LDAP server specified here using System.DirectoryServices.AccountManagement like this:
try
{
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "ldap.forumsys.com:389", "dc=example,dc=com", "cn=read-only-admin,dc=example,dc=com", "password"))
{
using (var searcher = new PrincipalSearcher(new UserPrincipal(ctx )))
{
foreach (var result in searcher.FindAll().Take(usersCount))
{
DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
}
}
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
But it throws the following exception:
Object reference not set to an instance of an object.
Could you please tell what is wrong with my code and how to be able to connect to that LDAP server?
PS: I am able to connect to that server using Apache Directory Studio
Stack Trace :
at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
at System.DirectoryServices.AccountManagement.PrincipalContext.DoServerVerifyAndPropRetrieval()
at System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String container, ContextOptions options, String userName, String password)
at System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String container, String userName, String password)
at ConsoleApp1.Program.GetGroups(String userName) in C:\Users\Simple Code\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 48
As said here, the problem could be that you try to connect to an Apache Directory Studio with the class PrincipalContext that not supports this OpenLDAP,
so one way to go is using the DirectoryEntry class
Using DirectoryEntry it works for me as following:
using (var searcher = new DirectorySearcher(new DirectoryEntry("LDAP://ldap.forumsys.com:389/dc=example,dc=com", "", "", AuthenticationTypes.None)))
{
searcher.Filter = "((objectClass=person))";
searcher.PropertiesToLoad.Add("mail");//email
searcher.PropertiesToLoad.Add("givenName");//first name
searcher.PropertiesToLoad.Add("sn"); //last name
searcher.PropertiesToLoad.Add("telephoneNumber");
searcher.PropertiesToLoad.Add("description");
searcher.PropertiesToLoad.Add("memberOf"); // groups
var activeDirectoryStaffs = searcher.FindAll();
if (activeDirectoryStaffs != null)
{
for (int i = 0; i < activeDirectoryStaffs.Count; i++)
{
SearchResult result = activeDirectoryStaffs[i];
var Email = result.Properties.Contains("mail") ? (string)result.Properties["mail"][0]:null;
var Mobile = result.Properties.Contains("telephoneNumber") ? (string)result.Properties["telephoneNumber"][0] : null;
var FirstName = result.Properties.Contains("givenName") ? (string)result.Properties["givenName"][0] : null;
var LastName = result.Properties.Contains("sn") ? (string)result.Properties["sn"][0] : null;
var Description = result.Properties.Contains("description") ? (string)result.Properties["description"][0] : null;
}
}
}

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.

LDAP | Check If UserID is Existing on AD

I just want to Add a new method on an existing code below.
Method is a simply check a given User_ID if it is exists on the AD.
It's my 1st time dealing with AD.
public class AD
{
// Fields
private static string ADPassword = ConfigurationManager.AppSettings["ADPassword"].ToString();
private static string ADPath = ConfigurationManager.AppSettings["ADConnection"].ToString();
private static string ADServerName = ConfigurationManager.AppSettings["ADServerName"].ToString();
private static string ADUserName = ConfigurationManager.AppSettings["ADUserName"].ToString();
// Methods
public static string GetLogin(string sUserName, string sPassword)
{
try
{
DirectoryEntry entry = new DirectoryEntry(ADPath, ADServerName + sUserName, sPassword);
object nativeObject = entry.NativeObject;
return string.Empty;
}
catch
{
return "Invalid Username or Password";
}
}
public static string Update(string sUserName, string sOldPassword, string sNewPassword)
{
string message;
try
{
DirectoryEntry searchRoot = new DirectoryEntry();
searchRoot.Path = ADPath;
searchRoot.Username = ADServerName + ADUserName;
searchRoot.Password = ADPassword;
DirectorySearcher searcher = new DirectorySearcher(searchRoot);
searcher.Filter = "(SAMAccountName=" + sUserName + ")";
DirectoryEntry directoryEntry = searcher.FindOne().GetDirectoryEntry();
directoryEntry.Invoke("ChangePassword", new object[] { sOldPassword, sNewPassword });
directoryEntry.CommitChanges();
directoryEntry.Close();
message = string.Empty;
}
catch (Exception exception)
{
try
{
message = exception.InnerException.Message;
}
catch
{
message = exception.Message;
}
}
return message;
}
}
Which version of the .NET Framework are you on??
In .NET before 3.5, you could probably do a DirectorySearch on the whole server (or alternatively a more constrained subtree):
public bool UserExists(string userName)
{
DirectoryEntry searchRoot = new DirectoryEntry("LDAP://dc=yourcompany,dc=com", userName, password);
DirectorySearcher searchForUser = new DirectorySearcher(searchRoot);
searchForUser.SearchScope = SearchScope.SubTree;
searchForUser.Filter = string.Format("(&(objectCategory=Person)(anr={0}))", userName);
if(searchForUser.FindOne() != null)
{
return true;
}
else
{
return false;
}
}
This is just off the top of my head, can't test it right now. This will search in your entire domain - check the LDAP path for the searchRoot - it would have to be something like
LDAP://dc=yourcompany,dc=com
or if you want to search just inside the "Users" container:
LDAP://cn=Users,dc=yourcompany,dc=com
With .NET 3.5 things got a lot easier - see this MSDN Article for a lot of useful info on how to search and find users and groups in .NET 3.5 using the new System.DirectoryServices.AccountManagement namespace. You can basically now do a FindByIdentity call:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "YOURDOMAIN");
UserPrincipal foundUser = UserPrincipal.FindByIdentity(ctx, "your user name");
and that's all there is.
Marc
If it's your first AD experience, it might be worth taking a look at this codeproject article: Howto: (Almost) Everything In Active Directory via C#. It contains lots of examples that might help you.
What do you mean exactly by User_ID? Account name? LDAP distinguished name?

How do I find a user's Active Directory display name in a C# web application?

I'm writing a web application which uses windows authentication and I can happily get the user's login name using something like:
string login = User.Identity.Name.ToString();
But I don't need their login name I want their DisplayName. I've been banging my head for a couple hours now...
Can I access my organisation's AD via a web application?
How about this:
private static string GetFullName()
{
try
{
DirectoryEntry de = new DirectoryEntry("WinNT://" + Environment.UserDomainName + "/" + Environment.UserName);
return de.Properties["displayName"].Value.ToString();
}
catch { return null; }
}
See related question: Active Directory: Retrieve User information
See also: Howto: (Almost) Everything In Active Directory via C# and more specifically section "Enumerate an object's properties".
If you have a path to connect to a group in a domain, the following snippet may be helpful:
GetUserProperty("<myaccount>", "DisplayName");
public static string GetUserProperty(string accountName, string propertyName)
{
DirectoryEntry entry = new DirectoryEntry();
// "LDAP://CN=<group name>, CN =<Users>, DC=<domain component>, DC=<domain component>,..."
entry.Path = "LDAP://...";
entry.AuthenticationType = AuthenticationTypes.Secure;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + accountName + ")";
search.PropertiesToLoad.Add(propertyName);
SearchResultCollection results = search.FindAll();
if (results != null && results.Count > 0)
{
return results[0].Properties[propertyName][0].ToString();
}
else
{
return "Unknown User";
}
}
Use this:
string displayName = UserPrincipal.Current.DisplayName;
In case anyone cares I managed to crack this one:
/// This is some imaginary code to show you how to use it
Session["USER"] = User.Identity.Name.ToString();
Session["LOGIN"] = RemoveDomainPrefix(User.Identity.Name.ToString()); // not a real function :D
string ldappath = "LDAP://your_ldap_path";
// "LDAP://CN=<group name>, CN =<Users>, DC=<domain component>, DC=<domain component>,..."
Session["cn"] = GetAttribute(ldappath, (string)Session["LOGIN"], "cn");
Session["displayName"] = GetAttribute(ldappath, (string)Session["LOGIN"], "displayName");
Session["mail"] = GetAttribute(ldappath, (string)Session["LOGIN"], "mail");
Session["givenName"] = GetAttribute(ldappath, (string)Session["LOGIN"], "givenName");
Session["sn"] = GetAttribute(ldappath, (string)Session["LOGIN"], "sn");
/// working code
public static string GetAttribute(string ldappath, string sAMAccountName, string attribute)
{
string OUT = string.Empty;
try
{
DirectoryEntry de = new DirectoryEntry(ldappath);
DirectorySearcher ds = new DirectorySearcher(de);
ds.Filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=" + sAMAccountName + "))";
SearchResultCollection results = ds.FindAll();
foreach (SearchResult result in results)
{
OUT = GetProperty(result, attribute);
}
}
catch (Exception t)
{
// System.Diagnostics.Debug.WriteLine(t.Message);
}
return (OUT != null) ? OUT : string.Empty;
}
public static string GetProperty(SearchResult searchResult, string PropertyName)
{
if (searchResult.Properties.Contains(PropertyName))
{
return searchResult.Properties[PropertyName][0].ToString();
}
else
{
return string.Empty;
}
}
There is a CodePlex project for Linq to AD, if you're interested.
It's also covered in the book LINQ Unleashed for C# by Paul Kimmel - he uses the above project as his starting point.
not affiliated with either source - I just read the book recently

Categories

Resources