|  | /* | 
|  | * Tests for the NTLM security provider | 
|  | * | 
|  | * Copyright 2005, 2006 Kai Blin | 
|  | * Copyright 2006 Dmitry Timoshkov | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | * | 
|  | * The code that tests for the behaviour of ISC_REQ_ALLOCATE_MEMORY is based | 
|  | * on code written by Dmitry Timoshkov. | 
|  |  | 
|  | */ | 
|  |  | 
|  | #include <stdarg.h> | 
|  | #include <stdio.h> | 
|  | #include <assert.h> | 
|  | #include <windef.h> | 
|  | #include <winbase.h> | 
|  | #define SECURITY_WIN32 | 
|  | #include <sspi.h> | 
|  | #include <rpc.h> | 
|  | #include <rpcdce.h> | 
|  | #include <secext.h> | 
|  |  | 
|  | #include "wine/test.h" | 
|  |  | 
|  | static HMODULE secdll; | 
|  | static PSecurityFunctionTableA (SEC_ENTRY * pInitSecurityInterfaceA)(void); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pFreeContextBuffer)(PVOID pv); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pQuerySecurityPackageInfoA)(SEC_CHAR*, PSecPkgInfoA*); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pAcquireCredentialsHandleA)(SEC_CHAR*, SEC_CHAR*, | 
|  | ULONG, PLUID, PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pInitializeSecurityContextA)(PCredHandle, PCtxtHandle, | 
|  | SEC_CHAR*, ULONG, ULONG, ULONG, PSecBufferDesc, ULONG, | 
|  | PCtxtHandle, PSecBufferDesc, PULONG, PTimeStamp); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pCompleteAuthToken)(PCtxtHandle, PSecBufferDesc); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pAcceptSecurityContext)(PCredHandle, PCtxtHandle, | 
|  | PSecBufferDesc, ULONG, ULONG, PCtxtHandle, PSecBufferDesc, | 
|  | PULONG, PTimeStamp); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pFreeCredentialsHandle)(PCredHandle); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pDeleteSecurityContext)(PCtxtHandle); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pQueryContextAttributesA)(PCtxtHandle, ULONG, PVOID); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pMakeSignature)(PCtxtHandle, ULONG, | 
|  | PSecBufferDesc, ULONG); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pVerifySignature)(PCtxtHandle, PSecBufferDesc, | 
|  | ULONG, PULONG); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pEncryptMessage)(PCtxtHandle, ULONG, | 
|  | PSecBufferDesc, ULONG); | 
|  | static SECURITY_STATUS (SEC_ENTRY * pDecryptMessage)(PCtxtHandle, PSecBufferDesc, | 
|  | ULONG, PULONG); | 
|  | static BOOLEAN (WINAPI * pGetUserNameExA)(EXTENDED_NAME_FORMAT, LPSTR, PULONG); | 
|  |  | 
|  | typedef struct _SspiData { | 
|  | CredHandle cred; | 
|  | CtxtHandle ctxt; | 
|  | PSecBufferDesc in_buf; | 
|  | PSecBufferDesc out_buf; | 
|  | PSEC_WINNT_AUTH_IDENTITY id; | 
|  | ULONG max_token; | 
|  | } SspiData; | 
|  |  | 
|  | static BYTE network_challenge[] = | 
|  | {0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, | 
|  | 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, | 
|  | 0x05, 0x82, 0x82, 0xa0, 0xe9, 0x58, 0x7f, 0x14, 0xa2, 0x86, | 
|  | 0x3b, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 0x54, 0x00, 0x54, 0x00, 0x40, 0x00, 0x00, 0x00, 0x43, 0x00, | 
|  | 0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x02, 0x00, 0x10, 0x00, 0x43, 0x00, | 
|  | 0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x01, 0x00, 0x10, 0x00, 0x43, 0x00, | 
|  | 0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x04, 0x00, 0x10, 0x00, 0x63, 0x00, | 
|  | 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x03, 0x00, 0x10, 0x00, 0x63, 0x00, | 
|  | 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00}; | 
|  |  | 
|  | static BYTE native_challenge[] = | 
|  | {0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, | 
|  | 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, | 
|  | 0x05, 0x82, 0x82, 0xa0, 0xb5, 0x60, 0x8e, 0x95, 0xb5, 0x3c, | 
|  | 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 0x54, 0x00, 0x54, 0x00, 0x40, 0x00, 0x00, 0x00, 0x43, 0x00, | 
|  | 0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x02, 0x00, 0x10, 0x00, 0x43, 0x00, | 
|  | 0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x01, 0x00, 0x10, 0x00, 0x43, 0x00, | 
|  | 0x41, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x04, 0x00, 0x10, 0x00, 0x63, 0x00, | 
|  | 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x03, 0x00, 0x10, 0x00, 0x63, 0x00, | 
|  | 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6f, 0x00, | 
|  | 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00}; | 
|  |  | 
|  | static BYTE message_signature[] = | 
|  | {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | 
|  |  | 
|  | static BYTE message_binary[] = | 
|  | {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, | 
|  | 0x6c, 0x64, 0x21}; | 
|  |  | 
|  | static char message[] = "Hello, world!"; | 
|  |  | 
|  | static char message_header[] = "Header Test"; | 
|  |  | 
|  | static BYTE crypt_trailer_client[] = | 
|  | {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xc7, | 
|  | 0xaa, 0x26, 0x16, 0x39, 0x07, 0x4e}; | 
|  |  | 
|  | static BYTE crypt_message_client[] = | 
|  | {0x86, 0x9c, 0x5a, 0x10, 0x78, 0xb3, 0x30, 0x98, 0x46, 0x15, | 
|  | 0xa0, 0x31, 0xd9}; | 
|  |  | 
|  | static BYTE crypt_trailer_client2[] = | 
|  | {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xa7, | 
|  | 0xf7, 0x0f, 0x5b, 0x25, 0xbe, 0xa4}; | 
|  |  | 
|  | static BYTE crypt_message_client2[] = | 
|  | {0x20, 0x6c, 0x01, 0xab, 0xb0, 0x4c, 0x93, 0xe4, 0x1e, 0xfc, | 
|  | 0xe1, 0xfa, 0xfe}; | 
|  |  | 
|  | static BYTE crypt_trailer_server[] = | 
|  | {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x46, | 
|  | 0x2e, 0x77, 0xeb, 0xf0, 0xf6, 0x9e}; | 
|  |  | 
|  | static BYTE crypt_message_server[] = | 
|  | {0xf6, 0xb7, 0x92, 0x0c, 0xac, 0xea, 0x98, 0xe6, 0xef, 0xa0, | 
|  | 0x29, 0x66, 0xfd}; | 
|  |  | 
|  | static BYTE crypt_trailer_server2[] = | 
|  | {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x4e, | 
|  | 0x46, 0xb7, 0xca, 0xf7, 0x7f, 0xb3}; | 
|  |  | 
|  | static BYTE crypt_message_server2[] = | 
|  | {0xc8, 0xf2, 0x39, 0x7f, 0x0c, 0xaf, 0xf5, 0x5d, 0xef, 0x0c, | 
|  | 0x8b, 0x5f, 0x82}; | 
|  |  | 
|  | static void InitFunctionPtrs(void) | 
|  | { | 
|  | secdll = LoadLibraryA("secur32.dll"); | 
|  | if(!secdll) | 
|  | secdll = LoadLibraryA("security.dll"); | 
|  | if(secdll) | 
|  | { | 
|  | pInitSecurityInterfaceA = (PVOID)GetProcAddress(secdll, "InitSecurityInterfaceA"); | 
|  | pFreeContextBuffer = (PVOID)GetProcAddress(secdll, "FreeContextBuffer"); | 
|  | pQuerySecurityPackageInfoA = (PVOID)GetProcAddress(secdll, "QuerySecurityPackageInfoA"); | 
|  | pAcquireCredentialsHandleA = (PVOID)GetProcAddress(secdll, "AcquireCredentialsHandleA"); | 
|  | pInitializeSecurityContextA = (PVOID)GetProcAddress(secdll, "InitializeSecurityContextA"); | 
|  | pCompleteAuthToken = (PVOID)GetProcAddress(secdll, "CompleteAuthToken"); | 
|  | pAcceptSecurityContext = (PVOID)GetProcAddress(secdll, "AcceptSecurityContext"); | 
|  | pFreeCredentialsHandle = (PVOID)GetProcAddress(secdll, "FreeCredentialsHandle"); | 
|  | pDeleteSecurityContext = (PVOID)GetProcAddress(secdll, "DeleteSecurityContext"); | 
|  | pQueryContextAttributesA = (PVOID)GetProcAddress(secdll, "QueryContextAttributesA"); | 
|  | pMakeSignature = (PVOID)GetProcAddress(secdll, "MakeSignature"); | 
|  | pVerifySignature = (PVOID)GetProcAddress(secdll, "VerifySignature"); | 
|  | pEncryptMessage = (PVOID)GetProcAddress(secdll, "EncryptMessage"); | 
|  | pDecryptMessage = (PVOID)GetProcAddress(secdll, "DecryptMessage"); | 
|  | pGetUserNameExA = (PVOID)GetProcAddress(secdll, "GetUserNameExA"); | 
|  | } | 
|  | } | 
|  |  | 
|  | static const char* getSecError(SECURITY_STATUS status) | 
|  | { | 
|  | static char buf[20]; | 
|  |  | 
|  | #define _SEC_ERR(x) case (x): return #x; | 
|  | switch(status) | 
|  | { | 
|  | _SEC_ERR(SEC_E_OK); | 
|  | _SEC_ERR(SEC_E_INSUFFICIENT_MEMORY); | 
|  | _SEC_ERR(SEC_E_INVALID_HANDLE); | 
|  | _SEC_ERR(SEC_E_UNSUPPORTED_FUNCTION); | 
|  | _SEC_ERR(SEC_E_TARGET_UNKNOWN); | 
|  | _SEC_ERR(SEC_E_INTERNAL_ERROR); | 
|  | _SEC_ERR(SEC_E_SECPKG_NOT_FOUND); | 
|  | _SEC_ERR(SEC_E_NOT_OWNER); | 
|  | _SEC_ERR(SEC_E_CANNOT_INSTALL); | 
|  | _SEC_ERR(SEC_E_INVALID_TOKEN); | 
|  | _SEC_ERR(SEC_E_CANNOT_PACK); | 
|  | _SEC_ERR(SEC_E_QOP_NOT_SUPPORTED); | 
|  | _SEC_ERR(SEC_E_NO_IMPERSONATION); | 
|  | _SEC_ERR(SEC_I_CONTINUE_NEEDED); | 
|  | _SEC_ERR(SEC_E_BUFFER_TOO_SMALL); | 
|  | _SEC_ERR(SEC_E_ILLEGAL_MESSAGE); | 
|  | _SEC_ERR(SEC_E_LOGON_DENIED); | 
|  | _SEC_ERR(SEC_E_NO_CREDENTIALS); | 
|  | _SEC_ERR(SEC_E_OUT_OF_SEQUENCE); | 
|  | _SEC_ERR(SEC_E_MESSAGE_ALTERED); | 
|  | default: | 
|  | sprintf(buf, "%08x\n", status); | 
|  | return buf; | 
|  | } | 
|  | #undef _SEC_ERR | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static SECURITY_STATUS setupBuffers(SspiData *sspi_data, SecPkgInfoA *sec_pkg_info) | 
|  | { | 
|  |  | 
|  | sspi_data->in_buf  = HeapAlloc(GetProcessHeap(), 0, sizeof(SecBufferDesc)); | 
|  | sspi_data->out_buf = HeapAlloc(GetProcessHeap(), 0, sizeof(SecBufferDesc)); | 
|  | sspi_data->max_token = sec_pkg_info->cbMaxToken; | 
|  |  | 
|  | if(sspi_data->in_buf != NULL) | 
|  | { | 
|  | PSecBuffer sec_buffer = HeapAlloc(GetProcessHeap(), 0, | 
|  | sizeof(SecBuffer)); | 
|  | if(sec_buffer == NULL){ | 
|  | trace("in_buf: sec_buffer == NULL\n"); | 
|  | return SEC_E_INSUFFICIENT_MEMORY; | 
|  | } | 
|  |  | 
|  | sspi_data->in_buf->ulVersion = SECBUFFER_VERSION; | 
|  | sspi_data->in_buf->cBuffers = 1; | 
|  | sspi_data->in_buf->pBuffers = sec_buffer; | 
|  |  | 
|  | sec_buffer->cbBuffer = sec_pkg_info->cbMaxToken; | 
|  | sec_buffer->BufferType = SECBUFFER_TOKEN; | 
|  | if((sec_buffer->pvBuffer = HeapAlloc(GetProcessHeap(), 0, | 
|  | sec_pkg_info->cbMaxToken)) == NULL) | 
|  | { | 
|  | trace("in_buf: sec_buffer->pvBuffer == NULL\n"); | 
|  | return SEC_E_INSUFFICIENT_MEMORY; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | trace("HeapAlloc in_buf returned NULL\n"); | 
|  | return SEC_E_INSUFFICIENT_MEMORY; | 
|  | } | 
|  |  | 
|  | if(sspi_data->out_buf != NULL) | 
|  | { | 
|  | PSecBuffer sec_buffer = HeapAlloc(GetProcessHeap(), 0, | 
|  | sizeof(SecBuffer)); | 
|  |  | 
|  | if(sec_buffer == NULL){ | 
|  | trace("out_buf: sec_buffer == NULL\n"); | 
|  | return SEC_E_INSUFFICIENT_MEMORY; | 
|  | } | 
|  |  | 
|  | sspi_data->out_buf->ulVersion = SECBUFFER_VERSION; | 
|  | sspi_data->out_buf->cBuffers = 1; | 
|  | sspi_data->out_buf->pBuffers = sec_buffer; | 
|  |  | 
|  | sec_buffer->cbBuffer = sec_pkg_info->cbMaxToken; | 
|  | sec_buffer->BufferType = SECBUFFER_TOKEN; | 
|  | if((sec_buffer->pvBuffer = HeapAlloc(GetProcessHeap(), 0, | 
|  | sec_pkg_info->cbMaxToken)) == NULL){ | 
|  | trace("out_buf: sec_buffer->pvBuffer == NULL\n"); | 
|  | return SEC_E_INSUFFICIENT_MEMORY; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | trace("HeapAlloc out_buf returned NULL\n"); | 
|  | return SEC_E_INSUFFICIENT_MEMORY; | 
|  | } | 
|  |  | 
|  | return SEC_E_OK; | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static void cleanupBuffers(SspiData *sspi_data) | 
|  | { | 
|  | ULONG i; | 
|  |  | 
|  | if(sspi_data->in_buf != NULL) | 
|  | { | 
|  | for(i = 0; i < sspi_data->in_buf->cBuffers; ++i) | 
|  | { | 
|  | HeapFree(GetProcessHeap(), 0, sspi_data->in_buf->pBuffers[i].pvBuffer); | 
|  | } | 
|  | HeapFree(GetProcessHeap(), 0, sspi_data->in_buf->pBuffers); | 
|  | HeapFree(GetProcessHeap(), 0, sspi_data->in_buf); | 
|  | } | 
|  |  | 
|  | if(sspi_data->out_buf != NULL) | 
|  | { | 
|  | for(i = 0; i < sspi_data->out_buf->cBuffers; ++i) | 
|  | { | 
|  | HeapFree(GetProcessHeap(), 0, sspi_data->out_buf->pBuffers[i].pvBuffer); | 
|  | } | 
|  | HeapFree(GetProcessHeap(), 0, sspi_data->out_buf->pBuffers); | 
|  | HeapFree(GetProcessHeap(), 0, sspi_data->out_buf); | 
|  | } | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static SECURITY_STATUS setupClient(SspiData *sspi_data, SEC_CHAR *provider) | 
|  | { | 
|  | SECURITY_STATUS ret; | 
|  | TimeStamp ttl; | 
|  | SecPkgInfoA *sec_pkg_info; | 
|  |  | 
|  | trace("Running setupClient\n"); | 
|  |  | 
|  | ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info); | 
|  |  | 
|  | ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret)); | 
|  |  | 
|  | setupBuffers(sspi_data, sec_pkg_info); | 
|  | pFreeContextBuffer(sec_pkg_info); | 
|  |  | 
|  | if((ret = pAcquireCredentialsHandleA(NULL, provider, SECPKG_CRED_OUTBOUND, | 
|  | NULL, sspi_data->id, NULL, NULL, &sspi_data->cred, &ttl)) | 
|  | != SEC_E_OK) | 
|  | { | 
|  | trace("AcquireCredentialsHandle() returned %s\n", getSecError(ret)); | 
|  | } | 
|  |  | 
|  | ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", | 
|  | getSecError(ret)); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static SECURITY_STATUS setupServer(SspiData *sspi_data, SEC_CHAR *provider) | 
|  | { | 
|  | SECURITY_STATUS ret; | 
|  | TimeStamp ttl; | 
|  | SecPkgInfoA *sec_pkg_info; | 
|  |  | 
|  | trace("Running setupServer\n"); | 
|  |  | 
|  | ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info); | 
|  |  | 
|  | ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret)); | 
|  |  | 
|  | setupBuffers(sspi_data, sec_pkg_info); | 
|  | pFreeContextBuffer(sec_pkg_info); | 
|  |  | 
|  | if((ret = pAcquireCredentialsHandleA(NULL, provider, SECPKG_CRED_INBOUND, | 
|  | NULL, NULL, NULL, NULL, &sspi_data->cred, &ttl)) != SEC_E_OK) | 
|  | { | 
|  | trace("AcquireCredentialsHandle() returned %s\n", getSecError(ret)); | 
|  | } | 
|  |  | 
|  | ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", | 
|  | getSecError(ret)); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static SECURITY_STATUS setupFakeServer(SspiData *sspi_data, SEC_CHAR *provider) | 
|  | { | 
|  | SECURITY_STATUS ret; | 
|  | SecPkgInfoA *sec_pkg_info; | 
|  |  | 
|  | trace("Running setupFakeServer\n"); | 
|  |  | 
|  | ret = pQuerySecurityPackageInfoA(provider, &sec_pkg_info); | 
|  |  | 
|  | ok(ret == SEC_E_OK, "QuerySecurityPackageInfo returned %s\n", getSecError(ret)); | 
|  |  | 
|  | ret = setupBuffers(sspi_data, sec_pkg_info); | 
|  | pFreeContextBuffer(sec_pkg_info); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static SECURITY_STATUS runClient(SspiData *sspi_data, BOOL first, ULONG data_rep) | 
|  | { | 
|  | SECURITY_STATUS ret; | 
|  | ULONG req_attr = 0; | 
|  | ULONG ctxt_attr; | 
|  | TimeStamp ttl; | 
|  | PSecBufferDesc in_buf = sspi_data->in_buf; | 
|  | PSecBufferDesc out_buf = sspi_data->out_buf; | 
|  |  | 
|  | assert(in_buf->cBuffers >= 1); | 
|  | assert(in_buf->pBuffers[0].pvBuffer != NULL); | 
|  | assert(in_buf->pBuffers[0].cbBuffer != 0); | 
|  |  | 
|  | assert(out_buf->cBuffers >= 1); | 
|  | assert(out_buf->pBuffers[0].pvBuffer != NULL); | 
|  | assert(out_buf->pBuffers[0].cbBuffer != 0); | 
|  |  | 
|  | trace("Running the client the %s time.\n", first?"first":"second"); | 
|  |  | 
|  | /* We can either use ISC_REQ_ALLOCATE_MEMORY flag to ask the provider | 
|  | * always allocate output buffers for us, or initialize cbBuffer | 
|  | * before each call because the API changes it to represent actual | 
|  | * amount of data in the buffer. | 
|  | */ | 
|  |  | 
|  | /* test a failing call only the first time, otherwise we get | 
|  | * SEC_E_OUT_OF_SEQUENCE | 
|  | */ | 
|  | if (first) | 
|  | { | 
|  | void *old_buf; | 
|  |  | 
|  | /* pass NULL as an output buffer */ | 
|  | ret = pInitializeSecurityContextA(&sspi_data->cred, NULL, NULL, req_attr, | 
|  | 0, data_rep, NULL, 0, &sspi_data->ctxt, NULL, | 
|  | &ctxt_attr, &ttl); | 
|  |  | 
|  | ok(ret == SEC_E_BUFFER_TOO_SMALL, "expected SEC_E_BUFFER_TOO_SMALL, got %s\n", getSecError(ret)); | 
|  |  | 
|  | /* pass NULL as an output buffer */ | 
|  | old_buf = out_buf->pBuffers[0].pvBuffer; | 
|  | out_buf->pBuffers[0].pvBuffer = NULL; | 
|  |  | 
|  | ret = pInitializeSecurityContextA(&sspi_data->cred, NULL, NULL, req_attr, | 
|  | 0, data_rep, NULL, 0, &sspi_data->ctxt, out_buf, | 
|  | &ctxt_attr, &ttl); | 
|  |  | 
|  | ok(ret == SEC_E_INTERNAL_ERROR || ret == SEC_I_CONTINUE_NEEDED, | 
|  | "expected SEC_E_INTERNAL_ERROR or SEC_I_CONTINUE_NEEDED, got %s\n", getSecError(ret)); | 
|  |  | 
|  | out_buf->pBuffers[0].pvBuffer = old_buf; | 
|  |  | 
|  | /* pass an output buffer of 0 size */ | 
|  | out_buf->pBuffers[0].cbBuffer = 0; | 
|  |  | 
|  | ret = pInitializeSecurityContextA(&sspi_data->cred, NULL, NULL, req_attr, | 
|  | 0, data_rep, NULL, 0, &sspi_data->ctxt, out_buf, | 
|  | &ctxt_attr, &ttl); | 
|  |  | 
|  | ok(ret == SEC_E_BUFFER_TOO_SMALL, "expected SEC_E_BUFFER_TOO_SMALL, got %s\n", getSecError(ret)); | 
|  |  | 
|  | ok(out_buf->pBuffers[0].cbBuffer == 0, | 
|  | "InitializeSecurityContext set buffer size to %u\n", out_buf->pBuffers[0].cbBuffer); | 
|  |  | 
|  | out_buf->pBuffers[0].cbBuffer = sspi_data->max_token; | 
|  | out_buf->pBuffers[0].BufferType = SECBUFFER_DATA; | 
|  |  | 
|  | ret = pInitializeSecurityContextA(&sspi_data->cred, NULL, NULL, req_attr, | 
|  | 0, data_rep, NULL, 0, &sspi_data->ctxt, out_buf, | 
|  | &ctxt_attr, &ttl); | 
|  |  | 
|  | ok(ret == SEC_E_BUFFER_TOO_SMALL, "expected SEC_E_BUFFER_TOO_SMALL, got %s\n", getSecError(ret)); | 
|  | out_buf->pBuffers[0].BufferType = SECBUFFER_TOKEN; | 
|  | } | 
|  |  | 
|  | out_buf->pBuffers[0].cbBuffer = sspi_data->max_token; | 
|  |  | 
|  | ret = pInitializeSecurityContextA(first?&sspi_data->cred:NULL, first?NULL:&sspi_data->ctxt, NULL, req_attr, | 
|  | 0, data_rep, first?NULL:in_buf, 0, &sspi_data->ctxt, out_buf, | 
|  | &ctxt_attr, &ttl); | 
|  |  | 
|  | if(ret == SEC_I_COMPLETE_AND_CONTINUE || ret == SEC_I_COMPLETE_NEEDED) | 
|  | { | 
|  | pCompleteAuthToken(&sspi_data->ctxt, out_buf); | 
|  | if(ret == SEC_I_COMPLETE_AND_CONTINUE) | 
|  | ret = SEC_I_CONTINUE_NEEDED; | 
|  | else if(ret == SEC_I_COMPLETE_NEEDED) | 
|  | ret = SEC_E_OK; | 
|  | } | 
|  |  | 
|  | ok(out_buf->pBuffers[0].BufferType == SECBUFFER_TOKEN, | 
|  | "buffer type was changed from SECBUFFER_TOKEN to %d\n", out_buf->pBuffers[0].BufferType); | 
|  | ok(out_buf->pBuffers[0].cbBuffer < sspi_data->max_token, | 
|  | "InitializeSecurityContext set buffer size to %u\n", out_buf->pBuffers[0].cbBuffer); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static SECURITY_STATUS runServer(SspiData *sspi_data, BOOL first, ULONG data_rep) | 
|  | { | 
|  | SECURITY_STATUS ret; | 
|  | ULONG ctxt_attr; | 
|  | TimeStamp ttl; | 
|  |  | 
|  | trace("Running the server the %s time\n", first?"first":"second"); | 
|  |  | 
|  | ret = pAcceptSecurityContext(&sspi_data->cred, first?NULL:&sspi_data->ctxt, | 
|  | sspi_data->in_buf, 0, data_rep, &sspi_data->ctxt, | 
|  | sspi_data->out_buf, &ctxt_attr, &ttl); | 
|  |  | 
|  | if(ret == SEC_I_COMPLETE_AND_CONTINUE || ret == SEC_I_COMPLETE_NEEDED) | 
|  | { | 
|  | pCompleteAuthToken(&sspi_data->ctxt, sspi_data->out_buf); | 
|  | if(ret == SEC_I_COMPLETE_AND_CONTINUE) | 
|  | ret = SEC_I_CONTINUE_NEEDED; | 
|  | else if(ret == SEC_I_COMPLETE_NEEDED) | 
|  | ret = SEC_E_OK; | 
|  | } | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static SECURITY_STATUS runFakeServer(SspiData *sspi_data, BOOL first, ULONG data_rep) | 
|  | { | 
|  | trace("Running the fake server the %s time\n", first?"first":"second"); | 
|  |  | 
|  | if(!first) | 
|  | { | 
|  | sspi_data->out_buf->pBuffers[0].cbBuffer = 0; | 
|  | return SEC_E_OK; | 
|  | } | 
|  |  | 
|  | if(data_rep == SECURITY_NATIVE_DREP) | 
|  | { | 
|  | sspi_data->out_buf->pBuffers[0].cbBuffer = sizeof(native_challenge); | 
|  | memcpy(sspi_data->out_buf->pBuffers[0].pvBuffer, native_challenge, | 
|  | sspi_data->out_buf->pBuffers[0].cbBuffer); | 
|  | } | 
|  | else | 
|  | { | 
|  | sspi_data->out_buf->pBuffers[0].cbBuffer = sizeof(network_challenge); | 
|  | memcpy(sspi_data->out_buf->pBuffers[0].pvBuffer, network_challenge, | 
|  | sspi_data->out_buf->pBuffers[0].cbBuffer); | 
|  | } | 
|  |  | 
|  | return SEC_I_CONTINUE_NEEDED; | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static void communicate(SspiData *from, SspiData *to) | 
|  | { | 
|  | if(from->out_buf != NULL && to->in_buf != NULL) | 
|  | { | 
|  | trace("Running communicate.\n"); | 
|  | if((from->out_buf->cBuffers >= 1) && (to->in_buf->cBuffers >= 1)) | 
|  | { | 
|  | if((from->out_buf->pBuffers[0].pvBuffer != NULL) && | 
|  | (to->in_buf->pBuffers[0].pvBuffer != NULL)) | 
|  | { | 
|  | memset(to->in_buf->pBuffers[0].pvBuffer, 0, to->max_token); | 
|  |  | 
|  | memcpy(to->in_buf->pBuffers[0].pvBuffer, | 
|  | from->out_buf->pBuffers[0].pvBuffer, | 
|  | from->out_buf->pBuffers[0].cbBuffer); | 
|  |  | 
|  | to->in_buf->pBuffers[0].cbBuffer = from->out_buf->pBuffers[0].cbBuffer; | 
|  |  | 
|  | memset(from->out_buf->pBuffers[0].pvBuffer, 0, from->max_token); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  | static void testInitializeSecurityContextFlags(void) | 
|  | { | 
|  | SECURITY_STATUS         sec_status; | 
|  | PSecPkgInfo             pkg_info = NULL; | 
|  | SspiData                client; | 
|  | SEC_WINNT_AUTH_IDENTITY id; | 
|  | static char             sec_pkg_name[] = "NTLM", | 
|  | test_user[]    = "testuser", | 
|  | workgroup[]    = "WORKGROUP", | 
|  | test_pass[]    = "testpass"; | 
|  | ULONG                   req_attr, ctxt_attr; | 
|  | TimeStamp               ttl; | 
|  | PBYTE                   packet; | 
|  |  | 
|  | if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info) != SEC_E_OK) | 
|  | { | 
|  | skip("Package not installed, skipping test!\n"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | pFreeContextBuffer(pkg_info); | 
|  | id.User = (unsigned char*) test_user; | 
|  | id.UserLength = strlen((char *) id.User); | 
|  | id.Domain = (unsigned char *) workgroup; | 
|  | id.DomainLength = strlen((char *) id.Domain); | 
|  | id.Password = (unsigned char*) test_pass; | 
|  | id.PasswordLength = strlen((char *) id.Password); | 
|  | id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; | 
|  |  | 
|  | client.id = &id; | 
|  |  | 
|  | if((sec_status = setupClient(&client, sec_pkg_name)) != SEC_E_OK) | 
|  | { | 
|  | skip("Setting up the client returned %s, skipping test!\n", | 
|  | getSecError(sec_status)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | packet = client.out_buf->pBuffers[0].pvBuffer; | 
|  |  | 
|  | /* Due to how the requesting of the flags is implemented in ntlm_auth, | 
|  | * the tests need to be in this order, as there is no way to specify | 
|  | * "I request no special features" in ntlm_auth */ | 
|  |  | 
|  | /* Without any flags, the lowest byte should not have bits 0x20 or 0x10 set*/ | 
|  | req_attr = 0; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok(((packet[12] & 0x10) == 0) && ((packet[12] & 0x20) == 0), | 
|  | "With req_attr == 0, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_CONNECTION, the lowest byte should not have bits 0x20 or 0x10 set*/ | 
|  | req_attr = ISC_REQ_CONNECTION; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok(((packet[12] & 0x10) == 0) && ((packet[12] & 0x20) == 0), | 
|  | "For ISC_REQ_CONNECTION, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_EXTENDED_ERROR, the lowest byte should not have bits 0x20 or 0x10 set*/ | 
|  | req_attr = ISC_REQ_EXTENDED_ERROR; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok(((packet[12] & 0x10) == 0) && ((packet[12] & 0x20) == 0), | 
|  | "For ISC_REQ_EXTENDED_ERROR, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_MUTUAL_AUTH, the lowest byte should not have bits 0x20 or 0x10 set*/ | 
|  | req_attr = ISC_REQ_MUTUAL_AUTH; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok(((packet[12] & 0x10) == 0) && ((packet[12] & 0x20) == 0), | 
|  | "For ISC_REQ_MUTUAL_AUTH, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_USE_DCE_STYLE, the lowest byte should not have bits 0x20 or 0x10 set*/ | 
|  | req_attr = ISC_REQ_USE_DCE_STYLE; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok(((packet[12] & 0x10) == 0) && ((packet[12] & 0x20) == 0), | 
|  | "For ISC_REQ_USE_DCE_STYLE, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_DELEGATE, the lowest byte should not have bits 0x20 or 0x10 set*/ | 
|  | req_attr = ISC_REQ_DELEGATE; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok(((packet[12] & 0x10) == 0) && ((packet[12] & 0x20) == 0), | 
|  | "For ISC_REQ_DELEGATE, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_INTEGRITY, the lowest byte should have bit 0x10 set */ | 
|  | req_attr = ISC_REQ_INTEGRITY; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok((packet[12] & 0x10) != 0, | 
|  | "For ISC_REQ_INTEGRITY, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_REPLAY_DETECT, the lowest byte should have bit 0x10 set */ | 
|  | req_attr = ISC_REQ_REPLAY_DETECT; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok((packet[12] & 0x10) != 0, | 
|  | "For ISC_REQ_REPLAY_DETECT, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_SEQUENCE_DETECT, the lowest byte should have bit 0x10 set */ | 
|  | req_attr = ISC_REQ_SEQUENCE_DETECT; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok((packet[12] & 0x10) != 0, | 
|  | "For ISC_REQ_SEQUENCE_DETECT, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | /* With ISC_REQ_CONFIDENTIALITY, the lowest byte should have bit 0x20 set */ | 
|  | req_attr = ISC_REQ_CONFIDENTIALITY; | 
|  |  | 
|  | if((sec_status = pInitializeSecurityContextA(&client.cred, NULL, NULL, req_attr, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &client.ctxt, client.out_buf, | 
|  | &ctxt_attr, &ttl)) != SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | trace("InitializeSecurityContext returned %s not SEC_I_CONTINUE_NEEDED, aborting.\n", | 
|  | getSecError(sec_status)); | 
|  | goto tISCFend; | 
|  | } | 
|  |  | 
|  | ok((packet[12] & 0x20) != 0, | 
|  | "For ISC_REQ_CONFIDENTIALITY, flags are 0x%02x%02x%02x%02x.\n", | 
|  | packet[15], packet[14], packet[13], packet[12]); | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  |  | 
|  | tISCFend: | 
|  | cleanupBuffers(&client); | 
|  | pFreeCredentialsHandle(&client.cred); | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static void testAuth(ULONG data_rep, BOOL fake) | 
|  | { | 
|  | SECURITY_STATUS         client_stat = SEC_I_CONTINUE_NEEDED; | 
|  | SECURITY_STATUS         server_stat = SEC_I_CONTINUE_NEEDED; | 
|  | SECURITY_STATUS         sec_status; | 
|  | PSecPkgInfo             pkg_info = NULL; | 
|  | BOOL                    first = TRUE; | 
|  | SspiData                client, server; | 
|  | SEC_WINNT_AUTH_IDENTITY id; | 
|  | SecPkgContext_Sizes     ctxt_sizes; | 
|  | static char             sec_pkg_name[] = "NTLM", | 
|  | test_user[] = "testuser", | 
|  | workgroup[] = "WORKGROUP", | 
|  | test_pass[] = "testpass"; | 
|  |  | 
|  | if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info)!= SEC_E_OK) | 
|  | { | 
|  | skip("Package not installed, skipping test.\n"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | pFreeContextBuffer(pkg_info); | 
|  | id.User = (unsigned char*) test_user; | 
|  | id.UserLength = strlen((char *) id.User); | 
|  | id.Domain = (unsigned char *) workgroup; | 
|  | id.DomainLength = strlen((char *) id.Domain); | 
|  | id.Password = (unsigned char*) test_pass; | 
|  | id.PasswordLength = strlen((char *) id.Password); | 
|  | id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; | 
|  |  | 
|  | client.id = &id; | 
|  |  | 
|  | sec_status = setupClient(&client, sec_pkg_name); | 
|  |  | 
|  | if(sec_status != SEC_E_OK) | 
|  | { | 
|  | skip("Error: Setting up the client returned %s, exiting test!\n", | 
|  | getSecError(sec_status)); | 
|  | pFreeCredentialsHandle(&client.cred); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if(fake) | 
|  | sec_status = setupFakeServer(&server, sec_pkg_name); | 
|  | else | 
|  | sec_status = setupServer(&server, sec_pkg_name); | 
|  |  | 
|  | if(sec_status != SEC_E_OK) | 
|  | { | 
|  | skip("Error: Setting up the server returned %s, exiting test!\n", | 
|  | getSecError(sec_status)); | 
|  | pFreeCredentialsHandle(&server.cred); | 
|  | pFreeCredentialsHandle(&client.cred); | 
|  | return; | 
|  | } | 
|  |  | 
|  | while(client_stat == SEC_I_CONTINUE_NEEDED && server_stat == SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | client_stat = runClient(&client, first, data_rep); | 
|  |  | 
|  | ok(client_stat == SEC_E_OK || client_stat == SEC_I_CONTINUE_NEEDED, | 
|  | "Running the client returned %s, more tests will fail.\n", | 
|  | getSecError(client_stat)); | 
|  |  | 
|  | communicate(&client, &server); | 
|  |  | 
|  | if(fake) | 
|  | server_stat = runFakeServer(&server, first, data_rep); | 
|  | else | 
|  | server_stat = runServer(&server, first, data_rep); | 
|  |  | 
|  | ok(server_stat == SEC_E_OK || server_stat == SEC_I_CONTINUE_NEEDED || | 
|  | server_stat == SEC_E_LOGON_DENIED, | 
|  | "Running the server returned %s, more tests will fail from now.\n", | 
|  | getSecError(server_stat)); | 
|  |  | 
|  | communicate(&server, &client); | 
|  | trace("Looping\n"); | 
|  | first = FALSE; | 
|  | } | 
|  |  | 
|  | if(client_stat != SEC_E_OK) | 
|  | { | 
|  | skip("Authentication failed, skipping test.\n"); | 
|  | goto tAuthend; | 
|  | } | 
|  |  | 
|  | sec_status = pQueryContextAttributesA(&client.ctxt, | 
|  | SECPKG_ATTR_SIZES, &ctxt_sizes); | 
|  |  | 
|  | ok(sec_status == SEC_E_OK, | 
|  | "pQueryContextAttributesA(SECPKG_ATTR_SIZES) returned %s\n", | 
|  | getSecError(sec_status)); | 
|  | ok((ctxt_sizes.cbMaxToken == 1904) || (ctxt_sizes.cbMaxToken == 2888), | 
|  | "cbMaxToken should be 1904 or 2888 but is %u\n", | 
|  | ctxt_sizes.cbMaxToken); | 
|  | ok(ctxt_sizes.cbMaxSignature == 16, | 
|  | "cbMaxSignature should be 16 but is %u\n", | 
|  | ctxt_sizes.cbMaxSignature); | 
|  | ok(ctxt_sizes.cbSecurityTrailer == 16, | 
|  | "cbSecurityTrailer should be 16 but is  %u\n", | 
|  | ctxt_sizes.cbSecurityTrailer); | 
|  | ok(ctxt_sizes.cbBlockSize == 0, | 
|  | "cbBlockSize should be 0 but is %u\n", | 
|  | ctxt_sizes.cbBlockSize); | 
|  |  | 
|  | tAuthend: | 
|  | cleanupBuffers(&client); | 
|  | cleanupBuffers(&server); | 
|  |  | 
|  | if(!fake) | 
|  | { | 
|  | sec_status = pDeleteSecurityContext(&server.ctxt); | 
|  | ok(sec_status == SEC_E_OK, "DeleteSecurityContext(server) returned %s\n", | 
|  | getSecError(sec_status)); | 
|  | } | 
|  |  | 
|  | sec_status = pDeleteSecurityContext(&client.ctxt); | 
|  | ok(sec_status == SEC_E_OK, "DeleteSecurityContext(client) returned %s\n", | 
|  | getSecError(sec_status)); | 
|  |  | 
|  | if(!fake) | 
|  | { | 
|  | sec_status = pFreeCredentialsHandle(&server.cred); | 
|  | ok(sec_status == SEC_E_OK, "FreeCredentialsHandle(server) returned %s\n", | 
|  | getSecError(sec_status)); | 
|  | } | 
|  |  | 
|  | sec_status = pFreeCredentialsHandle(&client.cred); | 
|  | ok(sec_status == SEC_E_OK, "FreeCredentialsHandle(client) returned %s\n", | 
|  | getSecError(sec_status)); | 
|  | } | 
|  |  | 
|  | static void testSignSeal(void) | 
|  | { | 
|  | SECURITY_STATUS         client_stat = SEC_I_CONTINUE_NEEDED; | 
|  | SECURITY_STATUS         server_stat = SEC_I_CONTINUE_NEEDED; | 
|  | SECURITY_STATUS         sec_status; | 
|  | PSecPkgInfo             pkg_info = NULL; | 
|  | BOOL                    first = TRUE; | 
|  | SspiData                client, server; | 
|  | SEC_WINNT_AUTH_IDENTITY id; | 
|  | static char             sec_pkg_name[] = "NTLM"; | 
|  | SecBufferDesc           crypt; | 
|  | SecBuffer               data[2], fake_data[2], complex_data[4]; | 
|  | ULONG                   qop = 0; | 
|  | SecPkgContext_Sizes     ctxt_sizes; | 
|  | static char             test_user[] = "testuser", | 
|  | workgroup[] = "WORKGROUP", | 
|  | test_pass[] = "testpass"; | 
|  |  | 
|  | complex_data[1].pvBuffer = complex_data[3].pvBuffer = NULL; | 
|  |  | 
|  | /**************************************************************** | 
|  | * This is basically the same as in testAuth with a fake server, | 
|  | * as we need a valid, authenticated context. | 
|  | */ | 
|  | if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info) != SEC_E_OK) | 
|  | { | 
|  | skip("Package not installed, skipping test.\n"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | pFreeContextBuffer(pkg_info); | 
|  | id.User = (unsigned char*) test_user; | 
|  | id.UserLength = strlen((char *) id.User); | 
|  | id.Domain = (unsigned char *) workgroup; | 
|  | id.DomainLength = strlen((char *) id.Domain); | 
|  | id.Password = (unsigned char*) test_pass; | 
|  | id.PasswordLength = strlen((char *) id.Password); | 
|  | id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; | 
|  |  | 
|  | client.id = &id; | 
|  |  | 
|  | sec_status = setupClient(&client, sec_pkg_name); | 
|  |  | 
|  | if(sec_status != SEC_E_OK) | 
|  | { | 
|  | skip("Error: Setting up the client returned %s, exiting test!\n", | 
|  | getSecError(sec_status)); | 
|  | pFreeCredentialsHandle(&client.cred); | 
|  | return; | 
|  | } | 
|  |  | 
|  | sec_status = setupFakeServer(&server, sec_pkg_name); | 
|  | ok(sec_status == SEC_E_OK, "setupFakeServer returned %s\n", getSecError(sec_status)); | 
|  |  | 
|  | while(client_stat == SEC_I_CONTINUE_NEEDED && server_stat == SEC_I_CONTINUE_NEEDED) | 
|  | { | 
|  | client_stat = runClient(&client, first, SECURITY_NETWORK_DREP); | 
|  |  | 
|  | communicate(&client, &server); | 
|  |  | 
|  | server_stat = runFakeServer(&server, first, SECURITY_NETWORK_DREP); | 
|  |  | 
|  | communicate(&server, &client); | 
|  | trace("Looping\n"); | 
|  | first = FALSE; | 
|  | } | 
|  |  | 
|  | /******************************************** | 
|  | *    Now start with the actual testing     * | 
|  | ********************************************/ | 
|  |  | 
|  | if(pQueryContextAttributesA(&client.ctxt, SECPKG_ATTR_SIZES, | 
|  | &ctxt_sizes) != SEC_E_OK) | 
|  | { | 
|  | skip("Failed to get context sizes, aborting test.\n"); | 
|  | goto end; | 
|  | } | 
|  |  | 
|  | crypt.ulVersion = SECBUFFER_VERSION; | 
|  | crypt.cBuffers = 2; | 
|  |  | 
|  | crypt.pBuffers = fake_data; | 
|  |  | 
|  | fake_data[0].BufferType = SECBUFFER_DATA; | 
|  | fake_data[0].cbBuffer = ctxt_sizes.cbSecurityTrailer; | 
|  | fake_data[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, fake_data[0].cbBuffer); | 
|  |  | 
|  | fake_data[1].BufferType = SECBUFFER_DATA; | 
|  | fake_data[1].cbBuffer = lstrlen(message); | 
|  | fake_data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, fake_data[1].cbBuffer); | 
|  |  | 
|  | sec_status = pMakeSignature(&client.ctxt, 0, &crypt, 0); | 
|  | ok(sec_status == SEC_E_INVALID_TOKEN, | 
|  | "MakeSignature returned %s, not SEC_E_INVALID_TOKEN.\n", | 
|  | getSecError(sec_status)); | 
|  |  | 
|  | crypt.pBuffers = data; | 
|  |  | 
|  | data[0].BufferType = SECBUFFER_TOKEN; | 
|  | data[0].cbBuffer = ctxt_sizes.cbSecurityTrailer; | 
|  | data[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[0].cbBuffer); | 
|  |  | 
|  | data[1].BufferType = SECBUFFER_DATA; | 
|  | data[1].cbBuffer = lstrlen(message); | 
|  | data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[1].cbBuffer); | 
|  | memcpy(data[1].pvBuffer, message, data[1].cbBuffer); | 
|  |  | 
|  | /* As we forced NTLM to fall back to a password-derived session key, | 
|  | * we should get the same signature for our data, no matter if | 
|  | * it is sent by the client or the server | 
|  | */ | 
|  | sec_status = pMakeSignature(&client.ctxt, 0, &crypt, 0); | 
|  | ok(sec_status == SEC_E_OK, "MakeSignature returned %s, not SEC_E_OK.\n", | 
|  | getSecError(sec_status)); | 
|  | ok(!memcmp(crypt.pBuffers[0].pvBuffer, message_signature, | 
|  | crypt.pBuffers[0].cbBuffer), "Signature is not as expected.\n"); | 
|  |  | 
|  | data[0].cbBuffer = sizeof(message_signature); | 
|  |  | 
|  | memcpy(data[0].pvBuffer, crypt_trailer_client, data[0].cbBuffer); | 
|  |  | 
|  | sec_status = pVerifySignature(&client.ctxt, &crypt, 0, &qop); | 
|  | ok(sec_status == SEC_E_MESSAGE_ALTERED, | 
|  | "VerifySignature returned %s, not SEC_E_MESSAGE_ALTERED.\n", | 
|  | getSecError(sec_status)); | 
|  |  | 
|  | memcpy(data[0].pvBuffer, message_signature, data[0].cbBuffer); | 
|  |  | 
|  | sec_status = pVerifySignature(&client.ctxt, &crypt, 0, &qop); | 
|  | ok(sec_status == SEC_E_OK, "VerifySignature returned %s, not SEC_E_OK.\n", | 
|  | getSecError(sec_status)); | 
|  |  | 
|  | sec_status = pEncryptMessage(&client.ctxt, 0, &crypt, 0); | 
|  | if (sec_status == SEC_E_UNSUPPORTED_FUNCTION) | 
|  | { | 
|  | skip("Encrypt message returned SEC_E_UNSUPPORTED_FUNCTION. " | 
|  | "Expected on Vista.\n"); | 
|  | goto end; | 
|  | } | 
|  | ok(sec_status == SEC_E_OK, "EncryptMessage returned %s, not SEC_E_OK.\n", | 
|  | getSecError(sec_status)); | 
|  |  | 
|  | ok(!memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client, | 
|  | crypt.pBuffers[0].cbBuffer), "Crypt trailer not as expected.\n"); | 
|  | if (memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client, | 
|  | crypt.pBuffers[0].cbBuffer)) | 
|  | { | 
|  | int i; | 
|  | for (i = 0; i < crypt.pBuffers[0].cbBuffer; i++) | 
|  | { | 
|  | if (i % 8 == 0) printf("     "); | 
|  | printf("0x%02x,", ((unsigned char *)crypt.pBuffers[0].pvBuffer)[i]); | 
|  | if (i % 8 == 7) printf("\n"); | 
|  | } | 
|  | printf("\n"); | 
|  | } | 
|  | ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client, | 
|  | crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n"); | 
|  | if (memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client, | 
|  | crypt.pBuffers[1].cbBuffer)) | 
|  | { | 
|  | int i; | 
|  | for (i = 0; i < crypt.pBuffers[1].cbBuffer; i++) | 
|  | { | 
|  | if (i % 8 == 0) printf("     "); | 
|  | printf("0x%02x,", ((unsigned char *)crypt.pBuffers[1].pvBuffer)[i]); | 
|  | if (i % 8 == 7) printf("\n"); | 
|  | } | 
|  | printf("\n"); | 
|  | } | 
|  |  | 
|  | data[0].cbBuffer = sizeof(crypt_trailer_server); | 
|  | data[1].cbBuffer = sizeof(crypt_message_server); | 
|  | memcpy(data[0].pvBuffer, crypt_trailer_server, data[0].cbBuffer); | 
|  | memcpy(data[1].pvBuffer, crypt_message_server, data[1].cbBuffer); | 
|  |  | 
|  | sec_status = pDecryptMessage(&client.ctxt, &crypt, 0, &qop); | 
|  |  | 
|  | ok(sec_status == SEC_E_OK, "DecryptMessage returned %s, not SEC_E_OK.\n", | 
|  | getSecError(sec_status)); | 
|  | ok(!memcmp(crypt.pBuffers[1].pvBuffer, message_binary, | 
|  | crypt.pBuffers[1].cbBuffer), | 
|  | "Failed to decrypt message correctly.\n"); | 
|  |  | 
|  | trace("Testing with more than one buffer.\n"); | 
|  |  | 
|  | crypt.cBuffers = sizeof(complex_data)/sizeof(complex_data[0]); | 
|  | crypt.pBuffers = complex_data; | 
|  |  | 
|  | complex_data[0].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; | 
|  | complex_data[0].cbBuffer = sizeof(message_header); | 
|  | complex_data[0].pvBuffer = message_header; | 
|  |  | 
|  | complex_data[1].BufferType = SECBUFFER_DATA; | 
|  | complex_data[1].cbBuffer = lstrlen(message); | 
|  | complex_data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[1].cbBuffer); | 
|  | memcpy(complex_data[1].pvBuffer, message, complex_data[1].cbBuffer); | 
|  |  | 
|  | complex_data[2].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; | 
|  | complex_data[2].cbBuffer = sizeof(message_header); | 
|  | complex_data[2].pvBuffer = message_header; | 
|  |  | 
|  | complex_data[3].BufferType = SECBUFFER_TOKEN; | 
|  | complex_data[3].cbBuffer = ctxt_sizes.cbSecurityTrailer; | 
|  | complex_data[3].pvBuffer = HeapAlloc(GetProcessHeap(), 0, complex_data[3].cbBuffer); | 
|  |  | 
|  | /* We should get a dummy signature again. */ | 
|  | sec_status = pMakeSignature(&client.ctxt, 0, &crypt, 0); | 
|  | ok(sec_status == SEC_E_OK, "MakeSignature returned %s, not SEC_E_OK.\n", | 
|  | getSecError(sec_status)); | 
|  | ok(!memcmp(crypt.pBuffers[3].pvBuffer, message_signature, | 
|  | crypt.pBuffers[3].cbBuffer), "Signature is not as expected.\n"); | 
|  |  | 
|  | /* Being a dummy signature, it will verify right away, as if the server | 
|  | * sent it */ | 
|  | sec_status = pVerifySignature(&client.ctxt, &crypt, 0, &qop); | 
|  | ok(sec_status == SEC_E_OK, "VerifySignature returned %s, not SEC_E_OK\n", | 
|  | getSecError(sec_status)); | 
|  |  | 
|  | sec_status = pEncryptMessage(&client.ctxt, 0, &crypt, 0); | 
|  | ok(sec_status == SEC_E_OK, "EncryptMessage returned %s, not SEC_E_OK.\n", | 
|  | getSecError(sec_status)); | 
|  |  | 
|  | ok(!memcmp(crypt.pBuffers[3].pvBuffer, crypt_trailer_client2, | 
|  | crypt.pBuffers[3].cbBuffer), "Crypt trailer not as expected.\n"); | 
|  | if (memcmp(crypt.pBuffers[3].pvBuffer, crypt_trailer_client2, | 
|  | crypt.pBuffers[3].cbBuffer)) | 
|  | { | 
|  | int i; | 
|  | for (i = 0; i < crypt.pBuffers[3].cbBuffer; i++) | 
|  | { | 
|  | if (i % 8 == 0) printf("     "); | 
|  | printf("0x%02x,", ((unsigned char *)crypt.pBuffers[3].pvBuffer)[i]); | 
|  | if (i % 8 == 7) printf("\n"); | 
|  | } | 
|  | printf("\n"); | 
|  | } | 
|  |  | 
|  | ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client2, | 
|  | crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n"); | 
|  | if (memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client2, | 
|  | crypt.pBuffers[1].cbBuffer)) | 
|  | { | 
|  | int i; | 
|  | for (i = 0; i < crypt.pBuffers[1].cbBuffer; i++) | 
|  | { | 
|  | if (i % 8 == 0) printf("     "); | 
|  | printf("0x%02x,", ((unsigned char *)crypt.pBuffers[1].pvBuffer)[i]); | 
|  | if (i % 8 == 7) printf("\n"); | 
|  | } | 
|  | printf("\n"); | 
|  | } | 
|  |  | 
|  | memcpy(complex_data[1].pvBuffer, crypt_message_server2, complex_data[1].cbBuffer); | 
|  | memcpy(complex_data[3].pvBuffer, crypt_trailer_server2, complex_data[3].cbBuffer); | 
|  |  | 
|  | sec_status = pDecryptMessage(&client.ctxt, &crypt, 0, &qop); | 
|  | ok(sec_status == SEC_E_OK, "DecryptMessage returned %s, not SEC_E_OK.\n", | 
|  | getSecError(sec_status)); | 
|  |  | 
|  |  | 
|  | end: | 
|  | cleanupBuffers(&client); | 
|  | cleanupBuffers(&server); | 
|  |  | 
|  | pDeleteSecurityContext(&client.ctxt); | 
|  | pFreeCredentialsHandle(&client.cred); | 
|  |  | 
|  | HeapFree(GetProcessHeap(), 0, fake_data[0].pvBuffer); | 
|  | HeapFree(GetProcessHeap(), 0, fake_data[1].pvBuffer); | 
|  | HeapFree(GetProcessHeap(), 0, data[0].pvBuffer); | 
|  | HeapFree(GetProcessHeap(), 0, data[1].pvBuffer); | 
|  | HeapFree(GetProcessHeap(), 0, complex_data[1].pvBuffer); | 
|  | HeapFree(GetProcessHeap(), 0, complex_data[3].pvBuffer); | 
|  | } | 
|  |  | 
|  | static void testAcquireCredentialsHandle(void) | 
|  | { | 
|  | CredHandle cred; | 
|  | TimeStamp ttl; | 
|  | static char test_user[] = "testuser", | 
|  | workgroup[] = "WORKGROUP", | 
|  | test_pass[] = "testpass", | 
|  | sec_pkg_name[] = "NTLM"; | 
|  | SECURITY_STATUS ret; | 
|  | SEC_WINNT_AUTH_IDENTITY id; | 
|  | PSecPkgInfo             pkg_info = NULL; | 
|  |  | 
|  | if(pQuerySecurityPackageInfoA(sec_pkg_name, &pkg_info) != SEC_E_OK) | 
|  | { | 
|  | skip("NTLM package not installed, skipping test\n"); | 
|  | return; | 
|  | } | 
|  | pFreeContextBuffer(pkg_info); | 
|  |  | 
|  | id.User = (unsigned char*) test_user; | 
|  | id.UserLength = strlen((char *) id.User); | 
|  | id.Domain = (unsigned char *) workgroup; | 
|  | id.DomainLength = strlen((char *) id.Domain); | 
|  | id.Password = (unsigned char*) test_pass; | 
|  | id.PasswordLength = strlen((char *) id.Password); | 
|  | id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; | 
|  |  | 
|  | ret = pAcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_OUTBOUND, | 
|  | NULL, &id, NULL, NULL, &cred, &ttl); | 
|  | ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", | 
|  | getSecError(ret)); | 
|  | pFreeCredentialsHandle(&cred); | 
|  |  | 
|  | id.DomainLength = 0; | 
|  | ret = pAcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_OUTBOUND, | 
|  | NULL, &id, NULL, NULL, &cred, &ttl); | 
|  | ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", | 
|  | getSecError(ret)); | 
|  | pFreeCredentialsHandle(&cred); | 
|  |  | 
|  | id.Domain = NULL; | 
|  | ret = pAcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_OUTBOUND, | 
|  | NULL, &id, NULL, NULL, &cred, &ttl); | 
|  | ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", | 
|  | getSecError(ret)); | 
|  | pFreeCredentialsHandle(&cred); | 
|  |  | 
|  | id.Domain = (unsigned char *) workgroup; | 
|  | id.DomainLength = strlen((char *) id.Domain); | 
|  | id.UserLength = 0; | 
|  | id.User = NULL; | 
|  | ret = pAcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_OUTBOUND, | 
|  | NULL, &id, NULL, NULL, &cred, &ttl); | 
|  | ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", | 
|  | getSecError(ret)); | 
|  | pFreeCredentialsHandle(&cred); | 
|  |  | 
|  | id.User = (unsigned char*) test_user; | 
|  | id.UserLength = strlen((char *) id.User); | 
|  | id.Password = NULL; | 
|  | id.PasswordLength = 0; | 
|  | ret = pAcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_OUTBOUND, | 
|  | NULL, &id, NULL, NULL, &cred, &ttl); | 
|  | ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", | 
|  | getSecError(ret)); | 
|  | pFreeCredentialsHandle(&cred); | 
|  | } | 
|  |  | 
|  | static void test_cred_multiple_use(void) | 
|  | { | 
|  | static char test_user[] = "testuser", | 
|  | workgroup[] = "WORKGROUP", | 
|  | test_pass[] = "testpass", | 
|  | sec_pkg_name[] = "NTLM"; | 
|  | SECURITY_STATUS ret; | 
|  | SEC_WINNT_AUTH_IDENTITY id; | 
|  | PSecPkgInfo             pkg_info = NULL; | 
|  | CredHandle              cred; | 
|  | CtxtHandle              ctxt1; | 
|  | CtxtHandle              ctxt2; | 
|  | SecBufferDesc           buffer_desc; | 
|  | SecBuffer               buffers[1]; | 
|  | ULONG                   ctxt_attr; | 
|  | TimeStamp               ttl; | 
|  |  | 
|  | if(pQuerySecurityPackageInfoA(sec_pkg_name, &pkg_info) != SEC_E_OK) | 
|  | { | 
|  | skip("NTLM package not installed, skipping test\n"); | 
|  | return; | 
|  | } | 
|  | buffers[0].cbBuffer = pkg_info->cbMaxToken; | 
|  | buffers[0].BufferType = SECBUFFER_TOKEN; | 
|  | buffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, buffers[0].cbBuffer); | 
|  |  | 
|  | pFreeContextBuffer(pkg_info); | 
|  |  | 
|  | id.User = (unsigned char*) test_user; | 
|  | id.UserLength = strlen((char *) id.User); | 
|  | id.Domain = (unsigned char *) workgroup; | 
|  | id.DomainLength = strlen((char *) id.Domain); | 
|  | id.Password = (unsigned char*) test_pass; | 
|  | id.PasswordLength = strlen((char *) id.Password); | 
|  | id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; | 
|  |  | 
|  | ret = pAcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_OUTBOUND, | 
|  | NULL, &id, NULL, NULL, &cred, &ttl); | 
|  | ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n", | 
|  | getSecError(ret)); | 
|  |  | 
|  | buffer_desc.ulVersion = SECBUFFER_VERSION; | 
|  | buffer_desc.cBuffers = sizeof(buffers)/sizeof(buffers[0]); | 
|  | buffer_desc.pBuffers = buffers; | 
|  |  | 
|  | ret = pInitializeSecurityContextA(&cred, NULL, NULL, ISC_REQ_CONNECTION, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &ctxt1, &buffer_desc, | 
|  | &ctxt_attr, &ttl); | 
|  | ok(ret == SEC_I_CONTINUE_NEEDED, "InitializeSecurityContextA failed with error 0x%x\n", ret); | 
|  |  | 
|  | ret = pInitializeSecurityContextA(&cred, NULL, NULL, ISC_REQ_CONNECTION, | 
|  | 0, SECURITY_NETWORK_DREP, NULL, 0, &ctxt2, &buffer_desc, | 
|  | &ctxt_attr, &ttl); | 
|  | ok(ret == SEC_I_CONTINUE_NEEDED, "Second InitializeSecurityContextA on cred handle failed with error 0x%x\n", ret); | 
|  |  | 
|  | ret = pDeleteSecurityContext(&ctxt1); | 
|  | ok(ret == SEC_E_OK, "DeleteSecurityContext failed with error 0x%x\n", ret); | 
|  | ret = pDeleteSecurityContext(&ctxt2); | 
|  | ok(ret == SEC_E_OK, "DeleteSecurityContext failed with error 0x%x\n", ret); | 
|  | ret = pFreeCredentialsHandle(&cred); | 
|  | ok(ret == SEC_E_OK, "FreeCredentialsHandle failed with error 0x%x\n", ret); | 
|  |  | 
|  | HeapFree(GetProcessHeap(), 0, buffers[0].pvBuffer); | 
|  | } | 
|  |  | 
|  | static void test_null_auth_data(void) | 
|  | { | 
|  | SECURITY_STATUS status; | 
|  | PSecPkgInfo info; | 
|  | CredHandle cred; | 
|  | CtxtHandle ctx; | 
|  | SecBufferDesc buffer_desc; | 
|  | SecBuffer buffers[1]; | 
|  | char user[256]; | 
|  | TimeStamp ttl; | 
|  | ULONG attr, size; | 
|  | BOOLEAN ret; | 
|  |  | 
|  | if(pQuerySecurityPackageInfoA((SEC_CHAR *)"NTLM", &info) != SEC_E_OK) | 
|  | { | 
|  | skip("NTLM package not installed, skipping test\n"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)"NTLM", SECPKG_CRED_OUTBOUND, | 
|  | NULL, NULL, NULL, NULL, &cred, &ttl); | 
|  | ok(status == SEC_E_OK, "AcquireCredentialsHande() failed %s\n", getSecError(status)); | 
|  |  | 
|  | buffers[0].cbBuffer = info->cbMaxToken; | 
|  | buffers[0].BufferType = SECBUFFER_TOKEN; | 
|  | buffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, buffers[0].cbBuffer); | 
|  |  | 
|  | buffer_desc.ulVersion = SECBUFFER_VERSION; | 
|  | buffer_desc.cBuffers = sizeof(buffers)/sizeof(buffers[0]); | 
|  | buffer_desc.pBuffers = buffers; | 
|  |  | 
|  | size = sizeof(user); | 
|  | ret = pGetUserNameExA(NameSamCompatible, user, &size); | 
|  | ok(ret, "GetUserNameExA failed %u\n", GetLastError()); | 
|  |  | 
|  | status = pInitializeSecurityContextA(&cred, NULL, (SEC_CHAR *)user, | 
|  | ISC_REQ_CONNECTION, 0, SECURITY_NETWORK_DREP, | 
|  | NULL, 0, &ctx, &buffer_desc, &attr, &ttl); | 
|  | ok(status == SEC_I_CONTINUE_NEEDED, "InitializeSecurityContextA failed %s\n", getSecError(status)); | 
|  |  | 
|  | ret = pDeleteSecurityContext(&ctx); | 
|  | ok(ret == SEC_E_OK, "DeleteSecurityContext failed with error 0x%x\n", ret); | 
|  | ret = pFreeCredentialsHandle(&cred); | 
|  | ok(ret == SEC_E_OK, "FreeCredentialsHandle failed with error 0x%x\n", ret); | 
|  |  | 
|  | pFreeContextBuffer(info); | 
|  | HeapFree(GetProcessHeap(), 0, buffers[0].pvBuffer); | 
|  | } | 
|  |  | 
|  | START_TEST(ntlm) | 
|  | { | 
|  | InitFunctionPtrs(); | 
|  |  | 
|  | if(pFreeCredentialsHandle && pDeleteSecurityContext && | 
|  | pDeleteSecurityContext && pAcquireCredentialsHandleA && | 
|  | pInitializeSecurityContextA && pCompleteAuthToken && | 
|  | pQuerySecurityPackageInfoA) | 
|  | { | 
|  | testAcquireCredentialsHandle(); | 
|  | testInitializeSecurityContextFlags(); | 
|  | if(pAcceptSecurityContext) | 
|  | { | 
|  | testAuth(SECURITY_NATIVE_DREP, TRUE); | 
|  | testAuth(SECURITY_NETWORK_DREP, TRUE); | 
|  | testAuth(SECURITY_NATIVE_DREP, FALSE); | 
|  | testAuth(SECURITY_NETWORK_DREP, FALSE); | 
|  | } | 
|  | if(pMakeSignature && pVerifySignature && pEncryptMessage && | 
|  | pDecryptMessage) | 
|  | testSignSeal(); | 
|  |  | 
|  | test_cred_multiple_use(); | 
|  | if (pGetUserNameExA) test_null_auth_data(); | 
|  | } | 
|  | else | 
|  | win_skip("Needed functions are not available\n"); | 
|  |  | 
|  | if(secdll) | 
|  | FreeLibrary(secdll); | 
|  | } |