secur32: Fix handling of buffers that don't have the SECBUFFER_TOKEN as the first...
[wine] / dlls / secur32 / tests / ntlm.c
1 /*
2  * Tests for the NTLM security provider
3  *
4  * Copyright 2005, 2006 Kai Blin
5  * Copyright 2006 Dmitry Timoshkov
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  * The code that tests for the behaviour of ISC_REQ_ALLOCATE_MEMORY is based
22  * on code written by Dmitry Timoshkov.
23  
24  */
25
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <assert.h>
29 #include <windef.h>
30 #include <winbase.h>
31 #define SECURITY_WIN32
32 #include <sspi.h>
33
34 #include "wine/test.h"
35
36 static HMODULE secdll;
37 static PSecurityFunctionTableA (SEC_ENTRY * pInitSecurityInterfaceA)(void);
38 static SECURITY_STATUS (SEC_ENTRY * pFreeContextBuffer)(PVOID pv);
39 static SECURITY_STATUS (SEC_ENTRY * pQuerySecurityPackageInfoA)(SEC_CHAR*, PSecPkgInfoA*);
40 static SECURITY_STATUS (SEC_ENTRY * pAcquireCredentialsHandleA)(SEC_CHAR*, SEC_CHAR*,
41                             ULONG, PLUID, PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp);
42 static SECURITY_STATUS (SEC_ENTRY * pInitializeSecurityContextA)(PCredHandle, PCtxtHandle,
43                             SEC_CHAR*, ULONG, ULONG, ULONG, PSecBufferDesc, ULONG, 
44                             PCtxtHandle, PSecBufferDesc, PULONG, PTimeStamp);
45 static SECURITY_STATUS (SEC_ENTRY * pCompleteAuthToken)(PCtxtHandle, PSecBufferDesc);
46 static SECURITY_STATUS (SEC_ENTRY * pAcceptSecurityContext)(PCredHandle, PCtxtHandle,
47                             PSecBufferDesc, ULONG, ULONG, PCtxtHandle, PSecBufferDesc,
48                             PULONG, PTimeStamp);
49 static SECURITY_STATUS (SEC_ENTRY * pFreeCredentialsHandle)(PCredHandle);
50 static SECURITY_STATUS (SEC_ENTRY * pDeleteSecurityContext)(PCtxtHandle);
51 static SECURITY_STATUS (SEC_ENTRY * pQueryContextAttributesA)(PCtxtHandle, ULONG, PVOID);
52 static SECURITY_STATUS (SEC_ENTRY * pMakeSignature)(PCtxtHandle, ULONG,
53                             PSecBufferDesc, ULONG);
54 static SECURITY_STATUS (SEC_ENTRY * pVerifySignature)(PCtxtHandle, PSecBufferDesc,
55                             ULONG, PULONG);
56 static SECURITY_STATUS (SEC_ENTRY * pEncryptMessage)(PCtxtHandle, ULONG,
57                             PSecBufferDesc, ULONG);
58 static SECURITY_STATUS (SEC_ENTRY * pDecryptMessage)(PCtxtHandle, PSecBufferDesc,
59                             ULONG, PULONG);
60
61 typedef struct _SspiData {
62     PCredHandle cred;
63     PCtxtHandle ctxt;
64     PSecBufferDesc in_buf;
65     PSecBufferDesc out_buf;
66     PSEC_WINNT_AUTH_IDENTITY id;
67     ULONG max_token;
68 } SspiData;
69
70 static BYTE network_challenge[] = 
71    {0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00,
72     0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00,
73     0x05, 0x82, 0x82, 0xa0, 0xe9, 0x58, 0x7f, 0x14, 0xa2, 0x86,
74     0x3b, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75     0x54, 0x00, 0x54, 0x00, 0x40, 0x00, 0x00, 0x00, 0x43, 0x00,
76     0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00,
77     0x30, 0x00, 0x31, 0x00, 0x02, 0x00, 0x10, 0x00, 0x43, 0x00,
78     0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00,
79     0x30, 0x00, 0x31, 0x00, 0x01, 0x00, 0x10, 0x00, 0x43, 0x00,
80     0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00,
81     0x30, 0x00, 0x31, 0x00, 0x04, 0x00, 0x10, 0x00, 0x63, 0x00,
82     0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6f, 0x00,
83     0x30, 0x00, 0x31, 0x00, 0x03, 0x00, 0x10, 0x00, 0x63, 0x00,
84     0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6f, 0x00,
85     0x30, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00};
86
87 static BYTE native_challenge[] = 
88    {0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00,
89     0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00,
90     0x05, 0x82, 0x82, 0xa0, 0xb5, 0x60, 0x8e, 0x95, 0xb5, 0x3c,
91     0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92     0x54, 0x00, 0x54, 0x00, 0x40, 0x00, 0x00, 0x00, 0x43, 0x00,
93     0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00,
94     0x30, 0x00, 0x31, 0x00, 0x02, 0x00, 0x10, 0x00, 0x43, 0x00,
95     0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00,
96     0x30, 0x00, 0x31, 0x00, 0x01, 0x00, 0x10, 0x00, 0x43, 0x00,
97     0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00,
98     0x30, 0x00, 0x31, 0x00, 0x04, 0x00, 0x10, 0x00, 0x63, 0x00,
99     0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6f, 0x00,
100     0x30, 0x00, 0x31, 0x00, 0x03, 0x00, 0x10, 0x00, 0x63, 0x00,
101     0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6f, 0x00,
102     0x30, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00};
103
104 static BYTE message_signature[] =
105    {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106     0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
107
108 static BYTE message_binary[] =
109    {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72,
110     0x6c, 0x64, 0x21};
111
112 static char message[] = "Hello, world!";
113
114 static char message_header[] = "Header Test";
115
116 static BYTE crypt_trailer_client[] =
117    {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xc7,
118     0xaa, 0x26, 0x16, 0x39, 0x07, 0x4e};
119
120 static BYTE crypt_message_client[] =
121    {0x86, 0x9c, 0x5a, 0x10, 0x78, 0xb3, 0x30, 0x98, 0x46, 0x15,
122     0xa0, 0x31, 0xd9};
123
124 static BYTE crypt_trailer_client2[] =
125    {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xa7,
126     0xf7, 0x0f, 0x5b, 0x25, 0xbe, 0xa4};
127
128 static BYTE crypt_message_client2[] =
129    {0x20, 0x6c, 0x01, 0xab, 0xb0, 0x4c, 0x93, 0xe4, 0x1e, 0xfc,
130     0xe1, 0xfa, 0xfe};
131
132 static BYTE crypt_trailer_server[] =
133    {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x46,
134     0x2e, 0x77, 0xeb, 0xf0, 0xf6, 0x9e};
135
136 static BYTE crypt_message_server[] =
137    {0xf6, 0xb7, 0x92, 0x0c, 0xac, 0xea, 0x98, 0xe6, 0xef, 0xa0,
138     0x29, 0x66, 0xfd};
139
140 static void InitFunctionPtrs(void)
141 {
142     secdll = LoadLibraryA("secur32.dll");
143     if(!secdll)
144         secdll = LoadLibraryA("security.dll");
145     if(secdll)
146     {
147         pInitSecurityInterfaceA = (PVOID)GetProcAddress(secdll, "InitSecurityInterfaceA");
148         pFreeContextBuffer = (PVOID)GetProcAddress(secdll, "FreeContextBuffer");
149         pQuerySecurityPackageInfoA = (PVOID)GetProcAddress(secdll, "QuerySecurityPackageInfoA");
150         pAcquireCredentialsHandleA = (PVOID)GetProcAddress(secdll, "AcquireCredentialsHandleA");
151         pInitializeSecurityContextA = (PVOID)GetProcAddress(secdll, "InitializeSecurityContextA");
152         pCompleteAuthToken = (PVOID)GetProcAddress(secdll, "CompleteAuthToken");
153         pAcceptSecurityContext = (PVOID)GetProcAddress(secdll, "AcceptSecurityContext");
154         pFreeCredentialsHandle = (PVOID)GetProcAddress(secdll, "FreeCredentialsHandle");
155         pDeleteSecurityContext = (PVOID)GetProcAddress(secdll, "DeleteSecurityContext");
156         pQueryContextAttributesA = (PVOID)GetProcAddress(secdll, "QueryContextAttributesA");
157         pMakeSignature = (PVOID)GetProcAddress(secdll, "MakeSignature");
158         pVerifySignature = (PVOID)GetProcAddress(secdll, "VerifySignature");
159         pEncryptMessage = (PVOID)GetProcAddress(secdll, "EncryptMessage");
160         pDecryptMessage = (PVOID)GetProcAddress(secdll, "DecryptMessage");
161     }
162 }
163
164 static const char* getSecError(SECURITY_STATUS status)
165 {
166     static char buf[20];
167
168 #define _SEC_ERR(x) case (x): return #x;
169     switch(status)
170     {
171         _SEC_ERR(SEC_E_OK);
172         _SEC_ERR(SEC_E_INSUFFICIENT_MEMORY);
173         _SEC_ERR(SEC_E_INVALID_HANDLE);
174         _SEC_ERR(SEC_E_UNSUPPORTED_FUNCTION);
175         _SEC_ERR(SEC_E_TARGET_UNKNOWN);
176         _SEC_ERR(SEC_E_INTERNAL_ERROR);
177         _SEC_ERR(SEC_E_SECPKG_NOT_FOUND);
178         _SEC_ERR(SEC_E_NOT_OWNER);
179         _SEC_ERR(SEC_E_CANNOT_INSTALL);
180         _SEC_ERR(SEC_E_INVALID_TOKEN);
181         _SEC_ERR(SEC_E_CANNOT_PACK);
182         _SEC_ERR(SEC_E_QOP_NOT_SUPPORTED);
183         _SEC_ERR(SEC_E_NO_IMPERSONATION);
184         _SEC_ERR(SEC_I_CONTINUE_NEEDED);
185         _SEC_ERR(SEC_E_BUFFER_TOO_SMALL);
186         _SEC_ERR(SEC_E_ILLEGAL_MESSAGE);
187         _SEC_ERR(SEC_E_LOGON_DENIED);
188         _SEC_ERR(SEC_E_NO_CREDENTIALS);
189         _SEC_ERR(SEC_E_OUT_OF_SEQUENCE);
190         _SEC_ERR(SEC_E_MESSAGE_ALTERED);
191         default:
192             sprintf(buf, "%08x\n", status);
193             return buf;
194     }
195 #undef _SEC_ERR
196 }
197
198 /**********************************************************************/
199
200 static SECURITY_STATUS setupBuffers(SspiData *sspi_data, SecPkgInfoA *sec_pkg_info)
201 {
202     
203     sspi_data->in_buf  = HeapAlloc(GetProcessHeap(), 0, sizeof(SecBufferDesc));
204     sspi_data->out_buf = HeapAlloc(GetProcessHeap(), 0, sizeof(SecBufferDesc));
205     sspi_data->max_token = sec_pkg_info->cbMaxToken;
206
207     if(sspi_data->in_buf != NULL)
208     {
209         PSecBuffer sec_buffer = HeapAlloc(GetProcessHeap(), 0,
210                 sizeof(SecBuffer));
211         if(sec_buffer == NULL){
212             trace("in_buf: sec_buffer == NULL\n");
213             return SEC_E_INSUFFICIENT_MEMORY;
214         }
215         
216         sspi_data->in_buf->ulVersion = SECBUFFER_VERSION;
217         sspi_data->in_buf->cBuffers = 1;
218         sspi_data->in_buf->pBuffers = sec_buffer;
219
220         sec_buffer->cbBuffer = sec_pkg_info->cbMaxToken;
221         sec_buffer->BufferType = SECBUFFER_TOKEN;
222         if((sec_buffer->pvBuffer = HeapAlloc(GetProcessHeap(), 0, 
223                         sec_pkg_info->cbMaxToken)) == NULL)
224         {
225             trace("in_buf: sec_buffer->pvBuffer == NULL\n");
226             return SEC_E_INSUFFICIENT_MEMORY;
227         }
228     }
229     else
230     {
231         trace("HeapAlloc in_buf returned NULL\n");
232         return SEC_E_INSUFFICIENT_MEMORY;
233     }
234     
235     if(sspi_data->out_buf != NULL)
236     {
237         PSecBuffer sec_buffer = HeapAlloc(GetProcessHeap(), 0,
238                 sizeof(SecBuffer));
239         
240         if(sec_buffer == NULL){
241             trace("out_buf: sec_buffer == NULL\n");
242             return SEC_E_INSUFFICIENT_MEMORY;
243         }
244
245         sspi_data->out_buf->ulVersion = SECBUFFER_VERSION;
246         sspi_data->out_buf->cBuffers = 1;
247         sspi_data->out_buf->pBuffers = sec_buffer;
248
249         sec_buffer->cbBuffer = sec_pkg_info->cbMaxToken;
250         sec_buffer->BufferType = SECBUFFER_TOKEN;
251         if((sec_buffer->pvBuffer = HeapAlloc(GetProcessHeap(), 0, 
252                         sec_pkg_info->cbMaxToken)) == NULL){
253             trace("out_buf: sec_buffer->pvBuffer == NULL\n");
254             return SEC_E_INSUFFICIENT_MEMORY;
255         }
256     }
257     else
258     {
259         trace("HeapAlloc out_buf returned NULL\n");
260         return SEC_E_INSUFFICIENT_MEMORY;
261     }
262
263     return SEC_E_OK;
264 }
265
266 /**********************************************************************/
267
268 static void cleanupBuffers(SspiData *sspi_data)
269 {
270     ULONG i;
271
272     if(sspi_data->in_buf != NULL)
273     {
274         for(i = 0; i < sspi_data->in_buf->cBuffers; ++i)
275         {
276             HeapFree(GetProcessHeap(), 0, sspi_data->in_buf->pBuffers[i].pvBuffer);
277         }
278         HeapFree(GetProcessHeap(), 0, sspi_data->in_buf->pBuffers);
279         HeapFree(GetProcessHeap(), 0, sspi_data->in_buf);
280     }
281     
282     if(sspi_data->out_buf != NULL)
283     {
284         for(i = 0; i < sspi_data->out_buf->cBuffers; ++i)
285         {
286             HeapFree(GetProcessHeap(), 0, sspi_data->out_buf->pBuffers[i].pvBuffer);
287         }
288         HeapFree(GetProcessHeap(), 0, sspi_data->out_buf->pBuffers);
289         HeapFree(GetProcessHeap(), 0, sspi_data->out_buf);
290     }
291 }
292
293 /**********************************************************************/
294
295 static SECURITY_STATUS setupClient(SspiData *sspi_data, SEC_CHAR *provider)
296 {
297     SECURITY_STATUS ret;
298     TimeStamp ttl;
299     SecPkgInfoA *sec_pkg_info;
300
301     trace("Running setupClient\n");
302     
303     sspi_data->cred = HeapAlloc(GetProcessHeap(), 0, sizeof(CredHandle));
304     sspi_data->ctxt = HeapAlloc(GetProcessHeap(), 0, sizeof(CtxtHandle));
305     
306     ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info);
307
308     ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret));
309
310     setupBuffers(sspi_data, sec_pkg_info);
311     
312     if((ret = pAcquireCredentialsHandleA(NULL, provider, SECPKG_CRED_OUTBOUND,
313             NULL, sspi_data->id, NULL, NULL, sspi_data->cred, &ttl))
314             != SEC_E_OK)
315     {
316         trace("AcquireCredentialsHandle() returned %s\n", getSecError(ret));
317     }
318
319     ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", 
320             getSecError(ret));
321
322     return ret;
323 }
324 /**********************************************************************/
325
326 static SECURITY_STATUS setupServer(SspiData *sspi_data, SEC_CHAR *provider)
327 {
328     SECURITY_STATUS ret;
329     TimeStamp ttl;
330     SecPkgInfoA *sec_pkg_info;
331
332     trace("Running setupServer\n");
333
334     sspi_data->cred = HeapAlloc(GetProcessHeap(), 0, sizeof(CredHandle));
335     sspi_data->ctxt = HeapAlloc(GetProcessHeap(), 0, sizeof(CtxtHandle));
336
337     ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info);
338
339     ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret));
340
341     setupBuffers(sspi_data, sec_pkg_info);
342
343     if((ret = pAcquireCredentialsHandleA(NULL, provider, SECPKG_CRED_INBOUND, 
344             NULL, NULL, NULL, NULL, sspi_data->cred, &ttl)) != SEC_E_OK)
345     {
346         trace("AcquireCredentialsHandle() returned %s\n", getSecError(ret));
347     }
348
349     ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n",
350             getSecError(ret));
351
352     return ret;
353 }
354
355 /**********************************************************************/
356
357 static SECURITY_STATUS setupFakeServer(SspiData *sspi_data, SEC_CHAR *provider)
358 {
359     SECURITY_STATUS ret;
360     SecPkgInfoA *sec_pkg_info;
361
362     trace("Running setupFakeServer\n");
363
364     sspi_data->cred = HeapAlloc(GetProcessHeap(), 0, sizeof(CredHandle));
365     sspi_data->ctxt = HeapAlloc(GetProcessHeap(), 0, sizeof(CtxtHandle));
366
367     ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info);
368
369     ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret));
370
371     ret = setupBuffers(sspi_data, sec_pkg_info);
372     
373     return ret;
374 }
375
376
377 /**********************************************************************/
378
379 static SECURITY_STATUS runClient(SspiData *sspi_data, BOOL first, ULONG data_rep)
380 {
381     SECURITY_STATUS ret;
382     ULONG req_attr = 0;
383     ULONG ctxt_attr;
384     TimeStamp ttl;
385     PSecBufferDesc in_buf = sspi_data->in_buf;
386     PSecBufferDesc out_buf = sspi_data->out_buf;
387
388     assert(in_buf->cBuffers >= 1);
389     assert(in_buf->pBuffers[0].pvBuffer != NULL);
390     assert(in_buf->pBuffers[0].cbBuffer != 0);
391
392     assert(out_buf->cBuffers >= 1);
393     assert(out_buf->pBuffers[0].pvBuffer != NULL);
394     assert(out_buf->pBuffers[0].cbBuffer != 0);
395
396     trace("Running the client the %s time.\n", first?"first":"second");
397
398     /* We can either use ISC_REQ_ALLOCATE_MEMORY flag to ask the provider
399      * always allocate output buffers for us, or initialize cbBuffer
400      * before each call because the API changes it to represent actual
401      * amount of data in the buffer.
402      */
403
404     /* test a failing call only the first time, otherwise we get
405      * SEC_E_OUT_OF_SEQUENCE
406      */
407     if (first)
408     {
409         void *old_buf;
410
411         /* pass NULL as an output buffer */
412         ret = pInitializeSecurityContextA(sspi_data->cred, NULL, NULL, req_attr,
413             0, data_rep, NULL, 0, sspi_data->ctxt, NULL,
414             &ctxt_attr, &ttl);
415
416         ok(ret == SEC_E_BUFFER_TOO_SMALL, "expected SEC_E_BUFFER_TOO_SMALL, got %s\n", getSecError(ret));
417
418         /* pass NULL as an output buffer */
419         old_buf = out_buf->pBuffers[0].pvBuffer;
420         out_buf->pBuffers[0].pvBuffer = NULL;
421
422         ret = pInitializeSecurityContextA(sspi_data->cred, NULL, NULL, req_attr, 
423             0, data_rep, NULL, 0, sspi_data->ctxt, out_buf,
424             &ctxt_attr, &ttl);
425
426         ok(ret == SEC_E_INTERNAL_ERROR, "expected SEC_E_INTERNAL_ERROR, got %s\n", getSecError(ret));
427
428         out_buf->pBuffers[0].pvBuffer = old_buf;
429
430         /* pass an output buffer of 0 size */
431         out_buf->pBuffers[0].cbBuffer = 0;
432
433         ret = pInitializeSecurityContextA(sspi_data->cred, NULL, NULL, req_attr, 
434             0, data_rep, NULL, 0, sspi_data->ctxt, out_buf,
435             &ctxt_attr, &ttl);
436
437         ok(ret == SEC_E_BUFFER_TOO_SMALL, "expected SEC_E_BUFFER_TOO_SMALL, got %s\n", getSecError(ret));
438
439         ok(out_buf->pBuffers[0].cbBuffer == 0,
440            "InitializeSecurityContext set buffer size to %lu\n", out_buf->pBuffers[0].cbBuffer);
441     }
442
443     out_buf->pBuffers[0].cbBuffer = sspi_data->max_token;
444
445     ret = pInitializeSecurityContextA(sspi_data->cred, first?NULL:sspi_data->ctxt, NULL, req_attr, 
446             0, data_rep, first?NULL:in_buf, 0, sspi_data->ctxt, out_buf,
447             &ctxt_attr, &ttl);
448
449     if(ret == SEC_I_COMPLETE_AND_CONTINUE || ret == SEC_I_COMPLETE_NEEDED)
450     {
451         pCompleteAuthToken(sspi_data->ctxt, out_buf);
452         if(ret == SEC_I_COMPLETE_AND_CONTINUE)
453             ret = SEC_I_CONTINUE_NEEDED;
454         else if(ret == SEC_I_COMPLETE_NEEDED)
455             ret = SEC_E_OK;
456     }       
457
458     ok(out_buf->pBuffers[0].cbBuffer < sspi_data->max_token,
459        "InitializeSecurityContext set buffer size to %lu\n", out_buf->pBuffers[0].cbBuffer);
460
461     return ret;
462 }
463
464 /**********************************************************************/
465
466 static SECURITY_STATUS runServer(SspiData *sspi_data, BOOL first, ULONG data_rep)
467 {
468     SECURITY_STATUS ret;
469     ULONG ctxt_attr;
470     TimeStamp ttl;
471
472     trace("Running the server the %s time\n", first?"first":"second");
473
474     ret = pAcceptSecurityContext(sspi_data->cred, first?NULL:sspi_data->ctxt, 
475             sspi_data->in_buf, 0, data_rep, sspi_data->ctxt, 
476             sspi_data->out_buf, &ctxt_attr, &ttl);
477
478     if(ret == SEC_I_COMPLETE_AND_CONTINUE || ret == SEC_I_COMPLETE_NEEDED)
479     {
480         pCompleteAuthToken(sspi_data->ctxt, sspi_data->out_buf);
481         if(ret == SEC_I_COMPLETE_AND_CONTINUE)
482             ret = SEC_I_CONTINUE_NEEDED;
483         else if(ret == SEC_I_COMPLETE_NEEDED)
484             ret = SEC_E_OK;
485     }
486
487     return ret;
488 }
489
490 /**********************************************************************/
491
492 static SECURITY_STATUS runFakeServer(SspiData *sspi_data, BOOL first, ULONG data_rep)
493 {
494     trace("Running the fake server the %s time\n", first?"first":"second");
495
496     if(!first)
497     {
498         sspi_data->out_buf->pBuffers[0].cbBuffer = 0;
499         return SEC_E_OK;
500     }
501     
502     if(data_rep == SECURITY_NATIVE_DREP)
503     {
504         sspi_data->out_buf->pBuffers[0].cbBuffer = sizeof(native_challenge);
505         memcpy(sspi_data->out_buf->pBuffers[0].pvBuffer, native_challenge, 
506                 sspi_data->out_buf->pBuffers[0].cbBuffer);
507     }
508     else
509     {
510         sspi_data->out_buf->pBuffers[0].cbBuffer = sizeof(network_challenge);
511         memcpy(sspi_data->out_buf->pBuffers[0].pvBuffer, network_challenge, 
512                 sspi_data->out_buf->pBuffers[0].cbBuffer);
513     }
514
515     return SEC_I_CONTINUE_NEEDED;
516 }
517
518 /**********************************************************************/
519
520 static void communicate(SspiData *from, SspiData *to)
521 {
522     if(from->out_buf != NULL && to->in_buf != NULL)
523     {
524         trace("Running communicate.\n");
525         if((from->out_buf->cBuffers >= 1) && (to->in_buf->cBuffers >= 1))
526         {
527             if((from->out_buf->pBuffers[0].pvBuffer != NULL) && 
528                     (to->in_buf->pBuffers[0].pvBuffer != NULL))
529             {
530                 memset(to->in_buf->pBuffers[0].pvBuffer, 0, to->max_token);
531                 
532                 memcpy(to->in_buf->pBuffers[0].pvBuffer, 
533                     from->out_buf->pBuffers[0].pvBuffer,
534                     from->out_buf->pBuffers[0].cbBuffer);
535                 
536                 to->in_buf->pBuffers[0].cbBuffer = from->out_buf->pBuffers[0].cbBuffer;
537                 
538                 memset(from->out_buf->pBuffers[0].pvBuffer, 0, from->max_token);
539             }
540         }
541     }
542 }
543    
544 /**********************************************************************/
545
546 static void testAuth(ULONG data_rep, BOOL fake)
547 {
548     SECURITY_STATUS         client_stat = SEC_I_CONTINUE_NEEDED;
549     SECURITY_STATUS         server_stat = SEC_I_CONTINUE_NEEDED;
550     SECURITY_STATUS         sec_status;
551     PSecPkgInfo             pkg_info = NULL;
552     BOOL                    first = TRUE;
553     SspiData                client, server;
554     SEC_WINNT_AUTH_IDENTITY id;
555     SecPkgContext_Sizes     ctxt_sizes;
556     static char             sec_pkg_name[] = "NTLM";
557
558     if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info)== SEC_E_OK)
559     {
560         pFreeContextBuffer(pkg_info);
561         id.User = (unsigned char*) "testuser";
562         id.UserLength = strlen((char *) id.User);
563         id.Domain = (unsigned char *) "WORKGROUP";
564         id.DomainLength = strlen((char *) id.Domain);
565         id.Password = (unsigned char*) "testpass";
566         id.PasswordLength = strlen((char *) id.Password);
567         id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
568
569         client.id = &id;
570         
571         sec_status = setupClient(&client, sec_pkg_name);
572
573         if(sec_status != SEC_E_OK)
574         {
575             trace("Error: Setting up the client returned %s, exiting test!\n",
576                     getSecError(sec_status));
577             pFreeCredentialsHandle(client.cred);
578             return;
579         }
580
581         if(fake)
582             sec_status = setupFakeServer(&server, sec_pkg_name);
583         else
584             sec_status = setupServer(&server, sec_pkg_name);
585
586         if(sec_status != SEC_E_OK)
587         {
588             trace("Error: Setting up the server returned %s, exiting test!\n",
589                     getSecError(sec_status));
590             pFreeCredentialsHandle(server.cred);
591             pFreeCredentialsHandle(client.cred);
592             return;
593         }
594
595
596         while(client_stat == SEC_I_CONTINUE_NEEDED && server_stat == SEC_I_CONTINUE_NEEDED)
597         {
598             client_stat = runClient(&client, first, data_rep);
599
600             ok(client_stat == SEC_E_OK || client_stat == SEC_I_CONTINUE_NEEDED,
601                     "Running the client returned %s, more tests will fail.\n",
602                     getSecError(client_stat));
603
604             communicate(&client, &server);
605
606             if(fake)
607                 server_stat = runFakeServer(&server, first, data_rep);
608             else
609                 server_stat = runServer(&server, first, data_rep);
610
611             ok(server_stat == SEC_E_OK || server_stat == SEC_I_CONTINUE_NEEDED ||
612                     server_stat == SEC_E_LOGON_DENIED,
613                     "Running the server returned %s, more tests will fail from now.\n",
614                     getSecError(server_stat));
615
616             communicate(&server, &client);
617             trace("Looping\n");
618             first = FALSE;
619         }
620
621         if(client_stat == SEC_E_OK)
622         {
623             sec_status = pQueryContextAttributesA(client.ctxt,
624                     SECPKG_ATTR_SIZES, &ctxt_sizes);
625
626             ok(sec_status == SEC_E_OK, 
627                     "pQueryContextAttributesA(SECPKG_ATTR_SIZES) returned %s\n",
628                     getSecError(sec_status));
629             ok(ctxt_sizes.cbMaxToken == 1904,
630                     "cbMaxToken should be 1904 but is %lu\n", 
631                     ctxt_sizes.cbMaxToken);
632             ok(ctxt_sizes.cbMaxSignature == 16,
633                     "cbMaxSignature should be 16 but is %lu\n",
634                     ctxt_sizes.cbMaxSignature);
635             ok(ctxt_sizes.cbSecurityTrailer == 16,
636                     "cbSecurityTrailer should be 16 but is  %lu\n",
637                     ctxt_sizes.cbSecurityTrailer);
638             ok(ctxt_sizes.cbBlockSize == 0,
639                     "cbBlockSize should be 0 but is %lu\n",
640                     ctxt_sizes.cbBlockSize);
641         }
642         else
643             trace("Authentication failed, skipping test.\n");
644
645         cleanupBuffers(&client);
646         cleanupBuffers(&server);
647         
648         if(!fake)
649         {
650             sec_status = pDeleteSecurityContext(server.ctxt);
651             ok(sec_status == SEC_E_OK, "DeleteSecurityContext(server) returned %s\n",
652                 getSecError(sec_status));
653         }
654
655         sec_status = pDeleteSecurityContext(client.ctxt);
656         ok(sec_status == SEC_E_OK, "DeleteSecurityContext(client) returned %s\n",
657                 getSecError(sec_status));
658         
659         if(!fake)
660         {   
661             sec_status = pFreeCredentialsHandle(server.cred);
662             ok(sec_status == SEC_E_OK, "FreeCredentialsHandle(server) returned %s\n",
663                 getSecError(sec_status));
664         }
665         
666         sec_status = pFreeCredentialsHandle(client.cred);
667         ok(sec_status == SEC_E_OK, "FreeCredentialsHandle(client) returned %s\n",
668                 getSecError(sec_status));
669     }
670     else
671     {
672         trace("Package not installed, skipping test.\n");
673     }
674 }
675
676 static void testSignSeal()
677 {
678     SECURITY_STATUS         client_stat = SEC_I_CONTINUE_NEEDED;
679     SECURITY_STATUS         server_stat = SEC_I_CONTINUE_NEEDED;
680     SECURITY_STATUS         sec_status;
681     PSecPkgInfo             pkg_info = NULL;
682     BOOL                    first = TRUE;
683     SspiData                client, server;
684     SEC_WINNT_AUTH_IDENTITY id;
685     static char             sec_pkg_name[] = "NTLM";
686     SecBufferDesc           crypt;
687     SecBuffer               data[2], fake_data[2], complex_data[4];
688     ULONG                   qop = 0;
689     SecPkgContext_Sizes     ctxt_sizes;
690
691     /****************************************************************
692      * This is basically the same as in testAuth with a fake server,
693      * as we need a valid, authenticated context.
694      */
695     if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info)== SEC_E_OK)
696     {
697         pFreeContextBuffer(pkg_info);
698         id.User = (unsigned char*) "testuser";
699         id.UserLength = strlen((char *) id.User);
700         id.Domain = (unsigned char *) "WORKGROUP";
701         id.DomainLength = strlen((char *) id.Domain);
702         id.Password = (unsigned char*) "testpass";
703         id.PasswordLength = strlen((char *) id.Password);
704         id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
705
706         client.id = &id;
707
708         sec_status = setupClient(&client, sec_pkg_name);
709
710         if(sec_status != SEC_E_OK)
711         {
712             trace("Error: Setting up the client returned %s, exiting test!\n",
713                     getSecError(sec_status));
714             pFreeCredentialsHandle(client.cred);
715             return;
716         }
717
718         sec_status = setupFakeServer(&server, sec_pkg_name);
719
720         while(client_stat == SEC_I_CONTINUE_NEEDED && server_stat == SEC_I_CONTINUE_NEEDED)
721         {
722             client_stat = runClient(&client, first, SECURITY_NETWORK_DREP);
723
724             communicate(&client, &server);
725
726             server_stat = runFakeServer(&server, first, SECURITY_NETWORK_DREP);
727
728             communicate(&server, &client);
729             trace("Looping\n");
730             first = FALSE;
731         }
732
733         /********************************************
734          *    Now start with the actual testing     *
735          ********************************************/
736
737         if(pQueryContextAttributesA(client.ctxt, SECPKG_ATTR_SIZES,
738                     &ctxt_sizes) != SEC_E_OK)
739         {
740             trace("Failed to get context sizes, aborting test.\n");
741             goto end;
742         }
743
744         crypt.ulVersion = SECBUFFER_VERSION;
745         crypt.cBuffers = 2;
746
747         crypt.pBuffers = fake_data;
748
749         fake_data[0].BufferType = SECBUFFER_DATA;
750         fake_data[0].cbBuffer = ctxt_sizes.cbSecurityTrailer;
751         fake_data[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, fake_data[0].cbBuffer);
752
753         fake_data[1].BufferType = SECBUFFER_DATA;
754         fake_data[1].cbBuffer = lstrlen(message);
755         fake_data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, fake_data[1].cbBuffer);
756
757         sec_status = pMakeSignature(client.ctxt, 0, &crypt, 0);
758         ok(sec_status == SEC_E_INVALID_TOKEN,
759                 "MakeSignature returned %s, not SEC_E_INVALID_TOKEN.\n",
760                 getSecError(sec_status));
761
762         crypt.pBuffers = data;
763
764         data[0].BufferType = SECBUFFER_TOKEN;
765         data[0].cbBuffer = ctxt_sizes.cbSecurityTrailer;
766         data[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[0].cbBuffer);
767
768         data[1].BufferType = SECBUFFER_DATA;
769         data[1].cbBuffer = lstrlen(message);
770         data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[1].cbBuffer);
771         memcpy(data[1].pvBuffer, message, data[1].cbBuffer);
772
773         /* As we forced NTLM to fall back to a password-derived session key,
774          * we should get the same signature for our data, no matter if
775          * it is sent by the client or the server
776          */
777         sec_status = pMakeSignature(client.ctxt, 0, &crypt, 0);
778         ok(sec_status == SEC_E_OK, "MakeSignature returned %s, not SEC_E_OK.\n",
779                 getSecError(sec_status));
780         ok(!memcmp(crypt.pBuffers[0].pvBuffer, message_signature,
781                    crypt.pBuffers[0].cbBuffer), "Signature is not as expected.\n");
782
783         data[0].cbBuffer = sizeof(message_signature);
784
785         memcpy(data[0].pvBuffer, crypt_trailer_client, data[0].cbBuffer);
786
787         sec_status = pVerifySignature(client.ctxt, &crypt, 0, &qop);
788         ok(sec_status == SEC_E_MESSAGE_ALTERED,
789                 "VerifySignature returned %s, not SEC_E_MESSAGE_ALTERED.\n",
790                 getSecError(sec_status));
791
792         memcpy(data[0].pvBuffer, message_signature, data[0].cbBuffer);
793
794         sec_status = pVerifySignature(client.ctxt, &crypt, 0, &qop);
795         ok(sec_status == SEC_E_OK, "VerifySignature returned %s, not SEC_E_OK.\n",
796                 getSecError(sec_status));
797
798         sec_status = pEncryptMessage(client.ctxt, 0, &crypt, 0);
799         ok(sec_status == SEC_E_OK, "EncryptMessage returned %s, not SEC_E_OK.\n",
800                 getSecError(sec_status));
801
802         ok(!memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client,
803                    crypt.pBuffers[0].cbBuffer), "Crypt trailer not as expected.\n");
804         ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client,
805                    crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n");
806
807         data[0].cbBuffer = sizeof(crypt_trailer_server);
808         data[1].cbBuffer = sizeof(crypt_message_server);
809         memcpy(data[0].pvBuffer, crypt_trailer_server, data[0].cbBuffer);
810         memcpy(data[1].pvBuffer, crypt_message_server, data[1].cbBuffer);
811
812         sec_status = pDecryptMessage(client.ctxt, &crypt, 0, &qop);
813
814         ok(sec_status == SEC_E_OK, "DecryptMessage returned %s, not SEC_E_OK.\n",
815                 getSecError(sec_status));
816         ok(!memcmp(crypt.pBuffers[1].pvBuffer, message_binary,
817                    crypt.pBuffers[1].cbBuffer),
818                 "Failed to decrypt message correctly.\n");
819
820         trace("Testing with more than one buffer.\n");
821
822         crypt.cBuffers = sizeof(complex_data)/sizeof(complex_data[0]);
823         crypt.pBuffers = complex_data;
824
825         complex_data[0].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM;
826         complex_data[0].cbBuffer = sizeof(message_header);
827         complex_data[0].pvBuffer = message_header;
828
829         complex_data[1].BufferType = SECBUFFER_DATA;
830         complex_data[1].cbBuffer = lstrlen(message);
831         complex_data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[1].cbBuffer);
832         memcpy(complex_data[1].pvBuffer, message, complex_data[1].cbBuffer);
833
834         complex_data[2].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM;
835         complex_data[2].cbBuffer = sizeof(message_header);
836         complex_data[2].pvBuffer = message_header;
837
838         complex_data[3].BufferType = SECBUFFER_TOKEN;
839         complex_data[3].cbBuffer = ctxt_sizes.cbSecurityTrailer;
840         complex_data[3].pvBuffer = HeapAlloc(GetProcessHeap(), 0, complex_data[3].cbBuffer);
841
842         /* We should get a dummy signature again. */
843         sec_status = pMakeSignature(client.ctxt, 0, &crypt, 0);
844         ok(sec_status == SEC_E_OK, "MakeSignature returned %s, not SEC_E_OK.\n",
845                 getSecError(sec_status));
846         ok(!memcmp(crypt.pBuffers[3].pvBuffer, message_signature,
847                    crypt.pBuffers[3].cbBuffer), "Signature is not as expected.\n");
848
849         sec_status = pEncryptMessage(client.ctxt, 0, &crypt, 0);
850         ok(sec_status == SEC_E_OK, "EncryptMessage returned %s, not SEC_E_OK.\n",
851                 getSecError(sec_status));
852
853         ok(!memcmp(crypt.pBuffers[3].pvBuffer, crypt_trailer_client2,
854                    crypt.pBuffers[3].cbBuffer), "Crypt trailer not as expected.\n");
855
856         ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client2,
857                    crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n");
858
859 end:
860         cleanupBuffers(&client);
861         cleanupBuffers(&server);
862
863         pDeleteSecurityContext(client.ctxt);
864         pFreeCredentialsHandle(client.cred);
865
866         HeapFree(GetProcessHeap(), 0, fake_data[0].pvBuffer);
867         HeapFree(GetProcessHeap(), 0, fake_data[1].pvBuffer);
868         HeapFree(GetProcessHeap(), 0, data[0].pvBuffer);
869         HeapFree(GetProcessHeap(), 0, data[1].pvBuffer);
870     }
871     else
872     {
873         trace("Package not installed, skipping test.\n");
874     }
875 }
876
877 START_TEST(ntlm)
878 {
879     InitFunctionPtrs();
880
881     if(pFreeCredentialsHandle && pDeleteSecurityContext &&
882        pDeleteSecurityContext && pAcquireCredentialsHandleA &&
883        pInitializeSecurityContextA && pCompleteAuthToken && 
884        pQuerySecurityPackageInfoA)
885     {
886         if(pAcceptSecurityContext)
887         {
888             testAuth(SECURITY_NATIVE_DREP, TRUE);
889             testAuth(SECURITY_NETWORK_DREP, TRUE);
890             testAuth(SECURITY_NATIVE_DREP, FALSE);
891             testAuth(SECURITY_NETWORK_DREP, FALSE);
892         }
893         if(pMakeSignature && pVerifySignature && pEncryptMessage &&
894            pDecryptMessage)
895             testSignSeal();
896      }
897
898     if(secdll)
899         FreeLibrary(secdll);
900 }