View Javadoc
1   /**
2    * Waffle (https://github.com/dblock/waffle)
3    *
4    * Copyright (c) 2010 - 2015 Application Security, Inc.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Eclipse Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/epl-v10.html
10   *
11   * Contributors:
12   *     Application Security, Inc.
13   */
14  package waffle.windows.auth;
15  
16  import org.assertj.core.api.Assertions;
17  import org.junit.Assert;
18  import org.junit.Assume;
19  import org.junit.Ignore;
20  import org.junit.Test;
21  import org.slf4j.Logger;
22  import org.slf4j.LoggerFactory;
23  
24  import waffle.mock.MockWindowsAccount;
25  import waffle.windows.auth.impl.WindowsAccountImpl;
26  import waffle.windows.auth.impl.WindowsAuthProviderImpl;
27  import waffle.windows.auth.impl.WindowsCredentialsHandleImpl;
28  import waffle.windows.auth.impl.WindowsSecurityContextImpl;
29  
30  import com.google.common.io.BaseEncoding;
31  import com.sun.jna.WString;
32  import com.sun.jna.platform.win32.Advapi32Util;
33  import com.sun.jna.platform.win32.LMAccess;
34  import com.sun.jna.platform.win32.LMErr;
35  import com.sun.jna.platform.win32.LMJoin;
36  import com.sun.jna.platform.win32.Netapi32;
37  import com.sun.jna.platform.win32.Netapi32Util;
38  import com.sun.jna.platform.win32.Sspi;
39  import com.sun.jna.platform.win32.Sspi.SecBufferDesc;
40  
41  /**
42   * @author dblock[at]dblock[dot]org
43   */
44  public class WindowsAuthProviderTests {
45  
46      private static final Logger LOGGER = LoggerFactory.getLogger(WindowsAuthProviderTests.class);
47  
48      // TODO This was commented out, uncommented and ignore until I can determine if this is valid
49      @Ignore
50      @Test
51      public void testLogonGuestUser() {
52          final IWindowsAuthProvider prov = new WindowsAuthProviderImpl();
53          final IWindowsIdentity identity = prov.logonUser("garbage", "garbage");
54          WindowsAuthProviderTests.LOGGER.debug("Fqn: {}", identity.getFqn());
55          WindowsAuthProviderTests.LOGGER.debug("Guest: {}", Boolean.valueOf(identity.isGuest()));
56          Assert.assertTrue(identity.getFqn().endsWith("\\Guest"));
57          Assert.assertTrue(identity.isGuest());
58          identity.dispose();
59      }
60  
61      @Test
62      public void testLogonUser() {
63          final LMAccess.USER_INFO_1 userInfo = new LMAccess.USER_INFO_1();
64          userInfo.usri1_name = new WString("WaffleTestUser");
65          userInfo.usri1_password = new WString("!WAFFLEP$$Wrd0");
66          userInfo.usri1_priv = LMAccess.USER_PRIV_USER;
67          // ignore test if not able to add user (need to be administrator to do this).
68          Assume.assumeTrue(LMErr.NERR_Success == Netapi32.INSTANCE.NetUserAdd(null, 1, userInfo, null));
69          try {
70              final IWindowsAuthProvider prov = new WindowsAuthProviderImpl();
71              final IWindowsIdentity identity = prov.logonUser(userInfo.usri1_name.toString(),
72                      userInfo.usri1_password.toString());
73              Assert.assertTrue(identity.getFqn().endsWith("\\" + userInfo.usri1_name.toString()));
74              Assert.assertFalse(identity.isGuest());
75              identity.dispose();
76          } finally {
77              Assert.assertEquals(LMErr.NERR_Success, Netapi32.INSTANCE.NetUserDel(null, userInfo.usri1_name.toString()));
78          }
79      }
80  
81      @Test
82      public void testImpersonateLoggedOnUser() {
83          final LMAccess.USER_INFO_1 userInfo = new LMAccess.USER_INFO_1();
84          userInfo.usri1_name = new WString(MockWindowsAccount.TEST_USER_NAME);
85          userInfo.usri1_password = new WString(MockWindowsAccount.TEST_PASSWORD);
86          userInfo.usri1_priv = LMAccess.USER_PRIV_USER;
87          // ignore test if not able to add user (need to be administrator to do this).
88          Assume.assumeTrue(LMErr.NERR_Success == Netapi32.INSTANCE.NetUserAdd(null, 1, userInfo, null));
89          try {
90              final IWindowsAuthProvider prov = new WindowsAuthProviderImpl();
91              final IWindowsIdentity identity = prov.logonUser(userInfo.usri1_name.toString(),
92                      userInfo.usri1_password.toString());
93              final IWindowsImpersonationContext ctx = identity.impersonate();
94              Assert.assertTrue(userInfo.usri1_name.toString().equals(Advapi32Util.getUserName()));
95              ctx.revertToSelf();
96              Assert.assertFalse(userInfo.usri1_name.toString().equals(Advapi32Util.getUserName()));
97              identity.dispose();
98          } finally {
99              Assert.assertEquals(LMErr.NERR_Success, Netapi32.INSTANCE.NetUserDel(null, userInfo.usri1_name.toString()));
100         }
101     }
102 
103     @Test
104     public void testGetCurrentComputer() {
105         final IWindowsAuthProvider prov = new WindowsAuthProviderImpl();
106         final IWindowsComputer computer = prov.getCurrentComputer();
107         WindowsAuthProviderTests.LOGGER.debug(computer.getComputerName());
108         Assertions.assertThat(computer.getComputerName().length()).isGreaterThan(0);
109         WindowsAuthProviderTests.LOGGER.debug(computer.getJoinStatus());
110         WindowsAuthProviderTests.LOGGER.debug(computer.getMemberOf());
111         final String[] localGroups = computer.getGroups();
112         Assert.assertNotNull(localGroups);
113         Assertions.assertThat(localGroups.length).isGreaterThan(0);
114         for (final String localGroup : localGroups) {
115             WindowsAuthProviderTests.LOGGER.debug(" {}", localGroup);
116         }
117     }
118 
119     @Test
120     public void testGetDomains() {
121         if (Netapi32Util.getJoinStatus() != LMJoin.NETSETUP_JOIN_STATUS.NetSetupDomainName) {
122             return;
123         }
124 
125         final IWindowsAuthProvider prov = new WindowsAuthProviderImpl();
126         final IWindowsDomain[] domains = prov.getDomains();
127         Assert.assertNotNull(domains);
128         for (final IWindowsDomain domain : domains) {
129             WindowsAuthProviderTests.LOGGER.debug("{}: {}", domain.getFqn(), domain.getTrustDirectionString());
130         }
131     }
132 
133     @Test
134     public void testAcceptSecurityToken() {
135         final String securityPackage = "Negotiate";
136         final String targetName = "localhost";
137         IWindowsCredentialsHandle clientCredentials = null;
138         WindowsSecurityContextImpl clientContext = null;
139         IWindowsSecurityContext serverContext = null;
140         try {
141             // client credentials handle
142             clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
143             clientCredentials.initialize();
144             // initial client security context
145             clientContext = new WindowsSecurityContextImpl();
146             clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
147             clientContext.setCredentialsHandle(clientCredentials.getHandle());
148             clientContext.setSecurityPackage(securityPackage);
149             clientContext.initialize(null, null, targetName);
150             // accept on the server
151             final WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl();
152             final String connectionId = "testConnection-" + Thread.currentThread().getId();
153             do {
154                 // accept the token on the server
155                 try {
156                     serverContext = provider.acceptSecurityToken(connectionId, clientContext.getToken(),
157                             securityPackage);
158                 } catch (final Exception e) {
159                     WindowsAuthProviderTests.LOGGER.error("{}", e);
160                     break;
161                 }
162 
163                 if (serverContext != null && serverContext.isContinue()) {
164                     // initialize on the client
165                     final SecBufferDesc continueToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, serverContext.getToken());
166                     clientContext.initialize(clientContext.getHandle(), continueToken, targetName);
167                     WindowsAuthProviderTests.LOGGER.debug("Token: {}", BaseEncoding.base64().encode(serverContext.getToken()));
168                 }
169 
170             } while (clientContext.isContinue() || serverContext != null && serverContext.isContinue());
171 
172             if (serverContext != null) {
173                 Assertions.assertThat(serverContext.getIdentity().getFqn().length()).isGreaterThan(0);
174 
175                 WindowsAuthProviderTests.LOGGER.debug(serverContext.getIdentity().getFqn());
176                 for (final IWindowsAccount group : serverContext.getIdentity().getGroups()) {
177                     WindowsAuthProviderTests.LOGGER.debug(" {}", group.getFqn());
178                 }
179             }
180         } finally {
181             if (serverContext != null) {
182                 serverContext.dispose();
183             }
184             if (clientContext != null) {
185                 clientContext.dispose();
186             }
187             if (clientCredentials != null) {
188                 clientCredentials.dispose();
189             }
190         }
191     }
192 
193     @Test
194     public void testSecurityContextsExpire() throws InterruptedException {
195         final String securityPackage = "Negotiate";
196         IWindowsCredentialsHandle clientCredentials = null;
197         WindowsSecurityContextImpl clientContext = null;
198         IWindowsSecurityContext serverContext = null;
199         try {
200             // client credentials handle
201             clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
202             clientCredentials.initialize();
203             // initial client security context
204             clientContext = new WindowsSecurityContextImpl();
205             clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
206             clientContext.setCredentialsHandle(clientCredentials.getHandle());
207             clientContext.setSecurityPackage(securityPackage);
208             clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername());
209             // accept on the server
210             final WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl(1);
211             final int max = 100;
212             for (int i = 0; i < max; i++) {
213                 Thread.sleep(25);
214                 final String connectionId = "testConnection_" + i;
215                 serverContext = provider.acceptSecurityToken(connectionId, clientContext.getToken(), securityPackage);
216                 Assertions.assertThat(provider.getContinueContextsSize()).isGreaterThan(0);
217             }
218             WindowsAuthProviderTests.LOGGER.debug("Cached security contexts: {}", Integer.valueOf(provider.getContinueContextsSize()));
219             Assert.assertFalse(max == provider.getContinueContextsSize());
220         } finally {
221             if (serverContext != null) {
222                 serverContext.dispose();
223             }
224             if (clientContext != null) {
225                 clientContext.dispose();
226             }
227             if (clientCredentials != null) {
228                 clientCredentials.dispose();
229             }
230         }
231     }
232 
233     @Test
234     public void testAcceptAndImpersonateSecurityToken() {
235         final String securityPackage = "Negotiate";
236         final String targetName = "localhost";
237         IWindowsCredentialsHandle clientCredentials = null;
238         WindowsSecurityContextImpl clientContext = null;
239         IWindowsSecurityContext serverContext = null;
240         try {
241             // client credentials handle
242             clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
243             clientCredentials.initialize();
244             // initial client security context
245             clientContext = new WindowsSecurityContextImpl();
246             clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
247             clientContext.setCredentialsHandle(clientCredentials.getHandle());
248             clientContext.setSecurityPackage(securityPackage);
249             clientContext.initialize(null, null, targetName);
250             // accept on the server
251             final WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl();
252             final String connectionId = "testConnection";
253             do {
254                 // accept the token on the server
255                 try {
256                     serverContext = provider.acceptSecurityToken(connectionId, clientContext.getToken(),
257                             securityPackage);
258                 } catch (final Exception e) {
259                     WindowsAuthProviderTests.LOGGER.error("{}", e);
260                     break;
261                 }
262 
263                 if (serverContext != null && serverContext.isContinue()) {
264                     // initialize on the client
265                     final SecBufferDesc continueToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, serverContext.getToken());
266                     clientContext.initialize(clientContext.getHandle(), continueToken, targetName);
267                 }
268 
269             } while (clientContext.isContinue() || serverContext != null && serverContext.isContinue());
270 
271             if (serverContext != null) {
272                 Assertions.assertThat(serverContext.getIdentity().getFqn().length()).isGreaterThan(0);
273 
274                 final IWindowsImpersonationContext impersonationCtx = serverContext.impersonate();
275                 impersonationCtx.revertToSelf();
276 
277                 WindowsAuthProviderTests.LOGGER.debug(serverContext.getIdentity().getFqn());
278                 for (final IWindowsAccount group : serverContext.getIdentity().getGroups()) {
279                     WindowsAuthProviderTests.LOGGER.debug(" {}", group.getFqn());
280                 }
281             }
282         } finally {
283             if (serverContext != null) {
284                 serverContext.dispose();
285             }
286             if (clientContext != null) {
287                 clientContext.dispose();
288             }
289             if (clientCredentials != null) {
290                 clientCredentials.dispose();
291             }
292         }
293     }
294 }