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.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tlsif 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)3072refand a separatereturn trueis 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 ausingon the connection object to dispose it.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tlsthen it's not using TLS 1.2