1

My requirement was to change the user password of AD. So, I created the LDAP SSL secure connection on the AD domain server by following https://bl.ocks.org/magnetikonline/0ccdabfec58eb1929c997d22e7341e45 successfully.

Using the ldp.exe tool (on the same AD server) I am able to connect with the SSL. This means LDAPS is enabled on the AD server.

Now I am trying to connect it from the ASP.NET Core application using the library Novell.Directory.Ldap which is on client-side using the following code:

public LdapConnection GetLDAPConnection(IOptions<ADConfiguration> _settings)
{
    LdapConnection connection = new LdapConnection { SecureSocketLayer = true };
    connection.Connect(_settings.Value.DomainIPAddress, _settings.Value.Port); //port is 636
    connection.Bind(_settings.Value.AdminDn, _settings.Value.Password);

    if (connection.Bound)
    {
        return connection;
    }

    return null;
}

The Connect method is throwing this error:

System.Security.Authentication.AuthenticationException: 'The remote certificate was rejected by the provided RemoteCertificateValidationCallback.'

Does the client machine also have settings for SSL? Or what else I am missing? Please help

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Varsh
  • 413
  • 9
  • 26
  • If you use ASP.NET Core you should take a look at `System.DirectoryServices` or `System.DirectoryServices.Protocols` which seems close of your `Novell.Directory.Ldap`. @Gabriel-Luci has already answered. The `LdapConnection.SessionOptions.VerifyServerCertificate` in `System.DirectoryServices.Protocols` can help you to validate the certificate. The callback has just to return `true`. – Hazrelle Dec 17 '21 at 00:26
  • ```System.DirectoryServices``` supports only windows. I want cross-platform. – Varsh Dec 17 '21 at 02:43
  • `System.DirectoryServices.Protocols` is cross platform. – Hazrelle Dec 17 '21 at 11:12

2 Answers2

1

I suspect your problem is using the IP address of the domain controller: _settings.Value.DomainIPAddress

SSL/TLS has two purposes: to encrypt the traffic, and to validate that the server is actually the server you want to be talking to. To address the second purpose, the domain name you use to connect must match the domain name in the certificate. In your case, when it validates the certificate, it sees that you connected to, let's say, 10.0.0.1, but the certificate it gets from the server says it is example.com and the validation fails because it doesn't match.

You will have to either:

  1. Change _settings.Value.DomainIPAddress to the domain name used in the certificate. If you don't have DNS setup for that domain name, you could add an entry in your hosts file.
  2. Tell LdapConnection to ignore certificate errors. The data will still be encrypted, but it won't validate the certificate (domain mismatch, expired cert, etc.). This is not recommended for a production application, but there is an example of that here: https://stackoverflow.com/a/67818854/1202807
Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • 1
    Using this library ```Novell.Directory.Ldap``` for option 1, if I try to connect using a domain name it returns an error ```SocketException: No such host is known. ``` . I got this error even without an SSL connection. For 2, I tried ```connection.UserDefinedServerCertValidationDelegate += (sender, certificate, chain, errors) => true;``` it runs successfully without validating the certificate. – Varsh Dec 17 '21 at 02:49
  • @Varsh "No such host is known" means a DNS issue. The domain name can't be resolved to an IP address. – Gabriel Luci Dec 17 '21 at 16:02
0

Below code worked for me to connect to AD using LDAPS

ldapConnection = new LdapConnection(new LdapDirectoryIdentifier("your.LDAPSserver.com", 636));

var networkCredential = new NetworkCredential("UsernameWithoutDomain", "yourPassword", "AD.yourDOMAIN.com");
ldapConnection.SessionOptions.SecureSocketLayer = true;
ldapConnection.SessionOptions.ProtocolVersion = 3;
ldapConnection.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(ServerCallback);
ldapConnection.AuthType = AuthType.Negotiate;
ldapConnection.Bind(networkCredential);
        
SearchRequest Srchrequest = new SearchRequest("CN=Users,DC=AD,DC=YOURCOMPANY,DC=COM", "mail=useremail@company.com", System.DirectoryServices.Protocols.SearchScope.Subtree);
SearchResponse SrchResponse = (SearchResponse)ldapConnection.SendRequest(Srchrequest);

// ServerCallback

private static bool ServerCallback(LdapConnection connection, X509Certificate certificate)
{
    return true;
}

Surprisingly it is also working when I am not using networkCredential and just using ldapConnection.Bind(); Seems it is using my local credentials as default on my local machine.

Himalaya Garg
  • 1,525
  • 18
  • 23
  • You can also do ldapConnection.UserDefinedServerCertValidationDelegate += new RemoteCertificateValidationCallback((sender, certificate, chain, errors) => true); If you want to save a few lines :D – ist_lion Sep 03 '22 at 17:07