Problems with LDAP - c#

I am having trouble with LDAP. Now I use this code:
DirectoryEntry ldapConnection = new DirectoryEntry("LDAPS://*******.com:636", "User#bloom.local", "Password");
ldapConnection.AuthenticationType = AuthenticationTypes.SecureSocketsLayer;
DirectorySearcher search = new DirectorySearcher(ldapConnection);
var result = search.Filter = "(objectClass=*)";
search.FindAll();
I spent a large number of experiments, but never received:
Unknown error (0x80005000)
or
The server is not operational.
My property in the softerra LDAP Administrator:

The problem is that the simple authentication mechanism requires an LDAP distinguished name (DN) and you provided just a user name. At least, this is what your screenshot shows.
The DN of the administrator is likely something like cn=Administrator,cn=Users,dc=bloom,dc=local.
Also, I would probably steer away from using the administrator credentials in production. It is much more preferable to create an account with the right privileges.

Related

The user name or password is incorrect-8009030C: LdapErr: DSID-0C090579, comment: AcceptSecurityContext error, data 52e, v3839

I am trying to connect AD with the following code
VMADProfile _VMADProfile = new VMADProfile();
DirectoryEntry searchRoot = new DirectoryEntry("Test AD LDAP Path", "DomainName\\username", "password");
directorySearcher.Filter = "(&(objectCategory=user)(samAccountName=" + username + "))";
directorySearcher.PropertiesToLoad.Add("displayname");
SearchResult one = directorySearcher.FindOne();
but it is giving me following Error
The user name or password is incorrect.
8009030C: LdapErr: DSID-0C090579, comment: AcceptSecurityContext error, data 52e, v3839
I am able to login with same user name and password if I login directly.
My AD that I am trying to connect is different from from which i am running code. Same code works fine if i change test AD to the production AD
I think this is the key:
My AD that I am trying to connect is different from from which i am running code.
It's probably trying to authenticate you on your domain, not the other one. Make sure your LDAP path includes the server to connect to for the other domain, and not just the distinguished name of the domain. The server name can just be the DNS name for the domain. It should look something like this:
DirectoryEntry searchRoot = new DirectoryEntry("LDAP://otherdomain.com/DC=otherdomain,DC=com", "DomainName\\username", "password");
If you just use "LDAP://DC=otherdomain,DC=com", it will try to connect to the domain the current computer is joined to first. That would actually work if there is a trust between the two domains, but if not, you need to specifically give it the server name to connect to.

autenticating ldap for web applications

please take a few minutes and read my question completely. here is my problem :
I want to connect to LDAP server by C# for a web application, means clients connecting to the asp.net server.
*- The ldap server and application server are not the same.
**- They are not in a same domain.
I have been trying 4 different ways and could not solve the problem by none of them.
1-
var credentials = new NetworkCredential(username, password);
var serverId = new LdapDirectoryIdentifier("domain.net");
var conn = new LdapConnection(serverId, credentials);
conn.Bind();
2-
System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry("LDAP://domain.net/DC=domain,DC=net");
entry.Username = "username";
entry.Password = "password";
System.DirectoryServices.DirectorySearcher searcher = new System.DirectoryServices.DirectorySearcher(entry);
searcher.Filter = "(&(objectClass=user))";
var results = searcher.FindAll();
the problem with these 2 ways is that the user must have an access to the server for login and we know that there is only admin of the system who has the permission.
3-
PrincipalContext pc = new PrincipalContext(ContextType.Domain, "domain.net");
var ret = pc.ValidateCredentials(model.UserName, model.Password);
the problem is the server must be in the domain of ldap server. we have this limitation !!
4-
https://auth0.com/blog/using-ldap-with-c-sharp/
public bool validateUser(string username, string password)
{
var sha1 = new SHA1Managed();
var digest = Convert.ToBase64String(sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password)));
var request = new CompareRequest(string.Format("uid={0},ou=users,dc=example,dc=com", username),
"userPassword", "{SHA}" + digest);
var response = (CompareResponse)connection.SendRequest(request);
return response.ResultCode == ResultCode.CompareTrue;
}
this code does not return any thing. it will be very helpful if there is a query to compare usernames and passwords. this code seems to use this way but there are different types of hash algorithms. I tried to use SHA1 and MD5, and userPassword , unicodePwd attribute. but the return is empty all the time.
is it the best solution to put both servers in a same domain? any other solution , Thank you so much.
Method 1 is the simplest way. If that doesn't work, nothing will. So you will have to change your configuration to make it work.
When you say:
the user must have an access to the server for login and we know that there is only admin of the system who has the permission.
What do you mean? Are you explicitly denying login rights to the domain controllers? Are there network issues between the computer this is running on and the domain controller (can you hit port 389 on the domain controller(s))?
Update: PrincipalContext.ValidateCredentials just does an LDAP bind in behind - it uses LdapConnection. You can see the source code here. The probable reason why ValidateCredentials is working on a domain machine and not otherwise is because it uses Kerberos authentication by default, which will only work from a domain computer.
The same is true with LdapConnection. So try setting the authentication mode. For example, try Basic
var credentials = new NetworkCredential(username, password);
var serverId = new LdapDirectoryIdentifier("domain.net");
var conn = new LdapConnection(serverId, credentials, AuthType.Basic);
conn.Bind();
Or look at the available values and try what works.

How to query Active Directory B if application server is in Active Directory A

So heres my question. I have a Asp.net application with a form based authentication. I have users in my database but the users also has to be in the active directory.
The following code is for me to check if user is in the domain A
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://domainA.com";
de.AuthenticationType = AuthenticationTypes.None;
DirectorySearcher search = new DirectorySearcher(de);
search.Filter = "(SAMAccountName=" + account + ")";
search.PropertiesToLoad.Add("displayName");
SearchResult result = search.FindOne();
This code work fine. The problem is client is requesting that domain B should also be able to connect to the application. So created the following code:
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://domainB.com";
de.AuthenticationType = AuthenticationTypes.None;
DirectorySearcher search = new DirectorySearcher(de);
search.Filter = "(SAMAccountName=" + account + ")";
search.PropertiesToLoad.Add("displayName");
SearchResult result = search.FindOne();
Since my server is in domainA this does not work. Is there a way for me to query domainB knowing that the server is in domainA? I found an article saying trust needs to be setup for domainA and B but this domains shouldnt be linked. Its only for this application that they need this functionality.
P.S. I might forgot to explain an important detail. domainA and B are not on the same network. But domainA can ping domainB
While trying samples against a foreign domain, I noticed that the foreign DC is giving the error message "The server is unavailable" when using the wrong authentication type. Please try:
de.User = #"DOMAINB\user";
de.Password = "YourPassword";
de.AuthenticationType = AuthenticationTypes.None;
Of course this results in an unsecured BASIC simple bind, which removes any encryption ADSI might offer. If this works, you should try a more secure authentication type that the server accepts.
An alternative might be using the "System.DirectoryServices.Protocols"-namespace which offers a more lightweight approach for AD access. I can provide you with a sample I you want to go in this direction.
You will need to provide credentials that have permission to query AD on domain B.
var de = new DirectoryEntry("LDAP://domainB.com", "Username", "Password");
var search = new DirectorySearcher(de);

DirectoryEntry results in The server is unwilling to process the request

I am writing a small app that integrates with AD and will be listing users and allowing members of the site to edit certain fields of the users. These fields will be, first name, last name, display name and email.
When I run the following code I get an exception that says
The server is unwilling to process the request.
Please note that result is not null and contains the correct active directory user that I want to edit. Also note that result is of type SearchResult. Also note that the user I am using to connect to AD is the Administrative user.
DirectoryEntry entryToUpdate = result.GetDirectoryEntry();
entryToUpdate.Properties["cn"].Value = user.Name;
entryToUpdate.Properties["mail"].Value = user.Email;
entryToUpdate.Properties["sn"].Value = user.Surname;
entryToUpdate.Properties["displayName"].Value = user.DisplayName;
string username = user.Email.Substring(0, user.Email.IndexOf("#"));
entryToUpdate.Properties["sAMAccountName"].Value = username;
entryToUpdate.CommitChanges();
Any Ideas?
I believe
entryToUpdate.Properties["cn"].Value = user.Name;
is your Problem. Use givenName as first Name. "cn" is managed by the System.
Also:
If using Exchange, the Mail attribute is managed by it.
Consider the ramifications of modifing samAccountName. Users may not know how to log in, seperate Systems with pseudo SSO may not recognize them, the Login Name does not match the local Profile Name, etc.

LDAP Directory Entry in .Net - not working with OU=Users

I have the following code (C#):
(Tweaked from: http://www.eggheadcafe.com/conversation.aspx?messageid=31766061&threadid=31766050)
DirectorySearcher dseSearcher = new DirectorySearcher();
string rootDSE = dseSearcher.SearchRoot.Path;
DirectoryEntry rootDE = new DirectoryEntry(rootDSE);
string userDSE = rootDSE.Insert(7, "OU=Users,");
DirectoryEntry userDE = new DirectoryEntry(userDSE);
The rootDSE is created correctly, however, the user userDSE is unusable and throws "There is no such object on the server" exception if I attempt to use it.
The LDAP strings are as follows:
Root: LDAP://DC=company,DC=local
User: LDAP://OU=Users,DC=company,DC=local
I'm running on Vista as Admin, but need this to work on XP (Admin) as well.
I'm new to LDAP and Directory Management, so I'm stumbling around in the dark here. Any thoughts? Also - any articles to link too that could give me some insight into how it all works would be appreciated.
The first thing I would try as a test is to hardcode your desired path when you create a directory entry like so:
DirectoryEntry de = new DirectoryEntry("LDAP://OU=Users,DC=company,DC=local");
This will tell you pretty quick if this is an actual path in your Active Directory. I don't know what your AD looks like so I can't tell you if this is a valid path or not. Under your Active Directory Users and Computers MMC plugin, if this path is correct, then you should have your root domain, and a OU folder under the root called Users.
Paths are generated backwards in AD, so if your Users folder is under another OU off the root than it would be
DirectoryEntry de = new DirectoryEntry("LDAP://OU=Users,OU=<first OU folder>,DC=company,DC=local");
So your AD schema would look like:
Root
|
--><first OU folder>
|
-->Users
A great article on how to manage Active Directory in .NET:
HowTo: Do (Almost) Everything in Active Directory via C#
You might also want to research the System.DirectoryServices, System.DirectoryServices.ActiveDirectory, and the System.DirectoryServices.AccountManagement namespaces provided in the .Net 3.5 Framework. I believe System.DirectoryServices, and ActiveDirctory namespaces were available staring in .Net 1.1, and AccountManagement was introduced in .Net 3.5.
Microsoft Documentation - A lot of good links on how to use the namespace
Addendum:
To actually find a user in AD you will want to do the following:
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://DC=company,DC=local";
de.AuthenticationType = AuthenticationTypes.Secure;
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(&(objectClass=user) (cn=" + username + "))";
SearchResult result = deSearch.FindOne();
if (result != null)
{
DirectoryEntry deUser = new DirectoryEntry(result.Path);
... do what ever you need to the deUser
deUser.Close();
}
This may seem silly and stupid, but the default tree setup in Active Directory is not OU=Users,dc=domain,dc=com but rather cn=Users,dc=domain,dc=com (Note the CN= not the OU= for Users.
It seems stupid since a container object (objectClass of cn) in AD cannot be a recipient of group policy, but for reasons I do not understand, that is the default. (actually I do understand, it is because containment for a CN is more similar to an NT domain than OU)
Gets almost everybody I meet, first time they try to LDAP bind/auth to AD.
As geoffc mentioned correctly, in Active Directory the "Users" under the domain is a container object rather than organizational unit object.
This results in a totally different LDAP path which is why you get the error message.
Try the following code and post if it fixes your issue:
// Replace the "company" and "com" with actual domain values...
DirectoryEntry de = new DirectoryEntry("LDAP://CN=Users,DC=company,DC=com");
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
// Set your other search params here

Categories