You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@manifoldcf.apache.org by ml...@apache.org on 2012/11/05 15:43:39 UTC

svn commit: r1405811 - in /manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main: java/org/apache/manifoldcf/authorities/authorities/ldap/ native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/

Author: mlizewski
Date: Mon Nov  5 14:43:38 2012
New Revision: 1405811

URL: http://svn.apache.org/viewvc?rev=1405811&view=rev
Log:
CONNECTORS-563 implementation

Modified:
    manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java
    manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_en_US.properties
    manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_ja_JP.properties

Modified: manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java?rev=1405811&r1=1405810&r2=1405811&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java (original)
+++ manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java Mon Nov  5 14:43:38 2012
@@ -7,9 +7,9 @@
  * "License"); you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
-* http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  * 
-* Unless required by applicable law or agreed to in writing, software
+ * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  * License for the specific language governing permissions and limitations under
@@ -17,17 +17,16 @@
  */
 package org.apache.manifoldcf.authorities.authorities.ldap;
 
-import org.apache.manifoldcf.core.interfaces.*;
-import org.apache.manifoldcf.agents.interfaces.*;
-import org.apache.manifoldcf.authorities.interfaces.*;
-import org.apache.manifoldcf.authorities.system.Logging;
-import org.apache.manifoldcf.authorities.system.ManifoldCF;
-
 import java.io.*;
 import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import javax.naming.*;
-import javax.naming.ldap.*;
 import javax.naming.directory.*;
+import javax.naming.ldap.*;
+import org.apache.manifoldcf.authorities.interfaces.*;
+import org.apache.manifoldcf.authorities.system.ManifoldCF;
+import org.apache.manifoldcf.core.interfaces.*;
 import org.apache.manifoldcf.ui.util.Encoder;
 
 /**
@@ -66,7 +65,15 @@ public class LDAPAuthority extends org.a
   private String groupBase;
   private String groupSearch;
   private String groupNameAttr;
-    
+  private boolean groupMemberDN;
+  private boolean addUserRecord;
+  private String userNameAttr;
+
+  private long responseLifetime = 60000L; //60sec
+  private int LRUsize = 1000;
+  /** Cache manager. */
+  private ICacheManager cacheManager = null;
+
   /**
    * Constructor.
    */
@@ -74,6 +81,16 @@ public class LDAPAuthority extends org.a
   }
 
   /**
+   * Set thread context.
+   */
+  @Override
+  public void setThreadContext(IThreadContext tc)
+    throws ManifoldCFException {
+    super.setThreadContext(tc);
+    cacheManager = CacheManagerFactory.make(tc);
+  }
+
+  /**
    * Connect. The configuration parameters are included.
    *
    * @param configParams are the configuration parameters for this connection.
@@ -82,6 +99,20 @@ public class LDAPAuthority extends org.a
   public void connect(ConfigParams configParams) {
     super.connect(configParams);
     parameters = configParams;
+
+    // We get the parameters here, so we can check them in case they are missing
+    serverName = configParams.getParameter( "ldapServerName" );
+    serverPort = configParams.getParameter( "ldapServerPort" );
+    serverBase = configParams.getParameter( "ldapServerBase" );
+
+    userBase = configParams.getParameter( "ldapUserBase" );
+    userSearch = configParams.getParameter( "ldapUserSearch" );
+    groupBase = configParams.getParameter( "ldapGroupBase" );
+    groupSearch = configParams.getParameter( "ldapGroupSearch" );
+    groupNameAttr = configParams.getParameter( "ldapGroupNameAttr" );
+    userNameAttr = configParams.getParameter( "ldapUserNameAttr" );
+    groupMemberDN = "1".equals(getParam(configParams, "ldapGroupMemberDn", ""));
+    addUserRecord = "1".equals(getParam(configParams, "ldapAddUserRecord", ""));
   }
 
   // All methods below this line will ONLY be called if a connect() call succeeded
@@ -93,37 +124,54 @@ public class LDAPAuthority extends org.a
   protected LdapContext getSession()
     throws ManifoldCFException
   {
-    // We get the parameters here, so we can check them in case they are missing
-    serverName = parameters.getParameter( "ldapServerName" );
-    if (serverName == null || serverName.length() == 0)
+    if (serverName == null || serverName.length() == 0) {
       throw new ManifoldCFException("Server name parameter missing but required");
-    serverPort = parameters.getParameter( "ldapServerPort" );
-    if (serverPort == null || serverPort.length() == 0)
+    }
+    if (serverPort == null || serverPort.length() == 0) {
       throw new ManifoldCFException("Server port parameter missing but required");
-    serverBase = parameters.getParameter( "ldapServerBase" );
-    if (serverBase == null)
+    }
+    if (serverBase == null) {
       throw new ManifoldCFException("Server base parameter missing but required");
-
-    userBase = parameters.getParameter( "ldapUserBase" );
-    if (userBase == null)
+    }
+    if (userBase == null) {
       throw new ManifoldCFException("User base parameter missing but required");
-    userSearch = parameters.getParameter( "ldapUserSearch" );
-    if (userSearch == null || userSearch.length() == 0)
+    }
+    if (userSearch == null || userSearch.length() == 0) {
       throw new ManifoldCFException("User search expression missing but required");
-    groupBase = parameters.getParameter( "ldapGroupBase" );
-    if (groupBase == null)
+    }
+    if (groupBase == null) {
       throw new ManifoldCFException("Group base parameter missing but required");
-    groupSearch = parameters.getParameter( "ldapGroupSearch" );
-    if (groupSearch == null || groupSearch.length() == 0)
+    }
+    if (groupSearch == null || groupSearch.length() == 0) {
       throw new ManifoldCFException("Group search expression missing but required");
-    groupNameAttr = parameters.getParameter( "ldapGroupNameAttr" );
-    if (groupNameAttr == null || groupNameAttr.length() == 0)
+    }
+    if (groupNameAttr == null || groupNameAttr.length() == 0) {
       throw new ManifoldCFException("Group name attribute missing but required");
+    }
+    if (userNameAttr == null || userNameAttr.length() == 0) {
+      throw new ManifoldCFException("User name attribute missing but required");
+    }
 
     Hashtable env = new Hashtable();
     env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
     env.put(Context.PROVIDER_URL, "ldap://"+serverName+":"+serverPort+"/"+serverBase);
 
+    //get bind credentials
+    String bindUser = getParam(parameters, "ldapBindUser", "");
+    String bindPass = "";
+    try {
+      bindPass = ManifoldCF.deobfuscate(getParam(parameters, "ldapBindPass", ""));
+    } catch (ManifoldCFException ex) {
+      if (!bindUser.isEmpty()) {
+        Logger.getLogger(LDAPAuthority.class.getName()).log(Level.SEVERE, "Deobfuscation error", ex);
+      }
+    }
+    if (!bindUser.isEmpty()) {
+      env.put(Context.SECURITY_AUTHENTICATION, "simple");
+      env.put(Context.SECURITY_PRINCIPAL, bindUser);
+      env.put(Context.SECURITY_CREDENTIALS, bindPass);
+    }
+
     try {
       if (session == null) {
         session = new InitialLdapContext(env, null);
@@ -145,7 +193,6 @@ public class LDAPAuthority extends org.a
       sessionExpirationTime = -1L;
       throw new ManifoldCFException("Naming error: "+e.getMessage(),e);
     }
-
   }
     
   /**
@@ -155,7 +202,7 @@ public class LDAPAuthority extends org.a
   public String check()
     throws ManifoldCFException {
     disconnectSession();
-    LdapContext session = getSession();
+    LdapContext fSession = getSession();
     // MHL for a real check of all the search etc.
     return super.check();
   }
@@ -166,15 +213,15 @@ public class LDAPAuthority extends org.a
   @Override
   public void poll()
     throws ManifoldCFException {
-    if (session != null && System.currentTimeMillis() > sessionExpirationTime)
+    if (session != null && System.currentTimeMillis() > sessionExpirationTime) {
       disconnectSession();
+    }
     super.poll();
   }
 
   /** Disconnect a session.
   */
-  protected void disconnectSession()
-  {
+  protected void disconnectSession() {
     if (session != null) {
       try {
         session.close();
@@ -184,15 +231,6 @@ public class LDAPAuthority extends org.a
       session = null;
       sessionExpirationTime = -1L;
     }
-    
-    serverName = null;
-    serverPort = null;
-    serverBase = null;
-    userBase = null;
-    userSearch = null;
-    groupBase = null;
-    groupSearch = null;
-    groupNameAttr = null;
   }
     
   /**
@@ -206,6 +244,24 @@ public class LDAPAuthority extends org.a
     super.disconnect();
   }
 
+  protected String createCacheConnectionString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(serverName).append(":").append(serverPort).append("/").append(serverBase);
+    return sb.toString();
+  }
+
+  protected String createUserSearchString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(userBase).append("|").append(userSearch).append("|").append(userNameAttr).append("|").append(addUserRecord ? 'Y' : 'N');
+    return sb.toString();
+  }
+
+  protected String createGroupSearchString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(groupBase).append("|").append(groupSearch).append("|").append(groupNameAttr).append("|").append(groupMemberDN ? 'Y' : 'N');
+    return sb.toString();
+  }
+  
   /**
   * Obtain the access tokens for a given user name.
   *
@@ -217,16 +273,63 @@ public class LDAPAuthority extends org.a
   @Override
   public AuthorizationResponse getAuthorizationResponse(String userName)
     throws ManifoldCFException {
+    
+    getSession();
+    // Construct a cache description object
+    ICacheDescription objectDescription = new LdapAuthorizationResponseDescription(userName,
+      createCacheConnectionString(), createUserSearchString(), createGroupSearchString(), this.responseLifetime, this.LRUsize);
+
+    // Enter the cache
+    ICacheHandle ch = cacheManager.enterCache(new ICacheDescription[]{objectDescription}, null, null);
+    try {
+      ICacheCreateHandle createHandle = cacheManager.enterCreateSection(ch);
+      try {
+        // Lookup the object
+        AuthorizationResponse response = (AuthorizationResponse) cacheManager.lookupObject(createHandle, objectDescription);
+        if (response != null) {
+          return response;
+        }
+        // Create the object.
+        response = getAuthorizationResponseUncached(userName);
+        // Save it in the cache
+        cacheManager.saveObject(createHandle, objectDescription, response);
+        // And return it...
+        return response;
+      } finally {
+        cacheManager.leaveCreateSection(createHandle);
+      }
+    } finally {
+      cacheManager.leaveCache(ch);
+    }
+  }
+
+  protected AuthorizationResponse getAuthorizationResponseUncached(String userName)
+    throws ManifoldCFException {
     LdapContext session = getSession();
     try {
-      //Get DistinguishedName (for this method we are using DomainPart as a searchBase ie: DC=qa-ad-76,DC=metacarta,DC=com")
-      String usrDN = getDistinguishedName(session, userName);
-      if (usrDN == null) {
+      //find user in LDAP tree
+      SearchResult usrRecord = getUserEntry(session, userName);
+      if (usrRecord == null) {
         return userNotFoundResponse;
       }
 
+      ArrayList theGroups = new ArrayList();
+
+      String usrName = userName;
+      if (userNameAttr != null && !"".equals(userNameAttr)) {
+        if (usrRecord.getAttributes() != null) {
+          Attribute attr = usrRecord.getAttributes().get(userNameAttr);
+          if (attr != null) {
+            usrName = attr.get().toString();
+          }
+        }
+      }
+      if (addUserRecord) {
+        theGroups.add(usrName);
+      }
+
       //specify the LDAP search filter
-      String searchFilter = groupSearch.replaceAll( "\\{0\\}", ldapEscape(usrDN));
+      String searchFilter = groupSearch.replaceAll("\\{0\\}", escapeLDAPSearchFilter(groupMemberDN ? usrRecord.getNameInNamespace() : usrName));
       SearchControls searchCtls = new SearchControls();
       searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
       String returnedAtts[] = {groupNameAttr};
@@ -235,8 +338,6 @@ public class LDAPAuthority extends org.a
       //Search for tokens.  Since every user *must* have a SID, the "no user" detection should be safe.
       NamingEnumeration answer = session.search(groupBase, searchFilter, searchCtls);
 
-      ArrayList theGroups = new ArrayList();
-        
       while (answer.hasMoreElements()) {
         SearchResult sr = (SearchResult) answer.next();
         Attributes attrs = sr.getAttributes();
@@ -414,15 +515,28 @@ public class LDAPAuthority extends org.a
   @Override
   public void outputConfigurationBody(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters, String tabName)
     throws ManifoldCFException, IOException {
-    String serverName = getParam( parameters, "ldapServerName", "");
-    String serverPort = getParam( parameters, "ldapServerPort", "389");
-    String serverBase = getParam( parameters, "ldapServerBase", "");
-    String userBase = getParam( parameters, "ldapUserBase", "ou=People" );
-    String userSearch = getParam( parameters, "ldapUserSearch", "(&(objectClass=inetOrgPerson)(uid={0}))" );
-    String groupBase = getParam( parameters, "ldapGroupBase", "ou=Groups" );
-    String groupSearch = getParam( parameters, "ldapGroupSearch", "(&(objectClass=groupOfNames)(member={0}))" );
-    String groupNameAttr = getParam( parameters, "ldapGroupNameAttr", "cn" );
-        
+    String fServerName = getParam( parameters, "ldapServerName", "");
+    String fServerPort = getParam( parameters, "ldapServerPort", "389");
+    String fServerBase = getParam( parameters, "ldapServerBase", "");
+    
+    String fUserBase = getParam( parameters, "ldapUserBase", "ou=People" );
+    String fUserSearch = getParam( parameters, "ldapUserSearch", "(&(objectClass=inetOrgPerson)(uid={0}))" );
+    String fUserNameAttr = getParam(parameters, "ldapUserNameAttr", "uid");
+    boolean fAddUserRecord = "1".equals(getParam(parameters, "ldapAddUserRecord", ""));
+    
+    String fGroupBase = getParam( parameters, "ldapGroupBase", "ou=Groups" );
+    String fGroupSearch = getParam( parameters, "ldapGroupSearch", "(&(objectClass=groupOfNames)(member={0}))" );
+    String fGroupNameAttr = getParam( parameters, "ldapGroupNameAttr", "cn" );
+    boolean fGroupMemberDN = "1".equals(getParam(parameters, "ldapGroupMemberDn", ""));
+    
+    String fBindUser = getParam(parameters, "ldapBindUser", "");
+    String fBindPass = "";
+    try {
+      fBindPass = ManifoldCF.deobfuscate(getParam(parameters, "ldapBindPass", ""));
+    } catch (ManifoldCFException ex) {
+      //ignore
+    }
+
     if (tabName.equals(Messages.getString(locale,"LDAP.LDAP"))) {
       out.print(
 "<table class=\"displaytable\">\n"+
@@ -430,55 +544,87 @@ public class LDAPAuthority extends org.a
                     
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPServerNameColon")+"</nobr></td>\n"+
-"  <td class=\"value\"><input type=\"text\" size=\"32\" name=\"ldapServerName\" value=\""+Encoder.attributeEscape(serverName)+"\"/></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"32\" name=\"ldapServerName\" value=\""+Encoder.attributeEscape(fServerName)+"\"/></td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPServerPortColon")+"</nobr></td>\n"+
-"  <td class=\"value\"><input type=\"text\" size=\"5\" name=\"ldapServerPort\" value=\""+Encoder.attributeEscape(serverPort)+"\"/></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"5\" name=\"ldapServerPort\" value=\""+Encoder.attributeEscape(fServerPort)+"\"/></td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPServerBaseColon")+"</nobr></td>\n"+
-"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapServerBase\" value=\""+Encoder.attributeEscape(serverBase)+"\"/></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapServerBase\" value=\""+Encoder.attributeEscape(fServerBase)+"\"/></td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPBindUserColon")+"</nobr></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapBindUser\" value=\""+Encoder.attributeEscape(fBindUser)+"\"/></td>\n"+
+" </tr>\n"+
+
+" <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPBindPasswordColon")+"</nobr></td>\n"+
+"  <td class=\"value\"><input type=\"password\" size=\"64\" name=\"ldapBindPass\" value=\""+Encoder.attributeEscape(fBindPass)+"\"/></td>\n"+
+" </tr>\n"+
+
+" <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+
+" <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.UserSearchBaseColon")+"</nobr></td>\n"+
-"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapUserBase\" value=\""+Encoder.attributeEscape(userBase)+"\"/></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapUserBase\" value=\""+Encoder.attributeEscape(fUserBase)+"\"/></td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.UserSearchFilterColon")+"</nobr></td>\n"+
-"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapUserSearch\" value=\""+Encoder.attributeEscape(userSearch)+"\"/></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapUserSearch\" value=\""+Encoder.attributeEscape(fUserSearch)+"\"/></td>\n"+
+" </tr>\n"+
+
+" <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.AddUserAuthColon")+"</nobr></td>\n"+
+"  <td class=\"value\"><input type=\"checkbox\" value=\"1\" name=\"ldapAddUserRecord\" " + (fAddUserRecord ? "checked=\"true\"" : "") + "/></td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.UserNameAttrColon")+"</nobr></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapUserNameAttr\" value=\"" + Encoder.attributeEscape(fUserNameAttr) + "\"/></td>\n"+
+" </tr>\n"+
+
+" <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n" +
+" <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.GroupSearchBaseColon")+"</nobr></td>\n"+
-"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapGroupBase\" value=\""+Encoder.attributeEscape(groupBase)+"\"/></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapGroupBase\" value=\""+Encoder.attributeEscape(fGroupBase)+"\"/></td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.GroupSearchFilterColon")+"</nobr></td>\n"+
-"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapGroupSearch\" value=\""+Encoder.attributeEscape(groupSearch)+"\"/></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapGroupSearch\" value=\""+Encoder.attributeEscape(fGroupSearch)+"\"/></td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.GroupNameAttributeColon")+"</nobr></td>\n"+
-"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapGroupNameAttr\" value=\""+Encoder.attributeEscape(groupNameAttr)+"\"/></td>\n"+
+"  <td class=\"value\"><input type=\"text\" size=\"64\" name=\"ldapGroupNameAttr\" value=\""+Encoder.attributeEscape(fGroupNameAttr)+"\"/></td>\n"+
+" </tr>\n"+
+
+" <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.GroupMemberDnColon")+"</nobr></td>\n"+
+"  <td class=\"value\"><input type=\"checkbox\" value=\"1\" name=\"ldapGroupMemberDn\" " + (fGroupMemberDN ? "checked=\"true\"" : "") + "/></td>\n"+
 " </tr>\n"+
 
 "</table>\n"
       );
     } else {
-      out.print( "<input type=\"hidden\" name=\"ldapServerName\" value=\""+Encoder.attributeEscape(serverName)+"\"/>\n");
-      out.print( "<input type=\"hidden\" name=\"ldapServerPort\" value=\""+Encoder.attributeEscape(serverPort)+"\"/>\n");
-      out.print( "<input type=\"hidden\" name=\"ldapServerBase\" value=\""+Encoder.attributeEscape(serverBase)+"\"/>\n");
-      out.print( "<input type=\"hidden\" name=\"ldapUserBase\" value=\""+Encoder.attributeEscape(userBase)+"\"/>\n");
-      out.print( "<input type=\"hidden\" name=\"ldapUserSearch\" value=\""+Encoder.attributeEscape(userSearch)+"\"/>\n");
-      out.print( "<input type=\"hidden\" name=\"ldapGroupBase\" value=\""+Encoder.attributeEscape(groupBase)+"\"/>\n");
-      out.print( "<input type=\"hidden\" name=\"ldapGroupSearch\" value=\""+Encoder.attributeEscape(groupSearch)+"\"/>\n");
-      out.print( "<input type=\"hidden\" name=\"ldapGroupNameAttr\" value=\""+Encoder.attributeEscape(groupNameAttr)+"\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapServerName\" value=\"" + Encoder.attributeEscape(fServerName) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapServerPort\" value=\"" + Encoder.attributeEscape(fServerPort) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapServerBase\" value=\"" + Encoder.attributeEscape(fServerBase) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapBindUser\" value=\"" + Encoder.attributeEscape(fBindUser) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapBindPass\" value=\"" + Encoder.attributeEscape(fBindPass) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapUserBase\" value=\"" + Encoder.attributeEscape(fUserBase) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapUserSearch\" value=\"" + Encoder.attributeEscape(fUserSearch) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapGroupBase\" value=\"" + Encoder.attributeEscape(fGroupBase) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapGroupSearch\" value=\"" + Encoder.attributeEscape(fGroupSearch) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapGroupNameAttr\" value=\"" + Encoder.attributeEscape(fGroupNameAttr) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapUserNameAttr\" value=\"" + Encoder.attributeEscape(fUserNameAttr) + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapAddUserRecord\" value=\"" + (fAddUserRecord ? "1" : "0") + "\"/>\n");
+      out.print("<input type=\"hidden\" name=\"ldapGroupMemberDn\" value=\"" + (fGroupMemberDN ? "1" : "0") + "\"/>\n");
     }
   }
 
@@ -499,6 +645,14 @@ public class LDAPAuthority extends org.a
     return true;
   }
 
+  private void copyParam2(IPostParameters variableContext, ConfigParams parameters, String name) {
+    String val = variableContext.getParameter(name);
+    if (val == null) {
+      val = "";
+    }
+    parameters.setParameter(name, val);
+  }
+
   /**
   * Process a configuration post. This method is called at the start of the
   * authority connector's configuration page, whenever there is a possibility
@@ -523,9 +677,20 @@ public class LDAPAuthority extends org.a
     copyParam(variableContext, parameters, "ldapServerBase" );
     copyParam(variableContext, parameters, "ldapUserBase" );
     copyParam(variableContext, parameters, "ldapUserSearch" );
+    copyParam(variableContext, parameters, "ldapUserNameAttr" );
     copyParam(variableContext, parameters, "ldapGroupBase" );
     copyParam(variableContext, parameters, "ldapGroupSearch" );
     copyParam(variableContext, parameters, "ldapGroupNameAttr" );
+    
+    copyParam2(variableContext, parameters, "ldapGroupMemberDn");
+    copyParam2(variableContext, parameters, "ldapAddUserRecord");
+    copyParam2(variableContext, parameters, "ldapBindUser");
+    String bindPass = variableContext.getParameter("ldapBindPass");
+    if (bindPass == null) {
+      bindPass = "";
+    }
+    parameters.setParameter("ldapBindPass", ManifoldCF.obfuscate(bindPass));
+
     return null;
   }
 
@@ -544,57 +709,88 @@ public class LDAPAuthority extends org.a
   @Override
   public void viewConfiguration(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters)
     throws ManifoldCFException, IOException {
-    String serverName = getViewParam( parameters, "ldapServerName" );
-    String serverPort = getViewParam( parameters, "ldapServerPort" );
-    String serverBase = getViewParam( parameters, "ldapServerBase" );
-
-    String userBase = getViewParam( parameters, "ldapUserBase" );
-    String userSearch = getViewParam( parameters, "ldapUserSearch" );
-    String groupBase = getViewParam( parameters, "ldapGroupBase" );
-    String groupSearch = getViewParam( parameters, "ldapGroupSearch" );
-    String groupNameAttr = getViewParam( parameters, "ldapGroupNameAttr" );
+    String f_serverName = getViewParam( parameters, "ldapServerName" );
+    String f_serverPort = getViewParam( parameters, "ldapServerPort" );
+    String f_serverBase = getViewParam( parameters, "ldapServerBase" );
+    String f_bindUser = getViewParam(parameters, "ldapBindUser");
+
+    String f_userBase = getViewParam( parameters, "ldapUserBase" );
+    String f_userSearch = getViewParam( parameters, "ldapUserSearch" );
+    String f_groupBase = getViewParam( parameters, "ldapGroupBase" );
+    String f_groupSearch = getViewParam( parameters, "ldapGroupSearch" );
+    String f_groupNameAttr = getViewParam( parameters, "ldapGroupNameAttr" );
+    
+    String f_userNameAttr = getViewParam(parameters, "ldapUserNameAttr");
+    boolean f_groupMemberDN = "1".equals(getViewParam(parameters, "ldapGroupMemberDn"));
+    boolean f_addUserRecord = "1".equals(getViewParam(parameters, "ldapAddUserRecord"));
+
     out.print(
 "<table class=\"displaytable\">\n"+
 " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+
                     
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPServerNameColon")+"</nobr></td>\n"+
-"  <td class=\"value\">"+Encoder.bodyEscape(serverName)+"</td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_serverName)+"</td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPServerPortColon")+"</nobr></td>\n"+
-"  <td class=\"value\">"+Encoder.bodyEscape(serverPort)+"</td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_serverPort)+"</td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPServerBaseColon")+"</nobr></td>\n"+
-"  <td class=\"value\">"+Encoder.bodyEscape(serverBase)+"</td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_serverBase)+"</td>\n"+
+" </tr>\n"+
+
+" <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPBindUserColon")+"</nobr></td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_bindUser)+"</td>\n"+
+" </tr>\n"+
+
+" <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.LDAPBindPasswordColon")+"</nobr></td>\n"+
+"  <td class=\"value\">*******</td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.UserSearchBaseColon")+"</nobr></td>\n"+
-"  <td class=\"value\">"+Encoder.bodyEscape(userBase)+"</td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_userBase)+"</td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.UserSearchFilterColon")+"</nobr></td>\n"+
-"  <td class=\"value\">"+Encoder.bodyEscape(userSearch)+"</td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_userSearch)+"</td>\n"+
+" </tr>\n"+
+
+" <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.AddUserAuthColon")+"</nobr></td>\n"+
+"  <td class=\"value\">" + (f_addUserRecord ? "Y" : "N") + "</td>\n"+
+" </tr>\n"+
+
+" <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.UserNameAttrColon")+"</nobr></td>\n"+
+"  <td class=\"value\">" + Encoder.bodyEscape(f_userNameAttr) + "</td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.GroupSearchBaseColon")+"</nobr></td>\n"+
-"  <td class=\"value\">"+Encoder.bodyEscape(groupBase)+"</td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_groupBase)+"</td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.GroupSearchFilterColon")+"</nobr></td>\n"+
-"  <td class=\"value\">"+Encoder.bodyEscape(groupSearch)+"</td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_groupSearch)+"</td>\n"+
 " </tr>\n"+
 
 " <tr>\n"+
 "  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.GroupNameAttributeColon")+"</nobr></td>\n"+
-"  <td class=\"value\">"+Encoder.bodyEscape(groupNameAttr)+"</td>\n"+
+"  <td class=\"value\">"+Encoder.bodyEscape(f_groupNameAttr)+"</td>\n"+
+" </tr>\n"+
+
+" <tr>\n"+
+"  <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"LDAP.GroupMemberDnColon")+"</nobr></td>\n"+
+"  <td class=\"value\">"+(f_groupMemberDN?"Y":"N")+"</td>\n"+
 " </tr>\n"+
 
 "</table>\n"
@@ -603,28 +799,25 @@ public class LDAPAuthority extends org.a
 
   // Protected methods
   /**
-  * Obtain the DistinguishedName for a given user logon name.
-  *
-  * @param ctx is the ldap context to use.
-  * @param userName (Domain Logon Name) is the user name or identifier.
-  * @param searchBase (Full Domain Name for the search ie:
-  * DC=qa-ad-76,DC=metacarta,DC=com)
-  * @return DistinguishedName for given domain user logon name. (Should
-  * throws an exception if user is not found.)
-  */
-  protected String getDistinguishedName(LdapContext ctx, String userName)
+   * Obtain the user LDAP record for a given user logon name.
+   *
+   * @param ctx is the ldap context to use.
+   * @param userName (Domain Logon Name) is the user name or identifier.
+   * @param searchBase (Full Domain Name for the search ie:
+   * DC=qa-ad-76,DC=metacarta,DC=com)
+   * @return SearchResult for given domain user logon name. (Should throws
+   * an exception if user is not found.)
+   */
+  protected SearchResult getUserEntry(LdapContext ctx, String userName)
     throws ManifoldCFException {
-    String returnedAtts[] = {"dn"};
-    String searchFilter = userSearch.replaceAll( "\\{0\\}", ldapEscape(userName));
+    String searchFilter = userSearch.replaceAll("\\{0\\}", escapeDN(userName));
     SearchControls searchCtls = new SearchControls();
-    searchCtls.setReturningAttributes(returnedAtts);
     searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
 
     try {
       NamingEnumeration answer = ctx.search(userBase, searchFilter, searchCtls);
-      while (answer.hasMoreElements()) {
-        SearchResult sr = (SearchResult) answer.next();
-        return sr.getNameInNamespace();
+      if (answer.hasMoreElements()) {
+        return (SearchResult) answer.next();
       }
       return null;
     } catch (Exception e) {
@@ -633,8 +826,8 @@ public class LDAPAuthority extends org.a
   }
 
   /**
-  * LDAP escape a string.
-  */
+   * LDAP escape a string.
+   */
   protected static String ldapEscape(String input) {
     //Add escape sequence to all commas
     StringBuilder sb = new StringBuilder();
@@ -651,4 +844,170 @@ public class LDAPAuthority extends org.a
     }
     return sb.toString();
   }
+
+  public static String escapeDN(String name) {
+    StringBuilder sb = new StringBuilder(); // If using JDK >= 1.5 consider using StringBuilder
+    if ((name.length() > 0) && ((name.charAt(0) == ' ') || (name.charAt(0) == '#'))) {
+      sb.append('\\'); // add the leading backslash if needed
+    }
+    for (int i = 0; i < name.length(); i++) {
+      char curChar = name.charAt(i);
+      switch (curChar) {
+        case '\\':
+          sb.append("\\\\");
+          break;
+        case ',':
+          sb.append("\\,");
+          break;
+        case '+':
+          sb.append("\\+");
+          break;
+        case '"':
+          sb.append("\\\"");
+          break;
+        case '<':
+          sb.append("\\<");
+          break;
+        case '>':
+          sb.append("\\>");
+          break;
+        case ';':
+          sb.append("\\;");
+          break;
+        default:
+          sb.append(curChar);
+      }
+    }
+    if ((name.length() > 1) && (name.charAt(name.length() - 1) == ' ')) {
+      sb.insert(sb.length() - 1, '\\'); // add the trailing backslash if needed
+    }
+    return sb.toString();
+  }
+
+  public static String escapeLDAPSearchFilter(String filter) {
+    StringBuilder sb = new StringBuilder(); // If using JDK >= 1.5 consider using StringBuilder
+    for (int i = 0; i < filter.length(); i++) {
+      char curChar = filter.charAt(i);
+      switch (curChar) {
+        case '\\':
+          sb.append("\\5c");
+          break;
+        case '*':
+          sb.append("\\2a");
+          break;
+        case '(':
+          sb.append("\\28");
+          break;
+        case ')':
+          sb.append("\\29");
+          break;
+        case '\u0000':
+          sb.append("\\00");
+          break;
+        default:
+          sb.append(curChar);
+      }
+    }
+    return sb.toString();
+  }
+  
+  protected static StringSet emptyStringSet = new StringSet();
+
+  /**
+   * This is the cache object descriptor for cached access tokens from this
+   * connector.
+   */
+  protected class LdapAuthorizationResponseDescription extends org.apache.manifoldcf.core.cachemanager.BaseDescription {
+
+    /**
+     * The user name
+     */
+    protected String userName;
+    /**
+     * LDAP connection string with server name and base DN
+     */
+    protected String connectionString;
+    /**
+     * User search definition
+     */
+    protected String userSearch;
+    /**
+     * Group search definition
+     */
+    protected String groupSearch;
+    /**
+     * The response lifetime
+     */
+    protected long responseLifetime;
+    /**
+     * The expiration time
+     */
+    protected long expirationTime = -1;
+
+    /**
+     * Constructor.
+     */
+    public LdapAuthorizationResponseDescription(String userName, String connectionString, String userSearch, String groupSearch, long responseLifetime, int LRUsize) {
+      super("LDAPAuthority", LRUsize);
+      this.userName = userName;
+      this.connectionString = connectionString;
+      this.userSearch = userSearch;
+      this.groupSearch = groupSearch;
+      this.responseLifetime = responseLifetime;
+    }
+
+    /**
+     * Return the invalidation keys for this object.
+     */
+    public StringSet getObjectKeys() {
+      return emptyStringSet;
+    }
+
+    /**
+     * Get the critical section name, used for synchronizing the creation of the
+     * object
+     */
+    public String getCriticalSectionName() {
+      StringBuilder sb = new StringBuilder(getClass().getName());
+      sb.append("-").append(userName).append("-").append(connectionString);
+      return sb.toString();
+    }
+
+    /**
+     * Return the object expiration interval
+     */
+    @Override
+    public long getObjectExpirationTime(long currentTime) {
+      if (expirationTime == -1) {
+        expirationTime = currentTime + responseLifetime;
+      }
+      return expirationTime;
+    }
+
+    @Override
+    public int hashCode() {
+      return userName.hashCode() + connectionString.hashCode() + userSearch.hashCode() + groupSearch.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (!(o instanceof LdapAuthorizationResponseDescription)) {
+        return false;
+      }
+      LdapAuthorizationResponseDescription ard = (LdapAuthorizationResponseDescription) o;
+      if (!ard.userName.equals(userName)) {
+        return false;
+      }
+      if (!ard.connectionString.equals(connectionString)) {
+        return false;
+      }
+      if (!ard.userSearch.equals(userSearch)) {
+        return false;
+      }
+      if (!ard.groupSearch.equals(groupSearch)) {
+        return false;
+      }
+      return true;
+    }
+  }
 }

Modified: manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_en_US.properties
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_en_US.properties?rev=1405811&r1=1405810&r2=1405811&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_en_US.properties (original)
+++ manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_en_US.properties Mon Nov  5 14:43:38 2012
@@ -17,11 +17,16 @@ LDAP.LDAP=LDAP
 LDAP.LDAPServerNameColon=LDAP server name:
 LDAP.LDAPServerPortColon=LDAP server port:
 LDAP.LDAPServerBaseColon=LDAP server base (e.g. 'dc=office,dc=com'):
+LDAP.LDAPBindUserColon=Bind to server as user (leave empty if not needed):
+LDAP.LDAPBindPasswordColon=Bind to server with password:
 LDAP.UserSearchBaseColon=User search base:
 LDAP.UserSearchFilterColon=User search filter:
 LDAP.GroupSearchBaseColon=Group search base:
 LDAP.GroupSearchFilterColon=Group search filter:
 LDAP.GroupNameAttributeColon=Group name attribute:
+LDAP.AddUserAuthColon=Add user as authorization token:
+LDAP.UserNameAttrColon=User name attribute:
+LDAP.GroupMemberDnColon=Member attribute is DN:
 
 LDAP.ServerNameCannotBeBlank=Server name cannot be blank
 LDAP.ServerPortCannotBeBlank=Server port cannot be blank

Modified: manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_ja_JP.properties
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_ja_JP.properties?rev=1405811&r1=1405810&r2=1405811&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_ja_JP.properties (original)
+++ manifoldcf/branches/CONNECTORS-563/connectors/ldap/connector/src/main/native2ascii/org/apache/manifoldcf/authorities/authorities/ldap/common_ja_JP.properties Mon Nov  5 14:43:38 2012
@@ -17,11 +17,16 @@ LDAP.LDAP=LDAP
 LDAP.LDAPServerNameColon=LDAPサーバ名:
 LDAP.LDAPServerPortColon=LDAPサーバポート:
 LDAP.LDAPServerBaseColon=LDAPサーバベース (例 'dc=office,dc=com'):
+LDAP.LDAPBindUserColon=Bind to server as user (leave empty if not needed):
+LDAP.LDAPBindPasswordColon=Bind to server with password:
 LDAP.UserSearchBaseColon=Userサーチベース:
 LDAP.UserSearchFilterColon=Userサーチフィルタ:
 LDAP.GroupSearchBaseColon=Groupサーチベース:
 LDAP.GroupSearchFilterColon=Groupサーチフィルタ:
 LDAP.GroupNameAttributeColon=Group名属性:
+LDAP.AddUserAuthColon=Add user as authorization token:
+LDAP.UserNameAttrColon=User name attribute:
+LDAP.GroupMemberDnColon=Member attribute is DN:
 
 LDAP.ServerNameCannotBeBlank=サーバ名は空白にできません
 LDAP.ServerPortCannotBeBlank=サーバポートは空白にできません