Java tutorial
/** * Copyright (C) 2008 Google - Enterprise EMEA SE * * Licensed 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.google.gsa.valve.modules.ldap; import java.io.IOException; import javax.naming.directory.DirContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.HttpException; import org.apache.log4j.Logger; import com.google.gsa.AuthenticationProcessImpl; import com.google.gsa.Credential; import com.google.gsa.Credentials; import com.google.gsa.valve.configuration.ValveConfiguration; import com.google.gsa.valve.configuration.ValveRepositoryConfiguration; import java.util.HashMap; import java.util.Map; import java.util.Vector; /** * The Security Framework is able to manage more than one credential per user. * This class is able to manage multiple credentials in a LDAP server. This has * been implemented using some attributes extended in the LDAP that hold the * credential information for accessing multiple sources. It checks the main * authentication credentials provided by the user against the LDAP, but once * the user is authenticated, it populates the multiple credentials to be * available during the whole security process. * <p> * It's able to read multiple username and password attributes from the LDAP * and populate them in the credential container. It enables the other * AuthN/AuthZ modules to use them when securely accessing the backend * systems. * <p> * This authentication module uses Java standard LDAP classes that makes * the integration independent of the directory server. * */ public class LDAPSSO implements AuthenticationProcessImpl { //logger private Logger logger = null; //Valve configuration private ValveConfiguration valveConf = null; //Hastable and Vector that contains authentication LDAP attributes private Vector<String> repositories = new Vector<String>(); private Map<String, LDAPAttrRepository> ldapAttributes = new HashMap<String, LDAPAttrRepository>(); //LDAP vars parameters private String ldapBaseuser = null; private String ldapHost = null; private String ldapDomain = null; private String rdnAttr = null; private static final String SSO_COOKIE_NAME = "gsa_ldap_auth"; //Cookie Max Age private int authMaxAge = -1; /** * Class constructor * */ public LDAPSSO() { logger = Logger.getLogger(LDAPSSO.class); } /** * Sets the Valve Configuration instance to read the parameters * from there * * @param valveConf the Valve configuration instance */ public void setValveConfiguration(ValveConfiguration valveConf) { this.valveConf = valveConf; } /** * This is the main method that does the authentication and should be * invoked by the classes that would like to populate new user authentication * credentials from the LDAP server. * <p> * It also authenticates the user against the LDAP server, so that only * priviledged users are able to read the LDAP attributes. These multiple * credentials are stored in the directory server and populate them in the * user's credential container. It enables the other AuthN/AuthZ modules to * use them when securely accessing the backend systems. * <p> * If the LDAP authentication result is OK, it creates an * authentication cookie. Anyway, the HTTP response code is returned in this * method to inform the caller on the status. * * @param request HTTP request * @param response HTTP response * @param authCookies vector that contains the authentication cookies * @param url the document url * @param creds an array of credentials for all external sources * @param id the default credential id to be retrieved from creds * @return the HTTP error code * @throws HttpException * @throws IOException */ public int authenticate(HttpServletRequest request, HttpServletResponse response, Vector<Cookie> authCookies, String url, Credentials creds, String id) throws HttpException, IOException { logger.debug("Start LDAPSSO AuthN process"); //protection repositories.clear(); ldapAttributes.clear(); //Insert LDAP attributes from the config file getLDAPAttributes(id); //First read the u/p the credentails store, in this case using the same as the root login logger.debug("LDAPSSO: trying to get creds from repository ID: " + id); Credential cred = null; try { cred = creds.getCredential(id); } catch (NullPointerException npe) { logger.error("NPE while reading credentials of ID: " + id); } if (cred == null) { cred = creds.getCredential("root"); if (cred != null) { logger.info("LDAPSSO: credential ID used is \"root\""); } else { logger.error("LDAPSSO: No credentials available for " + id); } } Cookie[] cookies = null; // Initialize status code int statusCode = HttpServletResponse.SC_UNAUTHORIZED; // Read cookies cookies = request.getCookies(); try { authMaxAge = Integer.parseInt(valveConf.getAuthMaxAge()); } catch (NumberFormatException nfe) { logger.error( "Configuration error: chack the configuration file as the number set for authMaxAge is not OK:"); } //If the required cookie was not found need to authenticate. logger.info("Authenticating root user with LDAP"); try { //Check if the LDAP credentials are OK Ldap ldapconn = new Ldap(ldapHost, cred.getUsername(), cred.getPassword(), ldapBaseuser, ldapDomain, rdnAttr); try { logger.debug("Connecting to LDAP"); DirContext ctx = ldapconn.openConnection(); if (ctx == null) { //Just send a comment logger.debug("The user(" + cred.getUsername() + ")/password doesn't match"); ldapconn.closeConnection(ctx); return (HttpServletResponse.SC_UNAUTHORIZED); } //Fetching credentials logger.debug("Fetching credentials from the LDAP"); fetchingCredentials(ldapconn, ctx, cred.getUsername(), creds); //Close the connection ldapconn.closeConnection(ctx); } catch (Exception ex) { logger.error("LDAP connection problem during user access: " + ex.getMessage(), ex); return (HttpServletResponse.SC_UNAUTHORIZED); } finally { } Cookie extAuthCookie = null; extAuthCookie = settingCookie(); //add sendCookies support logger.debug("Setting session"); boolean isSessionEnabled = new Boolean(valveConf.getSessionConfig().isSessionEnabled()).booleanValue(); boolean sendCookies = false; if (isSessionEnabled) { sendCookies = new Boolean(valveConf.getSessionConfig().getSendCookies()).booleanValue(); } if ((!isSessionEnabled) || ((isSessionEnabled) && (sendCookies))) { response.addCookie(extAuthCookie); } //add cookie to the array authCookies.add(extAuthCookie); //This would be set to OK or 401 in a real AuthN module statusCode = HttpServletResponse.SC_OK; } catch (Exception e) { // Log error logger.error("LDAP SSO authentication failure: " + e.getMessage(), e); // Update status code statusCode = HttpServletResponse.SC_UNAUTHORIZED; } // Debug logger.debug("Sample Authentication completed (" + statusCode + ")"); // Return status code return statusCode; } /** * Sets the LDAP authentication cookie * * @return the LDAP authentication cookie */ public Cookie settingCookie() { // Instantiate a new cookie Cookie extAuthCookie = new Cookie(SSO_COOKIE_NAME, "true"); String authCookieDomain = null; String authCookiePath = null; // Cache cookie properties authCookieDomain = valveConf.getAuthCookieDomain(); authCookiePath = valveConf.getAuthCookiePath(); // Set extra cookie parameters extAuthCookie.setDomain(authCookieDomain); extAuthCookie.setPath(authCookiePath); extAuthCookie.setMaxAge(authMaxAge); // Log info logger.debug("Adding cookie: " + extAuthCookie.getName() + ":" + extAuthCookie.getValue() + ":" + extAuthCookie.getPath() + ":" + extAuthCookie.getDomain() + ":" + extAuthCookie.getSecure()); return extAuthCookie; } /** * Gets the LDAP attributes coming from the config file * * @param id the repository id */ public void getLDAPAttributes(String id) { logger.debug("Getting LDAP Attributes"); ValveRepositoryConfiguration repositoryConfig = valveConf.getRepository(id); if (repositoryConfig != null) { //Reading LDAP vars from configfile logger.debug("Reading LDAP Attributes from config file"); ldapBaseuser = repositoryConfig.getParameterValue("ldapBaseuser"); if ((ldapBaseuser != null) && (ldapBaseuser == "")) { ldapBaseuser = null; } ldapHost = repositoryConfig.getParameterValue("ldapHost"); if ((ldapHost != null) && (ldapHost == "")) { ldapHost = null; } ldapDomain = repositoryConfig.getParameterValue("ldapDomain"); if ((ldapDomain != null) && (ldapDomain == "")) { ldapDomain = null; } rdnAttr = repositoryConfig.getParameterValue("rdnAttr"); if ((rdnAttr != null) && (rdnAttr == "")) { rdnAttr = null; } //Getting attributes username and password for all the credentials logger.debug("Getting LDAP username and password attributes per each repository"); boolean attributeExist = true; int index = 1; while (attributeExist) { String idAttr = "id" + index; logger.debug("ID is : " + idAttr); if (repositoryConfig.getParameterValue(idAttr) != null) { String userNameAttr = "username" + index; String passwordAttr = "password" + index; if ((repositoryConfig.getParameterValue(userNameAttr) != null) && (repositoryConfig.getParameterValue(passwordAttr) != null)) { logger.debug("Adding LDAP attributes for: " + repositoryConfig.getParameterValue(idAttr)); LDAPAttrRepository attrRepository = new LDAPAttrRepository( repositoryConfig.getParameterValue(userNameAttr), repositoryConfig.getParameterValue(passwordAttr)); ldapAttributes.put(repositoryConfig.getParameterValue(idAttr), attrRepository); repositories.add(repositoryConfig.getParameterValue(idAttr)); } else { logger.error("LDAP attribute username or password for repository number " + index + " [" + repositoryConfig.getParameterValue(idAttr) + "] does NOT exist in the config file. Review configuration"); } } else { attributeExist = false; } index++; } } } /** * * For every credentials read at the configuration file it gets the * LDAP attributes from the LDAP. * * @param ldapconn LDAP connection * @param ctx LDAP context * @param username user id * @param creds user credentials */ public void fetchingCredentials(Ldap ldapconn, DirContext ctx, String username, Credentials creds) { for (int i = 0; i < repositories.size(); i++) { String id = repositories.elementAt(i); logger.debug("ID [" + id + "] found at position #" + i); LDAPAttrRepository attrRepository; //fetch credentials try { attrRepository = ldapAttributes.get(id); //Get User's DN String userDName = ldapconn.getDN(username, ctx); logger.info("fetching credentials for (" + id + ")"); String usernameAttr = ldapconn.getAttributeByDN(attrRepository.getUsernameAttr(), userDName, ctx); String passwordAttr = null; if (!usernameAttr.equals(null)) { logger.debug("UserName id[" + id + "]: " + usernameAttr); passwordAttr = ldapconn.getAttributeByDN(attrRepository.getPasswordAttr(), userDName, ctx); //add the credentials into the "creds" object logger.debug("LDAP credentials were acquired OK. Adding them into the credential container"); Credential credAttr = new Credential(id); credAttr.setUsername(usernameAttr); credAttr.setPassword(passwordAttr); creds.add(credAttr); } else { logger.debug("Credentials for " + id + " were not found for the user " + username); } } catch (NullPointerException e) { logger.warn( "NullPointerException when fetching attrs in the LDAP. Probably due to the user does not have those attrs"); } catch (Exception e) { logger.error("Exception fetching LDAP attributes: " + e.getMessage(), e); } } } /** * Class that implements a pair of username and password LDAP attribute * names associated to a one or more repositories (i.e. a user can be * authenticated using the value of those attributes in the LDAP against * a repository) * */ public class LDAPAttrRepository { //Username and password pair String usernameAttr = null; String passwordAttr = null; /** * Class constructor * * @param usernameAttr LDAP username attribute * @param passwordAttr */ public LDAPAttrRepository(String usernameAttr, String passwordAttr) { setUsernameAttr(usernameAttr); setPasswordAttr(passwordAttr); } /** * Gets the LDAP username attribute * * @return LDAP username attribute */ public String getUsernameAttr() { return usernameAttr; } /** * Sets the LDAP username attribute * * @param usernameAttr LDAP username attribute */ public void setUsernameAttr(String usernameAttr) { this.usernameAttr = usernameAttr; } /** * Gets the LDAP password attribute * * @return LDAP password attribute */ public String getPasswordAttr() { return passwordAttr; } /** * Sets the LDAP password attribute * * @param passwordAttr LDAP password attribute */ public void setPasswordAttr(String passwordAttr) { this.passwordAttr = passwordAttr; } } }