KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.Map JavaDoc;
12 import java.util.Set JavaDoc;
13 import java.security.Principal JavaDoc;
14 import javax.security.auth.Subject JavaDoc;
15 import javax.security.auth.callback.Callback JavaDoc;
16 import javax.security.auth.callback.CallbackHandler JavaDoc;
17 import javax.security.auth.callback.NameCallback JavaDoc;
18 import javax.security.auth.callback.PasswordCallback JavaDoc;
19 import javax.security.auth.callback.UnsupportedCallbackException JavaDoc;
20 import javax.security.auth.login.LoginException JavaDoc;
21 import javax.security.auth.spi.LoginModule JavaDoc;
22
23 /** A simple implementation of LoginModule for use by JBoss clients for
24  the establishment of the caller identity and credentials. This simply sets
25  the SecurityAssociation principal to the value of the NameCallback
26  filled in by the CallbackHandler, and the SecurityAssociation credential
27  to the value of the PasswordCallback filled in by the CallbackHandler.
28  This is a variation of the original ClientLoginModule that does not set the
29  SecurityAssociation information until commit and that uses the Subject
30  principal over a SimplePrincipal if available.
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>password-stacking=tryFirstPass|useFirstPass
38  When password-stacking option is set, this module first looks for a shared
39  username and password using "javax.security.auth.login.name" and
40  "javax.security.auth.login.password" respectively. This allows a module configured
41  prior to this one to establish a valid username and password that should be passed
42  to JBoss.
43  </ul>
44  
45  @author Scott.Stark@jboss.org
46  @version $Revision: 1.4 $
47  */

48 public class AltClientLoginModule implements LoginModule JavaDoc
49 {
50    private Subject JavaDoc subject;
51    private CallbackHandler JavaDoc callbackHandler;
52    /** Shared state between login modules */
53    private Map JavaDoc sharedState;
54    /** Flag indicating if the shared password should be used */
55    private boolean useFirstPass;
56    private String JavaDoc username;
57    private char[] password = null;
58
59    /**
60     * Initialize this LoginModule.
61     */

62    public void initialize(Subject JavaDoc subject, CallbackHandler JavaDoc callbackHandler,
63       Map JavaDoc sharedState, Map JavaDoc options)
64    {
65       this.subject = subject;
66       this.callbackHandler = callbackHandler;
67       this.sharedState = sharedState;
68       // Check for multi-threaded option
69
String JavaDoc mt = (String JavaDoc) options.get("multi-threaded");
70       if( mt != null && Boolean.valueOf(mt).booleanValue() == true )
71       { /* Turn on the server mode which uses thread local storage for
72                 the principal information.
73          */

74          SecurityAssociationActions.setServer();
75       }
76       
77         /* Check for password sharing options. Any non-null value for
78             password_stacking sets useFirstPass as this module has no way to
79             validate any shared password.
80          */

81       String JavaDoc passwordStacking = (String JavaDoc) options.get("password-stacking");
82       useFirstPass = passwordStacking != null;
83    }
84
85    /**
86     * Method to authenticate a Subject (phase 1).
87     */

88    public boolean login() throws LoginException JavaDoc
89    {
90       // If useFirstPass is true, look for the shared password
91
if( useFirstPass == true )
92       {
93             return true;
94       }
95
96      /* There is no password sharing or we are the first login module. Get
97          the username and password from the callback hander.
98       */

99       if (callbackHandler == null)
100          throw new LoginException JavaDoc("Error: no CallbackHandler available " +
101             "to garner authentication information from the user");
102       
103       PasswordCallback JavaDoc pc = new PasswordCallback JavaDoc("Password: ", false);
104       NameCallback JavaDoc nc = new NameCallback JavaDoc("User name: ", "guest");
105       Callback JavaDoc[] callbacks = {nc, pc};
106       try
107       {
108          char[] tmpPassword;
109          
110          callbackHandler.handle(callbacks);
111          username = nc.getName();
112          tmpPassword = pc.getPassword();
113          if (tmpPassword != null)
114          {
115             password = new char[tmpPassword.length];
116             System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
117             pc.clearPassword();
118          }
119       }
120       catch (java.io.IOException JavaDoc ioe)
121       {
122          throw new LoginException JavaDoc(ioe.toString());
123       }
124       catch (UnsupportedCallbackException JavaDoc uce)
125       {
126          throw new LoginException JavaDoc("Error: " + uce.getCallback().toString() +
127          " not available to garner authentication information " +
128          "from the user");
129       }
130       return true;
131    }
132
133    /** Method to commit the authentication process (phase 2). This is where the
134     * SecurityAssociation information is set. The principal is obtained from:
135     * The shared state javax.security.auth.login.name property when useFirstPass
136     * is true. If the value is a Principal it is used as is, else a SimplePrincipal
137     * using the value.toString() as its name is used. If useFirstPass the
138     * username obtained from the callback handler is used to build the
139     * SimplePrincipal. Both may be overriden if the resulting authenticated
140     * Subject principals set it not empty.
141     *
142     */

143    public boolean commit() throws LoginException JavaDoc
144    {
145       Set JavaDoc principals = subject.getPrincipals();
146       Principal JavaDoc p = null;
147       Object JavaDoc credential = password;
148       if( useFirstPass == true )
149       {
150          Object JavaDoc user = sharedState.get("javax.security.auth.login.name");
151          if( (user instanceof Principal JavaDoc) == false )
152          {
153             username = user != null ? user.toString() : "";
154             p = new SimplePrincipal(username);
155          }
156          else
157          {
158             p = (Principal JavaDoc) user;
159          }
160          credential = sharedState.get("javax.security.auth.login.password");
161       }
162       else
163       {
164          p = new SimplePrincipal(username);
165       }
166
167       if( principals.isEmpty() == false )
168          p = (Principal JavaDoc) principals.iterator().next();
169       SecurityAssociationActions.setPrincipalInfo(p, credential, subject);
170       return true;
171    }
172
173    /**
174     * Method to abort the authentication process (phase 2).
175     */

176    public boolean abort() throws LoginException JavaDoc
177    {
178       int length = password != null ? password.length : 0;
179       for(int n = 0; n < length; n ++)
180          password[n] = 0;
181       SecurityAssociationActions.clear();
182       return true;
183    }
184
185    public boolean logout() throws LoginException JavaDoc
186    {
187       SecurityAssociationActions.clear();
188       return true;
189    }
190 }
191
Popular Tags