1 package com.atlassian.seraph.filter;
2
3 import com.atlassian.seraph.auth.Authenticator;
4 import com.atlassian.seraph.auth.AuthenticatorException;
5 import com.atlassian.seraph.config.SecurityConfig;
6 import com.atlassian.seraph.elevatedsecurity.CountingElevatedSecurityGuard;
7 import com.atlassian.seraph.interceptor.LoginInterceptor;
8 import com.atlassian.seraph.util.LocalMockHttpServletRequest;
9 import com.mockobjects.dynamic.C;
10 import com.mockobjects.dynamic.Mock;
11 import junit.framework.TestCase;
12
13 import java.security.Principal;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.Map;
18 import javax.servlet.http.HttpServletRequest;
19 import javax.servlet.http.HttpServletResponse;
20 import javax.servlet.http.HttpSession;
21
22
23
24
25 public class TestPasswordBasedLoginFilter extends TestCase
26 {
27 public void testNullUserNameFails()
28 {
29 final MockSecurityConfig securityConfig = new MockSecurityConfig(Collections.EMPTY_LIST);
30 final PasswordBasedLoginFilter passwordBasedLoginFilter = new TestedPasswordBasedLoginFilter(null, "password", securityConfig);
31
32 final String actualStatus = passwordBasedLoginFilter.login(makeHttpRequest(), makeHttpResponse());
33 assertEquals(PasswordBasedLoginFilter.LOGIN_NOATTEMPT, actualStatus);
34 }
35
36
37 public void testNullPasswordFails()
38 {
39 final MockSecurityConfig securityConfig = new MockSecurityConfig(Collections.EMPTY_LIST);
40 final PasswordBasedLoginFilter passwordBasedLoginFilter = new TestedPasswordBasedLoginFilter("userName", null, securityConfig);
41
42 final String actualStatus = passwordBasedLoginFilter.login(makeHttpRequest(), makeHttpResponse());
43 assertEquals(PasswordBasedLoginFilter.LOGIN_NOATTEMPT, actualStatus);
44 }
45
46 public void testNullUserPairFails()
47 {
48 final PasswordBasedLoginFilter passwordBasedLoginFilter = new PasswordBasedLoginFilter()
49 {
50 PasswordBasedLoginFilter.UserPasswordPair extractUserPasswordPair(final HttpServletRequest request)
51 {
52 return null;
53 }
54 };
55
56 final String actualStatus = passwordBasedLoginFilter.login(makeHttpRequest(), makeHttpResponse());
57 assertEquals(PasswordBasedLoginFilter.LOGIN_NOATTEMPT, actualStatus);
58 }
59
60 public void testElevatedSecurityGuard_FailedCheck()
61 {
62 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(false, "userName");
63
64 final MockSecurityConfig securityConfig = new MockSecurityConfig(null, securityGuard, null, null, Collections.EMPTY_LIST);
65 final PasswordBasedLoginFilter passwordBasedLoginFilter = new TestedPasswordBasedLoginFilter("userName", "password", securityConfig);
66
67
68 final String actualStatus = passwordBasedLoginFilter.login(makeHttpRequest(), makeHttpResponse());
69 assertEquals(PasswordBasedLoginFilter.LOGIN_FAILED, actualStatus);
70 assertEquals(1, securityGuard.getFailedCount());
71 assertEquals(0, securityGuard.getSuccessCount());
72 }
73
74 public void testElevatedSecurityGuard_PassedCheck_ButFailedAuthenticator()
75 {
76 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(true, "userName");
77
78 final AssertingAuthenticator authenticator = new AssertingAuthenticator(false, "userName", "password");
79
80 final MockSecurityConfig securityConfig = new MockSecurityConfig(null, securityGuard, authenticator, null, Collections.EMPTY_LIST);
81 final PasswordBasedLoginFilter passwordBasedLoginFilter = new TestedPasswordBasedLoginFilter("userName", "password", securityConfig);
82
83
84 final String actualStatus = passwordBasedLoginFilter.login(makeHttpRequest(), makeHttpResponse());
85 assertEquals(PasswordBasedLoginFilter.LOGIN_FAILED, actualStatus);
86 assertEquals(1, securityGuard.getFailedCount());
87 assertEquals(0, securityGuard.getSuccessCount());
88 }
89
90 public void testElevatedSecurityGuard_PassedCheck_ButAuthenticatorThrewException()
91 {
92 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(true, "userName");
93
94 @SuppressWarnings ({ "ThrowableInstanceNeverThrown" })
95 final AssertingAuthenticator authenticator = new AssertingAuthenticator(false, "userName", "password", new AuthenticatorException());
96
97 final MockSecurityConfig securityConfig = new MockSecurityConfig(null, securityGuard, authenticator, null, Collections.EMPTY_LIST);
98 final PasswordBasedLoginFilter passwordBasedLoginFilter = new TestedPasswordBasedLoginFilter("userName", "password", securityConfig);
99
100
101 final String actualStatus = passwordBasedLoginFilter.login(makeHttpRequest(), makeHttpResponse());
102 assertEquals(PasswordBasedLoginFilter.LOGIN_FAILED, actualStatus);
103
104
105 assertEquals(0, securityGuard.getFailedCount());
106 assertEquals(0, securityGuard.getSuccessCount());
107 }
108
109 public void testElevatedSecurityGuard_PassedCheck_AndPassedAuthenticator()
110 {
111 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(true, "userName");
112
113 final AssertingAuthenticator authenticator = new AssertingAuthenticator(true, "userName", "password");
114 final MockSecurityConfig securityConfig = new MockSecurityConfig(null, securityGuard, authenticator, null, Collections.EMPTY_LIST);
115 final PasswordBasedLoginFilter passwordBasedLoginFilter = new TestedPasswordBasedLoginFilter("userName", "password", securityConfig);
116
117
118 final String actualStatus = passwordBasedLoginFilter.login(makeHttpRequest(), makeHttpResponse());
119 assertEquals(PasswordBasedLoginFilter.LOGIN_SUCCESS, actualStatus);
120 assertEquals(0, securityGuard.getFailedCount());
121 assertEquals(1, securityGuard.getSuccessCount());
122 }
123
124
125 public void testInterceptorsAreCalled()
126 {
127 CountingLoginInterceptor loginInterceptor = new CountingLoginInterceptor();
128 List<CountingLoginInterceptor> interceptors = new ArrayList<CountingLoginInterceptor>();
129 interceptors.add(loginInterceptor);
130
131 final CountingElevatedSecurityGuard securityGuard = new CountingElevatedSecurityGuard(true, "userName");
132
133 final AssertingAuthenticator authenticator = new AssertingAuthenticator(true, "userName", "password", null);
134
135 final MockSecurityConfig securityConfig = new MockSecurityConfig(null, securityGuard, authenticator, null, interceptors);
136 final PasswordBasedLoginFilter passwordBasedLoginFilter = new TestedPasswordBasedLoginFilter("userName", "password", securityConfig);
137
138
139 passwordBasedLoginFilter.login(makeHttpRequest(), makeHttpResponse());
140 assertEquals(1, loginInterceptor.getBeforeLogin());
141 assertEquals(1, loginInterceptor.getAfterLogin());
142
143 }
144
145 class TestedPasswordBasedLoginFilter extends PasswordBasedLoginFilter
146 {
147 private final String userName;
148 private final String password;
149 private final MockSecurityConfig mockSecurityConfig;
150
151
152 TestedPasswordBasedLoginFilter(final String userName, final String password, final MockSecurityConfig mockSecurityConfig)
153 {
154 this.userName = userName;
155 this.password = password;
156 this.mockSecurityConfig = mockSecurityConfig;
157 }
158
159 @Override
160 PasswordBasedLoginFilter.UserPasswordPair extractUserPasswordPair(final HttpServletRequest request)
161 {
162 return new PasswordBasedLoginFilter.UserPasswordPair(userName, password, true);
163 }
164
165 @Override
166 protected SecurityConfig getSecurityConfig()
167 {
168 return mockSecurityConfig;
169 }
170 }
171
172 class AssertingAuthenticator implements Authenticator
173 {
174 private final boolean loginOK;
175 private final String expectedUserName;
176 private final String expectedPassword;
177 private final AuthenticatorException authenticatorException;
178
179 public AssertingAuthenticator(final boolean loginOK, final String expectedUserName, final String expectedPassword)
180 {
181 this(loginOK, expectedUserName, expectedPassword, null);
182 }
183
184 public AssertingAuthenticator(final boolean loginOK, final String expectedUserName, final String expectedPassword, final AuthenticatorException authenticatorException)
185 {
186 this.loginOK = loginOK;
187 this.expectedUserName = expectedUserName;
188 this.expectedPassword = expectedPassword;
189 this.authenticatorException = authenticatorException;
190 }
191
192 public boolean login(final HttpServletRequest request, final HttpServletResponse response, final String username, final String password)
193 throws AuthenticatorException
194 {
195 return loginImpl(username, password);
196 }
197
198 public boolean login(final HttpServletRequest request, final HttpServletResponse response, final String username, final String password, final boolean storeCookie)
199 throws AuthenticatorException
200 {
201 return loginImpl(username, password);
202 }
203
204 private boolean loginImpl(final String username, final String password) throws AuthenticatorException
205 {
206 assertEquals(expectedUserName, username);
207 assertEquals(expectedPassword, password);
208 if (authenticatorException != null)
209 {
210 throw authenticatorException;
211 }
212 return loginOK;
213 }
214
215 public String getRemoteUser(final HttpServletRequest request)
216 {
217 return null;
218 }
219
220 public void destroy()
221 {
222 }
223
224 public Principal getUser(final HttpServletRequest request)
225 {
226 return null;
227 }
228
229 public Principal getUser(final HttpServletRequest request, final HttpServletResponse response)
230 {
231 return null;
232 }
233
234 public boolean isUserInRole(final HttpServletRequest request, final String role)
235 {
236 return false;
237 }
238
239 public boolean logout(final HttpServletRequest request, final HttpServletResponse response)
240 throws AuthenticatorException
241 {
242 return false;
243 }
244
245 public void init(final Map<String, String> params, final SecurityConfig config)
246 {
247 }
248 }
249
250 class CountingLoginInterceptor implements LoginInterceptor
251 {
252 private int beforeLogin;
253 private int afterLogin;
254
255 public void beforeLogin(final HttpServletRequest request, final HttpServletResponse response, final String username, final String password, final boolean cookieLogin)
256 {
257 beforeLogin++;
258 }
259
260 public void afterLogin(final HttpServletRequest request, final HttpServletResponse response, final String username, final String password, final boolean cookieLogin, final String loginStatus)
261 {
262 afterLogin++;
263 }
264
265 public void destroy()
266 {
267 }
268
269 public void init(final Map<String, String> params, final SecurityConfig config)
270 {
271 }
272
273 public int getBeforeLogin()
274 {
275 return beforeLogin;
276 }
277
278 public int getAfterLogin()
279 {
280 return afterLogin;
281 }
282 }
283
284 private HttpServletResponse makeHttpResponse()
285 {
286 final Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
287 mockHttpServletResponse.expect("addHeader", C.ANY_ARGS);
288 return (HttpServletResponse) mockHttpServletResponse.proxy();
289 }
290
291 private LocalMockHttpServletRequest makeHttpRequest()
292 {
293 final LocalMockHttpServletRequest httpServletRequest = new LocalMockHttpServletRequest();
294 httpServletRequest.setupGetAttribute(null);
295
296 final HttpSession session = new MockSession();
297 httpServletRequest.setSession(session);
298 return httpServletRequest;
299 }
300
301
302 }