James Moger
2012-07-10 2ec0d7fcf3017c3b8f825bd6d1e82da0966b24ca
src/com/gitblit/LdapUserService.java
@@ -106,6 +106,29 @@
   }
   
   /**
    * If no displayName pattern is defined then Gitblit can manage the display name.
    *
    * @return true if Gitblit can manage the user display name
    * @since 1.0.0
    */
   @Override
   public boolean supportsDisplayNameChanges() {
      return StringUtils.isEmpty(settings.getString(Keys.realm.ldap.displayName, ""));
   }
   /**
    * If no email pattern is defined then Gitblit can manage the email address.
    *
    * @return true if Gitblit can manage the user email address
    * @since 1.0.0
    */
   @Override
   public boolean supportsEmailAddressChanges() {
      return StringUtils.isEmpty(settings.getString(Keys.realm.ldap.email, ""));
   }
   /**
    * If the LDAP server will maintain team memberships then LdapUserService
    * will not allow team membership changes.  In this scenario all team
    * changes must be made on the LDAP server by the LDAP administrator.
@@ -137,7 +160,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 +172,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 +209,41 @@
                   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 full name Attribute
      String displayName = settings.getString(Keys.realm.ldap.displayName, "");
      if (!StringUtils.isEmpty(displayName)) {
         // 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();
         }
      }
      // Get email address Attribute
      String email = settings.getString(Keys.realm.ldap.email, "");
      if (!StringUtils.isEmpty(email)) {
         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 +252,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 +281,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 +294,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 +315,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();
   }
}