James Moger
2012-04-25 d2426e1eb5d07664b5c26c4247fae3325282d60d
src/com/gitblit/LdapUserService.java
@@ -137,7 +137,7 @@
         // Find the logging in user's DN
         String accountBase = settings.getString(Keys.realm.ldap.accountBase, "");
         String accountPattern = settings.getString(Keys.realm.ldap.accountPattern, "(&(objectClass=person)(sAMAccountName=${username}))");
         accountPattern = StringUtils.replace(accountPattern, "${username}", simpleUsername);
         accountPattern = StringUtils.replace(accountPattern, "${username}", escapeLDAPSearchFilter(simpleUsername));
         SearchResult result = doSearch(ldapConnection, accountBase, accountPattern);
         if (result != null && result.getEntryCount() == 1) {
@@ -149,15 +149,15 @@
               
               UserModel user = getUserModel(simpleUsername);
               if (user == null)   // create user object for new authenticated user
                  user = createUserFromLdap(simpleUsername, loggingInUser);
                  user = new UserModel(simpleUsername);
               
               user.password = "StoredInLDAP";
               
               if (!supportsTeamMembershipChanges())
                  getTeamsFromLdap(ldapConnection, simpleUsername, loggingInUser, user);
               
               // Get Admin Attributes
               setAdminAttribute(user);
               // Get User Attributes
               setUserAttributes(user, loggingInUser);
               // Push the ldap looked up values to backing file
               super.updateUserModel(user);
@@ -186,6 +186,37 @@
                   user.canAdmin = true;
       }
   }
   private void setUserAttributes(UserModel user, SearchResultEntry userEntry) {
      // Is this user an admin?
      setAdminAttribute(user);
      // Don't want visibility into the real password, make up a dummy
      user.password = "StoredInLDAP";
      // Get Attributes for full name / email
      String displayName = settings.getString(Keys.realm.ldap.displayName, "displayName");
      String email = settings.getString(Keys.realm.ldap.email, "email");
      // Replace embedded ${} with attributes
      if (displayName.contains("${")) {
         for (Attribute userAttribute : userEntry.getAttributes())
            displayName = StringUtils.replace(displayName, "${" + userAttribute.getName() + "}", userAttribute.getValue());
         user.displayName = displayName;
      } else {
         user.displayName = userEntry.getAttribute(displayName).getValue();
      }
      if (email.contains("${")) {
         for (Attribute userAttribute : userEntry.getAttributes())
            email = StringUtils.replace(email, "${" + userAttribute.getName() + "}", userAttribute.getValue());
         user.emailAddress = email;
      } else {
         user.emailAddress = userEntry.getAttribute(email).getValue();
      }
   }
   private void getTeamsFromLdap(LDAPConnection ldapConnection, String simpleUsername, SearchResultEntry loggingInUser, UserModel user) {
      String loggingInUserDN = loggingInUser.getDN();
@@ -194,12 +225,12 @@
      String groupBase = settings.getString(Keys.realm.ldap.groupBase, "");
      String groupMemberPattern = settings.getString(Keys.realm.ldap.groupMemberPattern, "(&(objectClass=group)(member=${dn}))");
      
      groupMemberPattern = StringUtils.replace(groupMemberPattern, "${dn}", loggingInUserDN);
      groupMemberPattern = StringUtils.replace(groupMemberPattern, "${username}", simpleUsername);
      groupMemberPattern = StringUtils.replace(groupMemberPattern, "${dn}", escapeLDAPSearchFilter(loggingInUserDN));
      groupMemberPattern = StringUtils.replace(groupMemberPattern, "${username}", escapeLDAPSearchFilter(simpleUsername));
      
      // Fill in attributes into groupMemberPattern
      for (Attribute userAttribute : loggingInUser.getAttributes())
         groupMemberPattern = StringUtils.replace(groupMemberPattern, "${" + userAttribute.getName() + "}", userAttribute.getValue());
         groupMemberPattern = StringUtils.replace(groupMemberPattern, "${" + userAttribute.getName() + "}", escapeLDAPSearchFilter(userAttribute.getValue()));
      
      SearchResult teamMembershipResult = doSearch(ldapConnection, groupBase, groupMemberPattern);
      if (teamMembershipResult != null && teamMembershipResult.getEntryCount() > 0) {
@@ -223,13 +254,6 @@
      
      return answer;      
   }
   private UserModel createUserFromLdap(String simpleUserName, SearchResultEntry userEntry) {
      UserModel answer = new UserModel(simpleUserName);
      // potentially retrieve other attributes here in the future
      return answer;
   }
   private SearchResult doSearch(LDAPConnection ldapConnection, String base, String filter) {
      try {
@@ -243,6 +267,7 @@
   
   private boolean isAuthenticated(LDAPConnection ldapConnection, String userDn, String password) {
      try {
         // Binding will stop any LDAP-Injection Attacks since the searched-for user needs to bind to that DN
         ldapConnection.bind(userDn, password);
         return true;
      } catch (LDAPException e) {
@@ -263,6 +288,35 @@
      if (lastSlash > -1) {
         username = username.substring(lastSlash + 1);
      }
      return username;
   }
   // From: https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java
   public static final String escapeLDAPSearchFilter(String filter) {
      StringBuilder sb = new 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();
   }
}