View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 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.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.FailedLoginException;
35  import javax.security.auth.login.LoginException;
36  import javax.security.auth.spi.LoginModule;
37  
38  import org.eclipse.jetty.jaas.JAASPrincipal;
39  import org.eclipse.jetty.jaas.JAASRole;
40  import org.eclipse.jetty.jaas.callback.ObjectCallback;
41  
42  /**
43   * AbstractLoginModule
44   *
45   * Abstract base class for all LoginModules. Subclasses should
46   * just need to implement getUserInfo method.
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     public Subject getSubject ()
112     {
113         return this.subject;
114     }
115 
116     public void setSubject (Subject s)
117     {
118         this.subject = s;
119     }
120 
121     public JAASUserInfo getCurrentUser()
122     {
123         return this.currentUser;
124     }
125 
126     public void setCurrentUser (JAASUserInfo u)
127     {
128         this.currentUser = u;
129     }
130 
131     public CallbackHandler getCallbackHandler()
132     {
133         return this.callbackHandler;
134     }
135 
136     public void setCallbackHandler(CallbackHandler h)
137     {
138         this.callbackHandler = h;
139     }
140 
141     public boolean isAuthenticated()
142     {
143         return this.authState;
144     }
145 
146     public boolean isCommitted ()
147     {
148         return this.commitState;
149     }
150 
151     public void setAuthenticated (boolean authState)
152     {
153         this.authState = authState;
154     }
155 
156     public void setCommitted (boolean commitState)
157     {
158         this.commitState = commitState;
159     }
160     /**
161      * @see javax.security.auth.spi.LoginModule#abort()
162      * @throws LoginException if unable to abort
163      */
164     public boolean abort() throws LoginException
165     {
166         this.currentUser = null;
167         return (isAuthenticated() && isCommitted());
168     }
169 
170     /**
171      * @see javax.security.auth.spi.LoginModule#commit()
172      * @return true if committed, false if not (likely not authenticated)
173      * @throws LoginException if unable to commit
174      */
175     public boolean commit() throws LoginException
176     {
177 
178         if (!isAuthenticated())
179         {
180             currentUser = null;
181             setCommitted(false);
182             return false;
183         }
184 
185         setCommitted(true);
186         currentUser.setJAASInfo(subject);
187         return true;
188     }
189 
190 
191     public Callback[] configureCallbacks ()
192     {
193 
194         Callback[] callbacks = new Callback[3];
195         callbacks[0] = new NameCallback("Enter user name");
196         callbacks[1] = new ObjectCallback();
197         callbacks[2] = new PasswordCallback("Enter password", false); //only used if framework does not support the ObjectCallback
198         return callbacks;
199     }
200     
201     
202     public boolean isIgnored ()
203     {
204         return false;
205     }
206     
207     
208     public abstract UserInfo getUserInfo (String username) throws Exception;
209 
210 
211 
212     /**
213      * @see javax.security.auth.spi.LoginModule#login()
214      * @return true if is authenticated, false otherwise
215      * @throws LoginException if unable to login
216      */
217     public boolean login() throws LoginException
218     {
219         try
220         {  
221             if (isIgnored())
222                 return false;
223             
224             if (callbackHandler == null)
225                 throw new LoginException ("No callback handler");
226 
227             Callback[] callbacks = configureCallbacks();
228             callbackHandler.handle(callbacks);
229 
230             String webUserName = ((NameCallback)callbacks[0]).getName();
231             Object webCredential = null;
232 
233             webCredential = ((ObjectCallback)callbacks[1]).getObject(); //first check if ObjectCallback has the credential
234             if (webCredential == null)
235                 webCredential = ((PasswordCallback)callbacks[2]).getPassword(); //use standard PasswordCallback
236 
237             if ((webUserName == null) || (webCredential == null))
238             {
239                 setAuthenticated(false);
240                 throw new FailedLoginException();
241             }
242 
243             UserInfo userInfo = getUserInfo(webUserName);
244 
245             if (userInfo == null)
246             {
247                 setAuthenticated(false);
248                 throw new FailedLoginException();
249             }
250 
251             currentUser = new JAASUserInfo(userInfo);
252             setAuthenticated(currentUser.checkCredential(webCredential));
253           
254             if (isAuthenticated())
255                 return true;
256             else
257                 throw new FailedLoginException();
258         }
259         catch (IOException e)
260         {
261             throw new LoginException (e.toString());
262         }
263         catch (UnsupportedCallbackException e)
264         {
265             throw new LoginException (e.toString());
266         }
267         catch (Exception e)
268         {
269             if (e instanceof LoginException)
270                 throw (LoginException)e;
271             throw new LoginException (e.toString());
272         }
273     }
274 
275     /**
276      * @see javax.security.auth.spi.LoginModule#logout()
277      * @return true always
278      * @throws LoginException if unable to logout
279      */
280     public boolean logout() throws LoginException
281     {
282         this.currentUser.unsetJAASInfo(this.subject);
283         return true;
284     }
285 
286     /**
287      * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
288      * @param subject the subject
289      * @param callbackHandler the callback handler
290      * @param sharedState the shared state map
291      * @param options the option map
292      */
293     public void initialize(Subject subject, CallbackHandler callbackHandler,
294             Map<String,?> sharedState, Map<String,?> options)
295     {
296         this.callbackHandler = callbackHandler;
297         this.subject = subject;
298     }
299 
300 }