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.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   */
49  public abstract class AbstractLoginModule implements LoginModule
50  {
51      private CallbackHandler callbackHandler;
52  
53      private boolean authState = false;
54      private boolean commitState = false;
55      private JAASUserInfo currentUser;
56      private Subject subject;
57  
58      public class JAASUserInfo
59      {
60          private UserInfo user;
61          private Principal principal;
62          private List<JAASRole> roles;
63  
64          public JAASUserInfo (UserInfo u)
65          {
66              setUserInfo(u);
67          }
68  
69          public String getUserName ()
70          {
71              return this.user.getUserName();
72          }
73  
74          public Principal getPrincipal()
75          {
76              return this.principal;
77          }
78  
79          public void setUserInfo (UserInfo u)
80          {
81              this.user = u;
82              this.principal = new JAASPrincipal(u.getUserName());
83              this.roles = new ArrayList<JAASRole>();
84              if (u.getRoleNames() != null)
85              {
86                  Iterator<String> itor = u.getRoleNames().iterator();
87                  while (itor.hasNext())
88                      this.roles.add(new JAASRole((String)itor.next()));
89              }
90          }
91  
92          public void setJAASInfo (Subject subject)
93          {
94              subject.getPrincipals().add(this.principal);
95              subject.getPrivateCredentials().add(this.user.getCredential());
96              subject.getPrincipals().addAll(roles);
97          }
98  
99          public void unsetJAASInfo (Subject subject)
100         {
101             subject.getPrincipals().remove(this.principal);
102             subject.getPrivateCredentials().remove(this.user.getCredential());
103             subject.getPrincipals().removeAll(this.roles);
104         }
105 
106         public boolean checkCredential (Object suppliedCredential)
107         {
108             return this.user.checkCredential(suppliedCredential);
109         }
110     }
111 
112 
113 
114     public Subject getSubject ()
115     {
116         return this.subject;
117     }
118 
119     public void setSubject (Subject s)
120     {
121         this.subject = s;
122     }
123 
124     public JAASUserInfo getCurrentUser()
125     {
126         return this.currentUser;
127     }
128 
129     public void setCurrentUser (JAASUserInfo u)
130     {
131         this.currentUser = u;
132     }
133 
134     public CallbackHandler getCallbackHandler()
135     {
136         return this.callbackHandler;
137     }
138 
139     public void setCallbackHandler(CallbackHandler h)
140     {
141         this.callbackHandler = h;
142     }
143 
144     public boolean isAuthenticated()
145     {
146         return this.authState;
147     }
148 
149     public boolean isCommitted ()
150     {
151         return this.commitState;
152     }
153 
154     public void setAuthenticated (boolean authState)
155     {
156         this.authState = authState;
157     }
158 
159     public void setCommitted (boolean commitState)
160     {
161         this.commitState = commitState;
162     }
163     /**
164      * @see javax.security.auth.spi.LoginModule#abort()
165      * @throws LoginException
166      */
167     public boolean abort() throws LoginException
168     {
169         this.currentUser = null;
170         return (isAuthenticated() && isCommitted());
171     }
172 
173     /**
174      * @see javax.security.auth.spi.LoginModule#commit()
175      * @return true if committed, false if not (likely not authenticated)
176      * @throws LoginException
177      */
178     public boolean commit() throws LoginException
179     {
180 
181         if (!isAuthenticated())
182         {
183             currentUser = null;
184             setCommitted(false);
185             return false;
186         }
187 
188         setCommitted(true);
189         currentUser.setJAASInfo(subject);
190         return true;
191     }
192 
193 
194     public Callback[] configureCallbacks ()
195     {
196 
197         Callback[] callbacks = new Callback[3];
198         callbacks[0] = new NameCallback("Enter user name");
199         callbacks[1] = new ObjectCallback();
200         callbacks[2] = new PasswordCallback("Enter password", false); //only used if framework does not support the ObjectCallback
201         return callbacks;
202     }
203     
204     
205     public boolean isIgnored ()
206     {
207         return false;
208     }
209     
210     
211     public abstract UserInfo getUserInfo (String username) throws Exception;
212 
213 
214 
215     /**
216      * @see javax.security.auth.spi.LoginModule#login()
217      * @return true if is authenticated, false otherwise
218      * @throws LoginException
219      */
220     public boolean login() throws LoginException
221     {
222         try
223         {  
224             if (isIgnored())
225                 return false;
226             
227             if (callbackHandler == null)
228                 throw new LoginException ("No callback handler");
229 
230             Callback[] callbacks = configureCallbacks();
231             callbackHandler.handle(callbacks);
232 
233             String webUserName = ((NameCallback)callbacks[0]).getName();
234             Object webCredential = null;
235 
236             webCredential = ((ObjectCallback)callbacks[1]).getObject(); //first check if ObjectCallback has the credential
237             if (webCredential == null)
238                 webCredential = ((PasswordCallback)callbacks[2]).getPassword(); //use standard PasswordCallback
239 
240             if ((webUserName == null) || (webCredential == null))
241             {
242                 setAuthenticated(false);
243                 throw new FailedLoginException();
244             }
245 
246             UserInfo userInfo = getUserInfo(webUserName);
247 
248             if (userInfo == null)
249             {
250                 setAuthenticated(false);
251                 throw new FailedLoginException();
252             }
253 
254             currentUser = new JAASUserInfo(userInfo);
255             setAuthenticated(currentUser.checkCredential(webCredential));
256           
257             if (isAuthenticated())
258                 return true;
259             else
260                 throw new FailedLoginException();
261         }
262         catch (IOException e)
263         {
264             throw new LoginException (e.toString());
265         }
266         catch (UnsupportedCallbackException e)
267         {
268             throw new LoginException (e.toString());
269         }
270         catch (Exception e)
271         {
272             if (e instanceof LoginException)
273                 throw (LoginException)e;
274             throw new LoginException (e.toString());
275         }
276     }
277 
278     /**
279      * @see javax.security.auth.spi.LoginModule#logout()
280      * @return true always
281      * @throws LoginException
282      */
283     public boolean logout() throws LoginException
284     {
285         this.currentUser.unsetJAASInfo(this.subject);
286         return true;
287     }
288 
289     /**
290      * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
291      * @param subject
292      * @param callbackHandler
293      * @param sharedState
294      * @param options
295      */
296     public void initialize(Subject subject, CallbackHandler callbackHandler,
297             Map<String,?> sharedState, Map<String,?> options)
298     {
299         this.callbackHandler = callbackHandler;
300         this.subject = subject;
301     }
302 
303 }