package org.apache.catalina.realm; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.security.Principal; import java.util.List; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.AccountExpiredException; import javax.security.auth.login.Configuration; import javax.security.auth.login.CredentialExpiredException; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.ExceptionUtils; public class LocalConfigJAASRealm extends JAASRealm { private static final Log log = LogFactory.getLog(JAASRealm.class); protected String configfile; public String getConfigfile() { return configfile; } public void setConfigfile(String configfile) { this.configfile = configfile; } protected Configuration jaasConfiguration; protected volatile boolean jaasConfigurationLoaded = false; protected Configuration getConfig() { try { if (jaasConfigurationLoaded) { return jaasConfiguration; } synchronized (this) { if (configfile == null) { jaasConfigurationLoaded = true; return null; } URL resource = Thread.currentThread().getContextClassLoader().getResource(configfile); URI uri = resource.toURI(); Class sunConfigFile = Class.forName("com.sun.security.auth.login.ConfigFile"); Constructor constructor = sunConfigFile.getConstructor(URI.class); Configuration config = constructor.newInstance(uri); this.jaasConfiguration = config; this.jaasConfigurationLoaded = true; return this.jaasConfiguration; } } catch (URISyntaxException ex) { throw new RuntimeException(ex); } catch (NoSuchMethodException ex) { throw new RuntimeException(ex); } catch (SecurityException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { throw new RuntimeException(ex.getCause()); } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } } @Override protected void parseClassNames(String classNamesString, List classNamesList) { if (isUseContextClassLoader()) { // sometimes ContextClassLoader is not the Web Application Classloader classNamesList.clear(); if (classNamesString == null) { return; } String[] classNames = classNamesString.split("[ ]*,[ ]*"); for (int i = 0; i < classNames.length; i++) { if (classNames[i].length() == 0) { continue; } classNamesList.add(classNames[i]); } } else { super.parseClassNames(classNamesString, classNamesList); } } @Override protected Principal authenticate(String username, CallbackHandler callbackHandler) { // Establish a LoginContext to use for authentication try { LoginContext loginContext = null; if (appName == null) { appName = "Tomcat"; } if (log.isDebugEnabled()) { log.debug(sm.getString("jaasRealm.beginLogin", username, appName)); } // What if the LoginModule is in the container class loader ? ClassLoader ocl = null; if (!isUseContextClassLoader()) { ocl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader()); } try { Configuration config = getConfig(); loginContext = new LoginContext(appName, null, callbackHandler, config); } catch (Throwable e) { ExceptionUtils.handleThrowable(e); log.error(sm.getString("jaasRealm.unexpectedError"), e); return (null); } finally { if (!isUseContextClassLoader()) { Thread.currentThread().setContextClassLoader(ocl); } } if (log.isDebugEnabled()) { log.debug("Login context created " + username); } // Negotiate a login via this LoginContext Subject subject = null; try { loginContext.login(); subject = loginContext.getSubject(); if (subject == null) { if (log.isDebugEnabled()) { log.debug(sm.getString("jaasRealm.failedLogin", username)); } return (null); } } catch (AccountExpiredException e) { if (log.isDebugEnabled()) { log.debug(sm.getString("jaasRealm.accountExpired", username)); } return (null); } catch (CredentialExpiredException e) { if (log.isDebugEnabled()) { log.debug(sm.getString("jaasRealm.credentialExpired", username)); } return (null); } catch (FailedLoginException e) { if (log.isDebugEnabled()) { log.debug(sm.getString("jaasRealm.failedLogin", username)); } return (null); } catch (LoginException e) { log.warn(sm.getString("jaasRealm.loginException", username), e); return (null); } catch (Throwable e) { ExceptionUtils.handleThrowable(e); log.error(sm.getString("jaasRealm.unexpectedError"), e); return (null); } if (log.isDebugEnabled()) { log.debug(sm.getString("jaasRealm.loginContextCreated", username)); } // Return the appropriate Principal for this authenticated Subject Principal principal = createPrincipal(username, subject, loginContext); if (principal == null) { log.debug(sm.getString("jaasRealm.authenticateFailure", username)); return (null); } if (log.isDebugEnabled()) { log.debug(sm.getString("jaasRealm.authenticateSuccess", username)); } return (principal); } catch (Throwable t) { log.error("error ", t); return null; } } }