KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > security > ClientLoginModule


1 /*
2  * JBoss, the OpenSource WebOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7
8 package org.jboss.security;
9
10
11 import java.io.IOException JavaDoc;
12 import java.security.Principal JavaDoc;
13 import java.util.Map JavaDoc;
14 import java.util.Set JavaDoc;
15 import javax.security.auth.Subject JavaDoc;
16 import javax.security.auth.callback.Callback JavaDoc;
17 import javax.security.auth.callback.CallbackHandler JavaDoc;
18 import javax.security.auth.callback.NameCallback JavaDoc;
19 import javax.security.auth.callback.PasswordCallback JavaDoc;
20 import javax.security.auth.callback.UnsupportedCallbackException JavaDoc;
21 import javax.security.auth.login.LoginException JavaDoc;
22 import javax.security.auth.spi.LoginModule JavaDoc;
23
24 import org.jboss.logging.Logger;
25
26 /** A simple implementation of LoginModule for use by JBoss clients for
27  the establishment of the caller identity and credentials. This simply sets
28  the SecurityAssociation principal to the value of the NameCallback
29  filled in by the CallbackHandler, and the SecurityAssociation credential
30  to the value of the PasswordCallback filled in by the CallbackHandler.
31  
32  It has the following options:
33  <ul>
34  <li>multi-threaded=[true|false]
35  When the multi-threaded option is set to true, the SecurityAssociation.setServer()
36  so that each login thread has its own principal and credential storage.
37  <li>restore-login-identity=[true|false]
38  When restore-login-identity is true, the SecurityAssociation principal
39  and credential seen on entry to the login() method are saved and restored
40  on either abort or logout. When false (the default), the abort and logout
41  simply clear the SecurityAssociation. A restore-login-identity of true is
42  needed if one need to change identities and then restore the original
43  caller identity.
44  <li>password-stacking=tryFirstPass|useFirstPass
45  When password-stacking option is set, this module first looks for a shared
46  username and password using "javax.security.auth.login.name" and
47  "javax.security.auth.login.password" respectively. This allows a module configured
48  prior to this one to establish a valid username and password that should be passed
49  to JBoss.
50  </ul>
51  
52  @author <a HREF="mailto:on@ibis.odessa.ua">Oleg Nitz</a>
53  @author Scott.Stark@jboss.org
54  */

55 public class ClientLoginModule implements LoginModule JavaDoc
56 {
57    private static Logger log = Logger.getLogger(ClientLoginModule.class);
58    private Subject JavaDoc subject;
59    private CallbackHandler JavaDoc callbackHandler;
60    /** The principal set during login() */
61    private Principal JavaDoc loginPrincipal;
62    /** The credential set during login() */
63    private Object JavaDoc loginCredential;
64    /** Shared state between login modules */
65    private Map JavaDoc sharedState;
66    /** Flag indicating if the shared password should be used */
67    private boolean useFirstPass;
68    /** Flag indicating if the SecurityAssociation existing at login should
69     be restored on logout.
70     */

71    private boolean restoreLoginIdentity;
72    /** The SecurityAssociation principal seen on entry to login() */
73    private Principal JavaDoc restorePrincipal;
74    /** The SecurityAssociation credential seen on entry to login() */
75    private Object JavaDoc restoreCredential;
76    /** The SecurityAssociation subject seen on entry to login() */
77    private Subject JavaDoc restoreSubject;
78    private boolean trace;
79
80    /** Initialize this LoginModule. This checks for the options:
81     multi-threaded
82     restore-login-identity
83     password-stacking
84     */

85    public void initialize(Subject JavaDoc subject, CallbackHandler JavaDoc callbackHandler,
86                           Map JavaDoc sharedState, Map JavaDoc options)
87    {
88       this.trace = log.isTraceEnabled();
89       this.subject = subject;
90       this.callbackHandler = callbackHandler;
91       this.sharedState = sharedState;
92       // Check for multi-threaded option
93
String JavaDoc flag = (String JavaDoc) options.get("multi-threaded");
94       if (Boolean.valueOf(flag).booleanValue() == true)
95       { /* Turn on the server mode which uses thread local storage for
96                 the principal information.
97          */

98          if( trace )
99             log.trace("Enabling multi-threaded mode");
100          SecurityAssociationActions.setServer();
101       }
102
103       flag = (String JavaDoc) options.get("restore-login-identity");
104       restoreLoginIdentity = Boolean.valueOf(flag).booleanValue();
105
106       /* Check for password sharing options. Any non-null value for
107           password_stacking sets useFirstPass as this module has no way to
108           validate any shared password.
109        */

110       String JavaDoc passwordStacking = (String JavaDoc) options.get("password-stacking");
111       useFirstPass = passwordStacking != null;
112    }
113
114    /**
115     * Method to authenticate a Subject (phase 1).
116     */

117    public boolean login() throws LoginException JavaDoc
118    {
119       if( trace )
120          log.trace("Begin login");
121       if( restoreLoginIdentity == true )
122       {
123          restorePrincipal = SecurityAssociationActions.getPrincipal();
124          restoreCredential = SecurityAssociationActions.getCredential();
125          restoreSubject = SecurityAssociationActions.getSubject();
126       }
127
128       // If useFirstPass is true, look for the shared password
129
if (useFirstPass == true)
130       {
131          try
132          {
133             Object JavaDoc name = sharedState.get("javax.security.auth.login.name");
134             if ((name instanceof Principal JavaDoc) == false)
135             {
136                String JavaDoc username = name != null ? name.toString() : "";
137                loginPrincipal = new SimplePrincipal(username);
138             } else
139             {
140                loginPrincipal = (Principal JavaDoc) name;
141             }
142             loginCredential = sharedState.get("javax.security.auth.login.password");
143             return true;
144          }
145          catch (Exception JavaDoc e)
146          { // Dump the exception and continue
147
log.debug("Failed to obtain shared state", e);
148          }
149       }
150
151       /* There is no password sharing or we are the first login module. Get
152           the username and password from the callback hander.
153        */

154       if (callbackHandler == null)
155          throw new LoginException JavaDoc("Error: no CallbackHandler available " +
156             "to garner authentication information from the user");
157
158       PasswordCallback JavaDoc pc = new PasswordCallback JavaDoc("Password: ", false);
159       NameCallback JavaDoc nc = new NameCallback JavaDoc("User name: ", "guest");
160       Callback JavaDoc[] callbacks = {nc, pc};
161       try
162       {
163          String JavaDoc username;
164          char[] password = null;
165          char[] tmpPassword;
166
167          callbackHandler.handle(callbacks);
168          username = nc.getName();
169          loginPrincipal = new SimplePrincipal(username);
170          tmpPassword = pc.getPassword();
171          if (tmpPassword != null)
172          {
173             password = new char[tmpPassword.length];
174             System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
175             pc.clearPassword();
176          }
177          loginCredential = password;
178          if( trace )
179          {
180             String JavaDoc credType = "null";
181             if( loginCredential != null )
182                credType = loginCredential.getClass().getName();
183             log.trace("Obtained login: "+loginPrincipal
184                +", credential.class: " + credType);
185          }
186       }
187       catch (IOException JavaDoc ioe)
188       {
189          LoginException JavaDoc ex = new LoginException JavaDoc(ioe.toString());
190          ex.initCause(ioe);
191          throw ex;
192       }
193       catch (UnsupportedCallbackException JavaDoc uce)
194       {
195          LoginException JavaDoc ex = new LoginException JavaDoc("Error: " + uce.getCallback().toString() +
196             ", not able to use this callback for username/password");
197          ex.initCause(uce);
198          throw ex;
199       }
200       if( trace )
201          log.trace("End login");
202       return true;
203    }
204
205    /**
206     * Method to commit the authentication process (phase 2).
207     */

208    public boolean commit() throws LoginException JavaDoc
209    {
210       if( trace )
211          log.trace("commit, subject="+subject);
212       // Set the login principal and credential and subject
213
SecurityAssociationActions.setPrincipalInfo(loginPrincipal, loginCredential, subject);
214
215       // Add the login principal to the subject if is not there
216
Set JavaDoc principals = subject.getPrincipals();
217       if (principals.contains(loginPrincipal) == false)
218          principals.add(loginPrincipal);
219       return true;
220    }
221
222    /**
223     * Method to abort the authentication process (phase 2).
224     */

225    public boolean abort() throws LoginException JavaDoc
226    {
227       if( trace )
228          log.trace("abort");
229       SecurityAssociationActions.clear();
230       if( restoreLoginIdentity == true )
231       {
232          SecurityAssociationActions.setPrincipalInfo(restorePrincipal,
233             restoreCredential, restoreSubject);
234       }
235
236       return true;
237    }
238
239    public boolean logout() throws LoginException JavaDoc
240    {
241       if( trace )
242          log.trace("logout");
243       SecurityAssociationActions.clear();
244       if( restoreLoginIdentity == true )
245       {
246          SecurityAssociationActions.setPrincipalInfo(restorePrincipal,
247             restoreCredential, restoreSubject);
248       }
249       Set JavaDoc principals = subject.getPrincipals();
250       principals.remove(loginPrincipal);
251       return true;
252    }
253 }
254
Popular Tags