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 public class JAASLoginService extends AbstractLifeCycle implements LoginService
56 {
57 private static final Logger LOG = Log.getLogger(JAASLoginService.class);
58
59 public static final String DEFAULT_ROLE_CLASS_NAME = "org.eclipse.jetty.jaas.JAASRole";
60 public static final String[] DEFAULT_ROLE_CLASS_NAMES = {DEFAULT_ROLE_CLASS_NAME};
61
62 protected String[] _roleClassNames = DEFAULT_ROLE_CLASS_NAMES;
63 protected String _callbackHandlerClass;
64 protected String _realmName;
65 protected String _loginModuleName;
66 protected JAASUserPrincipal _defaultUser = new JAASUserPrincipal(null, null, null);
67 protected IdentityService _identityService;
68
69
70
71
72
73
74 public JAASLoginService()
75 {
76 }
77
78
79
80
81
82
83
84
85 public JAASLoginService(String name)
86 {
87 this();
88 _realmName = name;
89 _loginModuleName = name;
90 }
91
92
93
94
95
96
97
98
99 public String getName()
100 {
101 return _realmName;
102 }
103
104
105
106
107
108
109
110
111 public void setName (String name)
112 {
113 _realmName = name;
114 }
115
116
117
118
119
120 public IdentityService getIdentityService()
121 {
122 return _identityService;
123 }
124
125
126
127
128
129 public void setIdentityService(IdentityService identityService)
130 {
131 _identityService = identityService;
132 }
133
134
135
136
137
138
139
140
141 public void setLoginModuleName (String name)
142 {
143 _loginModuleName = name;
144 }
145
146
147 public void setCallbackHandlerClass (String classname)
148 {
149 _callbackHandlerClass = classname;
150 }
151
152
153 public void setRoleClassNames (String[] classnames)
154 {
155 ArrayList<String> tmp = new ArrayList<String>();
156
157 if (classnames != null)
158 tmp.addAll(Arrays.asList(classnames));
159
160 if (!tmp.contains(DEFAULT_ROLE_CLASS_NAME))
161 tmp.add(DEFAULT_ROLE_CLASS_NAME);
162 _roleClassNames = tmp.toArray(new String[tmp.size()]);
163 }
164
165
166 public String[] getRoleClassNames()
167 {
168 return _roleClassNames;
169 }
170
171
172
173
174
175 protected void doStart() throws Exception
176 {
177 if (_identityService==null)
178 _identityService=new DefaultIdentityService();
179 super.doStart();
180 }
181
182
183 @Override
184 public UserIdentity login(final String username,final Object credentials, final ServletRequest request)
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 RequestParameterCallback rpc = (RequestParameterCallback)callback;
214 if (request!=null)
215 rpc.setParameterValues(Arrays.asList(request.getParameterValues(rpc.getParameterName())));
216 }
217 else
218 throw new UnsupportedCallbackException(callback);
219 }
220 }
221 };
222 }
223 else
224 {
225 Class<?> clazz = Loader.loadClass(getClass(), _callbackHandlerClass);
226 callbackHandler = (CallbackHandler)clazz.newInstance();
227 }
228
229
230 Subject subject = new Subject();
231 LoginContext loginContext = new LoginContext(_loginModuleName, subject, callbackHandler);
232
233 loginContext.login();
234
235
236 JAASUserPrincipal userPrincipal = new JAASUserPrincipal(getUserName(callbackHandler), subject, loginContext);
237 subject.getPrincipals().add(userPrincipal);
238
239 return _identityService.newUserIdentity(subject,userPrincipal,getGroups(subject));
240 }
241 catch (LoginException e)
242 {
243 LOG.warn(e);
244 }
245 catch (IOException e)
246 {
247 LOG.warn(e);
248 }
249 catch (UnsupportedCallbackException e)
250 {
251 LOG.warn(e);
252 }
253 catch (InstantiationException e)
254 {
255 LOG.warn(e);
256 }
257 catch (IllegalAccessException e)
258 {
259 LOG.warn(e);
260 }
261 catch (ClassNotFoundException e)
262 {
263 LOG.warn(e);
264 }
265 return null;
266 }
267
268
269 public boolean validate(UserIdentity user)
270 {
271
272 return true;
273 }
274
275
276 private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
277 {
278 NameCallback nameCallback = new NameCallback("foo");
279 callbackHandler.handle(new Callback[] {nameCallback});
280 return nameCallback.getName();
281 }
282
283
284 public void logout(UserIdentity user)
285 {
286 Set<JAASUserPrincipal> userPrincipals = user.getSubject().getPrincipals(JAASUserPrincipal.class);
287 LoginContext loginContext = userPrincipals.iterator().next().getLoginContext();
288 try
289 {
290 loginContext.logout();
291 }
292 catch (LoginException e)
293 {
294 LOG.warn(e);
295 }
296 }
297
298
299
300 @SuppressWarnings({ "unchecked", "rawtypes" })
301 private String[] getGroups (Subject subject)
302 {
303
304 String[] roleClassNames = getRoleClassNames();
305 Collection<String> groups = new LinkedHashSet<String>();
306 try
307 {
308 for (String roleClassName : roleClassNames)
309 {
310 Class load_class = Thread.currentThread().getContextClassLoader().loadClass(roleClassName);
311 Set<Principal> rolesForType = subject.getPrincipals(load_class);
312 for (Principal principal : rolesForType)
313 {
314 groups.add(principal.getName());
315 }
316 }
317
318 return groups.toArray(new String[groups.size()]);
319 }
320 catch (ClassNotFoundException e)
321 {
322 throw new RuntimeException(e);
323 }
324 }
325
326 }