KickJava   Java API By Example, From Geeks To Geeks.

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


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 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: JResourceLoginModule.java,v 1.13 2005/04/19 07:59:00 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas.security.auth.spi;
27
28 import java.util.Map JavaDoc;
29
30 import javax.naming.InitialContext JavaDoc;
31 import javax.rmi.PortableRemoteObject 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.JonasSecurityServiceImpl;
41 import org.objectweb.jonas.security.auth.JSubject;
42 import org.objectweb.jonas.security.auth.callback.CertificateCallback;
43 import org.objectweb.jonas.security.realm.factory.JResourceRemote;
44
45 /**
46  * Define a login module for the authentication by using one of the JOnAS
47  * resource Datasource, LDAP or file.
48  * This LoginModule delegates to the Server the authentication.
49  * @author Florent Benoit
50  */

51 public class JResourceLoginModule implements LoginModule JavaDoc {
52
53     /**
54      * Default JOnAS server name
55      */

56     private static final String JavaDoc DEFAULT_SERVER_NAME = "jonas";
57
58     /**
59      * Subject used
60      */

61     private Subject JavaDoc subject = null;
62
63     /**
64      * Remote subject returned for authentication
65      */

66     private Subject JavaDoc remoteSubject = null;
67
68     /**
69      * The callbackhandler user for identification
70      */

71     private CallbackHandler JavaDoc callbackHandler = null;
72
73     /**
74      * Options for this login module
75      */

76     private Map JavaDoc options = null;
77
78     /**
79      * Password of the principal
80      */

81     private String JavaDoc password = null;
82
83     /**
84      * Indicates if the login was successfull or not
85      */

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

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

117     public boolean login() throws LoginException JavaDoc {
118
119         // No handler
120
if (callbackHandler == null) {
121             throw new LoginException JavaDoc("No handler has been defined.");
122         }
123
124         // Resource to be used (jndi name)
125
String JavaDoc resourceName = (String JavaDoc) options.get("resourceName");
126
127         // Name of the server for retrieving the security service
128
String JavaDoc serverName = (String JavaDoc) options.get("serverName");
129         if (serverName == null) {
130             serverName = DEFAULT_SERVER_NAME;
131         }
132
133         // Use certificate callback
134
String JavaDoc certCallback = (String JavaDoc) options.get("certCallback");
135
136         // No resource is specified -> fail
137
if (resourceName == null) {
138             throw new LoginException JavaDoc(
139                     "You have to give an argument to this login module. The 'resourceName' parameter is required.");
140         }
141
142         // Add the security name to servername to find the JNDI object
143
String JavaDoc remoteResourceName = serverName + JonasSecurityServiceImpl.REMOTE_RESOUCE;
144
145
146         // Get the resource and perform authentication
147
try {
148             InitialContext JavaDoc ictx = new InitialContext JavaDoc();
149             JResourceRemote jResourceRemote = null;
150             try {
151                 Object JavaDoc o = ictx.lookup(remoteResourceName);
152                 jResourceRemote = (JResourceRemote) PortableRemoteObject.narrow(o, JResourceRemote.class);
153             } catch (Exception JavaDoc e) {
154                 throw createChainedLoginException("Cannot retrieve the resource '" + remoteResourceName
155                         + "'. Check that this resource is bound in the registry and that the server name is correct", e);
156             }
157
158             // Handle callbacks
159
NameCallback JavaDoc nameCallback = new NameCallback JavaDoc("User :");
160             // False to hide password when it is entered
161
PasswordCallback JavaDoc passwordCallback = new PasswordCallback JavaDoc("Password :", false);
162             CertificateCallback certificateCallback = new CertificateCallback();
163             Callback JavaDoc[] callbacks = null;
164
165             if ((certCallback != null) && (Boolean.valueOf(certCallback).booleanValue())) {
166                 callbacks = new Callback JavaDoc[] {nameCallback, passwordCallback, certificateCallback};
167             } else {
168                 callbacks = new Callback JavaDoc[] {nameCallback, passwordCallback};
169             }
170             callbackHandler.handle(callbacks);
171
172             // Get values
173
String JavaDoc principalName = nameCallback.getName();
174             if (principalName == null) {
175                 throw new LoginException JavaDoc("A null username is not a valid username");
176             }
177             if (principalName.startsWith("##DN##") && (certificateCallback.getUserCertificate() == null)) {
178                 throw new LoginException JavaDoc("Name must have a certificate to access this certificate based access login");
179             }
180             char[] arrayPass = passwordCallback.getPassword();
181             if (arrayPass == null) {
182                 throw new LoginException JavaDoc("A null password is not a valid password");
183             }
184
185             password = new String JavaDoc(arrayPass);
186             JSubject jSubject = null;
187             try {
188                 jSubject = jResourceRemote.authenticate(principalName, arrayPass, resourceName);
189             } catch (Exception JavaDoc e) {
190                 throw createChainedLoginException("Cannot authenticate with principal name = '" + principalName + "' : " + e.getMessage(), e);
191             }
192             remoteSubject = new Subject JavaDoc();
193             remoteSubject.getPrivateCredentials().add(password);
194             remoteSubject.getPrincipals().add(jSubject.getName());
195             remoteSubject.getPrincipals().add(jSubject.getGroup());
196
197         } catch (Exception JavaDoc e) {
198             throw createChainedLoginException("Error during the login phase : " + e.getMessage(), e);
199         }
200         loginWasDoneWithSuccess = true;
201         return true;
202     }
203
204     /**
205      * Create a LoginException with the given message and set the cause to the given Exception
206      * @param msg Exception message
207      * @param e Root cause
208      * @return LoginException the chained LoginException
209      */

210     private static LoginException JavaDoc createChainedLoginException(String JavaDoc msg, Exception JavaDoc e) {
211         LoginException JavaDoc le = new LoginException JavaDoc(msg);
212         le.initCause(e);
213         return le;
214     }
215
216     /**
217      * Method to commit the authentication process (phase 2). This method is
218      * called if the LoginContext's overall authentication succeeded (the
219      * relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
220      * succeeded). If this LoginModule's own authentication attempt succeeded
221      * (checked by retrieving the private state saved by the login method), then
222      * this method associates relevant Principals and Credentials with the
223      * Subject located in the LoginModule. If this LoginModule's own
224      * authentication attempted failed, then this method removes/destroys any
225      * state that was originally saved.
226      * @return true if this method succeeded, or false if this LoginModule
227      * should be ignored.
228      * @throws LoginException if the commit fails
229      */

230     public boolean commit() throws LoginException JavaDoc {
231
232             //overall authentication succeeded
233
if (loginWasDoneWithSuccess && remoteSubject != null) {
234             // Add principal to the current subject
235
subject.getPrincipals().addAll(remoteSubject.getPrincipals());
236             subject.getPrivateCredentials().add(password);
237         }
238         return loginWasDoneWithSuccess;
239     }
240
241     /**
242      * Method to abort the authentication process (phase 2). This method is
243      * called if the LoginContext's overall authentication failed. (the relevant
244      * REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules did not
245      * succeed). If this LoginModule's own authentication attempt succeeded
246      * (checked by retrieving the private state saved by the login method), then
247      * this method cleans up any state that was originally saved.
248      * @return true if this method succeeded, or false if this LoginModule
249      * should be ignored.
250      * @throws LoginException if the abort fails
251      */

252     public boolean abort() throws LoginException JavaDoc {
253         //overall authentication succeeded
254
if (loginWasDoneWithSuccess && remoteSubject != null) {
255             // Reset temp values
256
remoteSubject = null;
257         }
258         return loginWasDoneWithSuccess;
259     }
260
261     /**
262      * Method which logs out a Subject. An implementation of this method might
263      * remove/destroy a Subject's Principals and Credentials.
264      * @return true if this method succeeded, or false if this LoginModule
265      * should be ignored.
266      * @throws LoginException if the logout fails
267      */

268     public boolean logout() throws LoginException JavaDoc {
269
270         //overall authentication succeeded
271
if (loginWasDoneWithSuccess && remoteSubject != null) {
272             // Remove principal name
273
subject.getPrincipals().remove(remoteSubject.getPrincipals());
274         }
275
276         return loginWasDoneWithSuccess;
277     }
278
279 }
Popular Tags