Commits

hani  committed 9e6e57a

Patch from USER-69

  • Participants
  • Parent commits a312e6b

Comments (0)

Files changed (1)

File src/java/com/opensymphony/user/provider/ldap/LDAPCredentialsProvider.java

 import java.util.*;
 
 import javax.naming.AuthenticationException;
+import javax.naming.CommunicationException;
 import javax.naming.Context;
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
  * </ul>
  *
  * @author <a href="mailto:jeff@atlassian.com">Jeff Turner</a>
+ * @author <a href="mailto:andrzej_michalec@o2.pl">Andrzej Michalec</a>
  */
 public class LDAPCredentialsProvider implements CredentialsProvider {
     //~ Static fields/initializers /////////////////////////////////////////////
             return true;
         }
 
-        DirContext ctx = null;
+        DirContext ctx;
 
         try {
             ctx = new InitialDirContext(env);
             log.debug("Doing initial search: " + "username='" + env.get(Context.SECURITY_PRINCIPAL) + "', password='" + env.get(Context.SECURITY_CREDENTIALS) + "', base='" + searchBase + "', filter='" + filterBuffer + "'");
         }
 
-        NamingEnumeration results = null;
+        NamingEnumeration results;
 
         try {
             results = ctx.search(searchBase, filterBuffer.toString(), ctls);
             return tryOtherCredentialsProviders(name, password);
         }
 
-        StringBuffer dnBuffer = new StringBuffer();
+        StringBuffer dnBuffer;
 
         try {
             if (log.isDebugEnabled()) {
                 }
             }
 
+            // Lotus Domino R5 LDAP server drops socket connection when
+            // switching credentials! First context (ctx) is used to iterate
+            // through results and only second context (ctx2) is used
+            // to authorize. Context ctx will survive whether ctx2 is dropped
+            // by Domino or not.
+            DirContext ctx2 = new InitialDirContext(ctx.getEnvironment());
+
             while ((results != null) && results.hasMore()) {
                 SearchResult sr = (SearchResult) results.next();
+                dnBuffer = new StringBuffer();
                 dnBuffer.append(sr.getName());
                 dnBuffer.append(",");
                 dnBuffer.append(searchBase);
 
                 try {
-                    ctx.removeFromEnvironment(Context.SECURITY_PRINCIPAL);
-                    ctx.removeFromEnvironment(Context.SECURITY_CREDENTIALS);
-                    ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, dnBuffer.toString());
-                    ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
+                    ctx2.removeFromEnvironment(Context.SECURITY_PRINCIPAL);
+                    ctx2.removeFromEnvironment(Context.SECURITY_CREDENTIALS);
+                    ctx2.addToEnvironment(Context.SECURITY_PRINCIPAL, dnBuffer.toString());
+                    ctx2.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
                 } catch (NamingException e) {
                     log.error("Connected and searched LDAP, but encountered unexpected error when switching authentication details.", e);
 
-                    return tryOtherCredentialsProviders(name, password);
+                    continue;
                 }
 
                 ctls = new SearchControls();
                 }
 
                 try {
-                    ctx.search(dnBuffer.toString(), filterBuffer.toString(), ctls);
+                    try {
+                        ctx2.search(dnBuffer.toString(), filterBuffer.toString(), ctls);
+                    } catch (CommunicationException ex) {
+                        log.info("Second phase connection failed. Trying to reconnect...");
+
+                        // Second context (ctx2) lost; we recreate this context and try once more.
+                        ctx2 = new InitialDirContext(ctx2.getEnvironment());
+                        ctx2.search(dnBuffer.toString(), filterBuffer.toString(), ctls);
+                    }
                 } catch (AuthenticationException ae) {
                     if (log.isDebugEnabled()) {
-                        log.debug("User with dn '" + dnBuffer + "' found, but wrong password entered.");
+                        log.debug("User with dn '" + dnBuffer + "' found, but authentication failed.");
                     }
 
-                    return false;
+                    continue;
                 } catch (NamingException e) {
                     log.error("Initial connect and search successful, but second phase connection to LDAP as '" + dnBuffer + "' failed.", e);
 
-                    return tryOtherCredentialsProviders(name, password);
+                    continue;
                 }
 
                 if (log.isDebugEnabled()) {
 
     public boolean init(Properties properties) {
         if (log.isDebugEnabled()) {
-            log.debug("LDAPCredentialsProvider $Revision: 1.4 $ initializing");
+            log.debug("LDAPCredentialsProvider $Revision: 1.5 $ initializing");
         }
 
         env = new Hashtable(properties);