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 WIN32_NO_STATUS
29 #define SECURITY_WIN32
38 #include "wine/test.h"
40 #define NEGOTIATE_BASE_CAPS ( \
41 SECPKG_FLAG_INTEGRITY | \
42 SECPKG_FLAG_PRIVACY | \
43 SECPKG_FLAG_CONNECTION | \
44 SECPKG_FLAG_MULTI_REQUIRED | \
45 SECPKG_FLAG_EXTENDED_ERROR | \
46 SECPKG_FLAG_IMPERSONATION | \
47 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
48 SECPKG_FLAG_NEGOTIABLE | \
49 SECPKG_FLAG_GSS_COMPATIBLE | \
52 #define NTLM_BASE_CAPS ( \
53 SECPKG_FLAG_INTEGRITY | \
54 SECPKG_FLAG_PRIVACY | \
55 SECPKG_FLAG_TOKEN_ONLY | \
56 SECPKG_FLAG_CONNECTION | \
57 SECPKG_FLAG_MULTI_REQUIRED | \
58 SECPKG_FLAG_IMPERSONATION | \
59 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
60 SECPKG_FLAG_NEGOTIABLE | \
67 PSecBufferDesc in_buf
;
68 PSecBufferDesc out_buf
;
69 PSEC_WINNT_AUTH_IDENTITY_A id
;
73 static void cleanup_buffers( struct sspi_data
*data
)
79 for (i
= 0; i
< data
->in_buf
->cBuffers
; ++i
)
80 HeapFree( GetProcessHeap(), 0, data
->in_buf
->pBuffers
[i
].pvBuffer
);
81 HeapFree( GetProcessHeap(), 0, data
->in_buf
->pBuffers
);
82 HeapFree( GetProcessHeap(), 0, data
->in_buf
);
86 for (i
= 0; i
< data
->out_buf
->cBuffers
; ++i
)
87 HeapFree( GetProcessHeap(), 0, data
->out_buf
->pBuffers
[i
].pvBuffer
);
88 HeapFree( GetProcessHeap(), 0, data
->out_buf
->pBuffers
);
89 HeapFree( GetProcessHeap(), 0, data
->out_buf
);
93 static void setup_buffers( struct sspi_data
*data
, SecPkgInfoA
*info
)
95 SecBuffer
*buffer
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer
) );
97 data
->in_buf
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc
) );
98 data
->out_buf
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc
) );
99 data
->max_token
= info
->cbMaxToken
;
101 data
->in_buf
->ulVersion
= SECBUFFER_VERSION
;
102 data
->in_buf
->cBuffers
= 1;
103 data
->in_buf
->pBuffers
= buffer
;
105 buffer
->cbBuffer
= info
->cbMaxToken
;
106 buffer
->BufferType
= SECBUFFER_TOKEN
;
107 buffer
->pvBuffer
= HeapAlloc( GetProcessHeap(), 0, info
->cbMaxToken
);
109 buffer
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer
) );
111 data
->out_buf
->ulVersion
= SECBUFFER_VERSION
;
112 data
->out_buf
->cBuffers
= 1;
113 data
->out_buf
->pBuffers
= buffer
;
115 buffer
->cbBuffer
= info
->cbMaxToken
;
116 buffer
->BufferType
= SECBUFFER_TOKEN
;
117 buffer
->pvBuffer
= HeapAlloc( GetProcessHeap(), 0, info
->cbMaxToken
);
120 static SECURITY_STATUS
setup_client( struct sspi_data
*data
, SEC_CHAR
*provider
)
126 trace( "setting up client\n" );
128 ret
= QuerySecurityPackageInfoA( provider
, &info
);
129 ok( ret
== SEC_E_OK
, "QuerySecurityPackageInfo returned %08lx\n", ret
);
131 setup_buffers( data
, info
);
132 FreeContextBuffer( info
);
134 ret
= AcquireCredentialsHandleA( NULL
, provider
, SECPKG_CRED_OUTBOUND
, NULL
,
135 data
->id
, NULL
, NULL
, &data
->cred
, &ttl
);
136 ok( ret
== SEC_E_OK
, "AcquireCredentialsHandleA returned %08lx\n", ret
);
140 static SECURITY_STATUS
setup_server( struct sspi_data
*data
, SEC_CHAR
*provider
)
146 trace( "setting up server\n" );
148 ret
= QuerySecurityPackageInfoA( provider
, &info
);
149 ok( ret
== SEC_E_OK
, "QuerySecurityPackageInfo returned %08lx\n", ret
);
151 setup_buffers( data
, info
);
152 FreeContextBuffer( info
);
154 ret
= AcquireCredentialsHandleA( NULL
, provider
, SECPKG_CRED_INBOUND
, NULL
,
155 NULL
, NULL
, NULL
, &data
->cred
, &ttl
);
156 ok( ret
== SEC_E_OK
, "AcquireCredentialsHandleA returned %08lx\n", ret
);
160 static SECURITY_STATUS
run_client( struct sspi_data
*data
, BOOL first
)
166 trace( "running client for the %s time\n", first
? "first" : "second" );
168 data
->out_buf
->pBuffers
[0].cbBuffer
= data
->max_token
;
169 data
->out_buf
->pBuffers
[0].BufferType
= SECBUFFER_TOKEN
;
171 ret
= InitializeSecurityContextA( first
? &data
->cred
: NULL
, first
? NULL
: &data
->ctxt
,
172 NULL
, 0, 0, SECURITY_NETWORK_DREP
, first
? NULL
: data
->in_buf
,
173 0, &data
->ctxt
, data
->out_buf
, &attr
, &ttl
);
174 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
|| ret
== SEC_I_COMPLETE_NEEDED
)
176 CompleteAuthToken( &data
->ctxt
, data
->out_buf
);
177 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
)
178 ret
= SEC_I_CONTINUE_NEEDED
;
179 else if (ret
== SEC_I_COMPLETE_NEEDED
)
182 ok( data
->out_buf
->pBuffers
[0].BufferType
== SECBUFFER_TOKEN
,
183 "buffer type changed from SECBUFFER_TOKEN to %lu\n", data
->out_buf
->pBuffers
[0].BufferType
);
184 ok( data
->out_buf
->pBuffers
[0].cbBuffer
< data
->max_token
,
185 "InitializeSecurityContext didn't change buffer size\n" );
189 static SECURITY_STATUS
run_server( struct sspi_data
*data
, BOOL first
)
195 trace( "running server for the %s time\n", first
? "first" : "second" );
197 ret
= AcceptSecurityContext( &data
->cred
, first
? NULL
: &data
->ctxt
,
198 data
->in_buf
, 0, SECURITY_NETWORK_DREP
,
199 &data
->ctxt
, data
->out_buf
, &attr
, &ttl
);
200 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
|| ret
== SEC_I_COMPLETE_NEEDED
)
202 CompleteAuthToken( &data
->ctxt
, data
->out_buf
);
203 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
)
204 ret
= SEC_I_CONTINUE_NEEDED
;
205 else if (ret
== SEC_I_COMPLETE_NEEDED
)
211 static void communicate( struct sspi_data
*from
, struct sspi_data
*to
)
213 trace( "running communicate\n" );
214 memset( to
->in_buf
->pBuffers
[0].pvBuffer
, 0, to
->max_token
);
215 memcpy( to
->in_buf
->pBuffers
[0].pvBuffer
, from
->out_buf
->pBuffers
[0].pvBuffer
,
216 from
->out_buf
->pBuffers
[0].cbBuffer
);
217 to
->in_buf
->pBuffers
[0].cbBuffer
= from
->out_buf
->pBuffers
[0].cbBuffer
;
218 memset( from
->out_buf
->pBuffers
[0].pvBuffer
, 0, from
->max_token
);
221 static void test_authentication(void)
223 SECURITY_STATUS status_c
= SEC_I_CONTINUE_NEEDED
,
224 status_s
= SEC_I_CONTINUE_NEEDED
, status
;
225 struct sspi_data client
, server
;
226 SEC_WINNT_AUTH_IDENTITY_A id
;
227 SecPkgContext_NegotiationInfoA info
;
228 SecPkgContext_Sizes sizes
;
232 memset(&client
, 0, sizeof(client
));
233 memset(&server
, 0, sizeof(server
));
235 id
.User
= (unsigned char *)"user";
236 id
.UserLength
= strlen( "user" );
237 id
.Domain
= (unsigned char *)"domain";
238 id
.DomainLength
= strlen( "domain" );
239 id
.Password
= (unsigned char *)"password";
240 id
.PasswordLength
= strlen( "password" );
241 id
.Flags
= SEC_WINNT_AUTH_IDENTITY_ANSI
;
244 if ((status
= setup_client( &client
, (SEC_CHAR
*)"Negotiate" )))
246 skip( "setup_client returned %08lx, skipping test\n", status
);
249 if ((status
= setup_server( &server
, (SEC_CHAR
*)"Negotiate" )))
251 skip( "setup_server returned %08lx, skipping test\n", status
);
252 FreeCredentialsHandle( &client
.cred
);
256 while (status_c
== SEC_I_CONTINUE_NEEDED
&& status_s
== SEC_I_CONTINUE_NEEDED
)
258 status_c
= run_client( &client
, first
);
259 ok( status_c
== SEC_E_OK
|| status_c
== SEC_I_CONTINUE_NEEDED
,
260 "client returned %08lx, more tests will fail\n", status_c
);
262 communicate( &client
, &server
);
264 status_s
= run_server( &server
, first
);
265 ok( status_s
== SEC_E_OK
|| status_s
== SEC_I_CONTINUE_NEEDED
||
266 status_s
== SEC_E_LOGON_DENIED
,
267 "server returned %08lx, more tests will fail\n", status_s
);
269 communicate( &server
, &client
);
273 if (status_c
!= SEC_E_OK
)
275 skip( "authentication failed, skipping remaining tests\n" );
279 sizes
.cbMaxToken
= 0xdeadbeef;
280 sizes
.cbMaxSignature
= 0xdeadbeef;
281 sizes
.cbSecurityTrailer
= 0xdeadbeef;
282 sizes
.cbBlockSize
= 0xdeadbeef;
283 status_c
= QueryContextAttributesA( &client
.ctxt
, SECPKG_ATTR_SIZES
, &sizes
);
284 ok( status_c
== SEC_E_OK
, "pQueryContextAttributesA returned %08lx\n", status_c
);
285 ok( sizes
.cbMaxToken
== 2888 || sizes
.cbMaxToken
== 1904,
286 "expected 2888 or 1904, got %lu\n", sizes
.cbMaxToken
);
287 ok( sizes
.cbMaxSignature
== 16, "expected 16, got %lu\n", sizes
.cbMaxSignature
);
288 ok( sizes
.cbSecurityTrailer
== 16, "expected 16, got %lu\n", sizes
.cbSecurityTrailer
);
289 ok( !sizes
.cbBlockSize
, "expected 0, got %lu\n", sizes
.cbBlockSize
);
291 memset( &info
, 0, sizeof(info
) );
292 status_c
= QueryContextAttributesA( &client
.ctxt
, SECPKG_ATTR_NEGOTIATION_INFO
, &info
);
293 ok( status_c
== SEC_E_OK
, "QueryContextAttributesA returned %08lx\n", status_c
);
295 pi
= info
.PackageInfo
;
296 ok( info
.NegotiationState
== SECPKG_NEGOTIATION_COMPLETE
, "got %lu\n", info
.NegotiationState
);
297 ok( pi
!= NULL
, "expected non-NULL PackageInfo\n" );
303 ok( pi
->fCapabilities
== NTLM_BASE_CAPS
||
304 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_READONLY_WITH_CHECKSUM
) ||
305 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
) ||
306 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|SECPKG_FLAG_APPCONTAINER_CHECKS
) ||
307 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|SECPKG_FLAG_APPLY_LOOPBACK
) ||
308 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|SECPKG_FLAG_APPLY_LOOPBACK
|
309 SECPKG_FLAG_APPCONTAINER_CHECKS
),
310 "got %08lx\n", pi
->fCapabilities
);
311 ok( pi
->wVersion
== 1, "got %u\n", pi
->wVersion
);
312 ok( pi
->wRPCID
== RPC_C_AUTHN_WINNT
, "got %u\n", pi
->wRPCID
);
313 ok( !lstrcmpA( pi
->Name
, "NTLM" ), "got %s\n", pi
->Name
);
315 expected
= sizeof(*pi
) + lstrlenA(pi
->Name
) + 1 + lstrlenA(pi
->Comment
) + 1;
316 got
= HeapSize(GetProcessHeap(), 0, pi
);
317 ok( got
== expected
, "got %u, expected %u\n", got
, expected
);
318 eob
= (char *)pi
+ expected
;
319 ok( pi
->Name
+ lstrlenA(pi
->Name
) < eob
, "Name doesn't fit into allocated block\n" );
320 ok( pi
->Comment
+ lstrlenA(pi
->Comment
) < eob
, "Comment doesn't fit into allocated block\n" );
322 status
= FreeContextBuffer( pi
);
323 ok( status
== SEC_E_OK
, "FreeContextBuffer error %#lx\n", status
);
327 cleanup_buffers( &client
);
328 cleanup_buffers( &server
);
330 if (client
.ctxt
.dwLower
|| client
.ctxt
.dwUpper
)
332 status_c
= DeleteSecurityContext( &client
.ctxt
);
333 ok( status_c
== SEC_E_OK
, "DeleteSecurityContext returned %08lx\n", status_c
);
336 if (server
.ctxt
.dwLower
|| server
.ctxt
.dwUpper
)
338 status_s
= DeleteSecurityContext( &server
.ctxt
);
339 ok( status_s
== SEC_E_OK
, "DeleteSecurityContext returned %08lx\n", status_s
);
342 if (client
.cred
.dwLower
|| client
.cred
.dwUpper
)
344 status_c
= FreeCredentialsHandle( &client
.cred
);
345 ok( status_c
== SEC_E_OK
, "FreeCredentialsHandle returned %08lx\n", status_c
);
348 if (server
.cred
.dwLower
|| server
.cred
.dwUpper
)
350 status_s
= FreeCredentialsHandle(&server
.cred
);
351 ok( status_s
== SEC_E_OK
, "FreeCredentialsHandle returned %08lx\n", status_s
);
355 static void test_Negotiate(void)
358 NTSTATUS status
, call_status
;
361 NEGOTIATE_CALLER_NAME_REQUEST req
;
362 NEGOTIATE_CALLER_NAME_RESPONSE
*resp
;
364 status
= LsaConnectUntrusted(&lsa
);
365 ok(!status
, "got %08lx\n", status
);
367 RtlInitAnsiString(&name
, "Negotiate");
369 status
= LsaLookupAuthenticationPackage(lsa
, &name
, &id
);
370 ok(!status
, "got %08lx\n", status
);
371 ok(id
== 0, "got %lu\n", id
);
373 req
.MessageType
= NegGetCallerName
;
374 req
.LogonId
.LowPart
= 0;
375 req
.LogonId
.HighPart
= 0;
376 resp
= (void *)(ULONG_PTR
)0xdeadbeef;
378 call_status
= 0xdeadbeef;
379 status
= LsaCallAuthenticationPackage(lsa
, 0, &req
, sizeof(req
), (void **)&resp
, &size
, &call_status
);
380 ok(status
== STATUS_SUCCESS
, "got %08lx\n", status
);
381 ok(call_status
== STATUS_NO_SUCH_LOGON_SESSION
|| call_status
== STATUS_SUCCESS
, "got %08lx\n", call_status
);
382 if (call_status
== STATUS_NO_SUCH_LOGON_SESSION
)
384 ok(size
== 0, "got %lu\n", size
);
385 ok(resp
== NULL
, "got %p\n", resp
);
387 else /* STATUS_SUCCESS */
389 if (resp
&& resp
->CallerName
)
390 trace("resp->CallerName = %s\n", debugstr_w(resp
->CallerName
));
391 ok(resp
!= NULL
, "got NULL\n");
392 ok(resp
->MessageType
== NegGetCallerName
, "got %lu\n", resp
->MessageType
);
393 ok((char *)resp
->CallerName
>= (char *)(resp
+ 1), "got %p/%p\n", resp
, resp
->CallerName
);
394 ok(size
>= sizeof(*resp
) + (wcslen(resp
->CallerName
) + 1) * sizeof(WCHAR
), "got %lu\n", size
);
398 call_status
= 0xdeadbeef;
399 status
= LsaCallAuthenticationPackage(lsa
, 0, NULL
, 0, NULL
, &size
, &call_status
);
400 ok(status
== STATUS_INVALID_PARAMETER
, "got %08lx\n", status
);
401 ok(call_status
== STATUS_SUCCESS
, "got %08lx\n", call_status
);
402 ok(size
== 0, "got %08lx\n", size
);
405 status
= LsaCallAuthenticationPackage(lsa
, 0, NULL
, 0, NULL
, &size
, NULL
);
406 ok(status
== STATUS_INVALID_PARAMETER
, "got %08lx\n", status
);
407 ok(size
== 0, "got %08lx\n", size
);
409 call_status
= 0xdeadbeef;
410 status
= LsaCallAuthenticationPackage(lsa
, 0, NULL
, 0, NULL
, NULL
, &call_status
);
411 ok(status
== STATUS_INVALID_PARAMETER
, "got %08lx\n", status
);
412 ok(call_status
== STATUS_SUCCESS
, "got %08lx\n", call_status
);
414 resp
= (void *)(ULONG_PTR
)0xdeadbeef;
416 call_status
= 0xdeadbeef;
417 status
= LsaCallAuthenticationPackage(lsa
, 0xdeadbeef, NULL
, 0, (void **)&resp
, &size
, &call_status
);
418 ok(status
== STATUS_NO_SUCH_PACKAGE
, "got %08lx\n", status
);
419 ok(call_status
== STATUS_SUCCESS
, "got %08lx\n", call_status
);
420 ok(size
== 0, "got %08lx\n", size
);
421 ok(resp
== NULL
, "got %p\n", resp
);
423 LsaDeregisterLogonProcess(lsa
);
426 START_TEST(negotiate
)
430 if (QuerySecurityPackageInfoA( (SEC_CHAR
*)"Negotiate", &info
))
432 ok( 0, "Negotiate package not installed, skipping test\n" );
435 ok( info
->fCapabilities
== NEGOTIATE_BASE_CAPS
||
436 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_READONLY_WITH_CHECKSUM
) ||
437 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
) ||
438 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|
439 SECPKG_FLAG_APPCONTAINER_CHECKS
),
440 "got %08lx\n", info
->fCapabilities
);
441 ok( info
->wVersion
== 1, "got %u\n", info
->wVersion
);
442 ok( info
->wRPCID
== RPC_C_AUTHN_GSS_NEGOTIATE
, "got %u\n", info
->wRPCID
);
443 ok( !lstrcmpA( info
->Name
, "Negotiate" ), "got %s\n", info
->Name
);
444 FreeContextBuffer( info
);
446 test_authentication();