1   // ========================================================================
2   // $Id: AbstractLoginModule.java 3847 2008-10-17 18:22:10Z jesse $
3   // Copyright 1999-2004 Mort Bay Consulting Pty. Ltd.
4   // ------------------------------------------------------------------------
5   // Licensed under the Apache License, Version 2.0 (the "License");
6   // you may not use this file except in compliance with the License.
7   // You may obtain a copy of the License at 
8   // http://www.apache.org/licenses/LICENSE-2.0
9   // Unless required by applicable law or agreed to in writing, software
10  // distributed under the License is distributed on an "AS IS" BASIS,
11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  // See the License for the specific language governing permissions and
13  // limitations under the License.
14  // ========================================================================
15  
16  package org.mortbay.jetty.plus.jaas.spi;
17  
18  import java.io.IOException;
19  import java.security.Principal;
20  import java.util.ArrayList;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Map;
24  
25  import javax.security.auth.Subject;
26  import javax.security.auth.callback.Callback;
27  import javax.security.auth.callback.CallbackHandler;
28  import javax.security.auth.callback.NameCallback;
29  import javax.security.auth.callback.UnsupportedCallbackException;
30  import javax.security.auth.login.LoginException;
31  import javax.security.auth.spi.LoginModule;
32  
33  import org.mortbay.jetty.plus.jaas.JAASPrincipal;
34  import org.mortbay.jetty.plus.jaas.JAASRole;
35  import org.mortbay.jetty.plus.jaas.callback.ObjectCallback;
36  
37  /**
38   * AbstractLoginModule
39   *
40   * Abstract base class for all LoginModules. Subclasses should 
41   * just need to implement getUserInfo method.
42   *
43   */
44  public abstract class AbstractLoginModule implements LoginModule
45  {
46      private CallbackHandler callbackHandler;
47      
48      private boolean authState = false;
49      private boolean commitState = false;
50      private JAASUserInfo currentUser;
51      private Subject subject;
52      
53      public class JAASUserInfo
54      {
55          private UserInfo user;
56          private Principal principal;
57          private List roles;
58                
59          public JAASUserInfo (UserInfo u)
60          {
61              setUserInfo(u);
62          }
63          
64          public String getUserName ()
65          {
66              return this.user.getUserName();
67          }
68          
69          public Principal getPrincipal()
70          {
71              return this.principal;
72          }
73          
74          public void setUserInfo (UserInfo u)
75          {
76              this.user = u;
77              this.principal = new JAASPrincipal(u.getUserName());
78              this.roles = new ArrayList();
79              if (u.getRoleNames() != null)
80              {
81                  Iterator itor = u.getRoleNames().iterator();
82                  while (itor.hasNext())
83                      this.roles.add(new JAASRole((String)itor.next()));
84              }
85          }
86                 
87          public void setJAASInfo (Subject subject)
88          {
89              subject.getPrincipals().add(this.principal);
90              subject.getPrivateCredentials().add(this.user.getCredential());
91              subject.getPrincipals().addAll(roles);
92          }
93          
94          public void unsetJAASInfo (Subject subject)
95          {
96              subject.getPrincipals().remove(this.principal);
97              subject.getPrivateCredentials().remove(this.user.getCredential());
98              subject.getPrincipals().removeAll(this.roles);
99          }
100         
101         public boolean checkCredential (Object suppliedCredential)
102         {
103             return this.user.checkCredential(suppliedCredential);
104         }
105     }
106     
107     
108     
109     public Subject getSubject ()
110     {
111         return this.subject;
112     }
113     
114     public void setSubject (Subject s)
115     {
116         this.subject = s;
117     }
118     
119     public JAASUserInfo getCurrentUser()
120     {
121         return this.currentUser;
122     }
123     
124     public void setCurrentUser (JAASUserInfo u)
125     {
126         this.currentUser = u;
127     }
128     
129     public CallbackHandler getCallbackHandler()
130     {
131         return this.callbackHandler;
132     }
133     
134     public void setCallbackHandler(CallbackHandler h)
135     {
136         this.callbackHandler = h; 
137     }
138     
139     public boolean isAuthenticated()
140     {
141         return this.authState;
142     }
143     
144     public boolean isCommitted ()
145     {
146         return this.commitState;
147     }
148     
149     public void setAuthenticated (boolean authState)
150     {
151         this.authState = authState;
152     }
153     
154     public void setCommitted (boolean commitState)
155     {
156         this.commitState = commitState;
157     }
158     /** 
159      * @see javax.security.auth.spi.LoginModule#abort()
160      * @throws LoginException
161      */
162     public boolean abort() throws LoginException
163     {
164         this.currentUser = null;
165         return (isAuthenticated() && isCommitted());
166     }
167 
168     /** 
169      * @see javax.security.auth.spi.LoginModule#commit()
170      * @return
171      * @throws LoginException
172      */
173     public boolean commit() throws LoginException
174     {
175 
176         if (!isAuthenticated())
177         {
178             currentUser = null;
179             setCommitted(false);
180             return false;
181         }
182         
183         setCommitted(true);
184         currentUser.setJAASInfo(subject);
185         return true;
186     }
187 
188     
189     public Callback[] configureCallbacks ()
190     {
191      
192         Callback[] callbacks = new Callback[2];
193         callbacks[0] = new NameCallback("Enter user name");
194         callbacks[1] = new ObjectCallback();
195         return callbacks;
196     }
197     
198     
199     
200     public abstract UserInfo getUserInfo (String username) throws Exception;
201     
202     
203     
204     /** 
205      * @see javax.security.auth.spi.LoginModule#login()
206      * @return
207      * @throws LoginException
208      */
209     public boolean login() throws LoginException
210     {
211         try
212         {  
213             if (callbackHandler == null)
214                 throw new LoginException ("No callback handler");
215             
216             Callback[] callbacks = configureCallbacks();
217             callbackHandler.handle(callbacks);
218 
219             String webUserName = ((NameCallback)callbacks[0]).getName();
220             Object webCredential = ((ObjectCallback)callbacks[1]).getObject();
221 
222             if ((webUserName == null) || (webCredential == null))
223             {
224                 setAuthenticated(false);
225                 return isAuthenticated();
226             }
227             
228             UserInfo userInfo = getUserInfo(webUserName);
229             
230             if (userInfo == null)
231             {
232                 setAuthenticated(false);
233                 return isAuthenticated();
234             }
235             
236             currentUser = new JAASUserInfo(userInfo);
237             setAuthenticated(currentUser.checkCredential(webCredential));
238             return isAuthenticated();
239         }
240         catch (IOException e)
241         {
242             throw new LoginException (e.toString());
243         }
244         catch (UnsupportedCallbackException e)
245         {
246             throw new LoginException (e.toString());
247         }
248         catch (Exception e)
249         {
250             e.printStackTrace();
251             throw new LoginException (e.toString());
252         }
253     }
254 
255     /** 
256      * @see javax.security.auth.spi.LoginModule#logout()
257      * @return
258      * @throws LoginException
259      */
260     public boolean logout() throws LoginException
261     {
262         this.currentUser.unsetJAASInfo(this.subject);
263         return true;
264     }
265 
266     /** 
267      * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
268      * @param subject
269      * @param callbackHandler
270      * @param sharedState
271      * @param options
272      */
273     public void initialize(Subject subject, CallbackHandler callbackHandler,
274             Map sharedState, Map options)
275     {
276         this.callbackHandler = callbackHandler;
277         this.subject = subject;
278     }
279 
280 }