View Javadoc

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