PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/JNA/waffle-tomcat7/src/test/java/waffle/apache/MixedAuthenticatorTests.java

http://github.com/dblock/waffle
Java | 410 lines | 284 code | 42 blank | 84 comment | 10 complexity | 2a2f51821f595944b40cdf0297be2e3a MD5 | raw file
Possible License(s): MIT, MPL-2.0-no-copyleft-exception, Apache-2.0, LGPL-3.0, LGPL-2.1, GPL-2.0
  1. /**
  2. * Waffle (https://github.com/Waffle/waffle)
  3. *
  4. * Copyright (c) 2010-2020 Application Security, Inc.
  5. *
  6. * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
  7. * Public License v1.0 which accompanies this distribution, and is available at
  8. * https://www.eclipse.org/legal/epl-v10.html.
  9. *
  10. * Contributors: Application Security, Inc.
  11. */
  12. package waffle.apache;
  13. import static org.assertj.core.api.Assertions.assertThat;
  14. import com.sun.jna.platform.win32.Sspi;
  15. import com.sun.jna.platform.win32.SspiUtil.ManagedSecBufferDesc;
  16. import java.io.IOException;
  17. import java.util.Base64;
  18. import java.util.Collections;
  19. import javax.servlet.ServletException;
  20. import mockit.Expectations;
  21. import mockit.Mocked;
  22. import org.apache.catalina.Context;
  23. import org.apache.catalina.Engine;
  24. import org.apache.catalina.LifecycleException;
  25. import org.apache.catalina.deploy.LoginConfig;
  26. import org.apache.catalina.realm.GenericPrincipal;
  27. import org.junit.jupiter.api.AfterEach;
  28. import org.junit.jupiter.api.Assertions;
  29. import org.junit.jupiter.api.BeforeEach;
  30. import org.junit.jupiter.api.Test;
  31. import waffle.apache.catalina.SimpleHttpRequest;
  32. import waffle.apache.catalina.SimpleHttpResponse;
  33. import waffle.mock.MockWindowsAuthProvider;
  34. import waffle.windows.auth.IWindowsCredentialsHandle;
  35. import waffle.windows.auth.IWindowsIdentity;
  36. import waffle.windows.auth.PrincipalFormat;
  37. import waffle.windows.auth.impl.WindowsAccountImpl;
  38. import waffle.windows.auth.impl.WindowsCredentialsHandleImpl;
  39. import waffle.windows.auth.impl.WindowsSecurityContextImpl;
  40. /**
  41. * Waffle Tomcat Mixed Authenticator Tests.
  42. *
  43. * @author dblock[at]dblock[dot]org
  44. */
  45. public class MixedAuthenticatorTests {
  46. /** The authenticator. */
  47. MixedAuthenticator authenticator;
  48. /** The context. */
  49. @Mocked
  50. Context context;
  51. /** The engine. */
  52. @Mocked
  53. Engine engine;
  54. /**
  55. * Sets the up.
  56. *
  57. * @throws LifecycleException
  58. * the lifecycle exception
  59. */
  60. @BeforeEach
  61. public void setUp() throws LifecycleException {
  62. this.authenticator = new MixedAuthenticator();
  63. this.authenticator.setContainer(this.context);
  64. Assertions.assertNotNull(new Expectations() {
  65. {
  66. MixedAuthenticatorTests.this.context.getName();
  67. this.result = "context";
  68. MixedAuthenticatorTests.this.context.getParent();
  69. this.result = MixedAuthenticatorTests.this.engine;
  70. MixedAuthenticatorTests.this.context.getParent();
  71. this.result = null;
  72. }
  73. });
  74. this.authenticator.start();
  75. }
  76. /**
  77. * Tear down.
  78. *
  79. * @throws LifecycleException
  80. * the lifecycle exception
  81. */
  82. @AfterEach
  83. public void tearDown() throws LifecycleException {
  84. this.authenticator.stop();
  85. }
  86. /**
  87. * Test challenge get.
  88. */
  89. @Test
  90. public void testChallengeGET() {
  91. final SimpleHttpRequest request = new SimpleHttpRequest();
  92. request.setMethod("GET");
  93. request.setQueryString("j_negotiate_check");
  94. final SimpleHttpResponse response = new SimpleHttpResponse();
  95. this.authenticator.authenticate(request, response, null);
  96. final String[] wwwAuthenticates = response.getHeaderValues("WWW-Authenticate");
  97. Assertions.assertNotNull(wwwAuthenticates);
  98. Assertions.assertEquals(2, wwwAuthenticates.length);
  99. Assertions.assertEquals("Negotiate", wwwAuthenticates[0]);
  100. Assertions.assertEquals("NTLM", wwwAuthenticates[1]);
  101. Assertions.assertEquals("close", response.getHeader("Connection"));
  102. Assertions.assertEquals(2, response.getHeaderNames().size());
  103. Assertions.assertEquals(401, response.getStatus());
  104. }
  105. /**
  106. * Test challenge post.
  107. */
  108. @Test
  109. public void testChallengePOST() {
  110. final LoginConfig loginConfig = new LoginConfig();
  111. loginConfig.setErrorPage("error.html");
  112. loginConfig.setLoginPage("login.html");
  113. final String securityPackage = "Negotiate";
  114. IWindowsCredentialsHandle clientCredentials = null;
  115. WindowsSecurityContextImpl clientContext = null;
  116. try {
  117. // client credentials handle
  118. clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
  119. clientCredentials.initialize();
  120. // initial client security context
  121. clientContext = new WindowsSecurityContextImpl();
  122. clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
  123. clientContext.setCredentialsHandle(clientCredentials);
  124. clientContext.setSecurityPackage(securityPackage);
  125. clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername());
  126. final SimpleHttpRequest request = new SimpleHttpRequest();
  127. request.setQueryString("j_negotiate_check");
  128. request.setMethod("POST");
  129. request.setContentLength(0);
  130. final String clientToken = Base64.getEncoder().encodeToString(clientContext.getToken());
  131. request.addHeader("Authorization", securityPackage + " " + clientToken);
  132. final SimpleHttpResponse response = new SimpleHttpResponse();
  133. this.authenticator.authenticate(request, response, loginConfig);
  134. Assertions.assertTrue(response.getHeader("WWW-Authenticate").startsWith(securityPackage + " "));
  135. Assertions.assertEquals("keep-alive", response.getHeader("Connection"));
  136. Assertions.assertEquals(2, response.getHeaderNames().size());
  137. Assertions.assertEquals(401, response.getStatus());
  138. } finally {
  139. if (clientContext != null) {
  140. clientContext.dispose();
  141. }
  142. if (clientCredentials != null) {
  143. clientCredentials.dispose();
  144. }
  145. }
  146. }
  147. /**
  148. * Test get.
  149. */
  150. @Test
  151. public void testGet() {
  152. final LoginConfig loginConfig = new LoginConfig();
  153. loginConfig.setErrorPage("error.html");
  154. loginConfig.setLoginPage("login.html");
  155. final SimpleHttpRequest request = new SimpleHttpRequest();
  156. final SimpleHttpResponse response = new SimpleHttpResponse();
  157. Assertions.assertFalse(this.authenticator.authenticate(request, response, loginConfig));
  158. }
  159. /**
  160. * Test get info.
  161. */
  162. @Test
  163. public void testGetInfo() {
  164. assertThat(this.authenticator.getInfo().length()).isGreaterThan(0);
  165. }
  166. /**
  167. * Test negotiate.
  168. */
  169. @Test
  170. public void testNegotiate() {
  171. final LoginConfig loginConfig = new LoginConfig();
  172. loginConfig.setErrorPage("error.html");
  173. loginConfig.setLoginPage("login.html");
  174. final String securityPackage = "Negotiate";
  175. IWindowsCredentialsHandle clientCredentials = null;
  176. WindowsSecurityContextImpl clientContext = null;
  177. try {
  178. // client credentials handle
  179. clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
  180. clientCredentials.initialize();
  181. // initial client security context
  182. clientContext = new WindowsSecurityContextImpl();
  183. clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
  184. clientContext.setCredentialsHandle(clientCredentials);
  185. clientContext.setSecurityPackage(securityPackage);
  186. clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername());
  187. // negotiate
  188. boolean authenticated = false;
  189. final SimpleHttpRequest request = new SimpleHttpRequest();
  190. request.setQueryString("j_negotiate_check");
  191. String clientToken;
  192. while (true) {
  193. clientToken = Base64.getEncoder().encodeToString(clientContext.getToken());
  194. request.addHeader("Authorization", securityPackage + " " + clientToken);
  195. final SimpleHttpResponse response = new SimpleHttpResponse();
  196. authenticated = this.authenticator.authenticate(request, response, loginConfig);
  197. if (authenticated) {
  198. assertThat(response.getHeaderNames().size()).isGreaterThanOrEqualTo(0);
  199. break;
  200. }
  201. Assertions.assertTrue(response.getHeader("WWW-Authenticate").startsWith(securityPackage + " "));
  202. Assertions.assertEquals("keep-alive", response.getHeader("Connection"));
  203. Assertions.assertEquals(2, response.getHeaderNames().size());
  204. Assertions.assertEquals(401, response.getStatus());
  205. final String continueToken = response.getHeader("WWW-Authenticate")
  206. .substring(securityPackage.length() + 1);
  207. final byte[] continueTokenBytes = Base64.getDecoder().decode(continueToken);
  208. assertThat(continueTokenBytes.length).isGreaterThan(0);
  209. final ManagedSecBufferDesc continueTokenBuffer = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN,
  210. continueTokenBytes);
  211. clientContext.initialize(clientContext.getHandle(), continueTokenBuffer,
  212. WindowsAccountImpl.getCurrentUsername());
  213. }
  214. Assertions.assertTrue(authenticated);
  215. } finally {
  216. if (clientContext != null) {
  217. clientContext.dispose();
  218. }
  219. if (clientCredentials != null) {
  220. clientCredentials.dispose();
  221. }
  222. }
  223. }
  224. /**
  225. * Test post security check.
  226. */
  227. @Test
  228. public void testPostSecurityCheck() {
  229. final LoginConfig loginConfig = new LoginConfig();
  230. loginConfig.setErrorPage("error.html");
  231. loginConfig.setLoginPage("login.html");
  232. final SimpleHttpRequest request = new SimpleHttpRequest();
  233. request.setQueryString("j_security_check");
  234. request.addParameter("j_username", "username");
  235. request.addParameter("j_password", "password");
  236. final SimpleHttpResponse response = new SimpleHttpResponse();
  237. Assertions.assertFalse(this.authenticator.authenticate(request, response, loginConfig));
  238. }
  239. /**
  240. * Test programmatic security BOTH.
  241. *
  242. * @param identity
  243. * the identity
  244. * @throws ServletException
  245. * the servlet exception
  246. */
  247. @Test
  248. public void testProgrammaticSecurityBoth(@Mocked final IWindowsIdentity identity) throws ServletException {
  249. this.authenticator.setAuth(new MockWindowsAuthProvider());
  250. final SimpleHttpRequest request = new SimpleHttpRequest();
  251. request.setContext((Context) this.authenticator.getContainer());
  252. request.login(WindowsAccountImpl.getCurrentUsername(), "");
  253. Assertions.assertNotNull(new Expectations() {
  254. {
  255. identity.getFqn();
  256. this.result = "fqn";
  257. identity.getSidString();
  258. this.result = "S-1234";
  259. }
  260. });
  261. request.setUserPrincipal(new GenericWindowsPrincipal(identity, PrincipalFormat.BOTH, PrincipalFormat.BOTH));
  262. Assertions.assertTrue(request.getUserPrincipal() instanceof GenericWindowsPrincipal);
  263. final GenericWindowsPrincipal windowsPrincipal = (GenericWindowsPrincipal) request.getUserPrincipal();
  264. Assertions.assertTrue(windowsPrincipal.getSidString().startsWith("S-"));
  265. }
  266. /**
  267. * Test programmatic security SID.
  268. *
  269. * @param identity
  270. * the identity
  271. * @throws ServletException
  272. * the servlet exception
  273. */
  274. @Test
  275. public void testProgrammaticSecuritySID(@Mocked final IWindowsIdentity identity) throws ServletException {
  276. this.authenticator.setAuth(new MockWindowsAuthProvider());
  277. final SimpleHttpRequest request = new SimpleHttpRequest();
  278. request.setContext((Context) this.authenticator.getContainer());
  279. request.login(WindowsAccountImpl.getCurrentUsername(), "");
  280. Assertions.assertNotNull(new Expectations() {
  281. {
  282. identity.getSidString();
  283. this.result = "S-1234";
  284. }
  285. });
  286. request.setUserPrincipal(new GenericWindowsPrincipal(identity, PrincipalFormat.SID, PrincipalFormat.SID));
  287. Assertions.assertTrue(request.getUserPrincipal() instanceof GenericWindowsPrincipal);
  288. final GenericWindowsPrincipal windowsPrincipal = (GenericWindowsPrincipal) request.getUserPrincipal();
  289. Assertions.assertTrue(windowsPrincipal.getSidString().startsWith("S-"));
  290. }
  291. /**
  292. * Test programmatic security NONE.
  293. *
  294. * @param identity
  295. * the identity
  296. * @throws ServletException
  297. * the servlet exception
  298. */
  299. @Test
  300. public void testProgrammaticSecurityNone(@Mocked final IWindowsIdentity identity) throws ServletException {
  301. this.authenticator.setAuth(new MockWindowsAuthProvider());
  302. final SimpleHttpRequest request = new SimpleHttpRequest();
  303. request.setContext((Context) this.authenticator.getContainer());
  304. request.login(WindowsAccountImpl.getCurrentUsername(), "");
  305. request.setUserPrincipal(new GenericWindowsPrincipal(identity, PrincipalFormat.NONE, PrincipalFormat.NONE));
  306. Assertions.assertTrue(request.getUserPrincipal() instanceof GenericWindowsPrincipal);
  307. final GenericWindowsPrincipal windowsPrincipal = (GenericWindowsPrincipal) request.getUserPrincipal();
  308. Assertions.assertNull(windowsPrincipal.getSidString());
  309. }
  310. /**
  311. * Test security check parameters.
  312. */
  313. @Test
  314. public void testSecurityCheckParameters() {
  315. this.authenticator.setAuth(new MockWindowsAuthProvider());
  316. final LoginConfig loginConfig = new LoginConfig();
  317. loginConfig.setErrorPage("error.html");
  318. loginConfig.setLoginPage("login.html");
  319. final SimpleHttpRequest request = new SimpleHttpRequest();
  320. request.addParameter("j_security_check", "");
  321. request.addParameter("j_username", WindowsAccountImpl.getCurrentUsername());
  322. request.addParameter("j_password", "");
  323. final SimpleHttpResponse response = new SimpleHttpResponse();
  324. Assertions.assertTrue(this.authenticator.authenticate(request, response, loginConfig));
  325. }
  326. /**
  327. * Test security check query string.
  328. */
  329. @Test
  330. public void testSecurityCheckQueryString() {
  331. this.authenticator.setAuth(new MockWindowsAuthProvider());
  332. final LoginConfig loginConfig = new LoginConfig();
  333. loginConfig.setErrorPage("error.html");
  334. loginConfig.setLoginPage("login.html");
  335. final SimpleHttpRequest request = new SimpleHttpRequest();
  336. request.setQueryString("j_security_check");
  337. request.addParameter("j_username", WindowsAccountImpl.getCurrentUsername());
  338. request.addParameter("j_password", "");
  339. final SimpleHttpResponse response = new SimpleHttpResponse();
  340. Assertions.assertTrue(this.authenticator.authenticate(request, response, loginConfig));
  341. }
  342. @Test
  343. public void testCustomPrincipal() throws LifecycleException, IOException {
  344. final GenericPrincipal genericPrincipal = new GenericPrincipal("my-principal", "my-password",
  345. Collections.emptyList());
  346. final MixedAuthenticator customAuthenticator = new MixedAuthenticator() {
  347. @Override
  348. protected GenericPrincipal createPrincipal(final IWindowsIdentity windowsIdentity) {
  349. return genericPrincipal;
  350. }
  351. };
  352. try {
  353. customAuthenticator.setContainer(this.context);
  354. customAuthenticator.setAlwaysUseSession(true);
  355. customAuthenticator.start();
  356. customAuthenticator.setAuth(new MockWindowsAuthProvider());
  357. final SimpleHttpRequest request = new SimpleHttpRequest();
  358. request.addParameter("j_security_check", "");
  359. request.addParameter("j_username", WindowsAccountImpl.getCurrentUsername());
  360. request.addParameter("j_password", "");
  361. final SimpleHttpResponse response = new SimpleHttpResponse();
  362. Assertions.assertTrue(customAuthenticator.authenticate(request, response));
  363. Assertions.assertEquals(genericPrincipal, request.getUserPrincipal());
  364. } finally {
  365. customAuthenticator.stop();
  366. }
  367. }
  368. }