1 /** 2 * 3 * Copyright 2003-2004 The Apache Software Foundation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.geronimo.tomcat.realm; 18 19 import java.security.Principal; 20 import javax.security.auth.Subject; 21 import javax.security.auth.login.AccountExpiredException; 22 import javax.security.auth.login.CredentialExpiredException; 23 import javax.security.auth.login.FailedLoginException; 24 import javax.security.auth.login.LoginContext; 25 import javax.security.auth.login.LoginException; 26 27 import org.apache.catalina.realm.JAASCallbackHandler; 28 import org.apache.catalina.realm.JAASRealm; 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 32 import org.apache.geronimo.security.ContextManager; 33 34 35 /** 36 * @version $Rev: 106522 $ $Date: 2004-11-25 01:28:57 +0100 (Thu, 25 Nov 2004) $ 37 */ 38 public class TomcatJAASRealm extends JAASRealm implements Cloneable { 39 private static final Log log = LogFactory.getLog(TomcatJAASRealm.class); 40 41 private static final String DEFAULT_NAME = "tomcat"; 42 43 /** 44 * Descriptive information about this <code>Realm</code> implementation. 45 */ 46 protected static final String info = "org.apache.geronimo.tomcat.realm.TomcatJAASRealm/1.0"; 47 48 /** 49 * Descriptive information about this <code>Realm</code> implementation. 50 */ 51 protected static final String name = "TomcatJAASRealm"; 52 53 public TomcatJAASRealm() { 54 super(); 55 } 56 57 58 /** 59 * Return the <code>Principal</code> associated with the specified 60 * username and credentials, if there is one; otherwise return 61 * <code>null</code>. 62 * <p/> 63 * If there are any errors with the JDBC connection, executing the query or 64 * anything we return null (don't authenticate). This event is also logged, 65 * and the connection will be closed so that a subsequent request will 66 * automatically re-open it. 67 * 68 * @param username Username of the <code>Principal</code> to look up 69 * @param credentials Password or other credentials to use in authenticating this 70 * username 71 */ 72 public Principal authenticate(String username, String credentials) { 73 74 // Establish a LoginContext to use for authentication 75 try { 76 LoginContext loginContext = null; 77 if (appName == null) 78 appName = DEFAULT_NAME; 79 80 if (log.isDebugEnabled()) 81 log.debug(sm.getString("jaasRealm.beginLogin", username, appName)); 82 83 // What if the LoginModule is in the container class loader ? 84 ClassLoader ocl = null; 85 86 if (isUseContextClassLoader()) { 87 ocl = Thread.currentThread().getContextClassLoader(); 88 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); 89 } 90 91 try { 92 loginContext = new LoginContext(appName, new JAASCallbackHandler(this, username, credentials)); 93 } catch (Throwable e) { 94 log.error(sm.getString("jaasRealm.unexpectedError"), e); 95 return (null); 96 } finally { 97 if (isUseContextClassLoader()) { 98 Thread.currentThread().setContextClassLoader(ocl); 99 } 100 } 101 102 if (log.isDebugEnabled()) 103 log.debug("Login context created " + username); 104 105 // Negotiate a login via this LoginContext 106 Subject subject = null; 107 try { 108 loginContext.login(); 109 Subject tempSubject = loginContext.getSubject(); 110 if (tempSubject == null) { 111 if (log.isDebugEnabled()) 112 log.debug(sm.getString("jaasRealm.failedLogin", username)); 113 return (null); 114 } 115 116 subject = ContextManager.getServerSideSubject(tempSubject); 117 if (subject == null) { 118 if (log.isDebugEnabled()) 119 log.debug(sm.getString("jaasRealm.failedLogin", username)); 120 return (null); 121 } 122 123 } catch (AccountExpiredException e) { 124 if (log.isDebugEnabled()) 125 log.debug(sm.getString("jaasRealm.accountExpired", username)); 126 return (null); 127 } catch (CredentialExpiredException e) { 128 if (log.isDebugEnabled()) 129 log.debug(sm.getString("jaasRealm.credentialExpired", username)); 130 return (null); 131 } catch (FailedLoginException e) { 132 if (log.isDebugEnabled()) 133 log.debug(sm.getString("jaasRealm.failedLogin", username)); 134 return (null); 135 } catch (LoginException e) { 136 log.warn(sm.getString("jaasRealm.loginException", username), e); 137 return (null); 138 } catch (Throwable e) { 139 log.error(sm.getString("jaasRealm.unexpectedError"), e); 140 return (null); 141 } 142 143 if (log.isDebugEnabled()) 144 log.debug(sm.getString("jaasRealm.loginContextCreated", username)); 145 146 // Return the appropriate Principal for this authenticated Subject 147 Principal principal = createPrincipal(username, subject); 148 if (principal == null) { 149 log.debug(sm.getString("jaasRealm.authenticateFailure", username)); 150 return (null); 151 } 152 if (log.isDebugEnabled()) { 153 log.debug(sm.getString("jaasRealm.authenticateSuccess", username)); 154 } 155 156 return (principal); 157 } catch (Throwable t) { 158 log.error("error ", t); 159 return null; 160 } 161 } 162 163 public Object clone() throws CloneNotSupportedException{ 164 return super.clone(); 165 } 166 }