1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.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.jaas.callback.ObjectCallback;
39 import org.eclipse.jetty.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.HttpChannel;
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 final String DEFAULT_ROLE_CLASS_NAME = "org.eclipse.jetty.jaas.JAASRole";
61 public static final 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 HttpChannel channel = HttpChannel.getCurrentHttpChannel();
214
215 if (channel == null)
216 return;
217 Request request = channel.getRequest();
218
219 if (request != null)
220 {
221 RequestParameterCallback rpc = (RequestParameterCallback)callback;
222 rpc.setParameterValues(Arrays.asList(request.getParameterValues(rpc.getParameterName())));
223 }
224 }
225 else
226 throw new UnsupportedCallbackException(callback);
227 }
228 }
229 };
230 }
231 else
232 {
233 Class clazz = Loader.loadClass(getClass(), _callbackHandlerClass);
234 callbackHandler = (CallbackHandler)clazz.newInstance();
235 }
236
237
238 Subject subject = new Subject();
239 LoginContext loginContext = new LoginContext(_loginModuleName, subject, callbackHandler);
240
241 loginContext.login();
242
243
244 JAASUserPrincipal userPrincipal = new JAASUserPrincipal(getUserName(callbackHandler), subject, loginContext);
245 subject.getPrincipals().add(userPrincipal);
246
247 return _identityService.newUserIdentity(subject,userPrincipal,getGroups(subject));
248 }
249 catch (LoginException e)
250 {
251 LOG.warn(e);
252 }
253 catch (IOException e)
254 {
255 LOG.warn(e);
256 }
257 catch (UnsupportedCallbackException e)
258 {
259 LOG.warn(e);
260 }
261 catch (InstantiationException e)
262 {
263 LOG.warn(e);
264 }
265 catch (IllegalAccessException e)
266 {
267 LOG.warn(e);
268 }
269 catch (ClassNotFoundException e)
270 {
271 LOG.warn(e);
272 }
273 return null;
274 }
275
276
277 public boolean validate(UserIdentity user)
278 {
279
280 return true;
281 }
282
283
284 private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
285 {
286 NameCallback nameCallback = new NameCallback("foo");
287 callbackHandler.handle(new Callback[] {nameCallback});
288 return nameCallback.getName();
289 }
290
291
292 public void logout(UserIdentity user)
293 {
294 Set<JAASUserPrincipal> userPrincipals = user.getSubject().getPrincipals(JAASUserPrincipal.class);
295 LoginContext loginContext = userPrincipals.iterator().next().getLoginContext();
296 try
297 {
298 loginContext.logout();
299 }
300 catch (LoginException e)
301 {
302 LOG.warn(e);
303 }
304 }
305
306
307
308 @SuppressWarnings({ "unchecked", "rawtypes" })
309 private String[] getGroups (Subject subject)
310 {
311
312 String[] roleClassNames = getRoleClassNames();
313 Collection<String> groups = new LinkedHashSet<String>();
314 try
315 {
316 for (String roleClassName : roleClassNames)
317 {
318 Class load_class = Thread.currentThread().getContextClassLoader().loadClass(roleClassName);
319 Set<Principal> rolesForType = subject.getPrincipals(load_class);
320 for (Principal principal : rolesForType)
321 {
322 groups.add(principal.getName());
323 }
324 }
325
326 return groups.toArray(new String[groups.size()]);
327 }
328 catch (ClassNotFoundException e)
329 {
330 throw new RuntimeException(e);
331 }
332 }
333
334 }