001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.tomcat.realm;
017:
018: import org.apache.catalina.realm.JAASCallbackHandler;
019: import org.apache.catalina.realm.JAASRealm;
020: import org.apache.commons.logging.Log;
021: import org.apache.commons.logging.LogFactory;
022: import org.apache.geronimo.security.ContextManager;
023: import org.apache.geronimo.tomcat.JAASTomcatPrincipal;
024:
025: import javax.security.auth.Subject;
026: import javax.security.auth.login.*;
027: import java.security.Principal;
028: import java.util.ArrayList;
029: import java.util.Iterator;
030: import java.util.List;
031:
032: /**
033: * @version $Rev: 565657 $ $Date: 2007-08-14 01:24:58 -0700 (Tue, 14 Aug 2007) $
034: */
035: public class TomcatJAASRealm extends JAASRealm implements Cloneable {
036: private static final Log log = LogFactory
037: .getLog(TomcatJAASRealm.class);
038:
039: private static final String DEFAULT_NAME = "tomcat";
040:
041: /**
042: * Descriptive information about this <code>Realm</code> implementation.
043: */
044: protected static final String info = "org.apache.geronimo.tomcat.realm.TomcatJAASRealm/1.0";
045:
046: /**
047: * Descriptive information about this <code>Realm</code> implementation.
048: */
049: protected static final String name = "TomcatJAASRealm";
050:
051: public TomcatJAASRealm() {
052: super ();
053: }
054:
055: /**
056: * Return the <code>Principal</code> associated with the specified
057: * username and credentials, if there is one; otherwise return
058: * <code>null</code>.
059: * <p/>
060: * If there are any errors with the JDBC connection, executing the query or
061: * anything we return null (don't authenticate). This event is also logged,
062: * and the connection will be closed so that a subsequent request will
063: * automatically re-open it.
064: *
065: * @param username Username of the <code>Principal</code> to look up
066: * @param credentials Password or other credentials to use in authenticating this
067: * username
068: */
069: public Principal authenticate(String username, String credentials) {
070:
071: // Establish a LoginContext to use for authentication
072: try {
073: LoginContext loginContext = null;
074: if (appName == null)
075: appName = DEFAULT_NAME;
076:
077: if (log.isDebugEnabled())
078: log.debug(sm.getString("jaasRealm.beginLogin",
079: username, appName));
080:
081: // What if the LoginModule is in the container class loader ?
082: ClassLoader ocl = null;
083:
084: if (isUseContextClassLoader()) {
085: ocl = Thread.currentThread().getContextClassLoader();
086: Thread.currentThread().setContextClassLoader(
087: this .getClass().getClassLoader());
088: }
089:
090: try {
091: loginContext = ContextManager.login(appName,
092: new JAASCallbackHandler(this , username,
093: credentials));
094: } catch (AccountExpiredException e) {
095: if (log.isDebugEnabled())
096: log.debug(sm.getString("jaasRealm.accountExpired",
097: username));
098: return (null);
099: } catch (CredentialExpiredException e) {
100: if (log.isDebugEnabled())
101: log.debug(sm.getString(
102: "jaasRealm.credentialExpired", username));
103: return (null);
104: } catch (FailedLoginException e) {
105: if (log.isDebugEnabled())
106: log.debug(sm.getString("jaasRealm.failedLogin",
107: username));
108: return (null);
109: } catch (LoginException e) {
110: log.warn(sm.getString("jaasRealm.loginException",
111: username), e);
112: return (null);
113: } catch (Throwable e) {
114: log.error(sm.getString("jaasRealm.unexpectedError"), e);
115: return (null);
116: } finally {
117: if (isUseContextClassLoader()) {
118: Thread.currentThread().setContextClassLoader(ocl);
119: }
120: }
121:
122: if (log.isDebugEnabled())
123: log.debug("Login context created " + username);
124:
125: // Negotiate a login via this LoginContext
126: Subject subject = loginContext.getSubject();
127: ContextManager.setCallers(subject, subject);
128: if (log.isDebugEnabled())
129: log.debug(sm.getString("jaasRealm.loginContextCreated",
130: username));
131:
132: // Return the appropriate Principal for this authenticated Subject
133: Principal principal = createPrincipal(username, subject);
134: if (principal == null) {
135: log.debug(sm.getString("jaasRealm.authenticateFailure",
136: username));
137: return (null);
138: }
139: if (log.isDebugEnabled()) {
140: log.debug(sm.getString("jaasRealm.authenticateSuccess",
141: username));
142: }
143:
144: return (principal);
145:
146: } catch (Throwable t) {
147: log.error("error ", t);
148: return null;
149: }
150: }
151:
152: protected Principal createPrincipal(String username, Subject subject) {
153: // Prepare to scan the Principals for this Subject
154: //String password = null; // Will not be carried forward
155:
156: List roles = new ArrayList();
157: Principal userPrincipal = null;
158:
159: // Scan the Principals for this Subject
160: Iterator principals = subject.getPrincipals().iterator();
161: while (principals.hasNext()) {
162: Principal principal = (Principal) principals.next();
163:
164: String principalClass = principal.getClass().getName();
165:
166: if (log.isDebugEnabled()) {
167: log.debug(sm.getString("jaasRealm.checkPrincipal",
168: principal, principalClass));
169: }
170:
171: if (userPrincipal == null
172: && userClasses.contains(principalClass)) {
173: userPrincipal = principal;
174: if (log.isDebugEnabled()) {
175: log.debug(sm.getString(
176: "jaasRealm.userPrincipalSuccess", principal
177: .getName()));
178: }
179: }
180:
181: if (roleClasses.contains(principalClass)) {
182: roles.add(principal.getName());
183: if (log.isDebugEnabled()) {
184: log.debug(sm.getString(
185: "jaasRealm.rolePrincipalAdd", principal
186: .getName()));
187: }
188: }
189: }
190:
191: // Print failure message if needed
192: if (userPrincipal == null) {
193: if (log.isDebugEnabled()) {
194: log.debug(sm
195: .getString("jaasRealm.userPrincipalFailure"));
196: log.debug(sm
197: .getString("jaasRealm.rolePrincipalFailure"));
198: }
199: } else {
200: if (roles.size() == 0) {
201: if (log.isDebugEnabled()) {
202: log
203: .debug(sm
204: .getString("jaasRealm.rolePrincipalFailure"));
205: }
206: }
207: }
208:
209: JAASTomcatPrincipal jaasPrincipal = new JAASTomcatPrincipal(
210: username);
211: jaasPrincipal.setSubject(subject);
212: jaasPrincipal.setRoles(roles);
213:
214: // Return the resulting Principal for our authenticated user
215: return jaasPrincipal;
216: }
217:
218: public Object clone() throws CloneNotSupportedException {
219: return super .clone();
220: }
221:
222: public boolean hasRole(Principal principal, String role) {
223:
224: if ((principal == null) || (role == null)
225: || !(principal instanceof JAASTomcatPrincipal))
226: return (false);
227:
228: JAASTomcatPrincipal jtp = (JAASTomcatPrincipal) principal;
229: if (jtp.getRoles().contains(role))
230: return true;
231:
232: return false;
233: }
234:
235: }
|