How to authenticate users in C# LDAP - c#

I am new to LDAP related coding and today I am asked to develop a code to check the users authentication against LDAP.
The tutorials I have found online are so simple but our company's Directory is so complicated that I don't know how to write a code for that. Here is the info of the LDAP . I have changed the company name to hide the name.
uri = ldaps://ABC.ad.XYZ.com:636
user_filter = memberOf=CN=TENXAIRFLOWPROD,OU=Security Groups,OU=Normal Users and Groups,OU=Account Management Services,OU=AD Master OU,DC=ABC,DC=ad,DC=XYZ,DC=com
user_name_attr = sAMAccountName
superuser_filter = memberOf=CN=TENXAIRFLOWPROD_ADM,OU=Security Groups,OU=Normal Users and Groups,OU=Account Management Services,OU=AD Master OU,DC=ABC,DC=ad,DC=XYZ,DC=com
bind_user = SCGLOBAL\twiki
bind_password_cmd = python /bns/tenx/airflow/ldap_password.py
basedn = DC=ABC,DC=ad,DC=XYZ,DC=com
search_scope = SUBTREE
Here is a code I have developed but it gives me error:
string username = "myUserName";
string domain = "ldaps://ABC.ad.XYZ.com:636";
string pwd = "myPasword";
try
{
DirectoryEntry entry = new DirectoryEntry(domain, username, pwd);
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
lblError.Text=("Login Successful");
//search some info of this user if any
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
SearchResult result = search.FindOne();
}
catch (Exception ex)
{
lblError.Text=("Login failed: " + ex.ToString());
}
Could anybody help plz?

Comment: According to the admin , I have been assigned to the group in AD. But how can I make sure I can access it?
It seems like Active Directory. If so, you could just use PrincipalContext.
public bool ValidateCredentials(string domain, string username, string password)
{
using (var context = new PrincipalContext(ContextType.Domain, domain))
{
return context.ValidateCredentials(username, password);
}
}
public bool IsUserInAdGroup(string domain, string username, string adGroupName)
{
bool result = false;
using (var context = new PrincipalContext(ContextType.Domain, domain))
{
var user = UserPrincipal.FindByIdentity(context, username);
if (user != null)
{
var group = GroupPrincipal.FindByIdentity(context, adGroupName);
if (group != null && user.IsMemberOf(group))
result = true;
}
}
return result;
}
Please make sure to reference System.DirectoryServices.AccountManagement.

Related

How to authenticate in LDAP in C#?

I am new to LDAP related coding and today I am asked to develop a code to check the users authentication against LDAP.
The tutorials I have found online are so simple but our company's Directory is so complicated that I don't know how to write a code for that. Here is the info of the LDAP . I have changed the company name to hide the name.
string domain = "ou=People,dc=my,dc=com";
string LDAP_Path= "dc01.my.com;
string LDAPconnect= "LDAP://dc01.my.com/";
Here is a code I have developed but it gives me error when run " LdapResult = LdapSearcher.FindOne();":
string domain = "ou=People,dc=my,dc=com";
string password = "";
string userName = "";
// define your connection
LdapConnection ldapConnection = new LdapConnection(LDAP_Path);
try
{
// authenticate the username and password
using (ldapConnection)
{
// pass in the network creds, and the domain.
var networkCredential = new NetworkCredential(userName, password, domain);
// if we're using unsecured port 389, set to false. If using port 636, set this to true.
ldapConnection.SessionOptions.SecureSocketLayer = false;
// since this is an internal application, just accept the certificate either way
ldapConnection.SessionOptions.VerifyServerCertificate += delegate { return true; };
// to force NTLM\Kerberos use AuthType.Negotiate, for non-TLS and unsecured, just use AuthType.Basic
ldapConnection.AuthType = AuthType.Basic;
// authenticate the user
ldapConnection.Bind(networkCredential);
Response.Write( "connect ldap success");
}
}
catch (LdapException ldapException)
{
Response.Write(ldapException + " <p>Ad connect failed</p>");
//Authentication failed, exception will dictate why
}
string strTmp0 = LDAPconnect + domain;
string user = "memberId";
string pwd = "memberPwd";
System.DirectoryServices.DirectoryEntry LdapEntry = new System.DirectoryServices.DirectoryEntry(strTmp0, "cn=" + user, pwd, AuthenticationTypes.None);
DirectorySearcher LdapSearcher = new DirectorySearcher(LdapEntry);
LdapSearcher.Filter = "(cn=" + user + ")";
string value = string.Empty;
SearchResult LdapResult=null;
try
{
LdapResult = LdapSearcher.FindOne();
}
catch (Exception ex)
{
Response.Write(ex.Message.ToString());
// .............get Error msg : username an password uncorrect
}
if ((LdapResult != null))
{
Response.Write("ldapresult not null");
}
Could anybody help plz?
In ldap connection setting , OP should use own configuration.
// Ldap connection setting. this should setup according to organization ldap configuration
int portnumber = 12345;
LdapConnection ldapConnection = new LdapConnection(new LdapDirectoryIdentifier("ldap.testxxxx.com", portnumber));
ldapConnection.AuthType = AuthType.Anonymous;
ldapConnection.Bind();
SearchRequest Srchrequest = null;
SearchResponse SrchResponse = null;
SearchResultEntryCollection SearchCollection = null;
Hashtable UserDetails = new Hashtable();
Srchrequest = new SearchRequest("distniguishged name e.g. o=testxxx.com", string.Format(CultureInfo.InvariantCulture, "preferredmail=test#testxxxx.com"), System.DirectoryServices.Protocols.SearchScope.Subtree);
SrchResponse = (SearchResponse)ldapConnection.SendRequest(Srchrequest);
SearchCollection = SrchResponse.Entries;
foreach (SearchResultEntry entry in SearchCollection)
{
foreach (DictionaryEntry att in entry.Attributes)
{
if (((DirectoryAttribute)(att.Value)).Count > 0)
{
UserDetails.Add(att.Key.ToString(), ((DirectoryAttribute)(att.Value))[0].ToString());
}
else
{
UserDetails.Add(att.Key.ToString(), string.Empty);
}
}
}
if (UserDetails.Count > 1)
{
Console.WriteLine("User exists");
}
else
{
Console.WriteLine("User does not exist");
}
You can use the DirectoryInfo conrstructor that has user and password arguments. That way, you don't need to do a query to the LDAP, you can simplify your code.
string username = "frederic";
string password = "myFanciPassword99";
string domain = "ou=People,dc=my,dc=com";
string LDAPconnect= "LDAP://dc01.my.com/";
string connectionString = LDAPconnect + domain;
bool userValid = false;
// Note: DirectoryEntry(domain, username, password) would also work
DirectoryEntry entry = new DirectoryEntry(connectionString, username, password);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
userValid = true;
}
catch (Exception ex)
{
}

Validate user in intranet application

I need to use the windows credentials to allow my users to log in an intranet application. I am planning to create a table with usernames and roles and compare the username from Environment.UserName with my table. How safe is to relay on this? Is there a better way to achieve this task?
Thank you in advance.
You can do this using active directory authentication:
Bellow is sample code that you can try in your application.
string domainUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
string[] paramsLogin = domainUser.Split('\\');
string domain = paramsLogin[0].ToString();
string LdapPath = "";
string strDomainPath = DomainPath();
LdapPath = string.Format("LDAP://{0}/{1}", DomainName, strDomainPath);
string username = LoginUser.UserName;
string password = LoginUser.Password;
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(LdapPath, domainAndUsername, password);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (result != null)
{
IsLoginSucess = true;
//Do your stuff here
}
// Update the new path to the user in the directory
LdapPath = result.Path;
string _filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
IsLoginSucess = false;
}
If you are developing in a Windows application, take a look at this:
Authenticate user in WinForms (Nothing to do with ASP.Net)
System.Security.Principal.WindowsIdentity.GetCurrent() will give you the current Windows user
If you are developing a Web application, there is built in-support, you would need to have relevant entries in your web.config file
Using windows authentication in asp.net with c#
HttpContext.Current.User.Identity will get you the user identity

Creating LDAP Connection on .NET

I am trying to Create LDAP Cnnection using c# .
I found this server which gives LDAP Server to Test
http://www.forumsys.com/en/tutorials/integration-how-to/ldap/online-ldap-test-server/
I have googled many post and Tried to create a consolidated Code
string domain = "ldap://ldap.forumsys.com/ou=mathematicians";
string username = "cn=read-only-admin,dc=example,dc=com";
string password = "password";
string LdapPath = "Ldap://ldap.forumsys.com:389/ou=scientists,dc=example,dc=com";
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(LdapPath, domainAndUsername, password);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
// Update the new path to the user in the directory
LdapPath = result.Path;
string _filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
throw new Exception("Error authenticating user." + ex.Message);
}
This code is not connecting it is giving unexpected error ..
I also Tried some other Credentials , But they are not helping either ...
AUTH_LDAP_SERVER_URI = “ldap://ldap.forumsys.com”
AUTH_LDAP_BIND_DN = “cn=read-only-admin,dc=example,dc=com”
AUTH_LDAP_BIND_PASSWORD = “password”
AUTH_LDAP_USER_SEARCH = LDAPSearch(“ou=mathematicians,dc=example,dc=com”,
ldap.SCOPE_SUBTREE, “(uid=%(user)s)”)
--------------------
$config[‘LDAP’][‘server’] = ‘ldap://ldap.forumsys.com';
$config[‘LDAP’][‘port’] = ‘389’;
$config[‘LDAP’][‘user’] = ‘cn=read-only-admin,dc=example,dc=com';
$config[‘LDAP’][‘password’] = ‘password';
-------------------------
$config[‘LDAP’][‘server’] = ‘ldap://ldap.forumsys.com/ou=mathematicians';
$config[‘LDAP’][‘port’] = ‘389’;
$config[‘LDAP’][‘user’] = ‘gauss';
$config[‘LDAP’][‘password’] = ‘password';
--------------------------
OpenDSObject/GetObject functions, but don’t see a way to run a query with the ASDI objects.
Set LDAP = GetObject(“LDAP:”)
Set root = LDAP.OpenDSObject(“LDAP://ldap.forumsys.com:389″, “cn=read-only-admin,dc=example,dc=com”, “password”, 0)
Set ou = LDAP.OpenDSObject(“LDAP://ldap.forumsys.com:389/ou=mathematicians,dc=example,dc=com””, “cn=read-only-admin,dc=example,dc=com”, “password”, 0)
Set user = LDAP.OpenDSObject(“LDAP://ldap.forumsys.com:389/uid=riemann,dc=example,dc=com”, “cn=read-only-admin,dc=example,dc=com”, “password”, 0)
I need some suggestion what I am missing . any resource will be helpful
I had a somewhat similar issue with this server and google sent me here.
One issue I see is that case sensitive issue in LDAP path. Also we should specify the AuthenticationType as well.
Please check following code block which should work.
string ldapServer = "LDAP://ldap.forumsys.com:389/ou=scientists,dc=example,dc=com";
string userName = "cn=read-only-admin,dc=example,dc=com";
string password = "password";
var dirctoryEntry = new DirectoryEntry(ldapServer, userName, password, AuthenticationTypes.ServerBind);
try {
object nativeObject = dirctoryEntry.NativeObject;
//Rest of the logic
} catch (Exception ex) {
//Handle error
}
Trying using PrincipalContext to connect to the LDAP server. Here is a good how-to article I referenced when I was getting started: http://ianatkinson.net/computing/adcsharp.htm
ctx = new PrincipalContext(
ContextType.Domain,
"contoso.local",
"OU=Security Groups,OU=Contoso Inc,DC=contoso,DC=local",
"contoso\sysadmin",
"P#ssword1");
Namespace - using System.DirectoryServices.Protocols;
methode -
private bool ldapValidateUser(string fullname, string password)
{
try
{
LdapDirectoryIdentifier ldap = new LdapDirectoryIdentifier("Directory Host", true, false);
LdapConnection connection = new LdapConnection(ldap);
connection.AuthType = AuthType.Basic;
string ldapuser = "cn=" + fullname + ",ou=Org Unit,dc=Value,dc=local";
connection.Credential = new System.Net.NetworkCredential(ldapuser, password);
connection.Bind();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return false;
}

Using C# to authenticate user against LDAP

I'm using DirectorySearcher to search for a user entry in LDAP server.
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://myserver/OU=People,O=mycompany";
de.AuthenticationType = AuthenticationTypes.None;
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(uid=" + model.UserName + ")";
SearchResult result = deSearch.FindOne();
I'm able to get th intended output in result variable.
However If I try to authenticate the same user by providing password in directory entry, I always get following error.
"The user name or password is incorrect."
DirectoryEntry entry = new DirectoryEntry("LDAP://myserver/OU=People,O=mycompany", username, password);
DirectorySearcher search = new DirectorySearcher(
entry,
"(uid=" + username + ")",
new string[] { "uid" }
);
search.SearchScope = System.DirectoryServices.SearchScope.Subtree;
SearchResult found = search.FindOne(); ->>>>>this is where I get wrong credential error.
The username and password are for the user I want to authenticate.
Can anyone tell me what I'm doing wrong here or how to debug this.
This username, password within this line:
DirectoryEntry("LDAP://myserver/OU=People,O=mycompany", username, password);
should be for an account that has permission for directory lookup. It could be a service account or testing purpose try with your own. This shouldn't be the user/pass of someone who you are trying to authenticate.
If you want to authenticate, you can use following steps using PrincipalContext:
using(var context = new PrincipalContext(ContextType.Domain, "mydomain", "mydomain\serviceAcct", "serviceAcctPass")) {
//Username and password for authentication.
return context.ValidateCredentials(username, password);
}
"serviceAcct" = an account within domain users that has permission for directory lookup.
"serviceAcctPass" = password for that service account.
As I said, for testing you can try with your own user/pass context.
Also, make sure supplied username has either "domain\username" or "username#domain" formatting.
Here we are getting the active directory user details and we can use DomainName and UserRole from web.config file
bool isAdmin = false;
RegisterInput model = new RegisterInput();
NewUserInput usr = new NewUserInput();
SearchResultCollection results;
string mobileNumber = string.Empty;
using (DirectoryEntry domainEntry = new DirectoryEntry("LDAP://" + AppSettings.DomainName))
{
using (DirectorySearcher searcher = new DirectorySearcher(domainEntry, "userPrincipalName=" + userName + "#" + AppSettings.DomainName) { Filter = string.Format("(&(objectClass=user)(samaccountname={0}))", userName) })
{
results = searcher.FindAll();
if (results.Count > 0)
{
usr.FirstName = results[0].GetDirectoryEntry().Properties["givenName"].Value.ToString();
usr.LastName = results[0].GetDirectoryEntry().Properties["sn"].Value?.ToString();
usr.EmailAddress = results[0].GetDirectoryEntry().Properties["mail"].Value?.ToString();
mobileNumber = results[0].GetDirectoryEntry().Properties["mobile"]?.Value?.ToString();
dynamic userRoleList = results[0].GetDirectoryEntry().Properties["memberOf"];
if (userRoleList != null)
{
foreach (var role in userRoleList)
{
string[] split = role.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
bool result = split.Any(x => x.ToLowerInvariant() == AppSettings.UserRole.ToLowerInvariant());
if (result)
{
isAdmin = true;
break;
}
}
}
}
}
}
model.NewUser = usr;

C# Active Directory: Get domain name of user?

I know that this type of question has been asked before, but other methods are failing me right now.
As it stands our windows service polls AD, given an LDAP (i.e. LDAP://10.32.16.80) and a list of usergroups within that AD server to search for.
It retrieves all users within those given groups, recursively searching those groups for more groups as well.
Each user is then added to another applications authenticated users list.
This part of the application is running successfully. However, we're in need of each user's friendly domain name (i.e. the part of their login DOMAIN/username)
So if there is a user that is part of TEST domain, named Steve: TEST/steve is his login.
I'm able to find steve in the AD, however I also need "TEST" to be stored along with his AD information.
Again, I can find 'steve' fine by using a directory searcher and the LDAP IP I'm given, but given the LDAP IP, how can I find the friendly domain name?
When I try the following code I'm given an error when attempting to access the 'defaultNamingContext':
System.Runtime.InteropServices.COMException (0x8007202A): The authentication mechanism is unknown.
Here is the code:
private string SetCurrentDomain(string server)
{
string result = string.Empty;
try
{
logger.Debug("'SetCurrentDomain'; Instantiating rootDSE LDAP");
DirectoryEntry ldapRoot = new DirectoryEntry(server + "/rootDSE", username, password);
logger.Debug("'SetCurrentDomain'; Successfully instantiated rootDSE LDAP");
logger.Debug("Attempting to retrieve 'defaultNamingContext'...");
string domain = (string)ldapRoot.Properties["defaultNamingContext"][0]; //THIS IS WHERE I HIT THE COMEXCEPTION
logger.Debug("Retrieved 'defaultNamingContext': " + domain);
if (!domain.IsEmpty())
{
logger.Debug("'SetCurrentDomain'; Instantiating partitions/configuration LDAP entry");
DirectoryEntry parts = new DirectoryEntry(server + "/CN=Partitions,CN=Configuration," + domain, username, password);
logger.Debug("'SetCurrentDomain'; Successfully instantiated partitions/configuration LDAP entry");
foreach (DirectoryEntry part in parts.Children)
{
if (part.Properties["nCName"] != null && (string)part.Properties["nCName"][0] != null)
{
logger.Debug("'SetCurrentDomain'; Found property nCName");
if ((string)part.Properties["nCName"][0] == domain)
{
logger.Debug("'SetCurrentDomain'; nCName matched defaultnamingcontext");
result = (string)part.Properties["NetBIOSName"][0];
logger.Debug("'SetCurrentDomain'; Found NetBIOSName (friendly domain name): " + result);
break;
}
}
}
}
logger.Debug("finished setting current domain...");
}
catch (Exception ex)
{
logger.Error("error attempting to set domain:" + ex.ToString());
}
return result;
}
edit
I added this sample method in order to attempt a suggestion but am getting an exception: "Unspecified error" when I hit the "FindAll()" call on the searcher.
The string being passed in is: "CN=TEST USER,CN=Users,DC=tempe,DC=ktregression,DC=com"
private string GetUserDomain(string dn)
{
string domain = string.Empty;
string firstPart = dn.Substring(dn.IndexOf("DC="));
string secondPart = "CN=Partitions,CN=Configuration," + firstPart;
DirectoryEntry root = new DirectoryEntry(secondPart, textBox2.Text, textBox3.Text);
DirectorySearcher searcher = new DirectorySearcher(root);
searcher.SearchScope = SearchScope.Subtree;
searcher.ReferralChasing = ReferralChasingOption.All;
searcher.Filter = "(&(nCName=" + firstPart + ")(nETBIOSName=*))";
try
{
SearchResultCollection rs = searcher.FindAll();
if (rs != null)
{
domain = GetProperty(rs[0], "nETBIOSName");
}
}
catch (Exception ex)
{
}
return domain;
This article helped me much to understand how to work with the Active Directory.
Howto: (Almost) Everything In Active Directory via C#
From this point forward, if you require further assitance, please let me know with proper questions in comment, and I shall answer them for you to the best of my knowledge.
EDIT #1
You had better go with this example's filter instead. I have written some sample code to briefly show how to work with the System.DirectoryServices and System.DirectoryServices.ActiveDirectory namespaces. The System.DirectoryServices.ActiveDirectory namespace is used to retrieve information about the domains within your Forest.
private IEnumerable<DirectoryEntry> GetDomains() {
ICollection<string> domains = new List<string>();
// Querying the current Forest for the domains within.
foreach(Domain d in Forest.GetCurrentForest().Domains)
domains.Add(d.Name);
return domains;
}
private string GetDomainFullName(string friendlyName) {
DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, friendlyName);
Domain domain = Domain.GetDomain(context);
return domain.Name;
}
private IEnumerable<string> GetUserDomain(string userName) {
foreach(string d in GetDomains())
// From the domains obtained from the Forest, we search the domain subtree for the given userName.
using (DirectoryEntry domain = new DirectoryEntry(GetDomainFullName(d))) {
using (DirectorySearcher searcher = new DirectorySearcher()){
searcher.SearchRoot = domain;
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("sAMAccountName");
// The Filter is very important, so is its query string. The 'objectClass' parameter is mandatory.
// Once we specified the 'objectClass', we want to look for the user whose login
// login is userName.
searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", userName);
try {
SearchResultCollection results = searcher.FindAll();
// If the user cannot be found, then let's check next domain.
if (results == null || results.Count = 0)
continue;
// Here, we yield return for we want all of the domain which this userName is authenticated.
yield return domain.Path;
} finally {
searcher.Dispose();
domain.Dispose();
}
}
}
Here, I didn't test this code and might have some minor issue to fix. This sample is provided as-is for the sake of helping you. I hope this will help.
EDIT #2
I found out another way out:
You have first to look whether you can find the user account within your domain;
If found, then get the domain NetBIOS Name; and
concatenate it to a backslash (****) and the found login.
The example below uses a NUnit TestCase which you can test for yourself and see if it does what you are required to.
[TestCase("LDAP://fully.qualified.domain.name", "TestUser1")]
public void GetNetBiosName(string ldapUrl, string login)
string netBiosName = null;
string foundLogin = null;
using (DirectoryEntry root = new DirectoryEntry(ldapUrl))
Using (DirectorySearcher searcher = new DirectorySearcher(root) {
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("sAMAccountName");
searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", login);
SearchResult result = null;
try {
result = searcher.FindOne();
if (result == null)
if (string.Equals(login, result.GetDirectoryEntry().Properties("sAMAccountName").Value))
foundLogin = result.GetDirectoryEntry().Properties("sAMAccountName").Value
} finally {
searcher.Dispose();
root.Dispose();
if (result != null) result = null;
}
}
if (!string.IsNullOrEmpty(foundLogin))
using (DirectoryEntry root = new DirectoryEntry(ldapUrl.Insert(7, "CN=Partitions,CN=Configuration,DC=").Replace(".", ",DC="))
Using DirectorySearcher searcher = new DirectorySearcher(root)
searcher.Filter = "nETBIOSName=*";
searcher.PropertiesToLoad.Add("cn");
SearchResultCollection results = null;
try {
results = searcher.FindAll();
if (results != null && results.Count > 0 && results[0] != null) {
ResultPropertyValueCollection values = results[0].Properties("cn");
netBiosName = rpvc[0].ToString();
} finally {
searcher.Dispose();
root.Dispose();
if (results != null) {
results.Dispose();
results = null;
}
}
}
Assert.AreEqual("FULLY\TESTUSER1", string.Concat(netBiosName, "\", foundLogin).ToUpperInvariant())
}
The source from which I inspired myself is:
Find the NetBios Name of a domain in AD
Since I could not find any example code I would like to share my own solution. This will search the parents of the DirectoryEntry object until it hits the domainDNS class.
using System.DirectoryServices;
public static class Methods
{
public static T ldap_get_value<T>(PropertyValueCollection property)
{
object value = null;
foreach (object tmpValue in property) value = tmpValue;
return (T)value;
}
public static string ldap_get_domainname(DirectoryEntry entry)
{
if (entry == null || entry.Parent == null) return null;
using (DirectoryEntry parent = entry.Parent)
{
if (ldap_get_value<string>(parent.Properties["objectClass"]) == "domainDNS")
return ldap_get_value<string>(parent.Properties["dc"]);
else
return ldap_get_domainname(parent);
}
}
}
Use it like this:
string[] _properties = new string[] { "objectClass", "distinguishedName", "samAccountName", "userPrincipalName", "displayName", "mail", "title", "company", "thumbnailPhoto", "useraccountcontrol" };
string account = "my-user-name";
// OR even better:
// string account = "my-user-name#DOMAIN.local";
using (DirectoryEntry ldap = new DirectoryEntry())
{
using (DirectorySearcher searcher = new DirectorySearcher(ldap))
{
searcher.PropertiesToLoad.AddRange(_properties);
if (account.Contains('#')) searcher.Filter = "(userPrincipalName=" + account + ")";
else searcher.Filter = "(samAccountName=" + account + ")";
var user = searcher.FindOne().GetDirectoryEntry();
Console.WriteLine("Name: " + Methods.ldap_get_value<string>(user.Properties["displayName"]));
Console.WriteLine("Domain: " + Methods.ldap_get_domainname(user));
Console.WriteLine("Login: " + Methods.ldap_get_domainname(user) + "\\" + Methods.ldap_get_value<string>(user.Properties["samAccountName"]));
}
}
I haven't got a forest to test it on but in theory this should cut it.
You can retrieve the name of the domain that the current user is on using the Environment.UserDomainName Property.
string domainName;
domainName = System.Environment.UserDomainName;
Maybe not entirely correct but...
DirectoryEntry dirEntry = new DirectoryEntry();
DirectorySearcher dirSearcher = new DirectorySearcher(dirEntry);
dirSearcher.SearchScope = SearchScope.Subtree;
dirSearcher.Filter = string.Format("(&(objectClass=user)(|(cn={0})(sn={0}*)(givenName={0})(sAMAccountName={0}*)))", userName);
var searchResults = dirSearcher.FindAll();
foreach (SearchResult sr in searchResults)
{
var de = sr.GetDirectoryEntry();
string user = de.Properties["SAMAccountName"][0].ToString();
string domain = de.Path.ToString().Split(new [] { ",DC=" },StringSplitOptions.None)[1];
MessageBox.Show(domain + "/" + user);
}
Because the value of de.Path is
LDAP://CN=FullName,DC=domain,DC=local

Categories