12

I've been stuck for the last couple of hours on an annoying Active Directory bit.

What I'm trying to accomplish is connect to an Active Directory via LDAP over SSL. The authentication type is anonymous. I'm using .NET Framework 4.0, C# and Visual Studio 2010.

The following code should work according to various online resources. But it keeps coming up with the amazing self-explanatory: 'Unknown Error (0x80005000)'.

DirectoryEntry entry = new DirectoryEntry();
entry.Path = "LDAPS://some.ldap.server:636";
entry.AuthenticationType = AuthenticationTypes.SecureSocketsLayer;

DirectorySearcher searcher = new DirectorySearcher();
searcher.searchRoot = entry;
searcher.Filter = "(&(objectCategory=person)(objectClass=user))";

SearchResultCollection results = searcher.FindAll();

I've simplified the actual query I want to perform to the one you find in the code. But even with this generic query (it should return work on every AD?) it returns the error.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Rob Maas
  • 475
  • 2
  • 4
  • 13
  • 1
    `The authentication type is anonymous`. It's not, you set it to AuthenticationTypes.SecureSocketsLayer. Which identifies the sender so you'd better set Username + Password as well. – Hans Passant Apr 03 '12 at 13:19
  • Hi Hans, I've tried connecting to AD using a tool called **JXplorer**. It worked fine when set to SSL and no user name or password specified.. – Rob Maas Apr 03 '12 at 13:36
  • Well, keep your eyes on the ball. Do you still get E_FAIL when you specify a valid user? Does it work when you specify AuthenticationTypes.Anonymous? If it does then feel free to assume that JXplorer does something like simply falling back to Anonymous or using logged-in user credentials when no user is specified. – Hans Passant Apr 03 '12 at 13:41
  • Hans, I've tried both specifying a valid user and specifying AuthenticationTypes.Anonymous. Still the same non-descriptive error. Any other tricks up your sleeves? – Rob Maas Apr 03 '12 at 14:09
  • One very stupid reason why you might get this error, in my case: because the path was coming from a value I'd defined earlier into a variable, and I failed to notice that I'd accidentally string-literal quoted that value. :D Thought it was a privs issue, didn't notice the extremely obvious data issue. That is, I was passing in Path = "\"LDAP://...\"" by accident. Will give you the same error if you do that, as if it were a priv issue. Not a very useful error message, that's for sure. – neminem Jul 17 '23 at 18:08

4 Answers4

14

Finally!

It seems that an ASP.NET application does not have the rights (or doesn't know how) to examine the trusted certificate store at machine level. Since the certificate was self-signed the ASP.NET application refused to establish a connection.

I fixed the problem using custom certificate validation. The following code did the trick:

LdapConnection con = new LdapConnection(new LdapDirectoryIdentifier("server", port));
con.SessionOptions.SecureSocketLayer = true;
con.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(ServerCallback);
con.Credential = new NetworkCredential(String.Empty, String.Empty);
con.AuthType = AuthType.Basic;
con.Bind();

Since I am sure the certificate is valid, the ServerCallBack method looks like this:

public static bool ServerCallBack(LdapConnection connection, X509Certificate certificate)
{
    return true;
}

But you can always of course retrieve the certificate from the local machine and validate it.

The namespace used in this example is:

System.DirectoryServices.Protocols;

This is because the namespace:

System.DirectoryServices.DirectoryEntry

does not contain a method for custom certificate validation.

Thank you all for your help and time, and hopefully this will help someone in the future!

Rob Maas
  • 475
  • 2
  • 4
  • 13
  • 1
    +1, also I'll add for anyone that comes here is make sure that you don't need creds to connect to the ldap server, because you might. Also, to query ldap you will need to use the SearchRequest and SearchResponse classes, and SearchResponse doesn't have sorting so you will have to implement that on your own. I used this not b/c of the custom cert validation but `DirectoryEntry` was failing in WinPE, don't know why but this worked so whatever... – MDMoore313 Feb 14 '13 at 19:27
  • You can grant asp.net rights to access a cert in the machine store by opening the certificate mmc snap-in for the machine store, finding the cert you want to use, right-click > tasks > manage private keys & grant network service read right. This is useful for anything that uses certs, eg Identity Foundation, etc – Simon Halsey Dec 28 '13 at 11:50
  • I find your answer today, I had the same problem. The exception throwed is not intuitive, and a lost many time to find this solution. This post is very userfull, +1 or course. – h_s Jun 13 '14 at 17:50
  • This line `new VerifyServerCertificateCallback(ServerCallback);` results in [CS0103 The name 'ServerCallback' does not exist in the current context](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0103), despite that `ServerCallBack` is a public method in the same class. It seems that `con.SessionOptions.VerifyServerCertificate = Program.ServerCallBack` is ok. What am i missing? – surfmuggle Apr 20 '22 at 13:14
5

Depending on how your directory server(or elements on your network are configured) sometimes a simple change such as this will work (LDAP vs. LDAPS, but leave port number)

entry.Path = "LDAP://some.ldap.server:636";
curtisk
  • 19,950
  • 4
  • 55
  • 71
  • 2
    It helped me but not sure what is that specific AD configuration which causes such a behavior. Also one another interesting behavior is that it doesn't work when you give ldap protocol name in lower case in the URL i.e. "LDAP://some.ldap.server:636" works but "ldap://some.ldap.server:636" doesn't. I got freaked out on this specially. – RBT Jan 27 '16 at 09:03
  • Also it worked for me without setting the AuthenticationType property on DirectoryEntry object to AuthenticationTypes.SecureSocketsLayer but I'm not sure if even this will be consistent across all environments and topologies. – RBT Jan 27 '16 at 12:06
  • In my case AD server URL given to me was with LDAPS without port number but to fix the same error I have to remove secure (S) to have LDAP and add the port number e.g. LDAP://some.ldap.server:636 – Shahzad Aug 09 '23 at 09:21
3

As far as I remember This error means that there is a problem with the directory path name.

  1. Be sure that "server.domainName" is the CN in the certificate of your AD server.
  2. Be sure that "some.domainName" is well resolved add the resolution in your hosts file for the test
  3. Be sure that the "domainName" is well resolved add the resolution in your hosts file for the test
  4. Be sure that the public ke of the certificate authority that issue the server certificate is in your computer trusted root certification authority store.
  5. try doing like this :

DirectoryEntry entry = new DirectoryEntry("LDAPS://srventr2.societe.fr:636/DC=societe,DC=fr", "user", "password");

DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchRoot = entry;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = "(&(objectCategory=person)(objectClass=user))";
SearchResultCollection results = searcher.FindAll(); 
JPBlanc
  • 70,406
  • 17
  • 130
  • 175
  • Hi, the code works without erros when I run it in the same windows server machine; But I need to work with DirectoryEntry from remote machine; In this case its not working; Any other changes I need to do? – Dinesh Kumar P Jul 02 '15 at 11:06
  • 1
    "It's not working" is not enough for me to help you. – JPBlanc Jul 02 '15 at 11:17
  • Apologize; I am running the same code in a remote machine and I get "Server is not operational" as exception message; I found that widows server certificate is not validated in the remote machine; To validate certificate with 'LdapConnection' API, code is in this "post,http://stackoverflow.com/questions/12621256/connect-to-open-ldap-over-ssl"; My requirement is I need to validate the certificate and make use of "DirectoryEntry" API same like you; – Dinesh Kumar P Jul 02 '15 at 11:37
0

For me starting and stopping the corresponding IIS website solved the problem.