View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.plus.jaas.spi;
20  
21  import java.io.IOException;
22  import java.security.Principal;
23  import java.util.ArrayList;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  
28  import javax.security.auth.Subject;
29  import javax.security.auth.callback.Callback;
30  import javax.security.auth.callback.CallbackHandler;
31  import javax.security.auth.callback.NameCallback;
32  import javax.security.auth.callback.PasswordCallback;
33  import javax.security.auth.callback.UnsupportedCallbackException;
34  import javax.security.auth.login.LoginException;
35  import javax.security.auth.spi.LoginModule;
36  
37  import org.eclipse.jetty.plus.jaas.JAASPrincipal;
38  import org.eclipse.jetty.plus.jaas.JAASRole;
39  import org.eclipse.jetty.plus.jaas.callback.ObjectCallback;
40  
41  /**
42   * AbstractLoginModule
43   *
44   * Abstract base class for all LoginModules. Subclasses should 
45   * just need to implement getUserInfo method.
46   *
47   */
48  public abstract class AbstractLoginModule implements LoginModule
49  {
50      private CallbackHandler callbackHandler;
51      
52      private boolean authState = false;
53      private boolean commitState = false;
54      private JAASUserInfo currentUser;
55      private Subject subject;
56      
57      public class JAASUserInfo
58      {
59          private UserInfo user;
60          private Principal principal;
61          private List<JAASRole> roles;
62                
63          public JAASUserInfo (UserInfo u)
64          {
65              setUserInfo(u);
66          }
67          
68          public String getUserName ()
69          {
70              return this.user.getUserName();
71          }
72          
73          public Principal getPrincipal()
74          {
75              return this.principal;
76          }
77          
78          public void setUserInfo (UserInfo u)
79          {
80              this.user = u;
81              this.principal = new JAASPrincipal(u.getUserName());
82              this.roles = new ArrayList<JAASRole>();
83              if (u.getRoleNames() != null)
84              {
85                  Iterator<String> itor = u.getRoleNames().iterator();
86                  while (itor.hasNext())
87                      this.roles.add(new JAASRole((String)itor.next()));
88              }
89          }
90                 
91          public void setJAASInfo (Subject subject)
92          {
93              subject.getPrincipals().add(this.principal);
94              subject.getPrivateCredentials().add(this.user.getCredential());
95              subject.getPrincipals().addAll(roles);
96          }
97          
98          public void unsetJAASInfo (Subject subject)
99          {
100             subject.getPrincipals().remove(this.principal);
101             subject.getPrivateCredentials().remove(this.user.getCredential());
102             subject.getPrincipals().removeAll(this.roles);
103         }
104         
105         public boolean checkCredential (Object suppliedCredential)
106         {
107             return this.user.checkCredential(suppliedCredential);
108         }
109     }
110     
111     
112     
113     public Subject getSubject ()
114     {
115         return this.subject;
116     }
117     
118     public void setSubject (Subject s)
119     {
120         this.subject = s;
121     }
122     
123     public JAASUserInfo getCurrentUser()
124     {
125         return this.currentUser;
126     }
127     
128     public void setCurrentUser (JAASUserInfo u)
129     {
130         this.currentUser = u;
131     }
132     
133     public CallbackHandler getCallbackHandler()
134     {
135         return this.callbackHandler;
136     }
137     
138     public void setCallbackHandler(CallbackHandler h)
139     {
140         this.callbackHandler = h; 
141     }
142     
143     public boolean isAuthenticated()
144     {
145         return this.authState;
146     }
147     
148     public boolean isCommitted ()
149     {
150         return this.commitState;
151     }
152     
153     public void setAuthenticated (boolean authState)
154     {
155         this.authState = authState;
156     }
157     
158     public void setCommitted (boolean commitState)
159     {
160         this.commitState = commitState;
161     }
162     /** 
163      * @see javax.security.auth.spi.LoginModule#abort()
164      * @throws LoginException
165      */
166     public boolean abort() throws LoginException
167     {
168         this.currentUser = null;
169         return (isAuthenticated() && isCommitted());
170     }
171 
172     /** 
173      * @see javax.security.auth.spi.LoginModule#commit()
174      * @return true if committed, false if not (likely not authenticated)
175      * @throws LoginException
176      */
177     public boolean commit() throws LoginException
178     {
179 
180         if (!isAuthenticated())
181         {
182             currentUser = null;
183             setCommitted(false);
184             return false;
185         }
186         
187         setCommitted(true);
188         currentUser.setJAASInfo(subject);
189         return true;
190     }
191 
192     
193     public Callback[] configureCallbacks ()
194     {
195      
196         Callback[] callbacks = new Callback[3];
197         callbacks[0] = new NameCallback("Enter user name");
198         callbacks[1] = new ObjectCallback();
199         callbacks[2] = new PasswordCallback("Enter password", false); //only used if framework does not support the ObjectCallback
200         return callbacks;
201     }
202     
203     
204     
205     public abstract UserInfo getUserInfo (String username) throws Exception;
206     
207     
208     
209     /** 
210      * @see javax.security.auth.spi.LoginModule#login()
211      * @return true if is authenticated, false otherwise
212      * @throws LoginException
213      */
214     public boolean login() throws LoginException
215     {
216         try
217         {  
218             if (callbackHandler == null)
219                 throw new LoginException ("No callback handler");
220             
221             Callback[] callbacks = configureCallbacks();
222             callbackHandler.handle(callbacks);
223 
224             String webUserName = ((NameCallback)callbacks[0]).getName();
225             Object webCredential = null;
226             
227             webCredential = ((ObjectCallback)callbacks[1]).getObject(); //first check if ObjectCallback has the credential
228             if (webCredential == null)
229                 webCredential = ((PasswordCallback)callbacks[2]).getPassword(); //use standard PasswordCallback
230 
231             if ((webUserName == null) || (webCredential == null))
232             {
233                 setAuthenticated(false);
234                 return isAuthenticated();
235             }
236             
237             UserInfo userInfo = getUserInfo(webUserName);
238             
239             if (userInfo == null)
240             {
241                 setAuthenticated(false);
242                 return isAuthenticated();
243             }
244             
245             currentUser = new JAASUserInfo(userInfo);
246             setAuthenticated(currentUser.checkCredential(webCredential));
247             return isAuthenticated();
248         }
249         catch (IOException e)
250         {
251             throw new LoginException (e.toString());
252         }
253         catch (UnsupportedCallbackException e)
254         {
255             throw new LoginException (e.toString());
256         }
257         catch (Exception e)
258         {
259             e.printStackTrace();
260             throw new LoginException (e.toString());
261         }
262     }
263 
264     /** 
265      * @see javax.security.auth.spi.LoginModule#logout()
266      * @return true always
267      * @throws LoginException
268      */
269     public boolean logout() throws LoginException
270     {
271         this.currentUser.unsetJAASInfo(this.subject);
272         return true;
273     }
274 
275     /** 
276      * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
277      * @param subject
278      * @param callbackHandler
279      * @param sharedState
280      * @param options
281      */
282     public void initialize(Subject subject, CallbackHandler callbackHandler,
283             Map<String,?> sharedState, Map<String,?> options)
284     {
285         this.callbackHandler = callbackHandler;
286         this.subject = subject;
287     }
288 
289 }