View Javadoc

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