KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > slide > jaas > spi > SlideLoginModule


1 /*
2  * $Header: /home/cvs/jakarta-slide/src/jaas/org/apache/slide/jaas/spi/SlideLoginModule.java,v 1.1.2.1 2004/10/06 16:12:40 ozeigermann Exp $
3  * $Revision: 1.1.2.1 $
4  * $Date: 2004/10/06 16:12:40 $
5  *
6  * ====================================================================
7  *
8  * Copyright 1999-2002 The Apache Software Foundation
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */

23 package org.apache.slide.jaas.spi;
24
25 import java.io.IOException JavaDoc;
26 import java.security.Principal JavaDoc;
27 import java.security.acl.Group JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Enumeration JavaDoc;
30 import java.util.Map JavaDoc;
31
32 import javax.security.auth.Subject JavaDoc;
33 import javax.security.auth.callback.Callback JavaDoc;
34 import javax.security.auth.callback.CallbackHandler JavaDoc;
35 import javax.security.auth.callback.NameCallback JavaDoc;
36 import javax.security.auth.callback.PasswordCallback JavaDoc;
37 import javax.security.auth.callback.UnsupportedCallbackException JavaDoc;
38 import javax.security.auth.login.LoginException JavaDoc;
39 import javax.security.auth.spi.LoginModule JavaDoc;
40
41 import org.apache.slide.authenticate.CredentialsToken;
42 import org.apache.slide.authenticate.SecurityToken;
43 import org.apache.slide.common.Domain;
44 import org.apache.slide.common.NamespaceAccessToken;
45 import org.apache.slide.common.SlideException;
46 import org.apache.slide.common.SlideToken;
47 import org.apache.slide.common.SlideTokenImpl;
48 import org.apache.slide.content.Content;
49 import org.apache.slide.content.NodeProperty;
50 import org.apache.slide.content.NodeRevisionDescriptor;
51 import org.apache.slide.content.NodeRevisionDescriptors;
52 import org.apache.slide.security.ACLSecurityImpl;
53 import org.apache.slide.security.Security;
54 import org.apache.slide.structure.ObjectNotFoundException;
55 import org.apache.slide.structure.SubjectNode;
56
57 /**
58  * JAAS LoginModule for authenticating against users in a Slide namespace.
59  *
60  * <p>
61  * The implementation assumes the ACLSecurityImpl is used.
62  * </p>
63  *
64  * Options include (to be specified in JAAS login configuration file):
65  * <ul>
66  * <li><code>namespace</code>: the namespace to load users from.
67  * Defaults to the default namespace from the Slide domain configuration.
68  * </li>
69  * </ul>
70  */

71 public class SlideLoginModule implements LoginModule JavaDoc {
72     
73     // Slide helpers
74
protected Content m_content;
75     protected Security m_security;
76     
77     // Slide configuration
78
protected String JavaDoc m_usersPath;
79     protected String JavaDoc m_rolesPath;
80     
81     // authentication state information
82
protected boolean m_authenticated = false;
83     protected Subject JavaDoc m_subject;
84     protected Principal JavaDoc m_principal;
85     protected Principal JavaDoc[] m_roles;
86     protected Group JavaDoc m_group;
87     
88     protected boolean m_committed = false;
89     
90     protected CallbackHandler JavaDoc m_callbackHandler;
91     protected Map JavaDoc m_sharedState;
92
93
94     public SlideLoginModule() {
95     }
96
97     /**
98      * Initialize this <code>LoginModule</code> with the specified
99      * configuration information.
100      *
101      * @param subject The <code>Subject</code> to be authenticated
102      * @param callbackHandler A <code>CallbackHandler</code> for communicating
103      * with the end user as necessary
104      * @param sharedState State information shared with other
105      * <code>LoginModule</code> instances
106      * @param options Configuration information for this specific
107      * <code>LoginModule</code> instance
108      */

109     public void initialize(
110         Subject JavaDoc subject,
111         CallbackHandler JavaDoc callbackHandler,
112         Map JavaDoc sharedState,
113         Map JavaDoc options) {
114         
115         m_subject = subject;
116         m_callbackHandler = callbackHandler;
117         m_sharedState = sharedState;
118         
119         // namespace option
120
String JavaDoc namespace = (String JavaDoc) options.get("namespace");
121         if (namespace == null) {
122             namespace = Domain.getDefaultNamespace();
123         }
124         
125         // access the namespace
126
NamespaceAccessToken nat = Domain.accessNamespace(new SecurityToken(this),namespace);
127         m_content = nat.getContentHelper();
128         m_security = nat.getSecurityHelper();
129         m_usersPath = nat.getNamespaceConfig().getUsersPath();
130         m_rolesPath = nat.getNamespaceConfig().getRolesPath();
131     }
132
133     /**
134      * Phase 1 of authenticating a <code>Subject</code>.
135      *
136      * @return <code>true</code> if the authentication succeeded, or
137      * <code>false</code> if this <code>LoginModule</code> should be ignored
138      *
139      * @exception LoginException if the authentication fails
140      */

141     public boolean login() throws LoginException JavaDoc {
142
143         if (m_callbackHandler == null) {
144             // we need a CallbackHandler to do our work
145
throw new LoginException JavaDoc ("No callback handler");
146         }
147         
148         Callback JavaDoc[] callbacks = new Callback JavaDoc[2];
149         callbacks[0] = new NameCallback JavaDoc("Username: ");
150         callbacks[1] = new PasswordCallback JavaDoc("Password: ",false);
151
152         try {
153             // prompt for username and password
154
m_callbackHandler.handle(callbacks);
155
156             String JavaDoc username = ((NameCallback JavaDoc) callbacks[0]).getName();
157             char[] password = ((PasswordCallback JavaDoc) callbacks[1]).getPassword();
158
159             if (username == null) {
160                 throw new LoginException JavaDoc("No user name entered");
161             }
162             if (password == null) {
163                 throw new LoginException JavaDoc("No password entered");
164             }
165             
166             // share username and password with other LoginModules
167
m_sharedState.put("javax.security.auth.login.name",username);
168             m_sharedState.put("javax.security.auth.login.password",password);
169             
170             // use the user's own credentials to retrieve its info
171
SlideToken slideToken = new SlideTokenImpl(new CredentialsToken(username));
172             
173             // retrieve user object
174
SubjectNode userNode;
175             try {
176                 userNode = (SubjectNode) m_security.getPrincipal(slideToken);
177             }
178             catch (ObjectNotFoundException e) {
179                 final String JavaDoc msg = "No such user";
180                 if (Domain.isDebugEnabled()) {
181                     Domain.debug("[SlideLoginModule] - " + msg);
182                 }
183                 throw new LoginException JavaDoc(msg);
184             }
185             catch (SlideException e) {
186                 final String JavaDoc msg = "Failure loading user object";
187                 Domain.error("[SlideLoginModule] - " + msg,e);
188                 throw new LoginException JavaDoc(msg);
189             }
190             
191             m_principal = new SlidePrincipal(username);
192             m_group = new SlideGroup();
193
194             // get the user's password property
195
NodeRevisionDescriptors revisions = m_content.retrieve(slideToken, m_usersPath + "/" + username);
196             NodeRevisionDescriptor revision = m_content.retrieve(slideToken, revisions);
197             NodeProperty property = revision.getProperty("password", NodeProperty.SLIDE_NAMESPACE);
198             if (property != null) {
199                 m_authenticated = new String JavaDoc(password).equals(property.getValue());
200                 
201                 if (!m_authenticated) {
202                     final String JavaDoc msg = "Authentication failed";
203                     if (Domain.isDebugEnabled()) {
204                         Domain.debug("[SlideLoginModule] - " + msg + " for user " + username
205                             + ": wrong password.");
206                     }
207                     throw new LoginException JavaDoc(msg);
208                 }
209                 else if (Domain.isDebugEnabled()) {
210                     Domain.debug("[SlideLoginModule] - user " + username
211                         + " successfully authenticated");
212                 }
213                 
214                 // find the roles the user is a member of
215
ArrayList JavaDoc list = new ArrayList JavaDoc();
216                 Enumeration JavaDoc roles = ((ACLSecurityImpl) m_security).
217                     getGroupMembership(slideToken, userNode);
218                 while (roles.hasMoreElements()) {
219                     String JavaDoc role = ((String JavaDoc) roles.nextElement()).substring(m_rolesPath.length()+1);
220                     if (Domain.isDebugEnabled()) {
221                         Domain.debug("[SlideLoginModule] - adding role " + role
222                             + " for user " + username);
223                     }
224                     SlideRole slideRole = new SlideRole(role);
225                     // apparently Jetty and Tomcat expect the roles to be
226
// at different locations:
227
// the Group is to satisfy Jetty, the list is to satisfy Tomcat
228
m_group.addMember(slideRole);
229                     list.add(slideRole);
230                 }
231                 m_roles = (Principal JavaDoc[]) list.toArray(new Principal JavaDoc[list.size()]);
232                 return true;
233             }
234             else {
235                 final String JavaDoc msg = "User " + username + " doesn't have his password " +
236                     "property set: can't authenticate.";
237                 Domain.warn("[SlideLoginModule] - " + msg);
238                 throw new LoginException JavaDoc(msg);
239             }
240         }
241         catch (IOException JavaDoc e) {
242             final String JavaDoc msg = "Failure during login()";
243             Domain.error("[SlideLoginModule] - " + msg,e);
244             throw new LoginException JavaDoc(msg);
245         }
246         catch (UnsupportedCallbackException JavaDoc e) {
247             final String JavaDoc msg = "Failure during login()";
248             Domain.error("[SlideLoginModule] - " + msg,e);
249             throw new LoginException JavaDoc(msg);
250         }
251         catch (SlideException e) {
252             final String JavaDoc msg = "Failure during login()";
253             Domain.error("[SlideLoginModule] - " + msg,e);
254             throw new LoginException JavaDoc(msg);
255         }
256     }
257
258     /**
259      * Phase 2 of authenticating a <code>Subject</code> when Phase 1
260      * was successful. This method is called if the <code>LoginContext</code>
261      * succeeded in the overall authentication chain.
262      *
263      * @return <code>true</code> if the authentication succeeded, or
264      * <code>false</code> if this <code>LoginModule</code> should be ignored
265      *
266      * @exception LoginException if the commit fails
267      */

268     public boolean commit() throws LoginException JavaDoc {
269         if (m_authenticated) {
270             m_subject.getPrincipals().add(m_principal);
271             m_subject.getPrincipals().add(m_group);
272             for (int i = 0; i < m_roles.length; i++) {
273                 m_subject.getPrincipals().add(m_roles[i]);
274             }
275         }
276         m_committed = true;
277         return m_authenticated;
278     }
279
280     /**
281      * Phase 2 of authenticating a <code>Subject</code> when Phase 1
282      * fails. This method is called if the <code>LoginContext</code>
283      * failed somewhere in the overall authentication chain.
284      *
285      * @return <code>true</code> if this method succeeded, or
286      * <code>false</code> if this <code>LoginModule</code> should be ignored
287      *
288      * @exception LoginException if the abort fails
289      */

290     public boolean abort() throws LoginException JavaDoc {
291         m_principal = null;
292         m_group = null;
293         m_roles = null;
294         return m_authenticated;
295     }
296
297     /**
298      * Log out this user.
299      *
300      * @return <code>true</code> in all cases because this
301      * <code>LoginModule</code> should not be ignored.
302      *
303      * @exception LoginException if logging out failed
304      */

305     public boolean logout() throws LoginException JavaDoc {
306         m_subject.getPrincipals().remove(m_principal);
307         m_subject.getPrincipals().remove(m_group);
308         for (int i = 0; i < m_roles.length; i++) {
309             m_subject.getPrincipals().remove(m_roles[i]);
310         }
311         m_committed = false;
312         m_principal = null;
313         m_group = null;
314         m_roles = null;
315         return true;
316     }
317     
318 }
319
Popular Tags