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 import javax.servlet.ServletRequest;
38
39 import org.eclipse.jetty.jaas.callback.ObjectCallback;
40 import org.eclipse.jetty.jaas.callback.RequestParameterCallback;
41 import org.eclipse.jetty.security.DefaultIdentityService;
42 import org.eclipse.jetty.security.IdentityService;
43 import org.eclipse.jetty.security.LoginService;
44 import org.eclipse.jetty.server.UserIdentity;
45 import org.eclipse.jetty.util.Loader;
46 import org.eclipse.jetty.util.component.AbstractLifeCycle;
47 import org.eclipse.jetty.util.log.Log;
48 import org.eclipse.jetty.util.log.Logger;
49
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 @Override
185 public UserIdentity login(final String username,final Object credentials, final ServletRequest request)
186 {
187 try
188 {
189 CallbackHandler callbackHandler = null;
190
191
192 if (_callbackHandlerClass == null)
193 {
194 callbackHandler = new CallbackHandler()
195 {
196 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
197 {
198 for (Callback callback: callbacks)
199 {
200 if (callback instanceof NameCallback)
201 {
202 ((NameCallback)callback).setName(username);
203 }
204 else if (callback instanceof PasswordCallback)
205 {
206 ((PasswordCallback)callback).setPassword((char[]) credentials.toString().toCharArray());
207 }
208 else if (callback instanceof ObjectCallback)
209 {
210 ((ObjectCallback)callback).setObject(credentials);
211 }
212 else if (callback instanceof RequestParameterCallback)
213 {
214 RequestParameterCallback rpc = (RequestParameterCallback)callback;
215 if (request!=null)
216 rpc.setParameterValues(Arrays.asList(request.getParameterValues(rpc.getParameterName())));
217 }
218 else
219 throw new UnsupportedCallbackException(callback);
220 }
221 }
222 };
223 }
224 else
225 {
226 Class<?> clazz = Loader.loadClass(getClass(), _callbackHandlerClass);
227 callbackHandler = (CallbackHandler)clazz.newInstance();
228 }
229
230
231 Subject subject = new Subject();
232 LoginContext loginContext = new LoginContext(_loginModuleName, subject, callbackHandler);
233
234 loginContext.login();
235
236
237 JAASUserPrincipal userPrincipal = new JAASUserPrincipal(getUserName(callbackHandler), subject, loginContext);
238 subject.getPrincipals().add(userPrincipal);
239
240 return _identityService.newUserIdentity(subject,userPrincipal,getGroups(subject));
241 }
242 catch (LoginException e)
243 {
244 LOG.warn(e);
245 }
246 catch (IOException e)
247 {
248 LOG.warn(e);
249 }
250 catch (UnsupportedCallbackException e)
251 {
252 LOG.warn(e);
253 }
254 catch (InstantiationException e)
255 {
256 LOG.warn(e);
257 }
258 catch (IllegalAccessException e)
259 {
260 LOG.warn(e);
261 }
262 catch (ClassNotFoundException e)
263 {
264 LOG.warn(e);
265 }
266 return null;
267 }
268
269
270 public boolean validate(UserIdentity user)
271 {
272
273 return true;
274 }
275
276
277 private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
278 {
279 NameCallback nameCallback = new NameCallback("foo");
280 callbackHandler.handle(new Callback[] {nameCallback});
281 return nameCallback.getName();
282 }
283
284
285 public void logout(UserIdentity user)
286 {
287 Set<JAASUserPrincipal> userPrincipals = user.getSubject().getPrincipals(JAASUserPrincipal.class);
288 LoginContext loginContext = userPrincipals.iterator().next().getLoginContext();
289 try
290 {
291 loginContext.logout();
292 }
293 catch (LoginException e)
294 {
295 LOG.warn(e);
296 }
297 }
298
299
300
301 @SuppressWarnings({ "unchecked", "rawtypes" })
302 private String[] getGroups (Subject subject)
303 {
304
305 String[] roleClassNames = getRoleClassNames();
306 Collection<String> groups = new LinkedHashSet<String>();
307 try
308 {
309 for (String roleClassName : roleClassNames)
310 {
311 Class load_class = Thread.currentThread().getContextClassLoader().loadClass(roleClassName);
312 Set<Principal> rolesForType = subject.getPrincipals(load_class);
313 for (Principal principal : rolesForType)
314 {
315 groups.add(principal.getName());
316 }
317 }
318
319 return groups.toArray(new String[groups.size()]);
320 }
321 catch (ClassNotFoundException e)
322 {
323 throw new RuntimeException(e);
324 }
325 }
326
327 }