1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package waffle.apache;
25
26 import static org.assertj.core.api.Assertions.assertThat;
27
28 import com.sun.jna.platform.win32.Sspi;
29 import com.sun.jna.platform.win32.SspiUtil.ManagedSecBufferDesc;
30
31 import java.util.Base64;
32
33 import mockit.Expectations;
34 import mockit.Mocked;
35
36 import org.apache.catalina.Context;
37 import org.apache.catalina.Engine;
38 import org.apache.catalina.LifecycleException;
39 import org.junit.jupiter.api.AfterEach;
40 import org.junit.jupiter.api.Assertions;
41 import org.junit.jupiter.api.BeforeEach;
42 import org.junit.jupiter.api.Test;
43
44 import waffle.apache.catalina.SimpleHttpRequest;
45 import waffle.apache.catalina.SimpleHttpResponse;
46 import waffle.windows.auth.IWindowsCredentialsHandle;
47 import waffle.windows.auth.PrincipalFormat;
48 import waffle.windows.auth.impl.WindowsAccountImpl;
49 import waffle.windows.auth.impl.WindowsAuthProviderImpl;
50 import waffle.windows.auth.impl.WindowsCredentialsHandleImpl;
51 import waffle.windows.auth.impl.WindowsSecurityContextImpl;
52
53
54
55
56 class NegotiateAuthenticatorTest {
57
58
59 private NegotiateAuthenticator authenticator;
60
61 @Mocked
62 Context context;
63
64 @Mocked
65 Engine engine;
66
67
68
69
70
71
72
73 @BeforeEach
74 void setUp() throws LifecycleException {
75 this.authenticator = new NegotiateAuthenticator();
76 this.authenticator.setContainer(this.context);
77 Assertions.assertNotNull(new Expectations() {
78 {
79 NegotiateAuthenticatorTest.this.context.getParent();
80 this.result = NegotiateAuthenticatorTest.this.engine;
81 NegotiateAuthenticatorTest.this.context.getParent();
82 this.result = null;
83 }
84 });
85 this.authenticator.start();
86 }
87
88
89
90
91
92
93
94 @AfterEach
95 void tearDown() throws LifecycleException {
96 this.authenticator.stop();
97 }
98
99
100
101
102 @Test
103 void testAllowGuestLogin() {
104 Assertions.assertTrue(this.authenticator.isAllowGuestLogin());
105 this.authenticator.setAllowGuestLogin(false);
106 Assertions.assertFalse(this.authenticator.isAllowGuestLogin());
107 }
108
109
110
111
112 @Test
113 void testChallengeGET() {
114 final SimpleHttpRequest request = new SimpleHttpRequest();
115 request.setMethod("GET");
116 final SimpleHttpResponse response = new SimpleHttpResponse();
117 this.authenticator.authenticate(request, response);
118 final String[] wwwAuthenticates = response.getHeaderValues("WWW-Authenticate");
119 Assertions.assertNotNull(wwwAuthenticates);
120 Assertions.assertEquals(2, wwwAuthenticates.length);
121 Assertions.assertEquals("Negotiate", wwwAuthenticates[0]);
122 Assertions.assertEquals("NTLM", wwwAuthenticates[1]);
123 Assertions.assertEquals("close", response.getHeader("Connection"));
124 Assertions.assertEquals(2, response.getHeaderNames().size());
125 Assertions.assertEquals(401, response.getStatus());
126 }
127
128
129
130
131 @Test
132 void testChallengePOST() {
133 final String securityPackage = "Negotiate";
134 IWindowsCredentialsHandle clientCredentials = null;
135 WindowsSecurityContextImpl clientContext = null;
136 try {
137
138 clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
139 clientCredentials.initialize();
140
141 clientContext = new WindowsSecurityContextImpl();
142 clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
143 clientContext.setCredentialsHandle(clientCredentials);
144 clientContext.setSecurityPackage(securityPackage);
145 clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername());
146 final SimpleHttpRequest request = new SimpleHttpRequest();
147 request.setMethod("POST");
148 request.setContentLength(0);
149 final String clientToken = Base64.getEncoder().encodeToString(clientContext.getToken());
150 request.addHeader("Authorization", securityPackage + " " + clientToken);
151 final SimpleHttpResponse response = new SimpleHttpResponse();
152 this.authenticator.authenticate(request, response);
153 Assertions.assertTrue(response.getHeader("WWW-Authenticate").startsWith(securityPackage + " "));
154 Assertions.assertEquals("keep-alive", response.getHeader("Connection"));
155 Assertions.assertEquals(2, response.getHeaderNames().size());
156 Assertions.assertEquals(401, response.getStatus());
157 } finally {
158 if (clientContext != null) {
159 clientContext.dispose();
160 }
161 if (clientCredentials != null) {
162 clientCredentials.dispose();
163 }
164 }
165 }
166
167
168
169
170 @Test
171 void testGetInfo() {
172 assertThat(this.authenticator.getInfo()).isNotEmpty();
173 Assertions.assertTrue(this.authenticator.getAuth() instanceof WindowsAuthProviderImpl);
174 }
175
176
177
178
179 @Test
180 void testNegotiate() {
181 final String securityPackage = "Negotiate";
182 IWindowsCredentialsHandle clientCredentials = null;
183 WindowsSecurityContextImpl clientContext = null;
184 try {
185
186 clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
187 clientCredentials.initialize();
188
189 clientContext = new WindowsSecurityContextImpl();
190 clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
191 clientContext.setCredentialsHandle(clientCredentials);
192 clientContext.setSecurityPackage(securityPackage);
193 clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername());
194
195 boolean authenticated = false;
196 final SimpleHttpRequest request = new SimpleHttpRequest();
197 while (true) {
198 final String clientToken = Base64.getEncoder().encodeToString(clientContext.getToken());
199 request.addHeader("Authorization", securityPackage + " " + clientToken);
200
201 final SimpleHttpResponse response = new SimpleHttpResponse();
202 authenticated = this.authenticator.authenticate(request, response);
203
204 if (authenticated) {
205 Assertions.assertNotNull(request.getUserPrincipal());
206 Assertions.assertTrue(request.getUserPrincipal() instanceof GenericWindowsPrincipal);
207 final GenericWindowsPrincipal windowsPrincipal = (GenericWindowsPrincipal) request
208 .getUserPrincipal();
209 Assertions.assertTrue(windowsPrincipal.getSidString().startsWith("S-"));
210 assertThat(windowsPrincipal.getSid()).isNotEmpty();
211 Assertions.assertTrue(windowsPrincipal.getGroups().containsKey("Everyone"));
212 assertThat(response.getHeaderNames()).hasSizeLessThanOrEqualTo(1);
213 break;
214 }
215
216 Assertions.assertTrue(response.getHeader("WWW-Authenticate").startsWith(securityPackage + " "));
217 Assertions.assertEquals("keep-alive", response.getHeader("Connection"));
218 Assertions.assertEquals(2, response.getHeaderNames().size());
219 Assertions.assertEquals(401, response.getStatus());
220 final String continueToken = response.getHeader("WWW-Authenticate")
221 .substring(securityPackage.length() + 1);
222 final byte[] continueTokenBytes = Base64.getDecoder().decode(continueToken);
223 assertThat(continueTokenBytes).isNotEmpty();
224 final ManagedSecBufferDesc continueTokenBuffer = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN,
225 continueTokenBytes);
226 clientContext.initialize(clientContext.getHandle(), continueTokenBuffer,
227 WindowsAccountImpl.getCurrentUsername());
228 }
229 Assertions.assertTrue(authenticated);
230 } finally {
231 if (clientContext != null) {
232 clientContext.dispose();
233 }
234 if (clientCredentials != null) {
235 clientCredentials.dispose();
236 }
237 }
238 }
239
240
241
242
243 @Test
244 void testPOSTEmpty() {
245 final String securityPackage = "Negotiate";
246 IWindowsCredentialsHandle clientCredentials = null;
247 WindowsSecurityContextImpl clientContext = null;
248 try {
249
250 clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
251 clientCredentials.initialize();
252
253 clientContext = new WindowsSecurityContextImpl();
254 clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
255 clientContext.setCredentialsHandle(clientCredentials);
256 clientContext.setSecurityPackage(securityPackage);
257 clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername());
258
259 boolean authenticated = false;
260 final SimpleHttpRequest request = new SimpleHttpRequest();
261 request.setMethod("POST");
262 request.setContentLength(0);
263 String clientToken;
264 String continueToken;
265 byte[] continueTokenBytes;
266 SimpleHttpResponse response;
267 ManagedSecBufferDesc continueTokenBuffer;
268 while (true) {
269 clientToken = Base64.getEncoder().encodeToString(clientContext.getToken());
270 request.addHeader("Authorization", securityPackage + " " + clientToken);
271
272 response = new SimpleHttpResponse();
273 authenticated = this.authenticator.authenticate(request, response);
274
275 if (authenticated) {
276 assertThat(response.getHeaderNames().size()).isNotNegative();
277 break;
278 }
279
280 if (response.getHeader("WWW-Authenticate").startsWith(securityPackage + ",")) {
281 Assertions.assertEquals("close", response.getHeader("Connection"));
282 Assertions.assertEquals(2, response.getHeaderNames().size());
283 Assertions.assertEquals(401, response.getStatus());
284 return;
285 }
286
287 Assertions.assertTrue(response.getHeader("WWW-Authenticate").startsWith(securityPackage + " "));
288 Assertions.assertEquals("keep-alive", response.getHeader("Connection"));
289 Assertions.assertEquals(2, response.getHeaderNames().size());
290 Assertions.assertEquals(401, response.getStatus());
291 continueToken = response.getHeader("WWW-Authenticate").substring(securityPackage.length() + 1);
292 continueTokenBytes = Base64.getDecoder().decode(continueToken);
293 assertThat(continueTokenBytes).isNotEmpty();
294 continueTokenBuffer = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, continueTokenBytes);
295 clientContext.initialize(clientContext.getHandle(), continueTokenBuffer,
296 WindowsAccountImpl.getCurrentUsername());
297 }
298 Assertions.assertTrue(authenticated);
299 } finally {
300 if (clientContext != null) {
301 clientContext.dispose();
302 }
303 if (clientCredentials != null) {
304 clientCredentials.dispose();
305 }
306 }
307 }
308
309
310
311
312 @Test
313 void testPrincipalFormat() {
314 Assertions.assertEquals(PrincipalFormat.FQN, this.authenticator.getPrincipalFormat());
315 this.authenticator.setPrincipalFormat("both");
316 Assertions.assertEquals(PrincipalFormat.BOTH, this.authenticator.getPrincipalFormat());
317 }
318
319
320
321
322 @Test
323 void testRoleFormat() {
324 Assertions.assertEquals(PrincipalFormat.FQN, this.authenticator.getRoleFormat());
325 this.authenticator.setRoleFormat("both");
326 Assertions.assertEquals(PrincipalFormat.BOTH, this.authenticator.getRoleFormat());
327 }
328
329 }