I need to do query raw on the LDAP server with c# 3.5. I use this code, but I can't find how I do for insert a raw query.
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, host, username, password);
UserPrincipal u = new UserPrincipal(ctx);
PrincipalSearcher search = new PrincipalSearcher(u);
foreach (UserPrincipal result in search.FindAll())
{
var s = result.UserPrincipalName;
}
Related
I'm trying to create a DLL that gets all the users from a certain OU group in Active Directory, but I'm getting this two errors:
System.DirectoryServices.AccountManagement.PrincipalServerDownException: The server could not be contacted. and
System.DirectoryServices.Protocols.LdapException: The LDAP server is unavailable.
My code is currently this:
public static void GetAllADUsers(string output, string filter, int mode) {
List<string> allUsers = new List<string>();
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "LDAP://mydomain.COM", filter);
UserPrincipal qbeUser = new UserPrincipal(ctx);
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
foreach (var found in srch.FindAll()) {
allUsers.Add(found.DisplayName);
}
if(mode == 1)
File.WriteAllText(output, allUsers.ToString());
else
File.AppendAllText(output, allUsers.ToString());
}
My input parameters are:
PCControl.PCC:GetAllADUsers("C:\temp\users.csv", "OU=Users,OU=...,OU=...,DC=mydomain,DC=com", 1).
I don't know if this helps, but I'm able to use this function into my DLL:
(That's where I got the PrincipalContext)
new DirectorySearcher(new DirectoryEntry("LDAP://mydomain.COM", user, password) {
AuthenticationType = AuthenticationTypes.Secure,
Username = user,
Password = password
}) {
Filter = "(objectclass=user)"
}.FindOne().Properties["displayname"][0].ToString();
Any sugestions on how I can fix this?
I'm trying to get user data from the active directory. Authentication process is true.
var context = new PrincipalContext(ContextType.Domain, "localhost-ad.local", "OU=LocalOu,DC=localhost-ad,DC=local", ContextOptions.Negotiate);
var login = context.ValidateCredentials("user.name", "password", ContextOptions.Negotiate);
But PrincipalSearcher returns a wrong username or password.
var user = new UserPrincipal(context);
var searcher = new PrincipalSearcher(user);
var searchResults = searcher.FindAll();
List<UserPrincipal> results = new List<UserPrincipal>();
foreach (Principal p in searchResults)
{
results.Add(p as UserPrincipal);
}
return results;
How can I solve this problem?
I think your problem may stem from a misunderstanding of what PrincipalContext.ValidateCredentials does.
It does not authenticate the context on the domain or allow access to the domain in any way, all it does is check if the username and password are correct and return True or False.
Instead you can authenticate with the domain as so:
var context = new PrincipalContext(ContextType.Domain, "localhost-ad.local",
"OU=LocalOu,DC=localhost-ad,DC=local", "user.name", "password");
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Domain, UserName, Password))
{
UserPrincipal U = new UserPrincipal(ctx);
U.GivenName = strFirstName;
U.Surname = strLastName;
U.EmailAddress = strEmail;
PrincipalSearcher srch = new PrincipalSearcher(U);
foreach (var principal in srch.FindAll())
{
var p = (UserPrincipal)principal;
if (!User.Any(x => x.Email == p.EmailAddress))
{
MyUserDataset.UserRow User = User.NewUserRow();
User.FirstName = p.GivenName;
User.LastName = p.Surname;
User.UserName = p.SamAccountName;
User.Email = p.EmailAddress;
User.AddUserRow(User);
}
}
User.AcceptChanges();
}
I'm using the PrincipalContext class above to establish a connection to the target directory and specify credentials for performing operations against the directory.
Does any one know how i can also specify the connection time out in the PrincipalContext Constructor?, i'm running into connection time out issues & i was wondering if i can control after how long the connection can time out.
Well, I guess the answer is no unfortunately. I have dig into the source code of PrincipalContext, it used DirectoryEntry which used unsafe native method System.DirectoryServices.Interop.UnsafeNativeMethods.ADsOpenObject to open LDAP connection.
As per this blog How to specify TimeOut for ldap bind in .Net, there is no way to configure the timeout on ADsOpenObject. However, it also mentioned that if using LdapConnection directly, then it is possible to set the timeout. In that case, you may not be able to user PrincipalContext.
DirectoryEntry DirEntry = new DirectoryEntry("LDAP://" + domain, null, null, AuthenticationTypes.None);
DirectorySearcher search = new DirectorySearcher(DirEntry);
search.Filter = String.Format("(SAMAccountName={0})", "my_login_name");
search.PropertiesToLoad.Add("cn");
SearchResult result1 = search.FindOne();
myDataTable Users = new myDataTable();
DataRow User;
foreach (SearchResult i in search.FindAll())
{
DirectoryEntry CurrentDirEntry;
User = Users.NewUserRow();
CurrentDirEntry = i.GetDirectoryEntry();
User.FirstName = (string)CurrentDirEntry.Properties["givenname"].Value;
User.LastName = (string)CurrentDirEntry.Properties["sn"].Value;
User.UserName = (string)CurrentDirEntry.Properties["sAMAccountName"].Value;
User.Email = (string)CurrentDirEntry.Properties["mail"].Value;
Users.AddUserRow(User);
}
I'm trying to read some properties from active directory but the value for
sAMAccountName
is always returned as null, i'm wondering why this is so since its being matched in the search filter. Could it be related to access privileges?
I want to return the FirstName, LastName, Email and login Name. I'm getting other properties except login name.
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, my_login_name);
if(user != null)
{
// do something here....
string samAccountName = user.SamAccountName;
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Update: if you need to search by fields that aren't handled by the .FindByIdentity() call, then you need to use the PrincipalSearcher and a "query-by-example" principal to do your searching:
// create your domain context
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// define a "query-by-example" principal - here, we search for a UserPrincipal
// and with the first name (GivenName) of "Bruce" and a last name (Surname) of "Miller"
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.GivenName = "Bruce";
qbeUser.Surname = "Miller";
// create your principal searcher passing in the QBE principal
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
// find all matches
foreach(var found in srch.FindAll())
{
// do whatever here - "found" is of type "Principal" - it could be user, group, computer.....
}
}
Could it be the spacing in ["sAMAccountName "] of :
User.UserName = (string)CurrentDirEntry.Properties["sAMAccountName "].Value;
Try this one , I used it before
VB
Dim myDe As New DirectoryEntry("LDAP://DOMAIN.LOCAL")
Dim deSearcher As New DirectorySearcher(myDe)
Dim userDE As DirectoryEntry
Dim email As String = ""
Try
deSearcher.Filter = "(&(sAMAccountName=" & UserName & "))"
userDE = deSearcher.FindOne().GetDirectoryEntry()
email = userDE.Properties("mail").Value
Catch ex As Exception
End Try
C#
DirectoryEntry myDe = new DirectoryEntry("LDAP://DOMAIN.LOCAL");
DirectorySearcher deSearcher = new DirectorySearcher(myDe);
DirectoryEntry userDE = default(DirectoryEntry);
string email = "";
try {
deSearcher.Filter = "(&(sAMAccountName=" + UserName + "))";
userDE = deSearcher.FindOne().GetDirectoryEntry();
email = userDE.Properties("mail").Value;
} catch (Exception ex) {}
I'm not sure how C# handles it but I've seen LDAP-libs returning attribute names all in lower case. So it might help to simply call for samaccountname instead of sAMAccountName.
I am creating this project to be deployed in our company's intranet. I am using this code to authenticate the users login:
entry.Username = strUserName;
entry.Password = strPassword;
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(objectclass=user)";
try
{
searcher.FindOne();
return true;
}
It working well on my localhost, but when I deployed it the intranet, I can't log in.
Now my question is, can I access the Directory over the intranet? or is there a better way to achieve this?
A simpler method would be to use System.DirectoryServices and System.DirectoryServices.AccountManagement
Use this in a function returning Boolean:
Dim context As PrincipalContext = New PrincipalContext(ContextType.Domain, domainName)
If context.ValidateCredentials(userAlias, userPassword, ContextOptions.Negotiate) Then
Return True
Else
Return False
End If
The snippet is in VB, but you get the idea. Replace domainName with your domain name, userAlias with your username, and userPassword with your password.
This worked great for me in the past:
var ldapConnectionString = "LDAP://servername/CN=Users,DC=domainname,DC=com";
using (var de = new DirectoryEntry(ldapConnectionString, username, password, AuthenticationTypes.Secure))
{
if(de.NativeObject != null)
{
// user is valid ...
}
}
You need a reference to: System.DirectoryServices