1 /* Copyright (c) 2010 Daniel Doubrovkine, All Rights Reserved
2  *
3  * The contents of this file is dual-licensed under 2
4  * alternative Open Source/Free licenses: LGPL 2.1 or later and
5  * Apache License 2.0. (starting with JNA version 4.0.0).
6  *
7  * You can freely decide which license you want to apply to
8  * the project.
9  *
10  * You may obtain a copy of the LGPL License at:
11  *
12  * http://www.gnu.org/licenses/licenses.html
13  *
14  * A copy is also included in the downloadable source code package
15  * containing JNA, in file "LGPL2.1".
16  *
17  * You may obtain a copy of the Apache License at:
18  *
19  * http://www.apache.org/licenses/
20  *
21  * A copy is also included in the downloadable source code package
22  * containing JNA, in file "AL2.0".
23  */
24 package com.sun.jna.platform.win32;
25 
26 import com.sun.jna.Memory;
27 import com.sun.jna.Native;
28 import com.sun.jna.platform.win32.SspiUtil.ManagedSecBufferDesc;
29 import com.sun.jna.platform.win32.Sspi.CredHandle;
30 import com.sun.jna.platform.win32.Sspi.CtxtHandle;
31 import com.sun.jna.platform.win32.Sspi.PSecPkgInfo;
32 import com.sun.jna.platform.win32.Sspi.SecPkgContext_PackageInfo;
33 import com.sun.jna.platform.win32.Sspi.SecPkgContext_Sizes;
34 import com.sun.jna.platform.win32.Sspi.SecPkgCredentials_Names;
35 import com.sun.jna.platform.win32.Sspi.SecPkgInfo;
36 import com.sun.jna.platform.win32.Sspi.SecPkgInfo.ByReference;
37 import com.sun.jna.platform.win32.Sspi.TimeStamp;
38 import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
39 import com.sun.jna.ptr.IntByReference;
40 import java.nio.charset.Charset;
41 import java.util.Arrays;
42 
43 import junit.framework.TestCase;
44 
45 /**
46  * @author dblock[at]dblock[dot]org
47  */
48 public class Secur32Test extends TestCase {
49 
main(String[] args)50     public static void main(String[] args) {
51         junit.textui.TestRunner.run(Secur32Test.class);
52     }
53 
54     @Override
tearDown()55     protected void tearDown() throws Exception {
56         super.tearDown();
57         // Drain last error to prevent test fails from lingering  last error
58         // states
59         Kernel32.INSTANCE.GetLastError();
60     }
61 
testGetUserNameEx()62     public void testGetUserNameEx() {
63         IntByReference len = new IntByReference();
64         Secur32.INSTANCE.GetUserNameEx(
65                 Secur32.EXTENDED_NAME_FORMAT.NameSamCompatible, null, len);
66         assertTrue(len.getValue() > 0);
67         char[] buffer = new char[len.getValue() + 1];
68         assertTrue(Secur32.INSTANCE.GetUserNameEx(
69                 Secur32.EXTENDED_NAME_FORMAT.NameSamCompatible, buffer, len));
70         String username = Native.toString(buffer);
71         assertTrue(username.length() > 0);
72     }
73 
testAcquireCredentialsHandle()74     public void testAcquireCredentialsHandle() {
75         CredHandle phCredential = new CredHandle();
76         TimeStamp ptsExpiry = new TimeStamp();
77         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
78                 null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
79                 null, phCredential, ptsExpiry));
80         assertTrue(phCredential.dwLower != null);
81         assertTrue(phCredential.dwUpper != null);
82         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
83                 phCredential));
84     }
85 
testAcquireCredentialsHandleInvalidPackage()86     public void testAcquireCredentialsHandleInvalidPackage() {
87         CredHandle phCredential = new CredHandle();
88         TimeStamp ptsExpiry = new TimeStamp();
89         assertEquals(W32Errors.SEC_E_SECPKG_NOT_FOUND, Secur32.INSTANCE.AcquireCredentialsHandle(
90                 null, "PackageDoesntExist", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
91                 null, phCredential, ptsExpiry));
92     }
93 
testInitializeSecurityContext()94     public void testInitializeSecurityContext() {
95         CredHandle phCredential = new CredHandle();
96         TimeStamp ptsExpiry = new TimeStamp();
97         // acquire a credentials handle
98         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
99                 null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
100                 null, phCredential, ptsExpiry));
101         // initialize security context
102         CtxtHandle phNewContext = new CtxtHandle();
103         ManagedSecBufferDesc pbToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
104         IntByReference pfContextAttr = new IntByReference();
105         int rc = Secur32.INSTANCE.InitializeSecurityContext(phCredential, null,
106                 Advapi32Util.getUserName(), Sspi.ISC_REQ_CONNECTION, 0,
107                 Sspi.SECURITY_NATIVE_DREP, null, 0, phNewContext, pbToken,
108                 pfContextAttr, null);
109         assertTrue(rc == W32Errors.SEC_I_CONTINUE_NEEDED || rc == W32Errors.SEC_E_OK);
110         assertTrue(phNewContext.dwLower != null);
111         assertTrue(phNewContext.dwUpper != null);
112         assertTrue(pbToken.getBuffer(0).getBytes().length > 0);
113         // release
114         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
115                 phNewContext));
116         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
117                 phCredential));
118     }
119 
testAcceptSecurityContext()120     public void testAcceptSecurityContext() {
121         // client ----------- acquire outbound credential handle
122         CredHandle phClientCredential = new CredHandle();
123         TimeStamp ptsClientExpiry = new TimeStamp();
124         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
125                 null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
126                 null, phClientCredential, ptsClientExpiry));
127         // client ----------- security context
128         CtxtHandle phClientContext = new CtxtHandle();
129         IntByReference pfClientContextAttr = new IntByReference();
130         // server ----------- acquire inbound credential handle
131         CredHandle phServerCredential = new CredHandle();
132         TimeStamp ptsServerExpiry = new TimeStamp();
133         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
134                 null, "Negotiate", Sspi.SECPKG_CRED_INBOUND, null, null, null,
135                 null, phServerCredential, ptsServerExpiry));
136         // server ----------- security context
137         CtxtHandle phServerContext = new CtxtHandle();
138         ManagedSecBufferDesc pbServerToken = null;
139         IntByReference pfServerContextAttr = new IntByReference();
140         int clientRc = W32Errors.SEC_I_CONTINUE_NEEDED;
141         int serverRc = W32Errors.SEC_I_CONTINUE_NEEDED;
142         do {
143             // client ----------- initialize security context, produce a client token
144             // client token returned is always new
145             ManagedSecBufferDesc pbClientToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
146             if (clientRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
147                 // server token is empty the first time
148                 ManagedSecBufferDesc pbServerTokenCopy = pbServerToken == null
149                         ? null : new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbServerToken.getBuffer(0).getBytes());
150                 clientRc = Secur32.INSTANCE.InitializeSecurityContext(
151                         phClientCredential,
152                         phClientContext.isNull() ? null : phClientContext,
153                         Advapi32Util.getUserName(),
154                         Sspi.ISC_REQ_CONNECTION,
155                         0,
156                         Sspi.SECURITY_NATIVE_DREP,
157                         pbServerTokenCopy,
158                         0,
159                         phClientContext,
160                         pbClientToken,
161                         pfClientContextAttr,
162                         null);
163                 assertTrue(clientRc == W32Errors.SEC_I_CONTINUE_NEEDED || clientRc == W32Errors.SEC_E_OK);
164             }
165             // server ----------- accept security context, produce a server token
166             if (serverRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
167                 pbServerToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
168                 ManagedSecBufferDesc pbClientTokenByValue = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbClientToken.getBuffer(0).getBytes());
169                 serverRc = Secur32.INSTANCE.AcceptSecurityContext(phServerCredential,
170                         phServerContext.isNull() ? null : phServerContext,
171                         pbClientTokenByValue,
172                         Sspi.ISC_REQ_CONNECTION,
173                         Sspi.SECURITY_NATIVE_DREP,
174                         phServerContext,
175                         pbServerToken,
176                         pfServerContextAttr,
177                         ptsServerExpiry);
178                 assertTrue(serverRc == W32Errors.SEC_I_CONTINUE_NEEDED || serverRc == W32Errors.SEC_E_OK);
179             }
180         } while (serverRc != W32Errors.SEC_E_OK || clientRc != W32Errors.SEC_E_OK);
181         // release server context
182         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
183                 phServerContext));
184         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
185                 phServerCredential));
186         // release client context
187         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
188                 phClientContext));
189         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
190                 phClientCredential));
191     }
192 
testImpersonateRevertSecurityContext()193     public void testImpersonateRevertSecurityContext() {
194         // client ----------- acquire outbound credential handle
195         CredHandle phClientCredential = new CredHandle();
196         TimeStamp ptsClientExpiry = new TimeStamp();
197         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
198                 null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
199                 null, phClientCredential, ptsClientExpiry));
200         // client ----------- security context
201         CtxtHandle phClientContext = new CtxtHandle();
202         IntByReference pfClientContextAttr = new IntByReference();
203         // server ----------- acquire inbound credential handle
204         CredHandle phServerCredential = new CredHandle();
205         TimeStamp ptsServerExpiry = new TimeStamp();
206         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
207                 null, "Negotiate", Sspi.SECPKG_CRED_INBOUND, null, null, null,
208                 null, phServerCredential, ptsServerExpiry));
209         // server ----------- security context
210         CtxtHandle phServerContext = new CtxtHandle();
211         ManagedSecBufferDesc pbServerToken = null;
212         IntByReference pfServerContextAttr = new IntByReference();
213         int clientRc = W32Errors.SEC_I_CONTINUE_NEEDED;
214         int serverRc = W32Errors.SEC_I_CONTINUE_NEEDED;
215         do {
216             // client ----------- initialize security context, produce a client token
217             // client token returned is always new
218             ManagedSecBufferDesc pbClientToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
219             if (clientRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
220                 // server token is empty the first time
221                 ManagedSecBufferDesc pbServerTokenCopy = pbServerToken == null
222                         ? null : new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbServerToken.getBuffer(0).getBytes());
223                 clientRc = Secur32.INSTANCE.InitializeSecurityContext(
224                         phClientCredential,
225                         phClientContext.isNull() ? null : phClientContext,
226                         Advapi32Util.getUserName(),
227                         Sspi.ISC_REQ_CONNECTION,
228                         0,
229                         Sspi.SECURITY_NATIVE_DREP,
230                         pbServerTokenCopy,
231                         0,
232                         phClientContext,
233                         pbClientToken,
234                         pfClientContextAttr,
235                         null);
236                 assertTrue(clientRc == W32Errors.SEC_I_CONTINUE_NEEDED || clientRc == W32Errors.SEC_E_OK);
237             }
238             // server ----------- accept security context, produce a server token
239             if (serverRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
240                 pbServerToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
241                 ManagedSecBufferDesc pbClientTokenByValue = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbClientToken.getBuffer(0).getBytes());
242                 serverRc = Secur32.INSTANCE.AcceptSecurityContext(phServerCredential,
243                         phServerContext.isNull() ? null : phServerContext,
244                         pbClientTokenByValue,
245                         Sspi.ISC_REQ_CONNECTION,
246                         Sspi.SECURITY_NATIVE_DREP,
247                         phServerContext,
248                         pbServerToken,
249                         pfServerContextAttr,
250                         ptsServerExpiry);
251                 assertTrue(serverRc == W32Errors.SEC_I_CONTINUE_NEEDED || serverRc == W32Errors.SEC_E_OK);
252             }
253         } while (serverRc != W32Errors.SEC_E_OK || clientRc != W32Errors.SEC_E_OK);
254         // impersonate
255         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.ImpersonateSecurityContext(
256                 phServerContext));
257         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.RevertSecurityContext(
258                 phServerContext));
259         // release server context
260         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
261                 phServerContext));
262         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
263                 phServerCredential));
264         // release client context
265         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
266                 phClientContext));
267         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
268                 phClientCredential));
269     }
270 
testEnumerateSecurityPackages()271     public void testEnumerateSecurityPackages() {
272         IntByReference pcPackages = new IntByReference();
273         PSecPkgInfo.ByReference pPackageInfo = new PSecPkgInfo.ByReference();
274         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.EnumerateSecurityPackages(
275                 pcPackages, pPackageInfo));
276         SecPkgInfo.ByReference[] packagesInfo = pPackageInfo.toArray(
277                 pcPackages.getValue());
278         for (SecPkgInfo.ByReference packageInfo : packagesInfo) {
279             assertTrue(packageInfo.Name.length() > 0);
280             assertTrue(packageInfo.Comment.length() >= 0);
281         }
282         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeContextBuffer(
283                 pPackageInfo.pPkgInfo.getPointer()));
284 
285     }
286 
testQuerySecurityContextToken()287     public void testQuerySecurityContextToken() {
288         // client ----------- acquire outbound credential handle
289         CredHandle phClientCredential = new CredHandle();
290         TimeStamp ptsClientExpiry = new TimeStamp();
291         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
292                 null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
293                 null, phClientCredential, ptsClientExpiry));
294         // client ----------- security context
295         CtxtHandle phClientContext = new CtxtHandle();
296         IntByReference pfClientContextAttr = new IntByReference();
297         // server ----------- acquire inbound credential handle
298         CredHandle phServerCredential = new CredHandle();
299         TimeStamp ptsServerExpiry = new TimeStamp();
300         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
301                 null, "Negotiate", Sspi.SECPKG_CRED_INBOUND, null, null, null,
302                 null, phServerCredential, ptsServerExpiry));
303         // server ----------- security context
304         CtxtHandle phServerContext = new CtxtHandle();
305         ManagedSecBufferDesc pbServerToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
306         IntByReference pfServerContextAttr = new IntByReference();
307         int clientRc = W32Errors.SEC_I_CONTINUE_NEEDED;
308         int serverRc = W32Errors.SEC_I_CONTINUE_NEEDED;
309         do {
310             // client token returned is always new
311             ManagedSecBufferDesc pbClientToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
312             // client ----------- initialize security context, produce a client token
313             if (clientRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
314                 // server token is empty the first time
315                 clientRc = Secur32.INSTANCE.InitializeSecurityContext(
316                         phClientCredential,
317                         phClientContext.isNull() ? null : phClientContext,
318                         Advapi32Util.getUserName(),
319                         Sspi.ISC_REQ_CONNECTION,
320                         0,
321                         Sspi.SECURITY_NATIVE_DREP,
322                         pbServerToken,
323                         0,
324                         phClientContext,
325                         pbClientToken,
326                         pfClientContextAttr,
327                         null);
328                 assertTrue(clientRc == W32Errors.SEC_I_CONTINUE_NEEDED || clientRc == W32Errors.SEC_E_OK);
329             }
330             // server ----------- accept security context, produce a server token
331             if (serverRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
332                 serverRc = Secur32.INSTANCE.AcceptSecurityContext(phServerCredential,
333                         phServerContext.isNull() ? null : phServerContext,
334                         pbClientToken,
335                         Sspi.ISC_REQ_CONNECTION,
336                         Sspi.SECURITY_NATIVE_DREP,
337                         phServerContext,
338                         pbServerToken,
339                         pfServerContextAttr,
340                         ptsServerExpiry);
341                 assertTrue(serverRc == W32Errors.SEC_I_CONTINUE_NEEDED || serverRc == W32Errors.SEC_E_OK);
342             }
343         } while (serverRc != W32Errors.SEC_E_OK || clientRc != W32Errors.SEC_E_OK);
344         // query security context token
345         HANDLEByReference phContextToken = new HANDLEByReference();
346         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.QuerySecurityContextToken(
347                 phServerContext, phContextToken));
348         // release security context token
349         Kernel32Util.closeHandleRef(phContextToken);
350         // release server context
351         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
352                 phServerContext));
353         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
354                 phServerCredential));
355         // release client context
356         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
357                 phClientContext));
358         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
359                 phClientCredential));
360     }
361 
testCreateEmptyToken()362     public void testCreateEmptyToken() {
363         ManagedSecBufferDesc token = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
364         assertEquals(1, token.cBuffers);
365         assertEquals(Sspi.SECBUFFER_TOKEN, token.getBuffer(0).BufferType);
366         assertEquals(Sspi.MAX_TOKEN_SIZE, token.getBuffer(0).cbBuffer);
367     }
368 
testQueryContextAttributes()369     public void testQueryContextAttributes() {
370         // client ----------- acquire outbound credential handle
371         CredHandle phClientCredential = new CredHandle();
372         TimeStamp ptsClientExpiry = new TimeStamp();
373         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
374                 null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
375                 null, phClientCredential, ptsClientExpiry));
376         // client ----------- security context
377         CtxtHandle phClientContext = new CtxtHandle();
378         IntByReference pfClientContextAttr = new IntByReference();
379         // server ----------- acquire inbound credential handle
380         CredHandle phServerCredential = new CredHandle();
381         TimeStamp ptsServerExpiry = new TimeStamp();
382         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
383                 null, "Negotiate", Sspi.SECPKG_CRED_INBOUND, null, null, null,
384                 null, phServerCredential, ptsServerExpiry));
385         // server ----------- security context
386         CtxtHandle phServerContext = new CtxtHandle();
387         ManagedSecBufferDesc pbServerToken = null;
388         IntByReference pfServerContextAttr = new IntByReference();
389         int clientRc = W32Errors.SEC_I_CONTINUE_NEEDED;
390         int serverRc = W32Errors.SEC_I_CONTINUE_NEEDED;
391         do {
392             // client ----------- initialize security context, produce a client token
393             // client token returned is always new
394             ManagedSecBufferDesc pbClientToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
395             if (clientRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
396                 // server token is empty the first time
397                 ManagedSecBufferDesc pbServerTokenCopy = pbServerToken == null
398                         ? null : new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbServerToken.getBuffer(0).getBytes());
399                 clientRc = Secur32.INSTANCE.InitializeSecurityContext(
400                         phClientCredential,
401                         phClientContext.isNull() ? null : phClientContext,
402                         Advapi32Util.getUserName(),
403                         Sspi.ISC_REQ_CONNECTION,
404                         0,
405                         Sspi.SECURITY_NATIVE_DREP,
406                         pbServerTokenCopy,
407                         0,
408                         phClientContext,
409                         pbClientToken,
410                         pfClientContextAttr,
411                         null);
412                 assertTrue(clientRc == W32Errors.SEC_I_CONTINUE_NEEDED || clientRc == W32Errors.SEC_E_OK);
413             }
414             // server ----------- accept security context, produce a server token
415             if (serverRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
416                 pbServerToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
417                 ManagedSecBufferDesc pbClientTokenByValue = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbClientToken.getBuffer(0).getBytes());
418                 serverRc = Secur32.INSTANCE.AcceptSecurityContext(phServerCredential,
419                         phServerContext.isNull() ? null : phServerContext,
420                         pbClientTokenByValue,
421                         Sspi.ISC_REQ_CONNECTION,
422                         Sspi.SECURITY_NATIVE_DREP,
423                         phServerContext,
424                         pbServerToken,
425                         pfServerContextAttr,
426                         ptsServerExpiry);
427                 assertTrue(serverRc == W32Errors.SEC_I_CONTINUE_NEEDED || serverRc == W32Errors.SEC_E_OK);
428             }
429         } while (serverRc != W32Errors.SEC_E_OK || clientRc != W32Errors.SEC_E_OK);
430         // query context attributes
431         SecPkgContext_PackageInfo packageinfo = new SecPkgContext_PackageInfo();
432         assertEquals(W32Errors.SEC_E_OK,
433                 Secur32.INSTANCE.QueryContextAttributes(phServerContext, Sspi.SECPKG_ATTR_PACKAGE_INFO, packageinfo));
434         ByReference info = packageinfo.PackageInfo;
435 
436         assertNotNull(info.Name);
437         assertNotNull(info.Comment);
438 
439         assertTrue(!info.Name.isEmpty());
440         assertTrue(!info.Comment.isEmpty());
441 
442         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeContextBuffer(info.getPointer()));
443 
444         // release server context
445         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(phServerContext));
446         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(phServerCredential));
447         // release client context
448         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(phClientContext));
449         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(phClientCredential));
450     }
451 
testQuerySecurityPackageInfo()452     public void testQuerySecurityPackageInfo() {
453         PSecPkgInfo pkgInfo = new PSecPkgInfo();
454         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.QuerySecurityPackageInfo("NTLM", pkgInfo));
455         assertEquals(pkgInfo.pPkgInfo.Name, "NTLM");
456         assertEquals(pkgInfo.pPkgInfo.fCapabilities & Sspi.SECPKG_FLAG_PRIVACY, Sspi.SECPKG_FLAG_PRIVACY);
457         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeContextBuffer(pkgInfo.getPointer()));
458     }
459 
testQueryCredentialAttribute()460     public void testQueryCredentialAttribute() {
461         // acquire sample credential handle
462         CredHandle phClientCredential = new CredHandle();
463         TimeStamp ptsClientExpiry = new TimeStamp();
464         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(null, "Negotiate",
465                 Sspi.SECPKG_CRED_OUTBOUND, null, null, null, null, phClientCredential, ptsClientExpiry));
466 
467         SecPkgCredentials_Names names = new SecPkgCredentials_Names();
468         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.QueryCredentialsAttributes(phClientCredential, Sspi.SECPKG_CRED_ATTR_NAMES, names));
469 
470         String accountName = names.getUserName();
471 
472         assertNotNull(accountName);
473         assertTrue(accountName.length() > 0);
474 
475         assertEquals(W32Errors.SEC_E_OK, names.free());
476     }
477 
testEncryptDecryptMessage()478     public void testEncryptDecryptMessage() {
479         // client ----------- acquire outbound credential handle
480         CredHandle phClientCredential = new CredHandle();
481         TimeStamp ptsClientExpiry = new TimeStamp();
482         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
483                 null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
484                 null, phClientCredential, ptsClientExpiry));
485         // client ----------- security context
486         CtxtHandle phClientContext = new CtxtHandle();
487         IntByReference pfClientContextAttr = new IntByReference();
488         // server ----------- acquire inbound credential handle
489         CredHandle phServerCredential = new CredHandle();
490         TimeStamp ptsServerExpiry = new TimeStamp();
491         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
492                 null, "Negotiate", Sspi.SECPKG_CRED_INBOUND, null, null, null,
493                 null, phServerCredential, ptsServerExpiry));
494         // server ----------- security context
495         CtxtHandle phServerContext = new CtxtHandle();
496         ManagedSecBufferDesc pbServerToken = null;
497         IntByReference pfServerContextAttr = new IntByReference();
498         int clientRc = W32Errors.SEC_I_CONTINUE_NEEDED;
499         int serverRc = W32Errors.SEC_I_CONTINUE_NEEDED;
500         do {
501             // client ----------- initialize security context, produce a client token
502             // client token returned is always new
503             ManagedSecBufferDesc pbClientToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
504             if (clientRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
505                 // server token is empty the first time
506                 ManagedSecBufferDesc pbServerTokenCopy = pbServerToken == null
507                         ? null : new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbServerToken.getBuffer(0).getBytes());
508                 clientRc = Secur32.INSTANCE.InitializeSecurityContext(
509                         phClientCredential,
510                         phClientContext.isNull() ? null : phClientContext,
511                         Advapi32Util.getUserName(),
512                         Sspi.ISC_REQ_CONNECTION | Sspi.ISC_REQ_CONFIDENTIALITY,
513                         0,
514                         Sspi.SECURITY_NATIVE_DREP,
515                         pbServerTokenCopy,
516                         0,
517                         phClientContext,
518                         pbClientToken,
519                         pfClientContextAttr,
520                         null);
521                 assertTrue(clientRc == W32Errors.SEC_I_CONTINUE_NEEDED || clientRc == W32Errors.SEC_E_OK);
522             }
523             // server ----------- accept security context, produce a server token
524             if (serverRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
525                 pbServerToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
526                 ManagedSecBufferDesc pbClientTokenByValue = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbClientToken.getBuffer(0).getBytes());
527                 serverRc = Secur32.INSTANCE.AcceptSecurityContext(phServerCredential,
528                         phServerContext.isNull() ? null : phServerContext,
529                         pbClientTokenByValue,
530                         Sspi.ISC_REQ_CONNECTION | Sspi.ISC_REQ_CONFIDENTIALITY,
531                         Sspi.SECURITY_NATIVE_DREP,
532                         phServerContext,
533                         pbServerToken,
534                         pfServerContextAttr,
535                         ptsServerExpiry);
536                 assertTrue(serverRc == W32Errors.SEC_I_CONTINUE_NEEDED || serverRc == W32Errors.SEC_E_OK);
537             }
538         } while (serverRc != W32Errors.SEC_E_OK || clientRc != W32Errors.SEC_E_OK);
539 
540         assertTrue((pfServerContextAttr.getValue() & Sspi.ISC_REQ_CONFIDENTIALITY) == Sspi.ISC_REQ_CONFIDENTIALITY);
541         assertTrue((pfClientContextAttr.getValue() & Sspi.ISC_REQ_CONFIDENTIALITY) == Sspi.ISC_REQ_CONFIDENTIALITY);
542 
543         // Fetch size limits for crypto functions
544         SecPkgContext_Sizes sizes = new SecPkgContext_Sizes();
545         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.QueryContextAttributes(phClientContext, Sspi.SECPKG_ATTR_SIZES, sizes));
546 
547         // Create sample input data
548         byte[] inputData = "Hallo Welt".getBytes(Charset.forName("ASCII"));
549 
550         // Do encryption, buffer 0 holds meta data, buffer 1 holds the
551         // clear text data on input and the encrypted data on output.
552         // Uses the phClientContext
553         ManagedSecBufferDesc encryptBuffers = new ManagedSecBufferDesc(2);
554 
555         Memory tokenMemory = new Memory(sizes.cbSecurityTrailer);
556         Memory dataMemory = new Memory(inputData.length);
557         dataMemory.write(0, inputData, 0, inputData.length);
558 
559         encryptBuffers.getBuffer(0).BufferType = Sspi.SECBUFFER_TOKEN;
560         encryptBuffers.getBuffer(0).cbBuffer = (int) tokenMemory.size();
561         encryptBuffers.getBuffer(0).pvBuffer = tokenMemory;
562         encryptBuffers.getBuffer(1).BufferType = Sspi.SECBUFFER_DATA;
563         encryptBuffers.getBuffer(1).cbBuffer = (int) dataMemory.size();
564         encryptBuffers.getBuffer(1).pvBuffer = dataMemory;
565 
566         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.EncryptMessage(phClientContext, 0, encryptBuffers, 0));
567 
568         byte[] encryptedTokenData = encryptBuffers.getBuffer(0).getBytes();
569         byte[] encryptedData = encryptBuffers.getBuffer(1).getBytes();
570 
571         assertNotNull(encryptedTokenData);
572         assertNotNull(encryptedData);
573         assertTrue(encryptedTokenData.length > 0);
574         assertTrue(encryptedData.length > 0);
575         assertFalse(Arrays.equals(inputData, encryptedData));
576 
577         // Do decryption of data with the pfServerContextAttr
578         ManagedSecBufferDesc decryptBuffers = new ManagedSecBufferDesc(2);
579 
580         Memory decryptTokenMemory = new Memory(encryptedTokenData.length);
581         decryptTokenMemory.write(0, encryptedTokenData, 0, encryptedTokenData.length);
582         Memory decryptDataMemory = new Memory(encryptedData.length);
583         decryptDataMemory.write(0, encryptedData, 0, encryptedData.length);
584 
585         decryptBuffers.getBuffer(0).BufferType = Sspi.SECBUFFER_TOKEN;
586         decryptBuffers.getBuffer(0).cbBuffer = (int) decryptTokenMemory.size();
587         decryptBuffers.getBuffer(0).pvBuffer = decryptTokenMemory;
588         decryptBuffers.getBuffer(1).BufferType = Sspi.SECBUFFER_DATA;
589         decryptBuffers.getBuffer(1).cbBuffer = (int) decryptDataMemory.size();
590         decryptBuffers.getBuffer(1).pvBuffer = decryptDataMemory;
591 
592         IntByReference qosResult = new IntByReference();
593         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DecryptMessage(phServerContext, decryptBuffers, 0, qosResult));
594 
595         byte[] decryptMessageResult = decryptBuffers.getBuffer(1).getBytes();
596         assertTrue(Arrays.equals(inputData, decryptMessageResult));
597 
598         // Modify message and retry decryption. Decryption is expected to be
599         // refused and the buffers should be untouched.
600         // Modification is done by injecting a NULL byte into the beginning of
601         // the message
602 
603         ManagedSecBufferDesc decryptBuffers2 = new ManagedSecBufferDesc(2);
604 
605         Memory decryptTokenMemory2 = new Memory(encryptedTokenData.length);
606         decryptTokenMemory2.write(0, encryptedTokenData, 0, encryptedTokenData.length);
607         Memory decryptDataMemory2 = new Memory(encryptedData.length + 1);
608         decryptDataMemory2.write(1, encryptedData, 0, encryptedData.length);
609 
610         decryptBuffers2.getBuffer(0).BufferType = Sspi.SECBUFFER_TOKEN;
611         decryptBuffers2.getBuffer(0).cbBuffer = (int) decryptTokenMemory2.size();
612         decryptBuffers2.getBuffer(0).pvBuffer = decryptTokenMemory2;
613         decryptBuffers2.getBuffer(1).BufferType = Sspi.SECBUFFER_DATA;
614         decryptBuffers2.getBuffer(1).cbBuffer = (int) decryptDataMemory2.size();
615         decryptBuffers2.getBuffer(1).pvBuffer = decryptDataMemory2;
616 
617         assertEquals(W32Errors.SEC_E_MESSAGE_ALTERED, Secur32.INSTANCE.DecryptMessage(phServerContext, decryptBuffers2, 0, qosResult));
618 
619         // release server context
620         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
621                 phServerContext));
622         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
623                 phServerCredential));
624         // release client context
625         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
626                 phClientContext));
627         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
628                 phClientCredential));
629     }
630 
testMakeVerifySignature()631     public void testMakeVerifySignature() {
632         // client ----------- acquire outbound credential handle
633         CredHandle phClientCredential = new CredHandle();
634         TimeStamp ptsClientExpiry = new TimeStamp();
635         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
636                 null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
637                 null, phClientCredential, ptsClientExpiry));
638         // client ----------- security context
639         CtxtHandle phClientContext = new CtxtHandle();
640         IntByReference pfClientContextAttr = new IntByReference();
641         // server ----------- acquire inbound credential handle
642         CredHandle phServerCredential = new CredHandle();
643         TimeStamp ptsServerExpiry = new TimeStamp();
644         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
645                 null, "Negotiate", Sspi.SECPKG_CRED_INBOUND, null, null, null,
646                 null, phServerCredential, ptsServerExpiry));
647         // server ----------- security context
648         CtxtHandle phServerContext = new CtxtHandle();
649         ManagedSecBufferDesc pbServerToken = null;
650         IntByReference pfServerContextAttr = new IntByReference();
651         int clientRc = W32Errors.SEC_I_CONTINUE_NEEDED;
652         int serverRc = W32Errors.SEC_I_CONTINUE_NEEDED;
653         do {
654             // client ----------- initialize security context, produce a client token
655             // client token returned is always new
656             ManagedSecBufferDesc pbClientToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
657             if (clientRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
658                 // server token is empty the first time
659                 ManagedSecBufferDesc pbServerTokenCopy = pbServerToken == null
660                         ? null : new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbServerToken.getBuffer(0).getBytes());
661                 clientRc = Secur32.INSTANCE.InitializeSecurityContext(
662                         phClientCredential,
663                         phClientContext.isNull() ? null : phClientContext,
664                         Advapi32Util.getUserName(),
665                         Sspi.ISC_REQ_CONNECTION | Sspi.ISC_REQ_CONFIDENTIALITY,
666                         0,
667                         Sspi.SECURITY_NATIVE_DREP,
668                         pbServerTokenCopy,
669                         0,
670                         phClientContext,
671                         pbClientToken,
672                         pfClientContextAttr,
673                         null);
674                 assertTrue(clientRc == W32Errors.SEC_I_CONTINUE_NEEDED || clientRc == W32Errors.SEC_E_OK);
675             }
676             // server ----------- accept security context, produce a server token
677             if (serverRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
678                 pbServerToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
679                 ManagedSecBufferDesc pbClientTokenByValue = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbClientToken.getBuffer(0).getBytes());
680                 serverRc = Secur32.INSTANCE.AcceptSecurityContext(phServerCredential,
681                         phServerContext.isNull() ? null : phServerContext,
682                         pbClientTokenByValue,
683                         Sspi.ISC_REQ_CONNECTION | Sspi.ISC_REQ_CONFIDENTIALITY,
684                         Sspi.SECURITY_NATIVE_DREP,
685                         phServerContext,
686                         pbServerToken,
687                         pfServerContextAttr,
688                         ptsServerExpiry);
689                 assertTrue(serverRc == W32Errors.SEC_I_CONTINUE_NEEDED || serverRc == W32Errors.SEC_E_OK);
690             }
691         } while(serverRc != W32Errors.SEC_E_OK || clientRc != W32Errors.SEC_E_OK);
692 
693         assertTrue((pfServerContextAttr.getValue() & Sspi.ISC_REQ_CONFIDENTIALITY) == Sspi.ISC_REQ_CONFIDENTIALITY);
694         assertTrue((pfClientContextAttr.getValue() & Sspi.ISC_REQ_CONFIDENTIALITY) == Sspi.ISC_REQ_CONFIDENTIALITY);
695 
696         // Fetch size limits for crypto functions
697         SecPkgContext_Sizes sizes = new SecPkgContext_Sizes();
698         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.QueryContextAttributes(phClientContext, Sspi.SECPKG_ATTR_SIZES, sizes));
699 
700         // Create sample input data
701         byte[] inputData = "Hallo Welt".getBytes(Charset.forName("ASCII"));
702 
703         // Make signature, buffer 0 holds signature data, buffer 1 holds the
704         // clear text data
705         ManagedSecBufferDesc signingBuffers = new ManagedSecBufferDesc(2);
706 
707         Memory tokenMemory = new Memory(sizes.cbMaxSignature);
708         Memory dataMemory = new Memory(inputData.length);
709         dataMemory.write(0, inputData, 0, inputData.length);
710 
711         signingBuffers.getBuffer(0).BufferType = Sspi.SECBUFFER_TOKEN;
712         signingBuffers.getBuffer(0).cbBuffer = (int) tokenMemory.size();
713         signingBuffers.getBuffer(0).pvBuffer = tokenMemory;
714         signingBuffers.getBuffer(1).BufferType = Sspi.SECBUFFER_DATA;
715         signingBuffers.getBuffer(1).cbBuffer = (int) dataMemory.size();
716         signingBuffers.getBuffer(1).pvBuffer = dataMemory;
717 
718         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.MakeSignature(phClientContext, 0, signingBuffers, 0));
719 
720         byte[] signingData = signingBuffers.getBuffer(0).getBytes();
721         byte[] signedData = signingBuffers.getBuffer(1).getBytes();
722 
723         assertNotNull(signingData);
724         assertNotNull(signedData);
725         assertTrue(signingData.length > 0);
726         assertTrue(signedData.length > 0);
727         assertTrue(Arrays.equals(inputData, signedData));
728 
729         // Do verification of data with the pfServerContextAttr
730         ManagedSecBufferDesc verificationBuffers = new ManagedSecBufferDesc(2);
731 
732         Memory verificationSigningMemory = new Memory(signingData.length);
733         verificationSigningMemory.write(0, signingData, 0, signingData.length);
734         Memory verificiationSignedMemory = new Memory(signedData.length);
735         verificiationSignedMemory.write(0, signedData, 0, signedData.length);
736 
737         verificationBuffers.getBuffer(0).BufferType = Sspi.SECBUFFER_TOKEN;
738         verificationBuffers.getBuffer(0).cbBuffer = (int) verificationSigningMemory.size();
739         verificationBuffers.getBuffer(0).pvBuffer = verificationSigningMemory;
740         verificationBuffers.getBuffer(1).BufferType = Sspi.SECBUFFER_DATA;
741         verificationBuffers.getBuffer(1).cbBuffer = (int) verificiationSignedMemory.size();
742         verificationBuffers.getBuffer(1).pvBuffer = verificiationSignedMemory;
743 
744         IntByReference qosResult = new IntByReference();
745         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.VerifySignature(phServerContext, verificationBuffers, 0, qosResult));
746 
747         byte[] decryptMessageResult = verificationBuffers.getBuffer(1).getBytes();
748         assertTrue(Arrays.equals(inputData, decryptMessageResult));
749 
750         // Modify message and retry decryption. Decryption is expected to be
751         // refused and the buffers should be untouched.
752         // Modification is done by injecting a NULL byte into the beginning of
753         // the message
754 
755         ManagedSecBufferDesc verificationBuffers2 = new ManagedSecBufferDesc(2);
756 
757         Memory verificationSigingMemory2 = new Memory(signingData.length);
758         verificationSigingMemory2.write(0, signingData, 0, signingData.length);
759         Memory verificationSignedMemory2 = new Memory(signedData.length + 1);
760         verificationSignedMemory2.write(1, signedData, 0, signedData.length);
761 
762         verificationBuffers2.getBuffer(0).BufferType = Sspi.SECBUFFER_TOKEN;
763         verificationBuffers2.getBuffer(0).cbBuffer = (int) verificationSigingMemory2.size();
764         verificationBuffers2.getBuffer(0).pvBuffer = verificationSigingMemory2;
765         verificationBuffers2.getBuffer(1).BufferType = Sspi.SECBUFFER_DATA;
766         verificationBuffers2.getBuffer(1).cbBuffer = (int) verificationSignedMemory2.size();
767         verificationBuffers2.getBuffer(1).pvBuffer = verificationSignedMemory2;
768 
769         qosResult = new IntByReference();
770         assertEquals(W32Errors.SEC_E_MESSAGE_ALTERED, Secur32.INSTANCE.VerifySignature(phServerContext, verificationBuffers2, 0, qosResult));
771 
772         // release server context
773         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
774                 phServerContext));
775         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
776                 phServerCredential));
777         // release client context
778         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
779                 phClientContext));
780         assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
781                 phClientCredential));
782     }
783 
testCompleteAuthToken()784     public void testCompleteAuthToken() {
785         /*
786         This is not a real test of the function, it just ensures, that it is
787         callable and returns a sane error code.
788         */
789         int result = Secur32.INSTANCE.CompleteAuthToken(null, null);
790         assertTrue(String.format("Unexpected error code: 0x%08X%n", result),
791                 result == WinError.SEC_E_INVALID_HANDLE
792                 || result == WinError.SEC_E_INVALID_TOKEN);
793     }
794 }
795