wbemprox: Handle NULL operands in eval_strcmp.
[wine] / dlls / secur32 / tests / negotiate.c
1 /*
2  * Tests for the Negotiate security provider
3  *
4  * Copyright 2005, 2006 Kai Blin
5  * Copyright 2012 Hans Leidekker for CodeWeavers
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #define SECURITY_WIN32
27 #include <sspi.h>
28 #include <rpc.h>
29 #include <rpcdce.h>
30 #include <secext.h>
31
32 #include "wine/test.h"
33
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,
47     PULONG, PTimeStamp);
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);
53
54 static void init_function_ptrs(void)
55 {
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");
71 }
72
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    | \
83     SECPKG_FLAG_LOGON )
84
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        | \
94     SECPKG_FLAG_LOGON )
95
96 struct sspi_data
97 {
98     CredHandle cred;
99     CtxtHandle ctxt;
100     PSecBufferDesc in_buf;
101     PSecBufferDesc out_buf;
102     PSEC_WINNT_AUTH_IDENTITY id;
103     ULONG max_token;
104 };
105
106 static void cleanup_buffers( struct sspi_data *data )
107 {
108     unsigned int i;
109
110     if (data->in_buf)
111     {
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 );
116     }
117     if (data->out_buf)
118     {
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 );
123     }
124 }
125
126 static void setup_buffers( struct sspi_data *data, SecPkgInfoA *info )
127 {
128     SecBuffer *buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer) );
129
130     data->in_buf  = HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc) );
131     data->out_buf = HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc) );
132     data->max_token = info->cbMaxToken;
133
134     data->in_buf->ulVersion = SECBUFFER_VERSION;
135     data->in_buf->cBuffers  = 1;
136     data->in_buf->pBuffers  = buffer;
137
138     buffer->cbBuffer   = info->cbMaxToken;
139     buffer->BufferType = SECBUFFER_TOKEN;
140     buffer->pvBuffer   = HeapAlloc( GetProcessHeap(), 0, info->cbMaxToken );
141
142     buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer) );
143
144     data->out_buf->ulVersion = SECBUFFER_VERSION;
145     data->out_buf->cBuffers  = 1;
146     data->out_buf->pBuffers  = buffer;
147
148     buffer->cbBuffer   = info->cbMaxToken;
149     buffer->BufferType = SECBUFFER_TOKEN;
150     buffer->pvBuffer   = HeapAlloc( GetProcessHeap(), 0, info->cbMaxToken );
151 }
152
153 static SECURITY_STATUS setup_client( struct sspi_data *data, SEC_CHAR *provider )
154 {
155     SECURITY_STATUS ret;
156     SecPkgInfoA *info;
157     TimeStamp ttl;
158
159     trace( "setting up client\n" );
160
161     ret = pQuerySecurityPackageInfoA( provider, &info );
162     ok( ret == SEC_E_OK, "QuerySecurityPackageInfo returned %08x\n", ret );
163
164     setup_buffers( data, info );
165     pFreeContextBuffer( info );
166
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 );
170     return ret;
171 }
172
173 static SECURITY_STATUS setup_server( struct sspi_data *data, SEC_CHAR *provider )
174 {
175     SECURITY_STATUS ret;
176     SecPkgInfoA *info;
177     TimeStamp ttl;
178
179     trace( "setting up server\n" );
180
181     ret = pQuerySecurityPackageInfoA( provider, &info );
182     ok( ret == SEC_E_OK, "QuerySecurityPackageInfo returned %08x\n", ret );
183
184     setup_buffers( data, info );
185     pFreeContextBuffer( info );
186
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 );
190     return ret;
191 }
192
193 static SECURITY_STATUS run_client( struct sspi_data *data, BOOL first )
194 {
195     SECURITY_STATUS ret;
196     TimeStamp ttl;
197     ULONG attr;
198
199     trace( "running client for the %s time\n", first ? "first" : "second" );
200
201     data->out_buf->pBuffers[0].cbBuffer = data->max_token;
202     data->out_buf->pBuffers[0].BufferType = SECBUFFER_TOKEN;
203
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)
208     {
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)
213             ret = SEC_E_OK;
214     }
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" );
219     return ret;
220 }
221
222 static SECURITY_STATUS run_server( struct sspi_data *data, BOOL first )
223 {
224     SECURITY_STATUS ret;
225     TimeStamp ttl;
226     ULONG attr;
227
228     trace( "running server for the %s time\n", first ? "first" : "second" );
229
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)
234     {
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)
239             ret = SEC_E_OK;
240     }
241     return ret;
242 }
243
244 static void communicate( struct sspi_data *from, struct sspi_data *to )
245 {
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 );
252 }
253
254 static void test_authentication(void)
255 {
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 id;
260     SecPkgContext_NegotiationInfo info;
261     SecPkgContext_Sizes sizes;
262     SecPkgInfo *pi;
263     BOOL first = TRUE;
264
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;
272
273     client.id = &id;
274     if ((status = setup_client( &client, (SEC_CHAR *)"Negotiate" )))
275     {
276         skip( "setup_client returned %08x, skipping test\n", status );
277         return;
278     }
279     if ((status = setup_server( &server, (SEC_CHAR *)"Negotiate" )))
280     {
281         skip( "setup_server returned %08x, skipping test\n", status );
282         pFreeCredentialsHandle( &client.cred );
283         return;
284     }
285
286     while (status_c == SEC_I_CONTINUE_NEEDED && status_s == SEC_I_CONTINUE_NEEDED)
287     {
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 );
291
292         communicate( &client, &server );
293
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 );
298
299         communicate( &server, &client );
300         trace( "looping\n");
301         first = FALSE;
302     }
303     if (status_c != SEC_E_OK)
304     {
305         skip( "authentication failed, skipping remaining tests\n" );
306         goto done;
307     }
308
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 );
320
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 );
324
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" );
328     if (pi)
329     {
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             "got %08x\n", pi->fCapabilities );
334         ok( pi->wVersion == 1, "got %u\n", pi->wVersion );
335         ok( pi->wRPCID == RPC_C_AUTHN_WINNT, "got %u\n", pi->wRPCID );
336         ok( !lstrcmpA( pi->Name, "NTLM" ), "got %s\n", pi->Name );
337     }
338
339 done:
340     cleanup_buffers( &client );
341     cleanup_buffers( &server );
342
343     status_c = pDeleteSecurityContext( &client.ctxt );
344     ok( status_c == SEC_E_OK, "DeleteSecurityContext returned %08x\n", status_c );
345
346     status_s = pDeleteSecurityContext( &server.ctxt );
347     ok( status_s == SEC_E_OK, "DeleteSecurityContext returned %08x\n", status_s );
348
349     status_c = pFreeCredentialsHandle( &client.cred );
350     ok( status_c == SEC_E_OK, "FreeCredentialsHandle returned %08x\n", status_c );
351
352     status_s = pFreeCredentialsHandle(&server.cred);
353     ok( status_s == SEC_E_OK, "FreeCredentialsHandle returned %08x\n", status_s );
354 }
355
356 START_TEST(negotiate)
357 {
358     SecPkgInfo *info;
359
360     init_function_ptrs();
361
362     if (!pFreeCredentialsHandle || !pAcquireCredentialsHandleA || !pQuerySecurityPackageInfoA ||
363         !pFreeContextBuffer)
364     {
365         win_skip("functions are not available\n");
366         return;
367     }
368     if (pQuerySecurityPackageInfoA( (SEC_CHAR *)"Negotiate", &info ))
369     {
370         ok( 0, "Negotiate package not installed, skipping test\n" );
371         return;
372     }
373     ok( info->fCapabilities == NEGOTIATE_BASE_CAPS ||
374         info->fCapabilities == (NEGOTIATE_BASE_CAPS|SECPKG_FLAG_READONLY_WITH_CHECKSUM) ||
375         info->fCapabilities == (NEGOTIATE_BASE_CAPS|SECPKG_FLAG_RESTRICTED_TOKENS),
376         "got %08x\n", info->fCapabilities );
377     ok( info->wVersion == 1, "got %u\n", info->wVersion );
378     ok( info->wRPCID == RPC_C_AUTHN_GSS_NEGOTIATE, "got %u\n", info->wRPCID );
379     ok( !lstrcmpA( info->Name, "Negotiate" ), "got %s\n", info->Name );
380     pFreeContextBuffer( info );
381
382     test_authentication();
383 }