locked
Connection to a secured LDAP (SSL) RRS feed

  • Question

  • User1831074503 posted

    Hi, 

    I can't connect my c# website to a LDAP server over SSL. When using ldap browsers, I can do it (they ask me to manually validate the certificate).

    When I do it in c#, I receive differents exceptions depending on my tests (unknown error, not operationnal server...)

    Note: I have no problem when I try to connect to a not SSL connection.

    If anyone could help me, this server is bindable for tests (ldapv3): 
    server: ldapclient.com 
    port: 389 
    authentication: anonymous

    or with SSL 
    server: ldapclient.com 
    port: 636 
    authentication: anonymous

    And there is one of the various codes I try:  


    public byte[] GetRecipientCertificateFromLDAPStore() 

    SearchResultCollection col; 
    DirectorySearcher searcher = new DirectorySearcher(); 
    string[] resultsFields = new string[] { "cn", "mail", "usercertificate;binary" }; 
    //Pass the IPAddress and the Port of the LDAP Server. 
    string[] textArray1 = new string[] { "LDAP://", "ldapclient.com", ":", "636", "" }; 
    searcher.SearchRoot = new DirectoryEntry(string.Concat(textArray1), null, null, AuthenticationTypes.SecureSocketsLayer); 
    searcher.SearchScope = System.DirectoryServices.SearchScope.Subtree; 
    searcher.PropertiesToLoad.AddRange(resultsFields); 
    searcher.Filter = string.Format("(&(cn={0})(mail={1}))", "* *", "* *"); 
    col = searcher.FindAll(); 



    X509Certificate2 certificate1 = new X509Certificate2(); 
    foreach (SearchResult result1 in col) 

    IEnumerator enumerator2; 
    try 

    enumerator2 = result1.GetDirectoryEntry().Properties["usercertificate;binary"].GetEnumerator(); 
    while (enumerator2.MoveNext()) 

    object obj1 = RuntimeHelpers.GetObjectValue(enumerator2.Current); 
    certificate1.Import((byte[])obj1); 
    //Can access different Properties for example: 
    //certificate1.Subject; 
    //certificate1.SerialNumber; 
    //certificate1.Version; 
    //certificate1.NotBefore; 
    //certificate1.NotAfter; 
    //certificate1.Issuer; 
    return certificate1.Export(X509ContentType.Cert); 



    catch { } 



    return null; 

    }


    Thanks for any help!

    Julien

    Wednesday, April 14, 2010 7:56 AM

All replies

  • User1831074503 posted

    Does anybody succeed to connect to ldapclient.com over SSL in c#?

    Please help me.

    Julien

    Wednesday, April 14, 2010 9:55 AM
  • User-571440000 posted

    Hi Julien,

       I am also looking for same task to connect to an LDAP server using SSL

     

    Have you succeeded in finding this out?

     

    Krishna   

    Monday, May 17, 2010 11:02 AM
  • User681375003 posted

    Hi,

    I'm also trying to conncect to LDAP with SSL. I need it to authenticate users. Somehow I got it working, but there are several things which do not work as I think they should: I cannot use LDAPS:// but only LDAP://, because it results in an unknown error. Anyway the connection is established via port 636 and seems to be encrypted when I look at it in wireshark.

    In addition the variable AuthenticationType seems to have no effect. The data which is transmitted is encrypted anyway.

    The final problem is that there is know way to check the certificate. I could only do it seperatly.

    Does anyone know how to fix any of my problems? Anyway my code works somehow and you can use it if you want to.

    Here it is:

    private String LDAP_ServerAddress = "ldap.xyz.com";
    private String LDAP_BaseDN = "ou=sub,o=xyz.com";
    
    /// <summary>
    /// This method authenticates a user with his password via LDAP
    /// </summary>
    /// <param name="user">User to authenticate</param>
    /// <param name="password">Users password</param>
    /// <returns>Whether user + password is correct</returns>
    public Boolean authenticateUser(String user, String password)
    {
    	//Create a directory entry with port 636 (LDAP SSL)
    	DirectoryEntry objDirEntry = new DirectoryEntry("LDAP://" + this.LDAP_ServerAddress + ":636/" + this.LDAP_BaseDN);     
    	//Add the username, it has to be the complete path
    	objDirEntry.Username = "uid="+user+",ou=sub,o=xyz.com";
    	//Add the users password
    	objDirEntry.Password = password;
    	//Authentication Type seems to have no effect 
    	objDirEntry.AuthenticationType = AuthenticationTypes.None;
    	try
    	{
    		//method to test the connection/username/password
    		object nativeObject = objDirEntry.NativeObject;             
    		objDirEntry.Close();
    	}
    	//catch exceptions(timeout, bad username or password)
    	catch (COMException exception)
    	{
    		//errorcode -2147023570 bad username or password
    		if (exception.ErrorCode == -2147023570) return false;
    
    		// errorcode -2147016646 -> timeout                
    		else throw new Exception("Exception in LDAPConenctor.cs Method: void authenticateUser(): " + exception.ToString(), exception);
    	}
    	return true;
    }
    
    

    Tuesday, June 1, 2010 6:17 AM
  • User31981750 posted

    Hi,

         I have the same problem. And I am using very similar code like yours for the SSL connection. However, it refuses to work for some certificate problem. Apparently the security certificate used by the LDAP server is not trusted by the client. I have imported every certificate into the trusted root store on the client, but the ASP.net application seems not to check against them. Do you know anything about it? How is your testing environment set up? Any suggestion?

     

    thanks.

     

    zheng 

    Friday, July 9, 2010 7:05 PM
  • User-571440000 posted

     private bool CreateConnection()
            {
                try
                {
                    con = new LdapConnection(new LdapDirectoryIdentifier(ConfigurationSettings.AppSettings["ServerName"].ToString()));
                    con.SessionOptions.SecureSocketLayer = true;
                    con.SessionOptions.ProtocolVersion = 3;
                    con.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(ServerCallback);
                    con.Credential = new NetworkCredential(_domainAndUserName, _pwd);
                    con.AuthType = AuthType.Basic;
                    con.Timeout = new TimeSpan(1, 0, 0);
                    return true;
                }
                catch (LdapException)
                {
                    return false;
                }
                catch (Exception)
                {
                    return false;
                }
            }
    
     public bool ServerCallback(LdapConnection connection, X509Certificate certificate)
            {
    ...return true/false;
    }
     public bool LDAPSAuthenticate(String username, String pwd)
            {
                username = username.Trim();
                try
                {
                    con.Bind();
                }
                catch (LdapException ex)
                {
                    throw new LdapException(ex.Message);
                }
                catch (DirectoryOperationException ex)
                {
                    throw new DirectoryOperationException(ex.Message);
                }
    
                try
                {
                    SearchRequest request = new SearchRequest(
                        UsersDN,
                        "(&(objectClass=person)(SAMAccountName=" + username + "))",
                        System.DirectoryServices.Protocols.SearchScope.Subtree
                        );
    
    
                    SearchResponse response = (SearchResponse)con.SendRequest(request);
    
    
                    if (response.Entries.Count == 0)
                    {
                        return false;
                    }
                    else
                    {
                        SearchResultEntry entry = response.Entries[0];
                        string dn = entry.DistinguishedName;
    
                        con.Credential = new NetworkCredential(dn, pwd);
                        con.Bind();
                        return true;
                    }
                }
                catch (DirectoryOperationException ex)
                {
                    throw new DirectoryOperationException(ex.Message);
                }
    
                catch (LdapException ex)
                {
                    throw new LdapException(ex.Message);
                }
                catch (Exception ex)
                {
                    throw new LdapException(ex.Message);
                }
            }


    I have used the above code and it is working fine for LDAP using SSL.  Please let me know if you need more information

     public bool LDAPSAuthenticate(String username, String pwd)
            {
                username = username.Trim();
                try
                {
                    con.Bind();
                }
                catch (LdapException ex)
                {
                    throw new LdapException(ex.Message);
                }
                catch (DirectoryOperationException ex)
                {
                    throw new DirectoryOperationException(ex.Message);
                }
                try
                {
                    SearchRequest request = new SearchRequest(
                        UsersDN,
                        "(&(objectClass=person)(SAMAccountName=" + username + "))",
                        System.DirectoryServices.Protocols.SearchScope.Subtree
                        );
                    SearchResponse response = (SearchResponse)con.SendRequest(request);
                    if (response.Entries.Count == 0)
                    {
                        return false;
                    }
                    else
                    {
                        SearchResultEntry entry = response.Entries[0];
                        string dn = entry.DistinguishedName;
                        con.Credential = new NetworkCredential(dn, pwd);
                        con.Bind();
                        return true;
                    }
                }
                catch (DirectoryOperationException ex)
                {
                    throw new DirectoryOperationException(ex.Message);
                }
                catch (LdapException ex)
                {
                    throw new LdapException(ex.Message);
                }
                catch (Exception ex)
                {
                    throw new LdapException(ex.Message);
                }
            }



    Saturday, July 17, 2010 10:56 PM
  • User924999067 posted

    Hi,

    I am trying to authenticate users through LDAP SSL.

    As far as i have understood,The different ways to connect to an AD and search is by using a directory entry object or by using a search request object.

    For LDAP SSL is it just enough to turn the AuthenticateType to SSL?

    What else should we do to enable SSL?Do we need to import any client certificates?

    could you please tell me any pre-requisites the client has to do to their AD for LDAPS?

    I have not really understood the servercall back?Is this used to check if the server has a valid certificate?

    From the product we just need to communicate to the AD securely,so what are the best ways to do it?

    Please clarify my doubts on LDAPS.

    Tuesday, November 30, 2010 8:10 AM
  • User1605197424 posted

    Your code seems to be exactly what I'm trying to do, but when I implement it on my system, it's not working.  It fails on the con.Bind() line saying "The LDAP server is unavailable."

    The way that I implemented it was I created a form with Server, Port, Username & Password.  When a user clicks the button I call the CreateConnection method and then the LDAPSAuthenticate() method.

    It appears to create the connection object properly.  The con object is not null at least.  I did notice that the con.SessionOptions.HostName & .DomainName are both null.  I'm not sure if they get populated after the Bind method.

    Everything works great when I use the DirectoryEntry class except I don't know how to ignore the Server Cert Verification, which I believe is what your code is supposed to fix.  Any ideas?  Thanks a ton!

     

    <form method="post" action="http://localhost:51723/Default.aspx" id="form1">
    </form>

     


    Monday, May 23, 2011 12:39 PM
  • User1386560551 posted

    This thread is a bit old, but I'm hoping someone might still respond as I am also running into this issue.  

    I tried the LdapConnection method specified above after the DirectorySearcher method failed to connect with SSL.  I built a windows forms application that was able to successfully connect, but when I move the code to ASP.NET it fails.  I wonder if there is a permission I need to grant to Network Services?

    Has anyone found a solution to this? 

    Friday, July 29, 2011 12:19 PM
  • User1386560551 posted

    I got it working for me.  I just had a bad variable in there. 

    Friday, July 29, 2011 6:02 PM
  • User1136858621 posted

    Hi,

    Can you share the flow / implementation code

    Thanks for the help

    Tuesday, September 13, 2011 8:23 AM
  • User-99942643 posted

    The following works great for LDAP authentication through SSL.:

    public static Boolean isUserCredentialsValid (string username, string password) {
                const int ldapErrorInvalidCredentials = 0x31;
                string activeDirectoryServer = "your.ad.server:636";
                string activeDirectpryDomain = "your.ad.server";
                try {
                    using (var ldapConnection = new LdapConnection(activeDirectoryServer)) {
                        var networkCredential = new NetworkCredential(username, password, activeDirectpryDomain);
                        ldapConnection.SessionOptions.SecureSocketLayer = true;
                        ldapConnection.AuthType = AuthType.Negotiate;
                        ldapConnection.Bind(networkCredential);
                    }
                    // If the bind succeeds, the credentials are valid
                    return true;
                }
                catch (LdapException ldapException) {
                    // Invalid credentials throw an exception with a specific error code
                    if (ldapException.ErrorCode.Equals(ldapErrorInvalidCredentials)) {
                        return false;
                    }
                    throw;
                }
            }

    You just need a reference to System.DirectoryServices.Protocols...

    Monday, August 15, 2016 9:20 PM
  • User-1736385833 posted

    Hi Koshera,

    i tried using your code but i am getting "A protocol error occurred." but credentials are correct might be i missed something. i am trying to run the code from locally. 

    i have just used the above code do i need to anything else ?

    I am new to this LDAP Service call and i don't have any idea about SSL, 

    Please advice what are the things i need to do to retrieve the user information from AD through LDAP SSL in .NET. 

    1. Will only the above Code works?

    2. Do i need to install any Certificates ? 

    3.  Our Application is  Windows Based Application 

    Thanks in advance! 

    regards, Ravi 

    Tuesday, May 2, 2017 8:24 AM