Connect to another domain Active Directory in ASP.NET - c#

I am trying to connect to another domain using from my C# code but I get an error.
Here is my code:
doLog("Going For establishing Connection");
var username = "cn=Directory Manager";
var password = "somepassword";
using (var context = new PrincipalContext(ContextType.Domain, "LDAP://10.10.10.132:2232", username, password))
{
using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
{
doLog("In the principal searcher");
foreach (var result in searcher.FindAll())
{
DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
doLog("Looping result:" + de.Properties["givenName"].Value);
Console.WriteLine("First Name: " + de.Properties["givenName"].Value);
}
}
}
It is working in java but from .net it always throw an error on this line
using (var context = new PrincipalContext(ContextType.Domain, "LDAP://10.10.10.132:2232", username, password))
This is the error I get:

Related

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;
}
}
}

How to validate LDAP path against Active Directory

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);
}
}

User Principal is always null

I am logged in under user User001 under domain DomainA and with password Pass001.
I use this code
//var principalContext = new PrincipalContext(
//ContextType.Domain,
//"DomainA",
//"User001",
//"Pass001");
var principalContext = new PrincipalContext(
ContextType.Domain,
domain,
userName,
password);
var userPrincipal = new UserPrincipal(principalContext);
And userPrincipal is always NULL.
How to fix it?
Somehow this code I found is working fine...
using (var context = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal principal = UserPrincipal.FindByIdentity(context, userName))
{
var uGroups = principal.GetGroups();
foreach (var group in uGroups)
{
Debug.WriteLine(group.DisplayName);
}
}
}

Setting DistinguishedName using UserPrincipal

When using DirectoryEntry, it is possible to set the CN of the new user account, but how to do it using UserPrincipal? The property is readonly.
// From : http://msdn.microsoft.com/en-us/magazine/cc135979.aspx
DirectoryEntry container = new DirectoryEntry("LDAP://ou=TechWriters,dc=fabrikam,dc=com");
// create a user directory entry in the container
DirectoryEntry newUser = container.Children.Add("cn=user1Acct", "user");
// add the samAccountName mandatory attribute
newUser.Properties["sAMAccountName"].Value = "User1Acct";
// save to the directory
newUser.CommitChanges();
But using UserPrincipal:
// For the example
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, null, "ou=TechWriters,dc=fabrikam,dc=com")
{
using (UserPrincipal user = new UserPrincipal(ctx, "User1Acct", "pwd", true))
{
// I would like to do :
user.DistinguishedName = "user1Acct";
//
user.Save();
}
}
Not the answer you want, but to my knowledge its not doable that way... The CN is 'protected' om the userprinciple class, as too much elsewhere relies on that being stable information.
I don't know why one would mix things up, but you could try this:
using (var ctx = new PrincipalContext(ContextType.Domain, null, "ou=TechWriters,dc=fabrikam,dc=com"))
{
using (var user = new UserPrincipal(ctx, "User1Acct", "pwd", true))
{
user.Save();
}
using (var entry = new DirectoryEntry("LDAP://cn=User1Acct;ou=TechWriters,dc=fabrikam,dc=com",null,null,AuthenticationTypes.Secure))
{
entry.Rename("cn=user1Acct");
}
}
(Maybe getting the LDAP string from the userPrinciple instead of hardcoding)
I do not have the possibillity to test this though..

Active Directory Connection C#

My purpose is to connect to the Active Directory (which runs on a virtual machine (Win SRV 2008R2)) within a console C# application and write down all the user names in the domain. Since I'm a newbie on AD I just got stuck setting a connection.
Now first thing is first;
Root DomainName = frt.local
IP : 192.168.x.x
Username: admin
Pass : yyyy
I have written the code below to set a connection but getting errors. Please tell me the point I missed.
DirectoryEntry entry = new DirectoryEntry();
entry.Path = "LDAP://192.168.x.x/dc=frt.local";
entry.Username = #"frt.local\admin";
entry.Password = "yyyy";
After pointing what I missed any help would be mostly welcome about writing down the usernames to the console.
Kind Regards
Nesim's answer is good - in the beginning. But I don't really see any point or need in using that
DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
line - the result of the PrincipalSearcher already is a UserPrincpial and you can access its properties much easier like this:
using (var searcher = new PrincipalSearcher(new UserPrincipal(ctx)))
{
foreach (var result in searcher.FindAll())
{
UserPrincipal foundUser = result as UserPrincipal;
if(foundUser != null)
{
Console.WriteLine("First Name: {0}", foundUser.GivenName);
Console.WriteLine("Last Name : {0}", foundUser.Surname);
Console.WriteLine("SAM account name; {0}", foundUser.SamAccountName);
Console.WriteLine("User principal name: {0}", foundUser.UserPrincipalName);
Console.WriteLine();
}
}
}
The UserPrincipal already and very nicely exposes the most frequently used attributes as properties on the object itself - no need for the rather messy code with the DirectoryEntry...
var username = "your username";
var password = "your password";
var domain = "your domain";
var ctx = new PrincipalContext(ContextType.Domain, domain, username, password);
using (var searcher = new PrincipalSearcher(new UserPrincipal(ctx)))
{
foreach (var result in searcher.FindAll())
{
DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
Console.WriteLine("First Name: " + de.Properties["givenName"].Value);
Console.WriteLine("Last Name : " + de.Properties["sn"].Value);
Console.WriteLine("SAM account name : " + de.Properties["samAccountName"].Value);
Console.WriteLine("User principal name: " + de.Properties["userPrincipalName"].Value);
Console.WriteLine();
}
}

Categories

Resources