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