secur32: Get rid of some HeapAlloc() calls to make code more readable.
[wine/wine-kai.git] / dlls / secur32 / tests / ntlm.c
blobb189685c1b2f3b5ce36b4d6454958ce1b9b9c2de
1 /*
2 * Tests for the NTLM security provider
4 * Copyright 2005, 2006 Kai Blin
5 * Copyright 2006 Dmitry Timoshkov
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
21 * The code that tests for the behaviour of ISC_REQ_ALLOCATE_MEMORY is based
22 * on code written by Dmitry Timoshkov.
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>
34 #include "wine/test.h"
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);
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;
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};
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};
104 static BYTE message_signature[] =
105 {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
108 static BYTE message_binary[] =
109 {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72,
110 0x6c, 0x64, 0x21};
112 static char message[] = "Hello, world!";
114 static BYTE crypt_trailer_client[] =
115 {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xc7,
116 0xaa, 0x26, 0x16, 0x39, 0x07, 0x4e};
118 static BYTE crypt_message_client[] =
119 {0x86, 0x9c, 0x5a, 0x10, 0x78, 0xb3, 0x30, 0x98, 0x46, 0x15,
120 0xa0, 0x31, 0xd9};
122 static BYTE crypt_trailer_server[] =
123 {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x46,
124 0x2e, 0x77, 0xeb, 0xf0, 0xf6, 0x9e};
126 static BYTE crypt_message_server[] =
127 {0xf6, 0xb7, 0x92, 0x0c, 0xac, 0xea, 0x98, 0xe6, 0xef, 0xa0,
128 0x29, 0x66, 0xfd};
130 static void InitFunctionPtrs(void)
132 secdll = LoadLibraryA("secur32.dll");
133 if(!secdll)
134 secdll = LoadLibraryA("security.dll");
135 if(secdll)
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");
154 static const char* getSecError(SECURITY_STATUS status)
156 static char buf[20];
158 #define _SEC_ERR(x) case (x): return #x;
159 switch(status)
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, "%08x\n", status);
183 return buf;
185 #undef _SEC_ERR
188 /**********************************************************************/
190 static SECURITY_STATUS setupBuffers(SspiData *sspi_data, SecPkgInfoA *sec_pkg_info)
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;
197 if(sspi_data->in_buf != NULL)
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;
206 sspi_data->in_buf->ulVersion = SECBUFFER_VERSION;
207 sspi_data->in_buf->cBuffers = 1;
208 sspi_data->in_buf->pBuffers = sec_buffer;
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)
215 trace("in_buf: sec_buffer->pvBuffer == NULL\n");
216 return SEC_E_INSUFFICIENT_MEMORY;
219 else
221 trace("HeapAlloc in_buf returned NULL\n");
222 return SEC_E_INSUFFICIENT_MEMORY;
225 if(sspi_data->out_buf != NULL)
227 PSecBuffer sec_buffer = HeapAlloc(GetProcessHeap(), 0,
228 sizeof(SecBuffer));
230 if(sec_buffer == NULL){
231 trace("out_buf: sec_buffer == NULL\n");
232 return SEC_E_INSUFFICIENT_MEMORY;
235 sspi_data->out_buf->ulVersion = SECBUFFER_VERSION;
236 sspi_data->out_buf->cBuffers = 1;
237 sspi_data->out_buf->pBuffers = sec_buffer;
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;
247 else
249 trace("HeapAlloc out_buf returned NULL\n");
250 return SEC_E_INSUFFICIENT_MEMORY;
253 return SEC_E_OK;
256 /**********************************************************************/
258 static void cleanupBuffers(SspiData *sspi_data)
260 ULONG i;
262 if(sspi_data->in_buf != NULL)
264 for(i = 0; i < sspi_data->in_buf->cBuffers; ++i)
266 HeapFree(GetProcessHeap(), 0, sspi_data->in_buf->pBuffers[i].pvBuffer);
268 HeapFree(GetProcessHeap(), 0, sspi_data->in_buf->pBuffers);
269 HeapFree(GetProcessHeap(), 0, sspi_data->in_buf);
272 if(sspi_data->out_buf != NULL)
274 for(i = 0; i < sspi_data->out_buf->cBuffers; ++i)
276 HeapFree(GetProcessHeap(), 0, sspi_data->out_buf->pBuffers[i].pvBuffer);
278 HeapFree(GetProcessHeap(), 0, sspi_data->out_buf->pBuffers);
279 HeapFree(GetProcessHeap(), 0, sspi_data->out_buf);
283 /**********************************************************************/
285 static SECURITY_STATUS setupClient(SspiData *sspi_data, SEC_CHAR *provider)
287 SECURITY_STATUS ret;
288 TimeStamp ttl;
289 SecPkgInfoA *sec_pkg_info;
291 trace("Running setupClient\n");
293 sspi_data->cred = HeapAlloc(GetProcessHeap(), 0, sizeof(CredHandle));
294 sspi_data->ctxt = HeapAlloc(GetProcessHeap(), 0, sizeof(CtxtHandle));
296 ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info);
298 ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret));
300 setupBuffers(sspi_data, sec_pkg_info);
302 if((ret = pAcquireCredentialsHandleA(NULL, provider, SECPKG_CRED_OUTBOUND,
303 NULL, sspi_data->id, NULL, NULL, sspi_data->cred, &ttl))
304 != SEC_E_OK)
306 trace("AcquireCredentialsHandle() returned %s\n", getSecError(ret));
309 ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n",
310 getSecError(ret));
312 return ret;
314 /**********************************************************************/
316 static SECURITY_STATUS setupServer(SspiData *sspi_data, SEC_CHAR *provider)
318 SECURITY_STATUS ret;
319 TimeStamp ttl;
320 SecPkgInfoA *sec_pkg_info;
322 trace("Running setupServer\n");
324 sspi_data->cred = HeapAlloc(GetProcessHeap(), 0, sizeof(CredHandle));
325 sspi_data->ctxt = HeapAlloc(GetProcessHeap(), 0, sizeof(CtxtHandle));
327 ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info);
329 ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret));
331 setupBuffers(sspi_data, sec_pkg_info);
333 if((ret = pAcquireCredentialsHandleA(NULL, provider, SECPKG_CRED_INBOUND,
334 NULL, NULL, NULL, NULL, sspi_data->cred, &ttl)) != SEC_E_OK)
336 trace("AcquireCredentialsHandle() returned %s\n", getSecError(ret));
339 ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n",
340 getSecError(ret));
342 return ret;
345 /**********************************************************************/
347 static SECURITY_STATUS setupFakeServer(SspiData *sspi_data, SEC_CHAR *provider)
349 SECURITY_STATUS ret;
350 SecPkgInfoA *sec_pkg_info;
352 trace("Running setupFakeServer\n");
354 sspi_data->cred = HeapAlloc(GetProcessHeap(), 0, sizeof(CredHandle));
355 sspi_data->ctxt = HeapAlloc(GetProcessHeap(), 0, sizeof(CtxtHandle));
357 ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info);
359 ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret));
361 ret = setupBuffers(sspi_data, sec_pkg_info);
363 return ret;
367 /**********************************************************************/
369 static SECURITY_STATUS runClient(SspiData *sspi_data, BOOL first, ULONG data_rep)
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;
378 assert(in_buf->cBuffers >= 1);
379 assert(in_buf->pBuffers[0].pvBuffer != NULL);
380 assert(in_buf->pBuffers[0].cbBuffer != 0);
382 assert(out_buf->cBuffers >= 1);
383 assert(out_buf->pBuffers[0].pvBuffer != NULL);
384 assert(out_buf->pBuffers[0].cbBuffer != 0);
386 trace("Running the client the %s time.\n", first?"first":"second");
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.
394 /* test a failing call only the first time, otherwise we get
395 * SEC_E_OUT_OF_SEQUENCE
397 if (first)
399 void *old_buf;
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);
406 ok(ret == SEC_E_BUFFER_TOO_SMALL, "expected SEC_E_BUFFER_TOO_SMALL, got %s\n", getSecError(ret));
408 /* pass NULL as an output buffer */
409 old_buf = out_buf->pBuffers[0].pvBuffer;
410 out_buf->pBuffers[0].pvBuffer = NULL;
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);
416 ok(ret == SEC_E_INTERNAL_ERROR, "expected SEC_E_INTERNAL_ERROR, got %s\n", getSecError(ret));
418 out_buf->pBuffers[0].pvBuffer = old_buf;
420 /* pass an output buffer of 0 size */
421 out_buf->pBuffers[0].cbBuffer = 0;
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);
427 ok(ret == SEC_E_BUFFER_TOO_SMALL, "expected SEC_E_BUFFER_TOO_SMALL, got %s\n", getSecError(ret));
429 ok(out_buf->pBuffers[0].cbBuffer == 0,
430 "InitializeSecurityContext set buffer size to %lu\n", out_buf->pBuffers[0].cbBuffer);
433 out_buf->pBuffers[0].cbBuffer = sspi_data->max_token;
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);
439 if(ret == SEC_I_COMPLETE_AND_CONTINUE || ret == SEC_I_COMPLETE_NEEDED)
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;
448 ok(out_buf->pBuffers[0].cbBuffer < sspi_data->max_token,
449 "InitializeSecurityContext set buffer size to %lu\n", out_buf->pBuffers[0].cbBuffer);
451 return ret;
454 /**********************************************************************/
456 static SECURITY_STATUS runServer(SspiData *sspi_data, BOOL first, ULONG data_rep)
458 SECURITY_STATUS ret;
459 ULONG ctxt_attr;
460 TimeStamp ttl;
462 trace("Running the server the %s time\n", first?"first":"second");
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);
468 if(ret == SEC_I_COMPLETE_AND_CONTINUE || ret == SEC_I_COMPLETE_NEEDED)
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;
477 return ret;
480 /**********************************************************************/
482 static SECURITY_STATUS runFakeServer(SspiData *sspi_data, BOOL first, ULONG data_rep)
484 trace("Running the fake server the %s time\n", first?"first":"second");
486 if(!first)
488 sspi_data->out_buf->pBuffers[0].cbBuffer = 0;
489 return SEC_E_OK;
492 if(data_rep == SECURITY_NATIVE_DREP)
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);
498 else
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);
505 return SEC_I_CONTINUE_NEEDED;
508 /**********************************************************************/
510 static void communicate(SspiData *from, SspiData *to)
512 if(from->out_buf != NULL && to->in_buf != NULL)
514 trace("Running communicate.\n");
515 if((from->out_buf->cBuffers >= 1) && (to->in_buf->cBuffers >= 1))
517 if((from->out_buf->pBuffers[0].pvBuffer != NULL) &&
518 (to->in_buf->pBuffers[0].pvBuffer != NULL))
520 memset(to->in_buf->pBuffers[0].pvBuffer, 0, to->max_token);
522 memcpy(to->in_buf->pBuffers[0].pvBuffer,
523 from->out_buf->pBuffers[0].pvBuffer,
524 from->out_buf->pBuffers[0].cbBuffer);
526 to->in_buf->pBuffers[0].cbBuffer = from->out_buf->pBuffers[0].cbBuffer;
528 memset(from->out_buf->pBuffers[0].pvBuffer, 0, from->max_token);
534 /**********************************************************************/
536 static void testAuth(ULONG data_rep, BOOL fake)
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";
548 if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info)== SEC_E_OK)
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;
559 client.id = &id;
561 sec_status = setupClient(&client, sec_pkg_name);
563 if(sec_status != SEC_E_OK)
565 trace("Error: Setting up the client returned %s, exiting test!\n",
566 getSecError(sec_status));
567 pFreeCredentialsHandle(client.cred);
568 return;
571 if(fake)
572 sec_status = setupFakeServer(&server, sec_pkg_name);
573 else
574 sec_status = setupServer(&server, sec_pkg_name);
576 if(sec_status != SEC_E_OK)
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;
586 while(client_stat == SEC_I_CONTINUE_NEEDED && server_stat == SEC_I_CONTINUE_NEEDED)
588 client_stat = runClient(&client, first, data_rep);
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));
594 communicate(&client, &server);
596 if(fake)
597 server_stat = runFakeServer(&server, first, data_rep);
598 else
599 server_stat = runServer(&server, first, data_rep);
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));
606 communicate(&server, &client);
607 trace("Looping\n");
608 first = FALSE;
611 if(client_stat == SEC_E_OK)
613 sec_status = pQueryContextAttributesA(client.ctxt,
614 SECPKG_ATTR_SIZES, &ctxt_sizes);
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);
632 else
633 trace("Authentication failed, skipping test.\n");
635 cleanupBuffers(&client);
636 cleanupBuffers(&server);
638 if(!fake)
640 sec_status = pDeleteSecurityContext(server.ctxt);
641 ok(sec_status == SEC_E_OK, "DeleteSecurityContext(server) returned %s\n",
642 getSecError(sec_status));
645 sec_status = pDeleteSecurityContext(client.ctxt);
646 ok(sec_status == SEC_E_OK, "DeleteSecurityContext(client) returned %s\n",
647 getSecError(sec_status));
649 if(!fake)
651 sec_status = pFreeCredentialsHandle(server.cred);
652 ok(sec_status == SEC_E_OK, "FreeCredentialsHandle(server) returned %s\n",
653 getSecError(sec_status));
656 sec_status = pFreeCredentialsHandle(client.cred);
657 ok(sec_status == SEC_E_OK, "FreeCredentialsHandle(client) returned %s\n",
658 getSecError(sec_status));
660 else
662 trace("Package not installed, skipping test.\n");
666 static void testSignSeal()
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 SecBufferDesc crypt;
677 SecBuffer data[2], fake_data[2];
678 ULONG qop = 0;
679 SecPkgContext_Sizes ctxt_sizes;
681 /****************************************************************
682 * This is basically the same as in testAuth with a fake server,
683 * as we need a valid, authenticated context.
685 if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info)== SEC_E_OK)
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;
696 client.id = &id;
698 sec_status = setupClient(&client, sec_pkg_name);
700 if(sec_status != SEC_E_OK)
702 trace("Error: Setting up the client returned %s, exiting test!\n",
703 getSecError(sec_status));
704 pFreeCredentialsHandle(client.cred);
705 return;
708 sec_status = setupFakeServer(&server, sec_pkg_name);
710 while(client_stat == SEC_I_CONTINUE_NEEDED && server_stat == SEC_I_CONTINUE_NEEDED)
712 client_stat = runClient(&client, first, SECURITY_NETWORK_DREP);
714 communicate(&client, &server);
716 server_stat = runFakeServer(&server, first, SECURITY_NETWORK_DREP);
718 communicate(&server, &client);
719 trace("Looping\n");
720 first = FALSE;
723 /********************************************
724 * Now start with the actual testing *
725 ********************************************/
727 if(pQueryContextAttributesA(client.ctxt, SECPKG_ATTR_SIZES,
728 &ctxt_sizes) != SEC_E_OK)
730 trace("Failed to get context sizes, aborting test.\n");
731 goto end;
734 crypt.ulVersion = SECBUFFER_VERSION;
735 crypt.cBuffers = 2;
737 crypt.pBuffers = fake_data;
739 fake_data[0].BufferType = SECBUFFER_DATA;
740 fake_data[0].cbBuffer = ctxt_sizes.cbSecurityTrailer;
741 fake_data[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, fake_data[0].cbBuffer);
743 fake_data[1].BufferType = SECBUFFER_DATA;
744 fake_data[1].cbBuffer = lstrlen(message);
745 fake_data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, fake_data[1].cbBuffer);
747 sec_status = pMakeSignature(client.ctxt, 0, &crypt, 0);
748 ok(sec_status == SEC_E_INVALID_TOKEN,
749 "MakeSignature returned %s, not SEC_E_INVALID_TOKEN.\n",
750 getSecError(sec_status));
752 crypt.pBuffers = data;
754 data[0].BufferType = SECBUFFER_TOKEN;
755 data[0].cbBuffer = ctxt_sizes.cbSecurityTrailer;
756 data[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[0].cbBuffer);
758 data[1].BufferType = SECBUFFER_DATA;
759 data[1].cbBuffer = lstrlen(message);
760 data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[1].cbBuffer);
761 memcpy(data[1].pvBuffer, message, data[1].cbBuffer);
763 /* As we forced NTLM to fall back to a password-derived session key,
764 * we should get the same signature for our data, no matter if
765 * it is sent by the client or the server
767 sec_status = pMakeSignature(client.ctxt, 0, &crypt, 0);
768 ok(sec_status == SEC_E_OK, "MakeSignature returned %s, not SEC_E_OK.\n",
769 getSecError(sec_status));
770 ok(!memcmp(crypt.pBuffers[0].pvBuffer, message_signature,
771 crypt.pBuffers[0].cbBuffer), "Signature is not as expected.\n");
773 data[0].cbBuffer = sizeof(message_signature);
775 memcpy(data[0].pvBuffer, crypt_trailer_client, data[0].cbBuffer);
777 sec_status = pVerifySignature(client.ctxt, &crypt, 0, &qop);
778 ok(sec_status == SEC_E_MESSAGE_ALTERED,
779 "VerifySignature returned %s, not SEC_E_MESSAGE_ALTERED.\n",
780 getSecError(sec_status));
782 memcpy(data[0].pvBuffer, message_signature, data[0].cbBuffer);
784 sec_status = pVerifySignature(client.ctxt, &crypt, 0, &qop);
785 ok(sec_status == SEC_E_OK, "VerifySignature returned %s, not SEC_E_OK.\n",
786 getSecError(sec_status));
788 sec_status = pEncryptMessage(client.ctxt, 0, &crypt, 0);
789 ok(sec_status == SEC_E_OK, "EncryptMessage returned %s, not SEC_E_OK.\n",
790 getSecError(sec_status));
792 ok(!memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client,
793 crypt.pBuffers[0].cbBuffer), "Crypt trailer not as expected.\n");
794 ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client,
795 crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n");
797 data[0].cbBuffer = sizeof(crypt_trailer_server);
798 data[1].cbBuffer = sizeof(crypt_message_server);
799 memcpy(data[0].pvBuffer, crypt_trailer_server, data[0].cbBuffer);
800 memcpy(data[1].pvBuffer, crypt_message_server, data[1].cbBuffer);
802 sec_status = pDecryptMessage(client.ctxt, &crypt, 0, &qop);
804 ok(sec_status == SEC_E_OK, "DecryptMessage returned %s, not SEC_E_OK.\n",
805 getSecError(sec_status));
806 ok(!memcmp(crypt.pBuffers[1].pvBuffer, message_binary,
807 crypt.pBuffers[1].cbBuffer),
808 "Failed to decrypt message correctly.\n");
810 end:
811 cleanupBuffers(&client);
812 cleanupBuffers(&server);
814 pDeleteSecurityContext(client.ctxt);
815 pFreeCredentialsHandle(client.cred);
817 HeapFree(GetProcessHeap(), 0, fake_data[0].pvBuffer);
818 HeapFree(GetProcessHeap(), 0, fake_data[1].pvBuffer);
819 HeapFree(GetProcessHeap(), 0, data[0].pvBuffer);
820 HeapFree(GetProcessHeap(), 0, data[1].pvBuffer);
822 else
824 trace("Package not installed, skipping test.\n");
828 START_TEST(ntlm)
830 InitFunctionPtrs();
832 if(pFreeCredentialsHandle && pDeleteSecurityContext &&
833 pDeleteSecurityContext && pAcquireCredentialsHandleA &&
834 pInitializeSecurityContextA && pCompleteAuthToken &&
835 pQuerySecurityPackageInfoA)
837 if(pAcceptSecurityContext)
839 testAuth(SECURITY_NATIVE_DREP, TRUE);
840 testAuth(SECURITY_NETWORK_DREP, TRUE);
841 testAuth(SECURITY_NATIVE_DREP, FALSE);
842 testAuth(SECURITY_NETWORK_DREP, FALSE);
844 if(pMakeSignature && pVerifySignature && pEncryptMessage &&
845 pDecryptMessage)
846 testSignSeal();
849 if(secdll)
850 FreeLibrary(secdll);