View Javadoc

1   /*
2    * $Id: DefaultLoginModule.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.extras.jaas.loginmodule;
12  
13  import java.io.IOException;
14  import java.util.List;
15  import java.util.Map;
16  import java.util.Vector;
17  
18  import javax.security.auth.Subject;
19  import javax.security.auth.callback.Callback;
20  import javax.security.auth.callback.CallbackHandler;
21  import javax.security.auth.callback.NameCallback;
22  import javax.security.auth.callback.PasswordCallback;
23  import javax.security.auth.callback.UnsupportedCallbackException;
24  import javax.security.auth.login.FailedLoginException;
25  import javax.security.auth.login.LoginException;
26  import javax.security.auth.spi.LoginModule;
27  
28  /**
29   * @author Marie.Rizzo This is the Default Login Module for the Mule Jaas
30   *         Authentication. It extends Jaas' own LoginModule interface.
31   */
32  public class DefaultLoginModule implements LoginModule
33  {
34  
35      // Callback Handlers
36      private CallbackHandler callbackHandler;
37  
38      // the authentication status
39      private boolean succeeded = false;
40      private boolean commitSucceeded = false;
41  
42      // username and password
43      private String username;
44      private String password;
45      private String credentials;
46      private List credentialList;
47  
48      /**
49       * Abort if authentication fails
50       * 
51       * @return boolean
52       * @throws LoginException
53       */
54      public final boolean abort() throws LoginException
55      {
56          if (!succeeded)
57          {
58              return false;
59          }
60          else if (succeeded && !commitSucceeded)
61          {
62              // login succeeded but overall authentication failed
63              succeeded = false;
64              username = null;
65              if (password != null)
66              {
67                  password = null;
68              }
69          }
70          else
71          {
72              // overall authentication succeeded and commit succeeded,
73              // but someone else's commit failed
74              logout();
75          }
76          return true;
77      }
78  
79      /**
80       * Commit if authentication succeeds, otherwise return false
81       * 
82       * @return boolean
83       * @throws LoginException
84       */
85      public final boolean commit() throws LoginException
86      {
87          if (!succeeded)
88          {
89              return false;
90          }
91          else
92          {
93              // in any case, clean out state
94              username = null;
95              password = null;
96  
97              commitSucceeded = true;
98              return true;
99          }
100     }
101 
102     /**
103      * Initialises the callbackHandler, the credentials and the credentials list
104      * 
105      * @param subject
106      * @param callbackHandler
107      * @param sharedState
108      * @param options
109      */
110     public final void initialize(Subject subject,
111                                  CallbackHandler callbackHandler,
112                                  Map sharedState,
113                                  Map options)
114     {
115         this.callbackHandler = callbackHandler;
116 
117         this.credentials = (String)options.get("credentials");
118         this.credentialList = getCredentialList(this.credentials);
119     }
120 
121     /**
122      * This method attempts to login the user by checking his credentials against
123      * those of the authorised users.
124      * 
125      * @throws LoginException This is thrown either when there is no callback Handler
126      *             or else when the user fails to be authenticated
127      */
128     public final boolean login() throws LoginException
129     {
130         if (callbackHandler == null)
131         {
132             throw new LoginException("Error: no CallbackHandler available "
133                                      + "to garner authentication information from the user");
134         }
135 
136         if (callbackHandler == null)
137         {
138             throw new LoginException("no handler");
139         }
140 
141         NameCallback nameCb = new NameCallback("user: ");
142         PasswordCallback passCb = new PasswordCallback("password: ", true);
143 
144         // Create the callbacks to send to the Callback Handler
145         Callback[] callbacks = new Callback[]{nameCb, passCb};
146 
147         // Call the handler to get the username and password of the user.
148         try
149         {
150             callbackHandler.handle(callbacks);
151         }
152         catch (IOException e)
153         {
154             throw new LoginException(e.toString());
155         }
156         catch (UnsupportedCallbackException e)
157         {
158             throw new LoginException("Error: " + e.getCallback().toString()
159                                      + " not available to garner authentication information "
160                                      + "from the user");
161         }
162 
163         username = nameCb.getName();
164         password = new String(passCb.getPassword());
165 
166         boolean usernameCorrect = false;
167         boolean passwordCorrect = false;
168         succeeded = false;
169 
170         // check the username and password against the list of authorised users
171         for (int i = 0; i < credentialList.size(); i = i + 2)
172         {
173             if (username.equals(credentialList.get(i).toString()))
174             {
175                 usernameCorrect = true;
176             }
177             else
178             {
179                 usernameCorrect = false;
180             }
181 
182             if (password.equals(credentialList.get(i + 1).toString()))
183             {
184                 passwordCorrect = true;
185             }
186             else
187             {
188                 passwordCorrect = false;
189             }
190 
191             // only if both the username and password are correct will the user be
192             // authenticated
193             if ((usernameCorrect) & (passwordCorrect))
194             {
195                 succeeded = true;
196             }
197         }
198 
199         if (succeeded)
200         {
201             return true;
202         }
203         else
204         {
205             succeeded = false;
206             username = null;
207             password = null;
208             if (!usernameCorrect)
209             {
210                 throw new FailedLoginException("User Name Incorrect");
211             }
212             else
213             {
214                 throw new FailedLoginException("Password Incorrect");
215             }
216         }
217     }
218 
219     /**
220      * Returns true when authentication succeeds or false when it fails
221      * 
222      * @return succeeded
223      */
224     public final boolean logout()
225     {
226         return succeeded;
227     }
228 
229     /**
230      * This method parses the credentials string and populates the credentials list
231      * against which the username and password submitted with the request will be
232      * checked
233      * 
234      * @param credentials
235      * @return outputList
236      */
237     public final List getCredentialList(String credentials)
238     {
239         boolean semicolonIsFound = false;
240         boolean dividerIsFound = false;
241         char[] credentialArray = credentials.toCharArray();
242         String username = "";
243         String password = "";
244         List outputList = new Vector();
245 
246         for (int i = 0; i < credentials.length(); i++)
247         {
248             if ((credentialArray[i] != ':') && (!dividerIsFound))
249             {
250                 username = username + credentialArray[i];
251             }
252             else if ((credentialArray[i] == ':') && (!dividerIsFound))
253             {
254                 dividerIsFound = true;
255             }
256             else if ((credentialArray[i] != ';') && (!semicolonIsFound) && (dividerIsFound))
257             {
258                 password = password + credentialArray[i];
259             }
260             else if ((credentialArray[i] != ';') && (!semicolonIsFound) && (dividerIsFound))
261             {
262                 password = password + credentialArray[i];
263             }
264             else if ((credentialArray[i] == ';') && (!semicolonIsFound) && (dividerIsFound))
265             {
266                 outputList.add(username);
267                 outputList.add(password);
268                 semicolonIsFound = false;
269                 dividerIsFound = false;
270                 username = "";
271                 password = "";
272             }
273         }
274         return outputList;
275     }
276 }