1

I have been stuck on this problem for weeks now. The application is a legacy .NET 4.0, and this is the code to connect to port 636:

LDAPModel message = new LDAPModel();

string ldapServer = ConfigurationManager.AppSettings["LDAP_host"];
string adminUsername = ConfigurationManager.AppSettings["LDAP_admin_username"];
string adminPassword = ConfigurationManager.AppSettings["LDAP_admin_password"];

int ldapPort = 636; //389

string UsersDN = "ou=users,o=data"; 

LdapConnection ldapConnection = null;
errorMessage = string.Empty;

try
{
    // Log: Attempting to create connection
    Log("Creating LDAP connection to server: " + ldapServer + " on port: " + ldapPort);

    if (CreateConnection(ref ldapConnection, ldapServer, ldapPort, adminUsername, adminPassword))
    {
        Log("LDAP connection created successfully. Attempting to bind with admin credentials.");

        try
        {
            ldapConnection.Bind();
            Log("Admin bind successful.");
        }
        catch (LdapException ex)
        {
            message.STATUS = false;
            message.VALUE = "Admin bind failed: " + ex.Message +
                            "\nError Code: " + ex.ErrorCode +
                            "\nServer Message: " + ex.ServerErrorMessage;

            if (ldapConnection != null)
            {
                ldapConnection.Dispose();
            }

            return message;
        }
    }
}

private bool CreateConnection(ref LdapConnection con, string server, int port, string username, string password) //this is for port 636
{
    try
    {
        //System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
                
        System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

        con = new LdapConnection(new LdapDirectoryIdentifier(server, port));
        con.SessionOptions.SecureSocketLayer = true;
        con.SessionOptions.VerifyServerCertificate = (connection, certificate) => true;

        // con.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(ServerCallBack);
        con.SessionOptions.ProtocolVersion = 3;
        con.AuthType = AuthType.Basic;

        con.Credential = new NetworkCredential(username, password);

        return true;
    }
    catch (LdapException)
    {
        return false;
    }
    catch (Exception)
    {
        return false;
    }
}

private bool CreateConnectionWithoutCert(ref LdapConnection con, string server, int port, string username, string password)//this is test for port 389
{
    try
    {
        con = new LdapConnection(new LdapDirectoryIdentifier(server, port));

        // ⚠️ Do not use SSL or StartTLS
        con.SessionOptions.SecureSocketLayer = false;

        // ⚠️ Do not use StartTLS — leave this out
        // con.SessionOptions.StartTransportLayerSecurity(null);

        con.SessionOptions.ProtocolVersion = 3;
        con.AuthType = AuthType.Basic;

        con.Credential = new NetworkCredential(username, password);

        return true;
    }
    catch (LdapException)
    {
        return false;
    }
    catch (Exception)
    {
        return false;
    }
}

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

I have shown you the relevant parts of the code. The principal, password and hostname come from the web.config file.

I know the issue is not the principal, password or hostname because when I tested with port 389, it works properly, I am able to bind properly. However to note, when I used the code of

con.SessionOptions.StartTransportLayerSecurity(null);

the bind failed and I get this error:

Check ldap credentials

The problem is port 636, the bind keeps failing and I keep getting:

Admin bind failed: Ldap server is unavailable.

Things I've tried:

  • Telnet to port 636, and the port shows that its open

  • I have gotten the certificates, one is self signed root cert and another is a leaf cert, I have placed the certs in the certlm and certmgr of both the trusted root and personal

  • The application only uses tls 1.2 because it's old

  • Apache directory was used to connect in the server to port 636, and it showed that it can connect with the certificate but also to note its using tls 1.3

  • I've used wireshark on the server, and it shows the client hello was sent from the application and it showed it was tls 1.2

I want to find the root of the problem, is it because of the certificates? I have asked the ldap team to give me a full certificate chain but they said a self signed cert is already enough. Is it because of the tls 1.2? Is there some code that I'm missing? I cannot figure out how to connect to port 636.

8
  • ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls if you're not on .NET 4.6 or lower then why are you messing with this? All it's going to do is disable TLS v1.1 to v1.3. Just remove that line. For .NET 4.6 or lower then use (SecurityProtocolType)3072 Commented Aug 15 at 11:25
  • Side note: your design of using a ref and a separate return true is very C-style, and not idiomatic for C#. Return the connection out of the function, and let functions bubble up to a suitable point to catch them. Put a using on the connection object to dispose it. Commented Aug 15 at 11:26
  • SSL, TLS 1.0, and TLS 1.1 are disabled on Windows since 2019. Net 4.0 will not support TLS 1.2. Commented Aug 15 at 12:21
  • @Charlieface I already changed to c# format, but the result is still the same, still error code 81 and that ldap server is unavailable. I checked in wireshark, the application can send the client hello in tls 1.2 Commented Aug 15 at 12:50
  • If you have ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls then it's not using TLS 1.2 Commented Aug 15 at 14:29

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.