Package com.esri.gpt.framework.security.identity.ldap

Source Code of com.esri.gpt.framework.security.identity.ldap.LdapEditFunctions

/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "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
*
* 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 the License.
*/
package com.esri.gpt.framework.security.identity.ldap;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.naming.NameAlreadyBoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;

import com.esri.gpt.framework.collection.StringSet;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.jsf.FacesContextBroker;
import com.esri.gpt.framework.jsf.MessageBroker;
import com.esri.gpt.framework.security.credentials.CredentialPolicyException;
import com.esri.gpt.framework.security.credentials.UsernamePasswordCredentials;
import com.esri.gpt.framework.security.identity.IdentityException;
import com.esri.gpt.framework.security.principal.Role;
import com.esri.gpt.framework.security.principal.Roles;
import com.esri.gpt.framework.security.principal.User;
import com.esri.gpt.framework.security.principal.UserAttribute;
import com.esri.gpt.framework.security.principal.UserAttributeMap;
import com.esri.gpt.framework.util.LogUtil;
import com.esri.gpt.framework.util.Val;

/**
* Handles functionality related to editing an LDAP identity store.
*/
public class LdapEditFunctions extends LdapFunctions {

// class variables =============================================================

// instance variables ==========================================================

// constructors ================================================================

/** Default constructor. */
protected LdapEditFunctions() {
  super();
}

/**
* Construct with a supplied configuration.
* @param configuration the configuration
*/
protected LdapEditFunctions(LdapConfiguration configuration) {
  super(configuration);
}

// properties ==================================================================

// methods =====================================================================

/**
* Adds and attribute(s) to an LDAP object.
* @param dirContext the directory context
* @param objectDN the distinguished name for the object to modify
* @param attributes the attribute collection to add
* @throws NamingException if an exception occurs
*/
protected void addAttribute(DirContext dirContext,
                            String objectDN,
                            Attributes attributes)
  throws NamingException {
  modifyEntry(dirContext,objectDN,DirContext.ADD_ATTRIBUTE,attributes);
}

/**
* Adds an entry to LDAP.
* @param dirContext the directory context
* @param objectDN the distinguished name for the new entry
* @param attributes the attributes for the new entry
* @throws NamingException if an exception occurs
*/
protected void addEntry(DirContext dirContext,
                        String objectDN,
                        Attributes attributes)
  throws NamingException {
  dirContext.createSubcontext(objectDN,attributes);
}

/**
* Modifies the attribute(s) for an LDAP object.
* @param dirContext the directory context
* @param objectDN the distinguished name for the object to modify
* @param operation the operation to perform
*        DirContext.[ADD_ATTRIBUTE|REPLACE_ATTRIBUTE|REMOVE_ATTRIBUTE]
* @param attributes the attribute collection to modify
* @throws NamingException if an exception occurs
*/
private void modifyEntry(DirContext dirContext,
                         String objectDN,
                         int operation,
                         Attributes attributes)
  throws NamingException {
  try{
    dirContext.modifyAttributes(objectDN,operation,attributes);
  }catch(javax.naming.directory.InvalidAttributeValueException iave){
    LogUtil.getLogger().severe(iave.getMessage());
    FacesContextBroker contextBroker = new FacesContextBroker();
    MessageBroker msgBroker = contextBroker.extractMessageBroker();
    String errMsg = "javax.naming.directory.InvalidAttributeValueException";
    if(msgBroker != null){
      errMsg = msgBroker.getMessage("javax.naming.directory.InvalidAttributeValueException").getSummary();
    }
    throw new LdapException(errMsg);
  }
}

/**
* Prepares attributes for a user that is about to be registered.
* @param credentials the user credentials
* @param localMap the user profile attribute map
*/
private Attributes prepareRegistrationAttributes(UsernamePasswordCredentials credentials,
                                                 UserAttributeMap localMap) {
  BasicAttributes ldapAttributes = new BasicAttributes();
  LdapUserProperties userProps = getConfiguration().getUserProperties();
  LdapNameMapping nameMap = userProps.getUserProfileMapping();

  // append required object classes
  Attribute objectClasses = userProps.getUserObjectClasses();
  if ((objectClasses != null) && (objectClasses.size() > 0)) {
    ldapAttributes.put(objectClasses);
  }

  // add the username and password from the credentials
  // ignore those profile attributes that do not have a corresponding LDAP key
  String sUsername = credentials.getUsername();
  String sPassword = credentials.encryptLdapPassword(
                     userProps.getPasswordEncryptionAlgorithm());
  localMap.set(UserAttributeMap.TAG_USER_NAME,sUsername);
  localMap.set(UserAttributeMap.TAG_USER_PASSWORD,sPassword);

  // append all attributes of the supplied user profile,
  // ignore those profile attributes that do not have a corresponding LDAP key
  BasicAttribute basicAttr;
  boolean bHasCN = false;
  for (UserAttribute localAttr: localMap.values()) {
    String sLdapKey = nameMap.findLdapName(localAttr.getKey());
    String sLocalValue = localAttr.getValue();
    if ((sLdapKey.length() > 0) && (sLocalValue != null) && (sLocalValue.length() > 0)) {
      basicAttr = new BasicAttribute(sLdapKey,localAttr.getValue());
      ldapAttributes.put(basicAttr);
      if (sLdapKey.equalsIgnoreCase("cn")) {
        bHasCN = false;
      }
    }
  }

  // ensure that a CN was added
  if (!bHasCN) {
    basicAttr = new BasicAttribute("cn",sUsername);
    ldapAttributes.put(basicAttr);
  }
  return ldapAttributes;
}

/**
* Recovers a password.
* <br/>The password is not actually recovered from LDAP,
* a new password is generated and written to LDAP, the new password
* is returned within the credentials.
* @param dirContext the directory context
* @param username the username
* @param emailAddress the email address
* @return the user associated with the recovered credentials (null if no match)
* @throws NamingException if an LDAP naming exception occurs
*/
protected User recoverUserPassword(DirContext dirContext,
                                   String username,
                                   String emailAddress)
  throws NamingException {
  User userFound = null;
  UsernamePasswordCredentials credentials = null;
  username = Val.chkStr(username);
  emailAddress = Val.chkStr(emailAddress);
  if ((username.length() > 0) && (emailAddress.length() > 0)) {
    LdapQueryFunctions queryFunctions = new LdapQueryFunctions(getConfiguration());
    LdapUserProperties userProps = getConfiguration().getUserProperties();
    boolean bMultipleFound = false;
    String sBaseDN = userProps.getUserSearchDIT();
    String sFilter = userProps.returnUserLoginSearchFilter(username);
    StringSet ssDNs = queryFunctions.searchDNs(dirContext,sBaseDN,sFilter);

    // loop through each DN found, check for an email address match
    for (String sDN: ssDNs) {
      User userTmp = new User();
      userTmp.setDistinguishedName(sDN);
      queryFunctions.readUserProfile(dirContext,userTmp);
      if (userTmp.getProfile().getEmailAddress().equals(emailAddress)) {
        if (userFound == null) {
          credentials = new UsernamePasswordCredentials();
          credentials.setUsername(username);
          credentials.generatePassword();
          userFound = userTmp;
          userFound.setCredentials(credentials);
        } else {
          bMultipleFound = true;
          userFound = null;
          break;
        }
      }
    }
   
    if (userFound != null) {
      updateUserPassword(dirContext,userFound,credentials);
    } else if (bMultipleFound) {
      String sMsg = "Multiple LDAP usernames with same email address were located: "+
                    "username:"+username+ "  emailAddress="+emailAddress;
      LogUtil.getLogger().warning(sMsg);
    }
  }
  return userFound;
}

/**
* Extract the request context.
* @return the request context
*/
public RequestContext extractRequestContext() {
  return RequestContext.extract(null);
}

/**
* Register a new user.
* @param dirContext the directory context
* @param user the subject user
* @throws CredentialPolicyException if the username or password is empty
* @throws NamingException if an LDAP naming exception occurs
* @throws NameAlreadyBoundException if the new user DN already exists
*/
protected void registerUser(DirContext dirContext, User user)
  throws CredentialPolicyException, NamingException, NameAlreadyBoundException {

  // initialize
  user.setDistinguishedName("");
  LdapUserProperties userProps = getConfiguration().getUserProperties();
  LdapGroupProperties groupProps = getConfiguration().getGroupProperties();
  UsernamePasswordCredentials upCreds;
  upCreds = user.getCredentials().getUsernamePasswordCredentials();
  if (upCreds != null) {
    user.setDistinguishedName(userProps.returnNewUserDN(upCreds.getUsername()));
  }
 
  if (upCreds == null) {
    throw new CredentialPolicyException("The credentials were not supplied.");
  } else if (user.getDistinguishedName().length() == 0) {
    throw new CredentialPolicyException("The supplied username is invalid.");
  } else if ((upCreds.getPassword() == null) || (upCreds.getPassword().length() == 0)) {
    throw new CredentialPolicyException("The supplied password is invalid.");
  }

  // prepare attributes and add the new user to LDAP
  Attributes attributes = prepareRegistrationAttributes(upCreds,user.getProfile())
  addEntry(dirContext,user.getDistinguishedName(),attributes);

  // add user to general user group
  Roles configuredRoles = getConfiguration().getIdentityConfiguration().getConfiguredRoles();
  if (configuredRoles.getAuthenticatedUserRequiresRole()) {
    String sRoleRegistered = configuredRoles.getRegisteredUserRoleKey();
    Role roleRegistered = configuredRoles.get(sRoleRegistered);
    String sGeneralDN = roleRegistered.getDistinguishedName();
    String sGroupAttribute = groupProps.getGroupMemberAttribute();
    BasicAttribute groupAttribute = new BasicAttribute(sGroupAttribute);
    BasicAttributes groupAttributes = new BasicAttributes();
    groupAttribute.add(user.getDistinguishedName());
    groupAttributes.put(groupAttribute);
    addAttribute(dirContext,sGeneralDN,groupAttributes);
  }
}

/**
* Adds user to role.
* @param dirContext the directory context
* @param user the subject user
* @param role the role key for the role
* @throws CredentialPolicyException if the username or password is empty
* @throws NamingException if an LDAP naming exception occurs
* @throws NameAlreadyBoundException if the new user DN already exists
*/
protected void addUserToRole(DirContext dirContext, User user, String role)
  throws CredentialPolicyException, NamingException {
   
//TODO: need to check if the user is already in role.

  // add user to general user group
  Roles configuredRoles = getConfiguration().getIdentityConfiguration().getConfiguredRoles();    
  Role roleRegistered = configuredRoles.get(role);   
  String sGeneralDN = roleRegistered.getDistinguishedName();
  addUserToGroup(dirContext, user, sGeneralDN);
}

/**
* Adds user to group.
* @param dirContext the directory context
* @param user the subject user
* @param groupDn the dn for the group
* @throws CredentialPolicyException if the username or password is empty
* @throws NamingException if an LDAP naming exception occurs
* @throws NameAlreadyBoundException if the new user DN already exists
*/
protected void addUserToGroup(DirContext dirContext, User user, String groupDn)
  throws CredentialPolicyException, NamingException {
   
  // initialize
  LdapGroupProperties groupProps = getConfiguration().getGroupProperties();  
 
  // add user to general user group
  String sGroupAttribute = groupProps.getGroupMemberAttribute();
  BasicAttribute groupAttribute = new BasicAttribute(sGroupAttribute);
  BasicAttributes groupAttributes = new BasicAttributes();
  groupAttribute.add(user.getDistinguishedName());
  groupAttributes.put(groupAttribute);
  addAttribute(dirContext,groupDn,groupAttributes)
  /*
  Roles configuredRoles = getConfiguration().getIdentityConfiguration().getConfiguredRoles();    
  for (Role role : configuredRoles.values()){
    if(role.getDistinguishedName().equalsIgnoreCase(groupDn)){
      String accessKeyAttribute = Val.chkStr(role.getAccessKey());
      if(accessKeyAttribute.length() > 0){
        BasicAttribute accessAttr = new BasicAttribute(accessKeyAttribute);
        BasicAttributes attributes = new BasicAttributes();
        attributes.put(accessAttr);
        try {
          removeEntry(dirContext,user.getDistinguishedName(), attributes);
        }catch(javax.naming.directory.AttributeInUseException aue){}
        catch(javax.naming.directory.NoSuchAttributeException nse){}
        break;
      }
    }
  }*/
}


/**
* Removes an attribute(s) from an LDAP object.
* @param dirContext the directory context
* @param objectDN the distinguished name for the object to modify
* @param attributes the attribute collection to remove
* @throws NamingException if an exception occurs
*/
protected void removeEntry(DirContext dirContext,
                           String objectDN,
                           Attributes attributes)
  throws NamingException {
  modifyEntry(dirContext,objectDN,DirContext.REMOVE_ATTRIBUTE,attributes);
}

/**
* Updates the profile attributes for a user.
* @param dirContext the directory context
* @param user the subject user
* @param considerUsername true if the username should be considered for update
* @param considerPassword true if the password should be considered for update
* @throws NamingException if an LDAP naming exception occurs
*/
protected void updateUserProfile(DirContext dirContext,
                                 User user,
                                 boolean considerUsername,
                                 boolean considerPassword
  throws NamingException {

  // initialize
  ArrayList<ModificationItem>  alModItems = new ArrayList<ModificationItem>();
  Attributes ldapAttributes = null;
  String sUserDN = user.getDistinguishedName();
  if (sUserDN.length() > 0) {
    ldapAttributes = dirContext.getAttributes(sUserDN);
  }
  if (ldapAttributes != null) {

    // iterate through the attributes of the supplied user profile
    LdapNameMapping  nameMap  = getConfiguration().getUserProperties().getUserProfileMapping();
    UserAttributeMap localMap = user.getProfile();
    ModificationItem modItem;
    for (UserAttribute localAttr: localMap.values()) {
     
      // determine the local and LDAP keys
      String sLocalKey = localAttr.getKey();
      String sLocalValue = localAttr.getValue();
      String sLdapKey = nameMap.findLdapName(localAttr.getKey());
      if ((sLocalValue == null) || (sLocalValue.length() == 0)) {
        sLocalValue = null;
      }
     
      //System.err.println("sLocalKey="+sLocalKey+" sLdapKey="+sLdapKey);
      if (sLocalKey.equalsIgnoreCase(UserAttributeMap.TAG_USER_NAME)) {
        if (!considerUsername) sLdapKey = "";
      } else if (sLocalKey.equalsIgnoreCase(UserAttributeMap.TAG_USER_PASSWORD)) {
        if (!considerPassword) sLdapKey = "";
      }

      if (sLdapKey.length() > 0) {

        // if the attribute exists in LDAP then replace the value,
        // otherwise create a new attribute
        Attribute ldapAttribute = ldapAttributes.get(sLdapKey);
        if (ldapAttribute != null) {
          if (!ldapAttribute.isOrdered()) {
            ldapAttribute.clear();
            ldapAttribute.add(sLocalValue);
          } else {
            ldapAttribute.set(0,sLocalValue);
          }
          modItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,ldapAttribute);
          alModItems.add(modItem);
        } else {
          if ((sLocalValue != null) && (sLocalValue.length() > 0)) {
            BasicAttribute basicAttr = new BasicAttribute(sLdapKey,sLocalValue);
            modItem = new ModificationItem(DirContext.ADD_ATTRIBUTE,basicAttr);
            alModItems.add(modItem);
          }
        }

       } else {
        // no associated LDAP key, we won't throw an exception in this case
      }
    }
  }

  // execute the LDAP modification if modification items exist
  if (alModItems.size() > 0) {
    ModificationItem[] modItems = (ModificationItem[])alModItems.toArray(
                                   new ModificationItem[0]);
    dirContext.modifyAttributes(sUserDN,modItems);

  }
}

/**
* Updates the password for a user.
* @param dirContext the directory context
* @param user the subject user
* @param newCredentials the credentials containing the new password
* @throws NamingException if an LDAP naming exception occurs
*/
protected void updateUserPassword(DirContext dirContext,
                                  User user,
                                  UsernamePasswordCredentials newCredentials)
  throws NamingException {
  User userUpd = new User();
  userUpd.setDistinguishedName(user.getDistinguishedName());
  String sPassword = newCredentials.encryptLdapPassword(
         getConfiguration().getUserProperties().getPasswordEncryptionAlgorithm());
  userUpd.getProfile().set(UserAttributeMap.TAG_USER_PASSWORD,sPassword);
  updateUserProfile(dirContext,userUpd,false,true);
}

/**
* Removes user from group.
* @param user the subject user
* @param groupDn the distinguishedName for the ldap group
* @throws CredentialPolicyException if the credentials are invalid
* @throws IdentityException if a system error occurs preventing the action
* @throws NamingException if an LDAP naming exception occurs
* @throws SQLException if a database communication exception occurs
*/
protected void removeUserFromGroup(DirContext dirContext,User user, String groupDn)
  throws CredentialPolicyException, IdentityException, NamingException, SQLException {
  LdapClient client = null;
  ArrayList<ModificationItem>  alModItems = new ArrayList<ModificationItem>();
  ModificationItem[] modItems = null;
  try {
                  
    Attributes attributes = dirContext.getAttributes(groupDn);
// initialize
   
    ModificationItem modItem;
   
    try {
      if (attributes != null) {
        Attribute attr = attributes.get("uniqueMember");
          NamingEnumeration<?> vals = attr.getAll();;
          while (vals.hasMore()) {
            String val = (String) vals.next();
            if(val.equalsIgnoreCase(user.getDistinguishedName())){
              attr.remove(val);
            }
           
          }
         
          modItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,attr);
          alModItems.add(modItem);

      }
    } finally {
    }
   
// execute the LDAP modification if modification items exist
    if (alModItems.size() > 0) {
      modItems = (ModificationItem[])alModItems.toArray(
                                     new ModificationItem[0]);
      dirContext.modifyAttributes(groupDn,modItems);
    }

   
  } finally {
    if (client != null) client.close();
  }
}

}
TOP

Related Classes of com.esri.gpt.framework.security.identity.ldap.LdapEditFunctions

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.