1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.plus.jaas;
20
21 import java.io.IOException;
22 import java.security.Principal;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.LinkedHashSet;
27 import java.util.Set;
28
29 import javax.security.auth.Subject;
30 import javax.security.auth.callback.Callback;
31 import javax.security.auth.callback.CallbackHandler;
32 import javax.security.auth.callback.NameCallback;
33 import javax.security.auth.callback.PasswordCallback;
34 import javax.security.auth.callback.UnsupportedCallbackException;
35 import javax.security.auth.login.LoginContext;
36 import javax.security.auth.login.LoginException;
37
38 import org.eclipse.jetty.plus.jaas.callback.ObjectCallback;
39 import org.eclipse.jetty.plus.jaas.callback.RequestParameterCallback;
40 import org.eclipse.jetty.security.DefaultIdentityService;
41 import org.eclipse.jetty.security.IdentityService;
42 import org.eclipse.jetty.security.LoginService;
43 import org.eclipse.jetty.server.AbstractHttpConnection;
44 import org.eclipse.jetty.server.Request;
45 import org.eclipse.jetty.server.UserIdentity;
46 import org.eclipse.jetty.util.Loader;
47 import org.eclipse.jetty.util.component.AbstractLifeCycle;
48 import org.eclipse.jetty.util.log.Log;
49 import org.eclipse.jetty.util.log.Logger;
50
51
52
53
54
55
56 public class JAASLoginService extends AbstractLifeCycle implements LoginService
57 {
58 private static final Logger LOG = Log.getLogger(JAASLoginService.class);
59
60 public static String DEFAULT_ROLE_CLASS_NAME = "org.eclipse.jetty.plus.jaas.JAASRole";
61 public static String[] DEFAULT_ROLE_CLASS_NAMES = {DEFAULT_ROLE_CLASS_NAME};
62
63 protected String[] _roleClassNames = DEFAULT_ROLE_CLASS_NAMES;
64 protected String _callbackHandlerClass;
65 protected String _realmName;
66 protected String _loginModuleName;
67 protected JAASUserPrincipal _defaultUser = new JAASUserPrincipal(null, null, null);
68 protected IdentityService _identityService;
69
70
71
72
73
74
75 public JAASLoginService()
76 {
77 }
78
79
80
81
82
83
84
85
86 public JAASLoginService(String name)
87 {
88 this();
89 _realmName = name;
90 _loginModuleName = name;
91 }
92
93
94
95
96
97
98
99
100 public String getName()
101 {
102 return _realmName;
103 }
104
105
106
107
108
109
110
111
112 public void setName (String name)
113 {
114 _realmName = name;
115 }
116
117
118
119
120
121 public IdentityService getIdentityService()
122 {
123 return _identityService;
124 }
125
126
127
128
129
130 public void setIdentityService(IdentityService identityService)
131 {
132 _identityService = identityService;
133 }
134
135
136
137
138
139
140
141
142 public void setLoginModuleName (String name)
143 {
144 _loginModuleName = name;
145 }
146
147
148 public void setCallbackHandlerClass (String classname)
149 {
150 _callbackHandlerClass = classname;
151 }
152
153
154 public void setRoleClassNames (String[] classnames)
155 {
156 ArrayList<String> tmp = new ArrayList<String>();
157
158 if (classnames != null)
159 tmp.addAll(Arrays.asList(classnames));
160
161 if (!tmp.contains(DEFAULT_ROLE_CLASS_NAME))
162 tmp.add(DEFAULT_ROLE_CLASS_NAME);
163 _roleClassNames = tmp.toArray(new String[tmp.size()]);
164 }
165
166
167 public String[] getRoleClassNames()
168 {
169 return _roleClassNames;
170 }
171
172
173
174
175
176 protected void doStart() throws Exception
177 {
178 if (_identityService==null)
179 _identityService=new DefaultIdentityService();
180 super.doStart();
181 }
182
183
184 public UserIdentity login(final String username,final Object credentials)
185 {
186 try
187 {
188 CallbackHandler callbackHandler = null;
189
190
191 if (_callbackHandlerClass == null)
192 {
193 callbackHandler = new CallbackHandler()
194 {
195 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
196 {
197 for (Callback callback: callbacks)
198 {
199 if (callback instanceof NameCallback)
200 {
201 ((NameCallback)callback).setName(username);
202 }
203 else if (callback instanceof PasswordCallback)
204 {
205 ((PasswordCallback)callback).setPassword((char[]) credentials.toString().toCharArray());
206 }
207 else if (callback instanceof ObjectCallback)
208 {
209 ((ObjectCallback)callback).setObject(credentials);
210 }
211 else if (callback instanceof RequestParameterCallback)
212 {
213 AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection();
214 Request request = (connection == null? null : connection.getRequest());
215
216 if (request != null)
217 {
218 RequestParameterCallback rpc = (RequestParameterCallback)callback;
219 rpc.setParameterValues(Arrays.asList(request.getParameterValues(rpc.getParameterName())));
220 }
221 }
222 else
223 throw new UnsupportedCallbackException(callback);
224 }
225 }
226 };
227 }
228 else
229 {
230 Class clazz = Loader.loadClass(getClass(), _callbackHandlerClass);
231 callbackHandler = (CallbackHandler)clazz.newInstance();
232 }
233
234
235 Subject subject = new Subject();
236 LoginContext loginContext = new LoginContext(_loginModuleName, subject, callbackHandler);
237
238 loginContext.login();
239
240
241 JAASUserPrincipal userPrincipal = new JAASUserPrincipal(getUserName(callbackHandler), subject, loginContext);
242 subject.getPrincipals().add(userPrincipal);
243
244 return _identityService.newUserIdentity(subject,userPrincipal,getGroups(subject));
245 }
246 catch (LoginException e)
247 {
248 LOG.debug(e);
249 }
250 catch (IOException e)
251 {
252 LOG.info(e.getMessage());
253 LOG.debug(e);
254 }
255 catch (UnsupportedCallbackException e)
256 {
257 LOG.info(e.getMessage());
258 LOG.debug(e);
259 }
260 catch (InstantiationException e)
261 {
262 LOG.info(e.getMessage());
263 LOG.debug(e);
264 }
265 catch (IllegalAccessException e)
266 {
267 LOG.info(e.getMessage());
268 LOG.debug(e);
269 }
270 catch (ClassNotFoundException e)
271 {
272 LOG.info(e.getMessage());
273 LOG.debug(e);
274 }
275 return null;
276 }
277
278
279 public boolean validate(UserIdentity user)
280 {
281
282 return true;
283 }
284
285
286 private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
287 {
288 NameCallback nameCallback = new NameCallback("foo");
289 callbackHandler.handle(new Callback[] {nameCallback});
290 return nameCallback.getName();
291 }
292
293
294 public void logout(UserIdentity user)
295 {
296 Set<JAASUserPrincipal> userPrincipals = user.getSubject().getPrincipals(JAASUserPrincipal.class);
297 LoginContext loginContext = userPrincipals.iterator().next().getLoginContext();
298 try
299 {
300 loginContext.logout();
301 }
302 catch (LoginException e)
303 {
304 LOG.warn(e);
305 }
306 }
307
308
309
310 @SuppressWarnings({ "unchecked", "rawtypes" })
311 private String[] getGroups (Subject subject)
312 {
313
314 String[] roleClassNames = getRoleClassNames();
315 Collection<String> groups = new LinkedHashSet<String>();
316 try
317 {
318 for (String roleClassName : roleClassNames)
319 {
320 Class load_class = Thread.currentThread().getContextClassLoader().loadClass(roleClassName);
321 Set<Principal> rolesForType = subject.getPrincipals(load_class);
322 for (Principal principal : rolesForType)
323 {
324 groups.add(principal.getName());
325 }
326 }
327
328 return groups.toArray(new String[groups.size()]);
329 }
330 catch (ClassNotFoundException e)
331 {
332 throw new RuntimeException(e);
333 }
334 }
335
336 }