/* =============================================================================== * * Part of the InfoGlue Content Management Platform (www.infoglue.org) * * =============================================================================== * * Copyright (C) * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2, as published by the * Free Software Foundation. See the file LICENSE.html for more information. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc. / 59 Temple * Place, Suite 330 / Boston, MA 02111-1307 / USA. * * =============================================================================== */ package org.infoglue.cms.security; import java.security.Principal; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import javax.servlet.FilterChain; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.exolab.castor.jdo.Database; import org.infoglue.cms.exception.SystemException; import org.infoglue.cms.util.CmsPropertyHandler; /** * @author Mattias Bogeblad * * This authorization module is a generic multi-source authentication module. With this you can * define any number of underlying authentication modules which is combined by this module. The order of lookup * is the same as the order the underlying modules are defined in. The module also supports ip-ranged based login. * * To use this you state org.infoglue.cms.security.GenericCombinedAuthenticationModule as AuthenticationModule * and then you add the underlying modules in Extra security parameters as index based properties like this: * * 0.authenticationClassName=org.infoglue.cms.security.CASBasicAuthenticationModule * 1.authenticationClassName=org.infoglue.cms.security.InfoGlueBasicAuthenticationModule * 2.authenticationClassName=com.mycompany.cms.security.MyCustomAuthenticationModule * * Then all modules in turn are asked the queries and if not found the next module is asked. * If you for example want to have several JNDI-sources you are free to define the same module several times and * you can differentiate what properties it should use by setting the index in front of the properties. * * For example if you have 2 JNDI sources and they differ in among other things * roleBase=cn=groups,dc=infoglue,dc=org you add the index in front of two lines of this: * * 0.roleBase=cn=groups,dc=infoglue,dc=org * 1.roleBase=cn=internal,cn=groups,dc=companyx,dc=com * * That way the module with index 0 will get all properties without an index and all properties with index 0 will * override the properties without index for just that module. That way you can also have some parameters in common * between two of the same modules. */ //TODO - document last part above public class GenericCombinedAuthenticationModule extends AuthenticationModule { private final static Logger logger = Logger.getLogger(GenericCombinedAuthenticationModule.class.getName()); private String loginUrl = null; private String logoutUrl = null; private String invalidLoginUrl = null; private String successLoginUrl = null; private String authenticatorClass = null; private String authorizerClass = null; private String serverName = null; private String casServiceUrl = null; private String casRenew = null; private String casValidateUrl = null; private String casProxyValidateUrl = null; private String casLogoutUrl = null; private String casAuthorizedProxy = null; private String disallowedIPAddresses = null; private Properties extraProperties = null; private Database transactionObject = null; private List authorizationModules = new ArrayList(); private AuthenticationModule getAuthenticationModule(String authenticationModuleClassName, int index) throws SystemException { AuthenticationModule authenticationModule = null; try { Properties extraProperties = InfoGlueAuthenticationFilter.extraProperties; if(logger.isInfoEnabled()) logger.info("InfoGlueAuthenticationFilter.authorizerClass:" + authenticationModuleClassName); authenticationModule = (AuthenticationModule)Class.forName(authenticationModuleClassName).newInstance(); logger.info("authenticationModule: " + authenticationModule); if(logger.isInfoEnabled()) logger.info("authenticationModule:" + authenticationModule); Properties localProperties = new Properties(); Iterator propertiesIterator = this.extraProperties.keySet().iterator(); while(propertiesIterator.hasNext()) { String property = (String)propertiesIterator.next(); String value = this.extraProperties.getProperty(property); if(property.startsWith("" + index + ".")) { property = property.substring(2); logger.info("" + property + "=" + value); if(property.equalsIgnoreCase("invalidLoginUrl")) authenticationModule.setInvalidLoginUrl(value); else if(property.equalsIgnoreCase("loginUrl")) authenticationModule.setLoginUrl(value); else if(property.equalsIgnoreCase("logoutUrl")) authenticationModule.setLogoutUrl(value); else if(property.equalsIgnoreCase("serverName")) authenticationModule.setServerName(value); else if(property.equalsIgnoreCase("casRenew")) authenticationModule.setCasRenew(value); else if(property.equalsIgnoreCase("casServiceUrl")) authenticationModule.setCasServiceUrl(value); else if(property.equalsIgnoreCase("casValidateUrl")) authenticationModule.setCasValidateUrl(value); else if(property.equalsIgnoreCase("casProxyValidateUrl")) authenticationModule.setCasProxyValidateUrl(value); else if(property.equalsIgnoreCase("casLogoutUrl")) authenticationModule.setCasLogoutUrl(value); } localProperties.setProperty(property, value); } localProperties.setProperty("authenticatorIndex", "" + index); authenticationModule.setExtraProperties(localProperties); authenticationModule.setTransactionObject(this.getTransactionObject()); } catch(Exception e) { logger.error("There was an error initializing the authorizerClass:" + e.getMessage(), e); throw new SystemException("There was an error initializing the authorizerClass:" + e.getMessage(), e); } return authenticationModule; } /** * This method handles all of the logic for checking how to handle a login. */ public String authenticateUser(HttpServletRequest request, HttpServletResponse response, FilterChain fc) throws Exception { logger.info("authenticateUser in Generic"); if(logger.isInfoEnabled()) this.extraProperties.list(System.out); String authenticatedUserName = null; int i=0; String authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); while(authenticatorClassName != null && !authenticatorClassName.equals("") && authenticatedUserName == null) { if(logger.isInfoEnabled()) logger.info("authenticateUser in " + authenticatorClassName); try { authenticatedUserName = getAuthenticationModule(authenticatorClassName, i).authenticateUser(request, response, fc); } catch(Exception e) { e.printStackTrace(); } i++; authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); } return authenticatedUserName; } /** * This method handles all of the logic for checking how to handle a login. */ public String authenticateUser(Map request) throws Exception { String authenticatedUserName = null; int i=0; String authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); while(authenticatorClassName != null && !authenticatorClassName.equals("") && authenticatedUserName == null) { if(logger.isInfoEnabled()) logger.info("authenticateUser in " + authenticatorClassName); try { authenticatedUserName = getAuthenticationModule(authenticatorClassName, i).authenticateUser(request); } catch(Exception e) { e.printStackTrace(); } i++; authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); } return authenticatedUserName; } /** * This method handles all of the logic for checking how to handle a login. */ public String getLoginDialogUrl(HttpServletRequest request, HttpServletResponse response) throws Exception { String loginDialogUrl = null; int i=0; String authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); while(authenticatorClassName != null && !authenticatorClassName.equals("") && loginDialogUrl == null) { if(logger.isInfoEnabled()) logger.info("authenticateUser in " + authenticatorClassName); try { loginDialogUrl = getAuthenticationModule(authenticatorClassName, i).getLoginDialogUrl(request, response); } catch(Exception e) { e.printStackTrace(); } i++; authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); } return loginDialogUrl; } public Principal loginUser(HttpServletRequest request, HttpServletResponse response, Map status) throws Exception { Principal principal = null; int i=0; String authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); while(authenticatorClassName != null && !authenticatorClassName.equals("") && principal == null) { if(logger.isInfoEnabled()) logger.info("authenticateUser in " + authenticatorClassName); try { principal = getAuthenticationModule(authenticatorClassName, i).loginUser(request, response, status); } catch(Exception e) { e.printStackTrace(); } i++; authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); } return principal; } public boolean logoutUser(HttpServletRequest request, HttpServletResponse response) throws Exception { boolean redirected = false; int i=0; String authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); while(authenticatorClassName != null && !authenticatorClassName.equals("") && redirected == false) { if(logger.isInfoEnabled()) logger.info("authenticateUser in " + authenticatorClassName); try { redirected = getAuthenticationModule(authenticatorClassName, i).logoutUser(request, response); } catch(Exception e) { e.printStackTrace(); } i++; authenticatorClassName = this.extraProperties.getProperty("" + i + ".authenticatorClassName"); } return redirected; } public String getAuthenticatorClass() { return authenticatorClass; } public void setAuthenticatorClass(String authenticatorClass) { this.authenticatorClass = authenticatorClass; } public String getAuthorizerClass() { return authorizerClass; } public void setAuthorizerClass(String authorizerClass) { this.authorizerClass = authorizerClass; } public String getInvalidLoginUrl() { return invalidLoginUrl; } public void setInvalidLoginUrl(String invalidLoginUrl) { this.invalidLoginUrl = invalidLoginUrl; } public String getLoginUrl() { return loginUrl; } public void setLoginUrl(String loginUrl) { this.loginUrl = loginUrl; } public String getLogoutUrl() { return logoutUrl; } public void setLogoutUrl(String logoutUrl) { this.logoutUrl = logoutUrl; } public String getSuccessLoginUrl() { return successLoginUrl; } public void setSuccessLoginUrl(String successLoginUrl) { this.successLoginUrl = successLoginUrl; } public String getServerName() { return this.serverName; } public void setServerName(String serverName) { this.serverName = serverName; } public Properties getExtraProperties() { return extraProperties; } public void setExtraProperties(Properties extraProperties) { this.extraProperties = extraProperties; } public String getCasRenew() { return casRenew; } public void setCasRenew(String casRenew) { this.casRenew = casRenew; } public String getCasServiceUrl() { return casServiceUrl; } public void setCasServiceUrl(String casServiceUrl) { this.casServiceUrl = casServiceUrl; } public String getCasValidateUrl() { return casValidateUrl; } public void setCasValidateUrl(String casValidateUrl) { this.casValidateUrl = casValidateUrl; } public String getCasProxyValidateUrl() { return casProxyValidateUrl; } public void setCasProxyValidateUrl(String casProxyValidateUrl) { this.casProxyValidateUrl = casProxyValidateUrl; } public String getCasAuthorizedProxy() { return casAuthorizedProxy; } public void setCasAuthorizedProxy(String casAuthorizedProxy) { this.casAuthorizedProxy = casAuthorizedProxy; } public Object getTransactionObject() { return this.transactionObject; } public void setTransactionObject(Object transactionObject) { this.transactionObject = (Database)transactionObject; } public String getCasLogoutUrl() { return casLogoutUrl; } public void setCasLogoutUrl(String casLogoutUrl) { this.casLogoutUrl = casLogoutUrl; } public boolean enforceJ2EEContainerPrincipal() { return false; } /** * This method handles all of the logic for checking how to handle a login. */ public String getSSOUserName(HttpServletRequest request) throws Exception { return null; } public void setDisallowedIPAddresses(String disallowedIPAddresses) { this.disallowedIPAddresses = disallowedIPAddresses; } public String getDisallowedIPAddresses() { return this.disallowedIPAddresses; } }