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