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 #define NEGOTIATE_BASE_CAPS ( \
35 SECPKG_FLAG_INTEGRITY | \
36 SECPKG_FLAG_PRIVACY | \
37 SECPKG_FLAG_CONNECTION | \
38 SECPKG_FLAG_MULTI_REQUIRED | \
39 SECPKG_FLAG_EXTENDED_ERROR | \
40 SECPKG_FLAG_IMPERSONATION | \
41 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
42 SECPKG_FLAG_NEGOTIABLE | \
43 SECPKG_FLAG_GSS_COMPATIBLE | \
46 #define NTLM_BASE_CAPS ( \
47 SECPKG_FLAG_INTEGRITY | \
48 SECPKG_FLAG_PRIVACY | \
49 SECPKG_FLAG_TOKEN_ONLY | \
50 SECPKG_FLAG_CONNECTION | \
51 SECPKG_FLAG_MULTI_REQUIRED | \
52 SECPKG_FLAG_IMPERSONATION | \
53 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
54 SECPKG_FLAG_NEGOTIABLE | \
61 PSecBufferDesc in_buf
;
62 PSecBufferDesc out_buf
;
63 PSEC_WINNT_AUTH_IDENTITY_A id
;
67 static void cleanup_buffers( struct sspi_data
*data
)
73 for (i
= 0; i
< data
->in_buf
->cBuffers
; ++i
)
74 HeapFree( GetProcessHeap(), 0, data
->in_buf
->pBuffers
[i
].pvBuffer
);
75 HeapFree( GetProcessHeap(), 0, data
->in_buf
->pBuffers
);
76 HeapFree( GetProcessHeap(), 0, data
->in_buf
);
80 for (i
= 0; i
< data
->out_buf
->cBuffers
; ++i
)
81 HeapFree( GetProcessHeap(), 0, data
->out_buf
->pBuffers
[i
].pvBuffer
);
82 HeapFree( GetProcessHeap(), 0, data
->out_buf
->pBuffers
);
83 HeapFree( GetProcessHeap(), 0, data
->out_buf
);
87 static void setup_buffers( struct sspi_data
*data
, SecPkgInfoA
*info
)
89 SecBuffer
*buffer
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer
) );
91 data
->in_buf
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc
) );
92 data
->out_buf
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc
) );
93 data
->max_token
= info
->cbMaxToken
;
95 data
->in_buf
->ulVersion
= SECBUFFER_VERSION
;
96 data
->in_buf
->cBuffers
= 1;
97 data
->in_buf
->pBuffers
= buffer
;
99 buffer
->cbBuffer
= info
->cbMaxToken
;
100 buffer
->BufferType
= SECBUFFER_TOKEN
;
101 buffer
->pvBuffer
= HeapAlloc( GetProcessHeap(), 0, info
->cbMaxToken
);
103 buffer
= HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer
) );
105 data
->out_buf
->ulVersion
= SECBUFFER_VERSION
;
106 data
->out_buf
->cBuffers
= 1;
107 data
->out_buf
->pBuffers
= buffer
;
109 buffer
->cbBuffer
= info
->cbMaxToken
;
110 buffer
->BufferType
= SECBUFFER_TOKEN
;
111 buffer
->pvBuffer
= HeapAlloc( GetProcessHeap(), 0, info
->cbMaxToken
);
114 static SECURITY_STATUS
setup_client( struct sspi_data
*data
, SEC_CHAR
*provider
)
120 trace( "setting up client\n" );
122 ret
= QuerySecurityPackageInfoA( provider
, &info
);
123 ok( ret
== SEC_E_OK
, "QuerySecurityPackageInfo returned %08x\n", ret
);
125 setup_buffers( data
, info
);
126 FreeContextBuffer( info
);
128 ret
= AcquireCredentialsHandleA( NULL
, provider
, SECPKG_CRED_OUTBOUND
, NULL
,
129 data
->id
, NULL
, NULL
, &data
->cred
, &ttl
);
130 ok( ret
== SEC_E_OK
, "AcquireCredentialsHandleA returned %08x\n", ret
);
134 static SECURITY_STATUS
setup_server( struct sspi_data
*data
, SEC_CHAR
*provider
)
140 trace( "setting up server\n" );
142 ret
= QuerySecurityPackageInfoA( provider
, &info
);
143 ok( ret
== SEC_E_OK
, "QuerySecurityPackageInfo returned %08x\n", ret
);
145 setup_buffers( data
, info
);
146 FreeContextBuffer( info
);
148 ret
= AcquireCredentialsHandleA( NULL
, provider
, SECPKG_CRED_INBOUND
, NULL
,
149 NULL
, NULL
, NULL
, &data
->cred
, &ttl
);
150 ok( ret
== SEC_E_OK
, "AcquireCredentialsHandleA returned %08x\n", ret
);
154 static SECURITY_STATUS
run_client( struct sspi_data
*data
, BOOL first
)
160 trace( "running client for the %s time\n", first
? "first" : "second" );
162 data
->out_buf
->pBuffers
[0].cbBuffer
= data
->max_token
;
163 data
->out_buf
->pBuffers
[0].BufferType
= SECBUFFER_TOKEN
;
165 ret
= InitializeSecurityContextA( first
? &data
->cred
: NULL
, first
? NULL
: &data
->ctxt
,
166 NULL
, 0, 0, SECURITY_NETWORK_DREP
, first
? NULL
: data
->in_buf
,
167 0, &data
->ctxt
, data
->out_buf
, &attr
, &ttl
);
168 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
|| ret
== SEC_I_COMPLETE_NEEDED
)
170 CompleteAuthToken( &data
->ctxt
, data
->out_buf
);
171 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
)
172 ret
= SEC_I_CONTINUE_NEEDED
;
173 else if (ret
== SEC_I_COMPLETE_NEEDED
)
176 ok( data
->out_buf
->pBuffers
[0].BufferType
== SECBUFFER_TOKEN
,
177 "buffer type changed from SECBUFFER_TOKEN to %u\n", data
->out_buf
->pBuffers
[0].BufferType
);
178 ok( data
->out_buf
->pBuffers
[0].cbBuffer
< data
->max_token
,
179 "InitializeSecurityContext didn't change buffer size\n" );
183 static SECURITY_STATUS
run_server( struct sspi_data
*data
, BOOL first
)
189 trace( "running server for the %s time\n", first
? "first" : "second" );
191 ret
= AcceptSecurityContext( &data
->cred
, first
? NULL
: &data
->ctxt
,
192 data
->in_buf
, 0, SECURITY_NETWORK_DREP
,
193 &data
->ctxt
, data
->out_buf
, &attr
, &ttl
);
194 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
|| ret
== SEC_I_COMPLETE_NEEDED
)
196 CompleteAuthToken( &data
->ctxt
, data
->out_buf
);
197 if (ret
== SEC_I_COMPLETE_AND_CONTINUE
)
198 ret
= SEC_I_CONTINUE_NEEDED
;
199 else if (ret
== SEC_I_COMPLETE_NEEDED
)
205 static void communicate( struct sspi_data
*from
, struct sspi_data
*to
)
207 trace( "running communicate\n" );
208 memset( to
->in_buf
->pBuffers
[0].pvBuffer
, 0, to
->max_token
);
209 memcpy( to
->in_buf
->pBuffers
[0].pvBuffer
, from
->out_buf
->pBuffers
[0].pvBuffer
,
210 from
->out_buf
->pBuffers
[0].cbBuffer
);
211 to
->in_buf
->pBuffers
[0].cbBuffer
= from
->out_buf
->pBuffers
[0].cbBuffer
;
212 memset( from
->out_buf
->pBuffers
[0].pvBuffer
, 0, from
->max_token
);
215 static void test_authentication(void)
217 SECURITY_STATUS status_c
= SEC_I_CONTINUE_NEEDED
,
218 status_s
= SEC_I_CONTINUE_NEEDED
, status
;
219 struct sspi_data client
, server
;
220 SEC_WINNT_AUTH_IDENTITY_A id
;
221 SecPkgContext_NegotiationInfoA info
;
222 SecPkgContext_Sizes sizes
;
226 memset(&client
, 0, sizeof(client
));
227 memset(&server
, 0, sizeof(server
));
229 id
.User
= (unsigned char *)"user";
230 id
.UserLength
= strlen( "user" );
231 id
.Domain
= (unsigned char *)"domain";
232 id
.DomainLength
= strlen( "domain" );
233 id
.Password
= (unsigned char *)"password";
234 id
.PasswordLength
= strlen( "password" );
235 id
.Flags
= SEC_WINNT_AUTH_IDENTITY_ANSI
;
238 if ((status
= setup_client( &client
, (SEC_CHAR
*)"Negotiate" )))
240 skip( "setup_client returned %08x, skipping test\n", status
);
243 if ((status
= setup_server( &server
, (SEC_CHAR
*)"Negotiate" )))
245 skip( "setup_server returned %08x, skipping test\n", status
);
246 FreeCredentialsHandle( &client
.cred
);
250 while (status_c
== SEC_I_CONTINUE_NEEDED
&& status_s
== SEC_I_CONTINUE_NEEDED
)
252 status_c
= run_client( &client
, first
);
253 ok( status_c
== SEC_E_OK
|| status_c
== SEC_I_CONTINUE_NEEDED
,
254 "client returned %08x, more tests will fail\n", status_c
);
256 communicate( &client
, &server
);
258 status_s
= run_server( &server
, first
);
259 ok( status_s
== SEC_E_OK
|| status_s
== SEC_I_CONTINUE_NEEDED
||
260 status_s
== SEC_E_LOGON_DENIED
,
261 "server returned %08x, more tests will fail\n", status_s
);
263 communicate( &server
, &client
);
267 if (status_c
!= SEC_E_OK
)
269 skip( "authentication failed, skipping remaining tests\n" );
273 sizes
.cbMaxToken
= 0xdeadbeef;
274 sizes
.cbMaxSignature
= 0xdeadbeef;
275 sizes
.cbSecurityTrailer
= 0xdeadbeef;
276 sizes
.cbBlockSize
= 0xdeadbeef;
277 status_c
= QueryContextAttributesA( &client
.ctxt
, SECPKG_ATTR_SIZES
, &sizes
);
278 ok( status_c
== SEC_E_OK
, "pQueryContextAttributesA returned %08x\n", status_c
);
279 ok( sizes
.cbMaxToken
== 2888 || sizes
.cbMaxToken
== 1904,
280 "expected 2888 or 1904, got %u\n", sizes
.cbMaxToken
);
281 ok( sizes
.cbMaxSignature
== 16, "expected 16, got %u\n", sizes
.cbMaxSignature
);
282 ok( sizes
.cbSecurityTrailer
== 16, "expected 16, got %u\n", sizes
.cbSecurityTrailer
);
283 ok( !sizes
.cbBlockSize
, "expected 0, got %u\n", sizes
.cbBlockSize
);
285 memset( &info
, 0, sizeof(info
) );
286 status_c
= QueryContextAttributesA( &client
.ctxt
, SECPKG_ATTR_NEGOTIATION_INFO
, &info
);
287 ok( status_c
== SEC_E_OK
, "QueryContextAttributesA returned %08x\n", status_c
);
289 pi
= info
.PackageInfo
;
290 ok( info
.NegotiationState
== SECPKG_NEGOTIATION_COMPLETE
, "got %u\n", info
.NegotiationState
);
291 ok( pi
!= NULL
, "expected non-NULL PackageInfo\n" );
297 ok( pi
->fCapabilities
== NTLM_BASE_CAPS
||
298 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_READONLY_WITH_CHECKSUM
) ||
299 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
) ||
300 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|SECPKG_FLAG_APPCONTAINER_CHECKS
) ||
301 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|SECPKG_FLAG_APPLY_LOOPBACK
) ||
302 pi
->fCapabilities
== (NTLM_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|SECPKG_FLAG_APPLY_LOOPBACK
|
303 SECPKG_FLAG_APPCONTAINER_CHECKS
),
304 "got %08x\n", pi
->fCapabilities
);
305 ok( pi
->wVersion
== 1, "got %u\n", pi
->wVersion
);
306 ok( pi
->wRPCID
== RPC_C_AUTHN_WINNT
, "got %u\n", pi
->wRPCID
);
307 ok( !lstrcmpA( pi
->Name
, "NTLM" ), "got %s\n", pi
->Name
);
309 expected
= sizeof(*pi
) + lstrlenA(pi
->Name
) + 1 + lstrlenA(pi
->Comment
) + 1;
310 got
= HeapSize(GetProcessHeap(), 0, pi
);
311 ok( got
== expected
, "got %u, expected %u\n", got
, expected
);
312 eob
= (char *)pi
+ expected
;
313 ok( pi
->Name
+ lstrlenA(pi
->Name
) < eob
, "Name doesn't fit into allocated block\n" );
314 ok( pi
->Comment
+ lstrlenA(pi
->Comment
) < eob
, "Comment doesn't fit into allocated block\n" );
316 status
= FreeContextBuffer( pi
);
317 ok( status
== SEC_E_OK
, "FreeContextBuffer error %#x\n", status
);
321 cleanup_buffers( &client
);
322 cleanup_buffers( &server
);
324 if (client
.ctxt
.dwLower
|| client
.ctxt
.dwUpper
)
326 status_c
= DeleteSecurityContext( &client
.ctxt
);
327 ok( status_c
== SEC_E_OK
, "DeleteSecurityContext returned %08x\n", status_c
);
330 if (server
.ctxt
.dwLower
|| server
.ctxt
.dwUpper
)
332 status_s
= DeleteSecurityContext( &server
.ctxt
);
333 ok( status_s
== SEC_E_OK
, "DeleteSecurityContext returned %08x\n", status_s
);
336 if (client
.cred
.dwLower
|| client
.cred
.dwUpper
)
338 status_c
= FreeCredentialsHandle( &client
.cred
);
339 ok( status_c
== SEC_E_OK
, "FreeCredentialsHandle returned %08x\n", status_c
);
342 if (server
.cred
.dwLower
|| server
.cred
.dwUpper
)
344 status_s
= FreeCredentialsHandle(&server
.cred
);
345 ok( status_s
== SEC_E_OK
, "FreeCredentialsHandle returned %08x\n", status_s
);
349 START_TEST(negotiate
)
353 if (QuerySecurityPackageInfoA( (SEC_CHAR
*)"Negotiate", &info
))
355 ok( 0, "Negotiate package not installed, skipping test\n" );
358 ok( info
->fCapabilities
== NEGOTIATE_BASE_CAPS
||
359 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_READONLY_WITH_CHECKSUM
) ||
360 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
) ||
361 info
->fCapabilities
== (NEGOTIATE_BASE_CAPS
|SECPKG_FLAG_RESTRICTED_TOKENS
|
362 SECPKG_FLAG_APPCONTAINER_CHECKS
),
363 "got %08x\n", info
->fCapabilities
);
364 ok( info
->wVersion
== 1, "got %u\n", info
->wVersion
);
365 ok( info
->wRPCID
== RPC_C_AUTHN_GSS_NEGOTIATE
, "got %u\n", info
->wRPCID
);
366 ok( !lstrcmpA( info
->Name
, "Negotiate" ), "got %s\n", info
->Name
);
367 FreeContextBuffer( info
);
369 test_authentication();