go to  ForumEasy.com   
LdapPro
Home » Archive » Message


[Email To Friend][View in Live Context][prev topic « prev post | next post » next topic]
  end-to-end DIGEST-MD5 possible?
 
Subject: end-to-end DIGEST-MD5 possible?
Author: dferrero
In response to: When and Why DIGEST-MD5 Authentication Does Not Work?
Posted on: 02/23/2012 04:40:24 PM

SteveHD:
Thank you for this article. It actually helped me add support for DIGEST-MD5 to our product. Simpler than I thought - just needed to get the username in correct format.

I've been looking for a way to do end-to-end SASL LDAP Auth but haven't seen an API to do so. The current JNDI APIs seem to expect you to provide the username and password in plain-text format, then under the covers JNDI will perform the SASL encryption / Hash work.

In my scenario, a client app (which I do not have control over) wants to authenticate with my server application. My server application wants to allow these client apps to authenticate through AD / LDAP. In other words, I am trying to "pass-thru" the client's SASL auth request to AD / LDAP and based on the success of this bind, I allow the client to connect to my server app. Is this possible? If so how? If not, why not? :-)

It defeats the purpose of security if I have to force the client apps to use PLAIN / simple SASL and give me their password in clear-text in order for me to perform the bind on their behalf.


 

> On 06/30/2006 07:03:52 PM SteveHB wrote:


The Digest-MD5 mechanism is described in RFC 2831. In Digest-MD5, the LDAP server sends data that includes various authentication options that it is willing to support plus a special token to the LDAP client. The client responds by sending an encrypted response that indicates the authentication options that it has selected. The response is encrypted in such a way that proves that the client knows its password. The LDAP server then verifies the client's response.

As it can be seen, the major advantages of DIGEST-MD5 are:
1) prevent user password being sent across the Internet via clear text;
2) provide message integrity and confidentiality protection, after authentication

Apparently, the disadvantages are not trivial:
Digest authentication requires that the authenticating agent (usually the server) store some data derived from the user's password in certain forms to be able to retrieve the value of:
    H({ username-value,":", realm-value, ":", passwd }). 

without directly exposing the user's password. This is the source of why DIGEST-MD5 does not work for a lot of cases. (discussed later)


The following example shows how a client performs authentication using Digest-MD5 to an LDAP server.

/**
 * 
 * SaslDigestMD5JndiClient.java
 * Sample code to explore how and when DIGEST-MD5 authentication works.
 * 
 */
 
import java.util.Hashtable;
import javax.naming.directory.*;
import javax.naming.*;
 
public class SaslDigestMD5JndiClient
{
    public static void main (String[] args)
    {
        String bind_dn       = "testuser";
        String bind_password = "secret";
        String init_url      = "ldap://myserver.mydomain.com:389";
    
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, init_url);
        
        // Set the authentication mechanism to be DIGEST-MD5
        env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
        env.put(Context.SECURITY_PRINCIPAL, bind_dn);
        env.put(Context.SECURITY_CREDENTIALS, bind_password);
        /*
         * other environment properties are: 
         * javax.security.sasl.qop:  
         *    specifies list of qops:  "auth", "auth-int", "auth-conf"
         *    auth      -- authentication only;
         *    auth-int  -- authentication & subsequent message's integrity check
         *    auth-conf -- authentication & subsequent message's 
         *                 confidentiality enforcement
         *    default is "auth" 
         *    env.put("javax.security.sasl.qop", "auth");
         * javax.security.sasl.strength 
         *    specifies low/medium/high strength of encryption; 
         *    default is all available ciphers [high,medium,low]; 
         *    high means des3 or rc4 (128); medium des or rc4-56; low is rc4-40. 
         *    env.put("javax.security.sasl.strength","high");
         * javax.security.sasl.maxbuf 
         *    specifies max receive buf size; default is 65536 
         * javax.security.sasl.sendmaxbuffer 
         *    specifies max send buf size; default is 65536 
         */
        
        DirContext ctx = null;
        try {
            // Create the initial directory context
            ctx = new InitialDirContext(env);
        } catch (Exception e) {
            System.err.println("Authentication failed: " + e);
        }
        
        try{
            
            // Create the search controls         
            SearchControls searchCtls = new SearchControls();
            
            //Specify the attributes to return
            String returnedAtts[]={"sn","givenName","mail"};
            searchCtls.setReturningAttributes(returnedAtts);
            
            //Specify the search scope
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
 
            //specify the LDAP search filter
            String searchFilter = "(&(objectClass=user)(mail=*))";
 
            //Specify the Base for the search
            String searchBase = "dc=mydomain,dc=com";
 
            // Search for objects using the filter
            NamingEnumeration results = ctx.search(searchBase,searchFilter,searchCtls);
 
            //Loop through the search results
            while (results.hasMoreElements()) {
                SearchResult sr = (SearchResult)results.next();
                System.out.println("dn: " + sr.getName());
                 Attributes attrs = sr.getAttributes();
                System.out.println("attributes: " + attrs);
             }
            
             ctx.close();
 
        } catch (NamingException e) {
            System.err.println("Searching failed: " + e);
        }
    }
}


The above code has been testet against SunONE and Active Directory, testing scenarios will be discussed in very details but the failed outputs are very much the same like:

javax.naming.AuthenticationException: [LDAP: error code 49 - 8009030C: LdapErr: DSID-0C09043E, comment: AcceptSecurityContext error, data 0, vece
at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:2988)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2934)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2735)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2649)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:290)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:243)
at javax.naming.InitialContext.init(InitialContext.java:219)
at javax.naming.InitialContext.<init>(InitialContext.java:195)
at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:80)





References:

 


 
Powered by ForumEasy © 2002-2022, All Rights Reserved. | Privacy Policy | Terms of Use
 
Get your own forum today. It's easy and free.