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 org.apache.catalina.realm.JAASCallbackHandler;
20 import org.apache.catalina.realm.JAASRealm;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.geronimo.security.ContextManager;
24 import org.apache.geronimo.tomcat.JAASTomcatPrincipal;
25
26 import javax.security.auth.Subject;
27 import javax.security.auth.login.*;
28 import java.security.Principal;
29 import java.util.ArrayList;
30 import java.util.Iterator;
31 import java.util.List;
32
33
34 /**
35 * @version $Rev: 355877 $ $Date: 2005-12-10 18:48:27 -0800 (Sat, 10 Dec 2005) $
36 */
37 public class TomcatJAASRealm extends JAASRealm implements Cloneable {
38 private static final Log log = LogFactory.getLog(TomcatJAASRealm.class);
39
40 private static final String DEFAULT_NAME = "tomcat";
41
42 /**
43 * Descriptive information about this <code>Realm</code> implementation.
44 */
45 protected static final String info = "org.apache.geronimo.tomcat.realm.TomcatJAASRealm/1.0";
46
47 /**
48 * Descriptive information about this <code>Realm</code> implementation.
49 */
50 protected static final String name = "TomcatJAASRealm";
51
52 public TomcatJAASRealm() {
53 super();
54 }
55
56
57 /**
58 * Return the <code>Principal</code> associated with the specified
59 * username and credentials, if there is one; otherwise return
60 * <code>null</code>.
61 * <p/>
62 * If there are any errors with the JDBC connection, executing the query or
63 * anything we return null (don't authenticate). This event is also logged,
64 * and the connection will be closed so that a subsequent request will
65 * automatically re-open it.
66 *
67 * @param username Username of the <code>Principal</code> to look up
68 * @param credentials Password or other credentials to use in authenticating this
69 * username
70 */
71 public Principal authenticate(String username, String credentials) {
72
73
74 try {
75 LoginContext loginContext = null;
76 if (appName == null)
77 appName = DEFAULT_NAME;
78
79 if (log.isDebugEnabled())
80 log.debug(sm.getString("jaasRealm.beginLogin", username, appName));
81
82
83 ClassLoader ocl = null;
84
85 if (isUseContextClassLoader()) {
86 ocl = Thread.currentThread().getContextClassLoader();
87 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
88 }
89
90 try {
91 loginContext = new LoginContext(appName, new JAASCallbackHandler(this, username, credentials));
92 } catch (Throwable e) {
93 log.error(sm.getString("jaasRealm.unexpectedError"), e);
94 return (null);
95 } finally {
96 if (isUseContextClassLoader()) {
97 Thread.currentThread().setContextClassLoader(ocl);
98 }
99 }
100
101 if (log.isDebugEnabled())
102 log.debug("Login context created " + username);
103
104
105 Subject subject = null;
106 try {
107 loginContext.login();
108 Subject tempSubject = loginContext.getSubject();
109 if (tempSubject == null) {
110 if (log.isDebugEnabled())
111 log.debug(sm.getString("jaasRealm.failedLogin", username));
112 return (null);
113 }
114
115 subject = ContextManager.getServerSideSubject(tempSubject);
116 if (subject == null) {
117 if (log.isDebugEnabled())
118 log.debug(sm.getString("jaasRealm.failedLogin", username));
119 return (null);
120 }
121
122 } catch (AccountExpiredException e) {
123 if (log.isDebugEnabled())
124 log.debug(sm.getString("jaasRealm.accountExpired", username));
125 return (null);
126 } catch (CredentialExpiredException e) {
127 if (log.isDebugEnabled())
128 log.debug(sm.getString("jaasRealm.credentialExpired", username));
129 return (null);
130 } catch (FailedLoginException e) {
131 if (log.isDebugEnabled())
132 log.debug(sm.getString("jaasRealm.failedLogin", username));
133 return (null);
134 } catch (LoginException e) {
135 log.warn(sm.getString("jaasRealm.loginException", username), e);
136 return (null);
137 } catch (Throwable e) {
138 log.error(sm.getString("jaasRealm.unexpectedError"), e);
139 return (null);
140 }
141
142 if (log.isDebugEnabled())
143 log.debug(sm.getString("jaasRealm.loginContextCreated", username));
144
145
146 Principal principal = createPrincipal(username, subject);
147 if (principal == null) {
148 log.debug(sm.getString("jaasRealm.authenticateFailure", username));
149 return (null);
150 }
151 if (log.isDebugEnabled()) {
152 log.debug(sm.getString("jaasRealm.authenticateSuccess", username));
153 }
154
155 return (principal);
156
157 } catch (Throwable t) {
158 log.error("error ", t);
159 return null;
160 }
161 }
162
163 protected Principal createPrincipal(String username, Subject subject) {
164
165 String password = null;
166
167 List roles = new ArrayList();
168 Principal userPrincipal = null;
169
170
171 Iterator principals = subject.getPrincipals().iterator();
172 while (principals.hasNext()) {
173 Principal principal = (Principal) principals.next();
174
175 String principalClass = principal.getClass().getName();
176
177 if( log.isDebugEnabled() ) {
178 log.debug(sm.getString("jaasRealm.checkPrincipal", principal, principalClass));
179 }
180
181 if (userPrincipal == null && userClasses.contains(principalClass)) {
182 userPrincipal = principal;
183 if( log.isDebugEnabled() ) {
184 log.debug(sm.getString("jaasRealm.userPrincipalSuccess", principal.getName()));
185 }
186 }
187
188 if (roleClasses.contains(principalClass)) {
189 roles.add(principal.getName());
190 if( log.isDebugEnabled() ) {
191 log.debug(sm.getString("jaasRealm.rolePrincipalAdd", principal.getName()));
192 }
193 }
194 }
195
196
197 if (userPrincipal == null) {
198 if (log.isDebugEnabled()) {
199 log.debug(sm.getString("jaasRealm.userPrincipalFailure"));
200 log.debug(sm.getString("jaasRealm.rolePrincipalFailure"));
201 }
202 } else {
203 if (roles.size() == 0) {
204 if (log.isDebugEnabled()) {
205 log.debug(sm.getString("jaasRealm.rolePrincipalFailure"));
206 }
207 }
208 }
209
210 JAASTomcatPrincipal jaasPrincipal = new JAASTomcatPrincipal(username);
211 jaasPrincipal.setSubject(subject);
212 jaasPrincipal.setRoles(roles);
213
214
215 return jaasPrincipal;
216 }
217
218
219 public Object clone() throws CloneNotSupportedException{
220 return super.clone();
221 }
222
223
224 public boolean hasRole(Principal principal, String role) {
225
226 if ((principal == null) || (role == null) ||
227 !(principal instanceof JAASTomcatPrincipal))
228 return (false);
229
230 JAASTomcatPrincipal jtp = (JAASTomcatPrincipal) principal;
231 if (jtp.getRoles().contains(role))
232 return true;
233
234 return false;
235 }
236
237 }