2 * Tests for the Negotiate security provider
4 * Copyright 2005, 2006 Kai Blin
5 * Copyright 2012 Hans Leidekker for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define SECURITY_WIN32
32 #include "wine/test.h"
34 static HMODULE hsecur32
;
35 static SECURITY_STATUS (SEC_ENTRY
* pAcceptSecurityContext
)(PCredHandle
, PCtxtHandle
,
36 PSecBufferDesc
, ULONG
, ULONG
, PCtxtHandle
, PSecBufferDesc
, PULONG
, PTimeStamp
);
37 static SECURITY_STATUS (SEC_ENTRY
* pAcquireCredentialsHandleA
)(SEC_CHAR
*, SEC_CHAR
*,
38 ULONG
, PLUID
, PVOID
, SEC_GET_KEY_FN
, PVOID
, PCredHandle
, PTimeStamp
);
39 static SECURITY_STATUS (SEC_ENTRY
* pCompleteAuthToken
)(PCtxtHandle
, PSecBufferDesc
);
40 static SECURITY_STATUS (SEC_ENTRY
* pDecryptMessage
)(PCtxtHandle
, PSecBufferDesc
, ULONG
, PULONG
);
41 static SECURITY_STATUS (SEC_ENTRY
* pDeleteSecurityContext
)(PCtxtHandle
);
42 static SECURITY_STATUS (SEC_ENTRY
* pEncryptMessage
)(PCtxtHandle
, ULONG
, PSecBufferDesc
, ULONG
);
43 static SECURITY_STATUS (SEC_ENTRY
* pFreeContextBuffer
)(PVOID
);
44 static SECURITY_STATUS (SEC_ENTRY
* pFreeCredentialsHandle
)(PCredHandle
);
45 static SECURITY_STATUS (SEC_ENTRY
* pInitializeSecurityContextA
)(PCredHandle
, PCtxtHandle
,
46 SEC_CHAR
*, ULONG
, ULONG
, ULONG
, PSecBufferDesc
, ULONG
, PCtxtHandle
, PSecBufferDesc
,
48 static PSecurityFunctionTableA (SEC_ENTRY
* pInitSecurityInterfaceA
)(void);
49 static SECURITY_STATUS (SEC_ENTRY
* pMakeSignature
)(PCtxtHandle
, ULONG
, PSecBufferDesc
, ULONG
);
50 static SECURITY_STATUS (SEC_ENTRY
* pQueryContextAttributesA
)(PCtxtHandle
, ULONG
, PVOID
);
51 static SECURITY_STATUS (SEC_ENTRY
* pQuerySecurityPackageInfoA
)(SEC_CHAR
*, PSecPkgInfoA
*);
52 static SECURITY_STATUS (SEC_ENTRY
* pVerifySignature
)(PCtxtHandle
, PSecBufferDesc
, ULONG
, PULONG
);
54 static void init_function_ptrs(void)
56 if (!(hsecur32
= LoadLibraryA("secur32.dll"))) return;
57 pAcceptSecurityContext
= (void *)GetProcAddress(hsecur32
, "AcceptSecurityContext");
58 pAcquireCredentialsHandleA
= (void *)GetProcAddress(hsecur32
, "AcquireCredentialsHandleA");
59 pCompleteAuthToken
= (void *)GetProcAddress(hsecur32
, "CompleteAuthToken");
60 pDecryptMessage
= (void *)GetProcAddress(hsecur32
, "DecryptMessage");
61 pDeleteSecurityContext
= (void *)GetProcAddress(hsecur32
, "DeleteSecurityContext");
62 pEncryptMessage
= (void *)GetProcAddress(hsecur32
, "EncryptMessage");
63 pFreeContextBuffer
= (void *)GetProcAddress(hsecur32
, "FreeContextBuffer");
64 pFreeCredentialsHandle
= (void *)GetProcAddress(hsecur32
, "FreeCredentialsHandle");
65 pInitializeSecurityContextA
= (void *)GetProcAddress(hsecur32
, "InitializeSecurityContextA");
66 pInitSecurityInterfaceA
= (void *)GetProcAddress(hsecur32
, "InitSecurityInterfaceA");
67 pMakeSignature
= (void *)GetProcAddress(hsecur32
, "MakeSignature");
68 pQueryContextAttributesA
= (void *)GetProcAddress(hsecur32
, "QueryContextAttributesA");
69 pQuerySecurityPackageInfoA
= (void *)GetProcAddress(hsecur32
, "QuerySecurityPackageInfoA");
70 pVerifySignature
= (void *)GetProcAddress(hsecur32
, "VerifySignature");
73 #define NEGOTIATE_BASE_CAPS ( \
74 SECPKG_FLAG_INTEGRITY | \
75 SECPKG_FLAG_PRIVACY | \
76 SECPKG_FLAG_CONNECTION | \
77 SECPKG_FLAG_MULTI_REQUIRED | \
78 SECPKG_FLAG_EXTENDED_ERROR | \
79 SECPKG_FLAG_IMPERSONATION | \
80 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
81 SECPKG_FLAG_NEGOTIABLE | \
82 SECPKG_FLAG_GSS_COMPATIBLE | \
85 #define NTLM_BASE_CAPS ( \
86 SECPKG_FLAG_INTEGRITY | \
87 SECPKG_FLAG_PRIVACY | \
88 SECPKG_FLAG_TOKEN_ONLY | \
89 SECPKG_FLAG_CONNECTION | \
90 SECPKG_FLAG_MULTI_REQUIRED | \
91 SECPKG_FLAG_IMPERSONATION | \
92 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
93 SECPKG_FLAG_NEGOTIABLE | \
100 PSecBufferDesc in_buf
;
101 PSecBufferDesc out_buf
;
102 PSEC_WINNT_AUTH_IDENTITY_A id
;
106 static void cleanup_buffers( struct sspi_data
*data
)
112 for (i
= 0; i
< data
->in_buf
->cBuffers
; ++i
)
113 HeapFree( GetProcessHeap(), 0, data
->in_buf
->pBuffers
[i
].pvBuffer
);
114 HeapFree( GetProcessHeap(), 0, data
->in_buf
->pBuffers
);
115 HeapFree( GetProcessHeap(), 0, data
->in_buf
);
119 for (i
= 0; i
< data
->out_buf
->cBuffers
; ++i
)
120 HeapFree( GetProcessHeap(), 0, data
->out_buf
->pBuffers
[i
].pvBuffer
);
121 HeapFree( GetProcessHeap(), 0, data
->out_buf
->pBuffers
);
122 HeapFree( GetProcessHeap(), 0, data
->out_buf
);
126 static void setup_buffers( struct sspi_data
*data
, SecPkgInfoA
*info
)
128 SecBuffer
*buffer
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer
) );
130 data
->in_buf
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc
) );
131 data
->out_buf
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc
) );
132 data
->max_token
= info
->cbMaxToken
;
134 data
->in_buf
->ulVersion
= SECBUFFER_VERSION
;
135 data
->in_buf
->cBuffers
= 1;
136 data
->in_buf
->pBuffers
= buffer
;
138 buffer
->cbBuffer
= info
->cbMaxToken
;
139 buffer
->BufferType
= SECBUFFER_TOKEN
;
140 buffer
->pvBuffer
= HeapAlloc( GetProcessHeap(), 0, info
->cbMaxToken
);
142 buffer
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer
) );
144 data
->out_buf
->ulVersion
= SECBUFFER_VERSION
;
145 data
->out_buf
->cBuffers
= 1;
146 data
->out_buf
->pBuffers
= buffer
;
148 buffer
->cbBuffer
= info
->cbMaxToken
;
149 buffer
->BufferType
= SECBUFFER_TOKEN
;
150 buffer
->pvBuffer
= HeapAlloc( GetProcessHeap(), 0, info
->cbMaxToken
);
153 static SECURITY_STATUS
setup_client( struct sspi_data
*data
, SEC_CHAR
*provider
)
159 trace( "setting up client\n" );
161 ret
= pQuerySecurityPackageInfoA( provider
, &info
);
162 ok( ret
== SEC_E_OK
, "QuerySecurityPackageInfo returned %08x\n", ret
);
164 setup_buffers( data
, info
);
165 pFreeContextBuffer( info
);
167 ret
= pAcquireCredentialsHandleA( NULL
, provider
, SECPKG_CRED_OUTBOUND
, NULL
,
168 data
->id
, NULL
, NULL
, &data
->cred
, &ttl
);
169 ok( ret
== SEC_E_OK
, "AcquireCredentialsHandleA returned %08x\n", ret
);
173 static SECURITY_STATUS
setup_server( struct sspi_data
*data
, SEC_CHAR
*provider
)
179 trace( "setting up server\n" );
181 ret
= pQuerySecurityPackageInfoA( provider
, &info
);
182 ok( ret
== SEC_E_OK
, "QuerySecurityPackageInfo returned %08x\n", ret
);
184 setup_buffers( data
, info
);
185 pFreeContextBuffer( info
);
187 ret
= pAcquireCredentialsHandleA( NULL
, provider
, SECPKG_CRED_INBOUND
, NULL
,
188 NULL
, NULL
, NULL
, &data
->cred
, &ttl
);
189 ok( ret
== SEC_E_OK
, "AcquireCredentialsHandleA returned %08x\n", ret
);
193 static SECURITY_STATUS
run_client( struct sspi_data
*data
, BOOL first
)
199 trace( "running client for the %s time\n", first
? "first" : "second" );
201 data
->out_buf
->pBuffers
[0].cbBuffer
= data
->max_token
;
202 data
->out_buf
->pBuffers
[0].BufferType
= SECBUFFER_TOKEN
;
204 ret
= pInitializeSecurityContextA( first
? &data
->cred
: NULL
, first
? NULL
: &data
->ctxt
,
205 NULL
, 0, 0, SECURITY_NETWORK_DREP
, first
? NULL
: data
->in_buf
,
206 0, &data
->ctxt
, data
->out_buf
, &attr
, &ttl
);
207 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
|| ret
== SEC_I_COMPLETE_NEEDED
)
209 pCompleteAuthToken( &data
->ctxt
, data
->out_buf
);
210 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
)
211 ret
= SEC_I_CONTINUE_NEEDED
;
212 else if (ret
== SEC_I_COMPLETE_NEEDED
)
215 ok( data
->out_buf
->pBuffers
[0].BufferType
== SECBUFFER_TOKEN
,
216 "buffer type changed from SECBUFFER_TOKEN to %u\n", data
->out_buf
->pBuffers
[0].BufferType
);
217 ok( data
->out_buf
->pBuffers
[0].cbBuffer
< data
->max_token
,
218 "InitializeSecurityContext didn't change buffer size\n" );
222 static SECURITY_STATUS
run_server( struct sspi_data
*data
, BOOL first
)
228 trace( "running server for the %s time\n", first
? "first" : "second" );
230 ret
= pAcceptSecurityContext( &data
->cred
, first
? NULL
: &data
->ctxt
,
231 data
->in_buf
, 0, SECURITY_NETWORK_DREP
,
232 &data
->ctxt
, data
->out_buf
, &attr
, &ttl
);
233 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
|| ret
== SEC_I_COMPLETE_NEEDED
)
235 pCompleteAuthToken( &data
->ctxt
, data
->out_buf
);
236 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
)
237 ret
= SEC_I_CONTINUE_NEEDED
;
238 else if (ret
== SEC_I_COMPLETE_NEEDED
)
244 static void communicate( struct sspi_data
*from
, struct sspi_data
*to
)
246 trace( "running communicate\n" );
247 memset( to
->in_buf
->pBuffers
[0].pvBuffer
, 0, to
->max_token
);
248 memcpy( to
->in_buf
->pBuffers
[0].pvBuffer
, from
->out_buf
->pBuffers
[0].pvBuffer
,
249 from
->out_buf
->pBuffers
[0].cbBuffer
);
250 to
->in_buf
->pBuffers
[0].cbBuffer
= from
->out_buf
->pBuffers
[0].cbBuffer
;
251 memset( from
->out_buf
->pBuffers
[0].pvBuffer
, 0, from
->max_token
);
254 static void test_authentication(void)
256 SECURITY_STATUS status_c
= SEC_I_CONTINUE_NEEDED
,
257 status_s
= SEC_I_CONTINUE_NEEDED
, status
;
258 struct sspi_data client
, server
;
259 SEC_WINNT_AUTH_IDENTITY_A id
;
260 SecPkgContext_NegotiationInfoA info
;
261 SecPkgContext_Sizes sizes
;
265 id
.User
= (unsigned char *)"user";
266 id
.UserLength
= strlen( "user" );
267 id
.Domain
= (unsigned char *)"domain";
268 id
.DomainLength
= strlen( "domain" );
269 id
.Password
= (unsigned char *)"password";
270 id
.PasswordLength
= strlen( "password" );
271 id
.Flags
= SEC_WINNT_AUTH_IDENTITY_ANSI
;
274 if ((status
= setup_client( &client
, (SEC_CHAR
*)"Negotiate" )))
276 skip( "setup_client returned %08x, skipping test\n", status
);
279 if ((status
= setup_server( &server
, (SEC_CHAR
*)"Negotiate" )))
281 skip( "setup_server returned %08x, skipping test\n", status
);
282 pFreeCredentialsHandle( &client
.cred
);
286 while (status_c
== SEC_I_CONTINUE_NEEDED
&& status_s
== SEC_I_CONTINUE_NEEDED
)
288 status_c
= run_client( &client
, first
);
289 ok( status_c
== SEC_E_OK
|| status_c
== SEC_I_CONTINUE_NEEDED
,
290 "client returned %08x, more tests will fail\n", status_c
);
292 communicate( &client
, &server
);
294 status_s
= run_server( &server
, first
);
295 ok( status_s
== SEC_E_OK
|| status_s
== SEC_I_CONTINUE_NEEDED
||
296 status_s
== SEC_E_LOGON_DENIED
,
297 "server returned %08x, more tests will fail\n", status_s
);
299 communicate( &server
, &client
);
303 if (status_c
!= SEC_E_OK
)
305 skip( "authentication failed, skipping remaining tests\n" );
309 sizes
.cbMaxToken
= 0xdeadbeef;
310 sizes
.cbMaxSignature
= 0xdeadbeef;
311 sizes
.cbSecurityTrailer
= 0xdeadbeef;
312 sizes
.cbBlockSize
= 0xdeadbeef;
313 status_c
= pQueryContextAttributesA( &client
.ctxt
, SECPKG_ATTR_SIZES
, &sizes
);
314 ok( status_c
== SEC_E_OK
, "pQueryContextAttributesA returned %08x\n", status_c
);
315 ok( sizes
.cbMaxToken
== 2888 || sizes
.cbMaxToken
== 1904,
316 "expected 2888 or 1904, got %u\n", sizes
.cbMaxToken
);
317 ok( sizes
.cbMaxSignature
== 16, "expected 16, got %u\n", sizes
.cbMaxSignature
);
318 ok( sizes
.cbSecurityTrailer
== 16, "expected 16, got %u\n", sizes
.cbSecurityTrailer
);
319 ok( !sizes
.cbBlockSize
, "expected 0, got %u\n", sizes
.cbBlockSize
);
321 memset( &info
, 0, sizeof(info
) );
322 status_c
= pQueryContextAttributesA( &client
.ctxt
, SECPKG_ATTR_NEGOTIATION_INFO
, &info
);
323 ok( status_c
== SEC_E_OK
, "pQueryContextAttributesA returned %08x\n", status_c
);
325 pi
= info
.PackageInfo
;
326 ok( info
.NegotiationState
== SECPKG_NEGOTIATION_COMPLETE
, "got %u\n", info
.NegotiationState
);
327 ok( pi
!= NULL
, "expected non-NULL PackageInfo\n" );
330 ok( pi
->fCapabilities
== NTLM_BASE_CAPS
||
331 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_READONLY_WITH_CHECKSUM
) ||
332 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
) ||
333 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|
334 SECPKG_FLAG_APPCONTAINER_CHECKS
),
335 "got %08x\n", pi
->fCapabilities
);
336 ok( pi
->wVersion
== 1, "got %u\n", pi
->wVersion
);
337 ok( pi
->wRPCID
== RPC_C_AUTHN_WINNT
, "got %u\n", pi
->wRPCID
);
338 ok( !lstrcmpA( pi
->Name
, "NTLM" ), "got %s\n", pi
->Name
);
342 cleanup_buffers( &client
);
343 cleanup_buffers( &server
);
345 status_c
= pDeleteSecurityContext( &client
.ctxt
);
346 ok( status_c
== SEC_E_OK
, "DeleteSecurityContext returned %08x\n", status_c
);
348 status_s
= pDeleteSecurityContext( &server
.ctxt
);
349 ok( status_s
== SEC_E_OK
, "DeleteSecurityContext returned %08x\n", status_s
);
351 status_c
= pFreeCredentialsHandle( &client
.cred
);
352 ok( status_c
== SEC_E_OK
, "FreeCredentialsHandle returned %08x\n", status_c
);
354 status_s
= pFreeCredentialsHandle(&server
.cred
);
355 ok( status_s
== SEC_E_OK
, "FreeCredentialsHandle returned %08x\n", status_s
);
358 START_TEST(negotiate
)
362 init_function_ptrs();
364 if (!pFreeCredentialsHandle
|| !pAcquireCredentialsHandleA
|| !pQuerySecurityPackageInfoA
||
367 win_skip("functions are not available\n");
370 if (pQuerySecurityPackageInfoA( (SEC_CHAR
*)"Negotiate", &info
))
372 ok( 0, "Negotiate package not installed, skipping test\n" );
375 ok( info
->fCapabilities
== NEGOTIATE_BASE_CAPS
||
376 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_READONLY_WITH_CHECKSUM
) ||
377 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
) ||
378 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|
379 SECPKG_FLAG_APPCONTAINER_CHECKS
),
380 "got %08x\n", info
->fCapabilities
);
381 ok( info
->wVersion
== 1, "got %u\n", info
->wVersion
);
382 ok( info
->wRPCID
== RPC_C_AUTHN_GSS_NEGOTIATE
, "got %u\n", info
->wRPCID
);
383 ok( !lstrcmpA( info
->Name
, "Negotiate" ), "got %s\n", info
->Name
);
384 pFreeContextBuffer( info
);
386 test_authentication();