KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > security > auth > spi > JDirectResourceLoginModule


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2005 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or 1any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: JDirectResourceLoginModule.java,v 1.1 2005/04/12 15:40:21 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas.security.auth.spi;
27
28 import java.util.ArrayList JavaDoc;
29 import java.util.Map JavaDoc;
30
31 import javax.naming.InitialContext JavaDoc;
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.login.LoginException JavaDoc;
38 import javax.security.auth.spi.LoginModule JavaDoc;
39
40 import org.objectweb.jonas.security.auth.JGroup;
41 import org.objectweb.jonas.security.auth.JPrincipal;
42 import org.objectweb.jonas.security.auth.JRole;
43 import org.objectweb.jonas.security.auth.callback.CertificateCallback;
44 import org.objectweb.jonas.security.realm.factory.JResource;
45 import org.objectweb.jonas.security.realm.factory.JResourceException;
46 import org.objectweb.jonas.security.realm.principals.User;
47
48 /**
49  * Define a login module for the authentication by using one of the JOnAS
50  * resource Datasource, LDAP or file
51  * @author Florent Benoit (initial developer)
52  * @author Alexandre Thaveau (add callback for certificates)
53  * @author Marc-Antoine Bourgeot (add callback for certificates)
54  */

55 public class JDirectResourceLoginModule implements LoginModule JavaDoc {
56
57     /**
58      * Subject used
59      */

60     private Subject JavaDoc subject = null;
61
62     /**
63      * The callbackhandler user for identification
64      */

65     private CallbackHandler JavaDoc callbackHandler = null;
66
67     /**
68      * Options for this login module
69      */

70     private Map JavaDoc options = null;
71
72     /**
73      * Name of the principal
74      */

75     private String JavaDoc principalName = null;
76
77     /**
78      * Password of the principal
79      */

80     private String JavaDoc password = null;
81
82     /**
83      * Roles of the principal
84      */

85     private ArrayList JavaDoc principalRoles = null;
86
87     /**
88      * Indicates if the login was successfull or not
89      */

90     private boolean loginWasDoneWithSuccess = false;;
91
92     /**
93      * Initialize this LoginModule. This method is called by the LoginContext
94      * after this LoginModule has been instantiated. The purpose of this method
95      * is to initialize this LoginModule with the relevant information. If this
96      * LoginModule does not understand any of the data stored in sharedState or
97      * options parameters, they can be ignored.
98      * @param subject the Subject to be authenticated.
99      * @param callbackHandler a CallbackHandler for communicating with the end
100      * user (prompting for usernames and passwords, for example).
101      * @param sharedState state shared with other configured LoginModules.
102      * @param options options specified in the login Configuration for this
103      * particular LoginModule.
104      */

105     public void initialize(Subject JavaDoc subject, CallbackHandler JavaDoc callbackHandler, Map JavaDoc sharedState, Map JavaDoc options) {
106         this.subject = subject;
107         this.callbackHandler = callbackHandler;
108         this.options = options;
109     }
110
111     /**
112      * Method to authenticate a Subject (phase 1). The implementation of this
113      * method authenticates a Subject. For example, it may prompt for Subject
114      * information such as a username and password and then attempt to verify
115      * the password. This method saves the result of the authentication attempt
116      * as private state within the LoginModule.
117      * @return true if the authentication succeeded, or false if this
118      * LoginModule should be ignored.
119      * @throws LoginException if the authentication fails
120      */

121     public boolean login() throws LoginException JavaDoc {
122
123         // No handler
124
if (callbackHandler == null) {
125             throw new LoginException JavaDoc("No handler has been defined.");
126         }
127
128         // Resource to be used (jndi name)
129
String JavaDoc resourceName = (String JavaDoc) options.get("resourceName");
130
131         // Use certificate callback
132
String JavaDoc certCallback = (String JavaDoc) options.get("certCallback");
133
134         // No resource is specified -> fail
135
if (resourceName == null) {
136             throw new LoginException JavaDoc(
137                     "You have to give an argument to this login module. The 'resourceName' parameter is required.");
138         }
139
140         // Get the resource and perform authentication
141
try {
142             InitialContext JavaDoc ictx = new InitialContext JavaDoc();
143             JResource jResource = null;
144             try {
145                 jResource = (JResource) ictx.lookup(resourceName);
146             } catch (Exception JavaDoc e) {
147                 throw createChainedLoginException("Cannot retrieve the resource '" + resourceName
148                         + "'. Check that this resource is bound in the registry", e);
149             }
150
151             // Handle callbacks
152
NameCallback JavaDoc nameCallback = new NameCallback JavaDoc("User :");
153             // False to hide password when it is entered
154
PasswordCallback JavaDoc passwordCallback = new PasswordCallback JavaDoc("Password :", false);
155             CertificateCallback certificateCallback = new CertificateCallback();
156             Callback JavaDoc[] callbacks = null;
157
158             if ((certCallback != null) && (Boolean.valueOf(certCallback).booleanValue())) {
159                 callbacks = new Callback JavaDoc[] {nameCallback, passwordCallback, certificateCallback};
160             } else {
161                 callbacks = new Callback JavaDoc[] {nameCallback, passwordCallback};
162             }
163             callbackHandler.handle(callbacks);
164
165             // Get values
166
principalName = nameCallback.getName();
167             if (principalName == null) {
168                 throw new LoginException JavaDoc("A null username is not a valid username");
169             }
170             if (principalName.startsWith("##DN##") && (certificateCallback.getUserCertificate() == null)) {
171                 throw new LoginException JavaDoc("Name must have a certificate to access this certificate based access login");
172             }
173             char[] arrayPass = passwordCallback.getPassword();
174             if (arrayPass == null) {
175                 throw new LoginException JavaDoc("A null password is not a valid password");
176             }
177
178             // Authentication - step 1 (user)
179
User user = null;
180             try {
181                 user = jResource.findUser(principalName);
182             } catch (Exception JavaDoc jre) {
183                 // could not retrieve user
184
throw createChainedLoginException("Can not find the user", jre);
185             }
186             // User was not found
187
if (user == null) {
188                 throw new LoginException JavaDoc("User '" + principalName + "' not found.");
189             }
190
191             // Authentication - step 2 (password)
192
boolean validated = jResource.isValidUser(user, new String JavaDoc(arrayPass));
193             if (!validated) {
194                 throw new LoginException JavaDoc("The password for the user '" + principalName + "' is not valid");
195             }
196
197             // user password
198
if (user.getPassword() != null) {
199                 this.password = user.getPassword();
200             } else {
201                 this.password = new String JavaDoc(arrayPass);
202             }
203
204             // Authentication - step 3 (roles)
205
try {
206                 principalRoles = jResource.getArrayListCombinedRoles(user);
207             } catch (JResourceException jre) {
208                 throw createChainedLoginException(jre.getMessage(), jre);
209             }
210
211         } catch (Exception JavaDoc e) {
212             throw createChainedLoginException("Error during the login phase : " + e.getMessage(), e);
213         }
214         loginWasDoneWithSuccess = true;
215         return true;
216     }
217
218     /**
219      * Create a LoginException with the given message and set the cause to the given Exception
220      * @param msg Exception message
221      * @param e Root cause
222      * @return LoginException the chained LoginException
223      */

224     private static LoginException JavaDoc createChainedLoginException(String JavaDoc msg, Exception JavaDoc e) {
225         LoginException JavaDoc le = new LoginException JavaDoc(msg);
226         le.initCause(e);
227         return le;
228     }
229
230     /**
231      * Method to commit the authentication process (phase 2). This method is
232      * called if the LoginContext's overall authentication succeeded (the
233      * relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
234      * succeeded). If this LoginModule's own authentication attempt succeeded
235      * (checked by retrieving the private state saved by the login method), then
236      * this method associates relevant Principals and Credentials with the
237      * Subject located in the LoginModule. If this LoginModule's own
238      * authentication attempted failed, then this method removes/destroys any
239      * state that was originally saved.
240      * @return true if this method succeeded, or false if this LoginModule
241      * should be ignored.
242      * @throws LoginException if the commit fails
243      */

244     public boolean commit() throws LoginException JavaDoc {
245
246             //overall authentication succeeded
247
if (loginWasDoneWithSuccess) {
248             // Add principal to the current subject
249
subject.getPrincipals().add(new JPrincipal(principalName));
250             subject.getPrivateCredentials().add(password);
251             JGroup group = new JGroup("Roles");
252
253             // Convert list into array
254
String JavaDoc[] roles = new String JavaDoc[principalRoles.size()];
255             roles = (String JavaDoc[]) principalRoles.toArray(roles);
256             int size = principalRoles.size();
257             for (int i = 0; i < size; i++) {
258                 group.addMember(new JRole(roles[i]));
259             }
260
261             // Add group
262
subject.getPrincipals().add(group);
263         }
264         return loginWasDoneWithSuccess;
265     }
266
267     /**
268      * Method to abort the authentication process (phase 2). This method is
269      * called if the LoginContext's overall authentication failed. (the relevant
270      * REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules did not
271      * succeed). If this LoginModule's own authentication attempt succeeded
272      * (checked by retrieving the private state saved by the login method), then
273      * this method cleans up any state that was originally saved.
274      * @return true if this method succeeded, or false if this LoginModule
275      * should be ignored.
276      * @throws LoginException if the abort fails
277      */

278     public boolean abort() throws LoginException JavaDoc {
279         //overall authentication succeeded
280
if (loginWasDoneWithSuccess) {
281             // Reset temp values
282
principalName = null;
283             principalRoles = null;
284         }
285         return loginWasDoneWithSuccess;
286     }
287
288     /**
289      * Method which logs out a Subject. An implementation of this method might
290      * remove/destroy a Subject's Principals and Credentials.
291      * @return true if this method succeeded, or false if this LoginModule
292      * should be ignored.
293      * @throws LoginException if the logout fails
294      */

295     public boolean logout() throws LoginException JavaDoc {
296
297         //overall authentication succeeded
298
if (loginWasDoneWithSuccess) {
299             // Remove principal name
300
subject.getPrincipals().remove(new JPrincipal(principalName));
301         }
302
303         return loginWasDoneWithSuccess;
304     }
305
306 }
Popular Tags