/* ===============================================================================
*
* 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.net.URLEncoder;
import java.security.Principal;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.infoglue.cms.util.CmsPropertyHandler;
/**
* @author Mattias Bogeblad
*
* This authentication module authenticates an user against the ordinary infoglue database.
*/
public class JNDIBasicAuthenticationModule extends AuthenticationModule
{
private final static Logger logger = Logger.getLogger(JNDIBasicAuthenticationModule.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 Properties extraProperties = null;
/**
* 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
{
String authenticatedUserName = null;
HttpSession session = ((HttpServletRequest)request).getSession();
//otherwise, we need to authenticate somehow
String userName = request.getParameter("j_username");
String password = request.getParameter("j_password");
String disableRedirect = (String)request.getAttribute("disableRedirect");
// no userName? abort request processing and redirect
if (userName == null || userName.equals(""))
{
if (loginUrl == null)
{
throw new ServletException(
"When InfoGlueFilter protects pages that do not receive a 'userName' " +
"parameter, it needs a org.infoglue.cms.security.loginUrl " +
"filter parameter");
}
String requestURI = request.getRequestURI();
String requestQueryString = request.getQueryString();
if(requestQueryString != null)
{
requestQueryString = "?" + requestQueryString;
}
else
{
requestQueryString = "";
}
logger.info("requestQueryString:" + requestQueryString);
String redirectUrl = "";
if(requestURI.indexOf("?") > 0)
{
redirectUrl = loginUrl + "&referringUrl=" + URLEncoder.encode(requestURI + requestQueryString, "UTF-8") + "&returnAddress=" + URLEncoder.encode(requestURI + requestQueryString, "UTF-8");
}
else
{
redirectUrl = loginUrl + "?referringUrl=" + URLEncoder.encode(requestURI + requestQueryString, "UTF-8") + "&returnAddress=" + URLEncoder.encode(requestURI + requestQueryString, "UTF-8");
}
logger.info("redirectUrl:" + redirectUrl);
if(disableRedirect == null || !disableRedirect.equals("true"))
response.sendRedirect(redirectUrl);
return null;
}
boolean isAuthenticated = authenticate(userName, password, new HashMap());
logger.info("authenticated:" + isAuthenticated);
authenticatedUserName = userName;
if(!isAuthenticated)
{
String referringUrl = request.getRequestURI();
if(request.getParameter("referringUrl") != null)
referringUrl = request.getParameter("referringUrl");
String requestQueryString = request.getQueryString();
if(requestQueryString != null)
requestQueryString = "?" + requestQueryString;
else
requestQueryString = "";
logger.info("requestQueryString:" + requestQueryString);
String redirectUrl = "";
if(referringUrl.indexOf("?") > 0)
redirectUrl = invalidLoginUrl + "?userName=" + URLEncoder.encode(userName, "UTF-8") + "&errorMessage=" + URLEncoder.encode("Invalid login - please try again..", "UTF-8") + "&referringUrl=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8") + "&returnAddress=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8");
else
redirectUrl = invalidLoginUrl + "?userName=" + URLEncoder.encode(userName, "UTF-8") + "?errorMessage=" + URLEncoder.encode("Invalid login - please try again..", "UTF-8") + "&referringUrl=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8") + "&returnAddress=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8");
//String redirectUrl = invalidLoginUrl + "?userName=" + URLEncoder.encode(userName, "UTF-8") + "&errorMessage=" + URLEncoder.encode("Invalid login - please try again..", "UTF-8") + "&referringUrl=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8");
logger.info("redirectUrl:" + redirectUrl);
if(disableRedirect == null || !disableRedirect.equals("true"))
response.sendRedirect(redirectUrl);
return null;
}
//fc.doFilter(request, response);
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;
//otherwise, we need to authenticate somehow
String userName = (String)request.get("j_username");
String password = (String)request.get("j_password");
logger.info("authenticateUser:userName:" + userName);
// no userName? abort request processing and redirect
if (userName == null || userName.equals(""))
{
return null;
}
boolean isAuthenticated = authenticate(userName, password, new HashMap());
logger.info("authenticated:" + isAuthenticated);
if(!isAuthenticated)
{
return null;
}
authenticatedUserName = userName;
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
{
if(CmsPropertyHandler.getApplicationName().equals("deliver"))
{
logger.info("It was a deliver request... let's keep it simple...");
String returnAddress = null;
String referer = request.getHeader("Referer");
if(referer == null || referer.indexOf("ViewStructureToolToolBar.action") != -1)
referer = "/";
logger.info("successLoginUrl:" + successLoginUrl);
if(successLoginUrl != null)
{
returnAddress = successLoginUrl;
}
else
{
returnAddress = request.getRequestURL().toString() + "?" + request.getQueryString() + "&referer=" + URLEncoder.encode(referer, "UTF-8") + "&date=" + System.currentTimeMillis();
}
logger.info("returnAddress:" + returnAddress);
return request.getContextPath() + "/ExtranetLogin!loginForm.action?returnAddress=" + URLEncoder.encode(returnAddress, "UTF-8");
}
String url = null;
//otherwise, we need to authenticate somehow
String userName = request.getParameter("j_username");
String password = request.getParameter("j_password");
// no userName? abort request processing and redirect
if (userName == null || userName.equals(""))
{
if (loginUrl == null)
{
throw new ServletException(
"When InfoGlueFilter protects pages that do not receive a 'userName' " +
"parameter, it needs a org.infoglue.cms.security.loginUrl " +
"filter parameter");
}
String requestURI = request.getRequestURI();
String requestQueryString = request.getQueryString();
if(requestQueryString != null)
{
requestQueryString = "?" + requestQueryString;
}
else
{
requestQueryString = "";
}
logger.info("requestQueryString:" + requestQueryString);
String redirectUrl = "";
if(requestURI.indexOf("?") > 0)
{
redirectUrl = loginUrl + "&referringUrl=" + URLEncoder.encode(requestURI + requestQueryString, "UTF-8") + "&returnAddress=" + URLEncoder.encode(requestURI + requestQueryString, "UTF-8");
}
else
{
redirectUrl = loginUrl + "?referringUrl=" + URLEncoder.encode(requestURI + requestQueryString, "UTF-8") + "&returnAddress=" + URLEncoder.encode(requestURI + requestQueryString, "UTF-8");
}
logger.info("redirectUrl:" + redirectUrl);
return redirectUrl;
}
boolean isAuthenticated = authenticate(userName, password, new HashMap());
logger.info("authenticated:" + isAuthenticated);
String authenticatedUserName = userName;
if(!isAuthenticated)
{
String referringUrl = request.getRequestURI();
if(request.getParameter("referringUrl") != null)
referringUrl = request.getParameter("referringUrl");
String requestQueryString = request.getQueryString();
if(requestQueryString != null)
requestQueryString = "?" + requestQueryString;
else
requestQueryString = "";
logger.info("requestQueryString:" + requestQueryString);
String redirectUrl = "";
if(referringUrl.indexOf("?") > 0)
redirectUrl = invalidLoginUrl + "?userName=" + URLEncoder.encode(userName, "UTF-8") + "&errorMessage=" + URLEncoder.encode("Invalid login - please try again..", "UTF-8") + "&referringUrl=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8") + "&returnAddress=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8");
else
redirectUrl = invalidLoginUrl + "?userName=" + URLEncoder.encode(userName, "UTF-8") + "?errorMessage=" + URLEncoder.encode("Invalid login - please try again..", "UTF-8") + "&referringUrl=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8") + "&returnAddress=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8");
//String redirectUrl = invalidLoginUrl + "?userName=" + URLEncoder.encode(userName, "UTF-8") + "&errorMessage=" + URLEncoder.encode("Invalid login - please try again..", "UTF-8") + "&referringUrl=" + URLEncoder.encode(referringUrl + requestQueryString, "UTF-8");
logger.info("redirectUrl:" + redirectUrl);
return redirectUrl;
}
return url;
}
/**
* This method authenticates against the infoglue extranet user database.
*/
private boolean authenticate(String userName, String password, Map parameters) throws Exception
{
boolean isAuthenticated = false;
String administratorUserName = CmsPropertyHandler.getAdministratorUserName();
//String administratorPassword = CmsPropertyHandler.getAdministratorPassword();
//boolean isAdministrator = (userName.equalsIgnoreCase(administratorUserName) && password.equalsIgnoreCase(administratorPassword)) ? true : false;
boolean matchesRootPassword = CmsPropertyHandler.getMatchesAdministratorPassword(password);
boolean isAdministrator = (userName.equalsIgnoreCase(administratorUserName) && matchesRootPassword) ? true : false;
if(isAdministrator || bindUserUsingJNDI(userName, password))
{
isAuthenticated = true;
}
return isAuthenticated;
}
public Principal loginUser(HttpServletRequest request, HttpServletResponse response, Map status) throws Exception
{
return null;
}
public boolean logoutUser(HttpServletRequest request, HttpServletResponse response) throws Exception
{
return false;
}
private boolean bindUserUsingJNDI(String userName, String password)
{
if(password == null || password.equals(""))
{
String allowAnonymousBind = this.extraProperties.getProperty("allowAnonymousBind");
if(allowAnonymousBind == null || !allowAnonymousBind.equalsIgnoreCase("true"))
{
logger.warn("Anonymous bind attemped by not giving any password. Not allowed - now using password '--No password given but anonymous binds not allowed--'");
password = "--No password given but anonymous binds not allowed--";
}
}
boolean result = false;
DirContext ctx = null;
String connectionURL = this.extraProperties.getProperty("connectionURL");
String ldapUserName = this.extraProperties.getProperty("userNamePattern");
String anonymousUserName = CmsPropertyHandler.getAnonymousUser();
if(userName.equals(anonymousUserName))
{
ldapUserName = this.extraProperties.getProperty("anonymousUserNamePattern");
}
ldapUserName = ldapUserName.replaceFirst("infoglue.user", userName);
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, connectionURL);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUserName);
env.put(Context.SECURITY_CREDENTIALS, password);
try
{
ctx = new InitialDirContext(env);
logger.info("User: " + ldapUserName + " successfully bound.");
ctx.close();
result = true;
}
catch (Exception e)
{
logger.info("Could not bind user: " + ldapUserName + ", " + e.getMessage());
}
return result;
}
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 null;
}
public void setTransactionObject(Object 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;
}
}