/* * Copyright (C) 2013 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.web.login; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.login.LoginException; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import org.exoplatform.container.component.ComponentRequestLifecycle; import org.exoplatform.container.component.RequestLifeCycle; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.organization.OrganizationService; import org.exoplatform.services.organization.User; import org.exoplatform.services.organization.UserHandler; import org.exoplatform.services.organization.UserStatus; import org.exoplatform.services.organization.impl.UserImpl; import org.exoplatform.services.security.jaas.AbstractLoginModule; public class FilterDisabledLoginModule extends AbstractLoginModule { private static final Log log = ExoLogger.getLogger(FilterDisabledLoginModule.class); /** JACC get context method. */ private static Method getContextMethod; public static final String DISABLED_USER_NAME = "_disabledUserName"; static { try { Class<?> policyContextClass = Thread.currentThread().getContextClassLoader() .loadClass("javax.security.jacc.PolicyContext"); getContextMethod = policyContextClass.getDeclaredMethod("getContext", String.class); } catch (ClassNotFoundException ignore) { log.debug("JACC not found ignoring it", ignore); } catch (Exception e) { log.error("Could not obtain JACC get context method", e); } } @Override public boolean login() throws LoginException { log.debug("In login of FilterDisabledLoginModule."); try { Callback[] callbacks = new Callback[] { new NameCallback("Username") }; callbackHandler.handle(callbacks); String username = ((NameCallback) callbacks[0]).getName(); if (username != null) { OrganizationService service = (OrganizationService) getContainer().getComponentInstanceOfType( OrganizationService.class); try { begin(service); UserHandler uHandler = service.getUserHandler(); User user = uHandler.findUserByName(username, UserStatus.ANY); if (user == null) { log.debug("user {0} doesn't exists. FilterDisabledLoginModule will be ignored.", username); } else if (user instanceof UserImpl && !((UserImpl) user).isEnabled()) { HttpServletRequest request = getCurrentHttpServletRequest(); if (request != null) { request.setAttribute(DISABLED_USER_NAME, username); } throw new LoginException("Can't authenticate. user " + username + " is disabled"); } } finally { end(service); } } else { log.debug("No username has been committed. FilterDisabledLoginModule will be ignored."); } return true; } catch (final Exception e) { log.warn(e.getMessage()); throw new LoginException(e.getMessage()); } } protected HttpServletRequest getCurrentHttpServletRequest() { HttpServletRequest request = null; // JBoss way if (getContextMethod != null) { try { request = (HttpServletRequest) getContextMethod.invoke(null, "javax.servlet.http.HttpServletRequest"); } catch (Throwable e) { log.error("LoginModule error. Turn off session credentials checking with proper configuration option of " + "LoginModule set to false"); log.error(this, e); } } else { // Tomcat way (Assumed that ServletAccessValve has been configured in context.xml) try { // TODO: improve this Class<?> clazz = Thread.currentThread().getContextClassLoader() .loadClass("org.gatein.sso.agent.tomcat.ServletAccess"); Method getRequestMethod = clazz.getDeclaredMethod("getRequest"); request = (HttpServletRequest) getRequestMethod.invoke(null); } catch (Exception e) { log.error("Unexpected exception when trying to obtain HttpServletRequest from ServletAccess thread-local", e); } } log.trace("Returning HttpServletRequest {0}", request); return request; } @Override public boolean commit() throws LoginException { return true; } @Override public boolean abort() throws LoginException { return true; } @Override public boolean logout() throws LoginException { return true; } @Override protected Log getLogger() { return log; } private void begin(OrganizationService orgService) { if (orgService instanceof ComponentRequestLifecycle) { RequestLifeCycle.begin((ComponentRequestLifecycle) orgService); } } private void end(OrganizationService orgService) { if (orgService instanceof ComponentRequestLifecycle) { RequestLifeCycle.end(); } } }