Blame winpr/libwinpr/sspi/NTLM/ntlm.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * NTLM Security Package
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/sspi.h>
Packit 1fb8d4
#include <winpr/print.h>
Packit 1fb8d4
#include <winpr/tchar.h>
Packit 1fb8d4
#include <winpr/sysinfo.h>
Packit 1fb8d4
#include <winpr/registry.h>
Packit 1fb8d4
#include <winpr/endian.h>
Packit 1fb8d4
#include <freerdp/build-config.h>
Packit 1fb8d4
Packit 1fb8d4
#include "ntlm.h"
Packit 1fb8d4
#include "../sspi.h"
Packit 1fb8d4
Packit 1fb8d4
#include "ntlm_message.h"
Packit 1fb8d4
Packit 1fb8d4
#include "../../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("sspi.NTLM")
Packit 1fb8d4
Packit Service 5a9772
#define WINPR_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\WinPR\\NTLM"
Packit 1fb8d4
Packit 1fb8d4
static const char* NTLM_PACKAGE_NAME = "NTLM";
Packit 1fb8d4
Packit 1fb8d4
static int ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	char* ws = Workstation;
Packit 1fb8d4
	DWORD nSize = 0;
Packit 1fb8d4
	CHAR* computerName;
Packit 1fb8d4
Packit 1fb8d4
	if (!Workstation)
Packit 1fb8d4
	{
Packit Service 5a9772
		if (GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize) ||
Packit Service 5a9772
		    GetLastError() != ERROR_MORE_DATA)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		computerName = calloc(nSize, sizeof(CHAR));
Packit 1fb8d4
Packit 1fb8d4
		if (!computerName)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize))
Packit 1fb8d4
		{
Packit 1fb8d4
			free(computerName);
Packit 1fb8d4
			return -1;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (nSize > MAX_COMPUTERNAME_LENGTH)
Packit 1fb8d4
			computerName[MAX_COMPUTERNAME_LENGTH] = '\0';
Packit 1fb8d4
Packit 1fb8d4
		ws = computerName;
Packit 1fb8d4
Packit 1fb8d4
		if (!ws)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	context->Workstation.Buffer = NULL;
Packit 1fb8d4
	status = ConvertToUnicode(CP_UTF8, 0, ws, -1, &context->Workstation.Buffer, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (!Workstation)
Packit 1fb8d4
		free(ws);
Packit 1fb8d4
Packit 1fb8d4
	if (status <= 0)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	context->Workstation.Length = (USHORT)(status - 1);
Packit 1fb8d4
	context->Workstation.Length *= 2;
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePrincipalName)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!ServicePrincipalName)
Packit 1fb8d4
	{
Packit 1fb8d4
		context->ServicePrincipalName.Buffer = NULL;
Packit 1fb8d4
		context->ServicePrincipalName.Length = 0;
Packit 1fb8d4
		return 1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	context->ServicePrincipalName.Length = (USHORT)(_wcslen(ServicePrincipalName) * 2);
Packit Service 5a9772
	context->ServicePrincipalName.Buffer = (PWSTR)malloc(context->ServicePrincipalName.Length + 2);
Packit 1fb8d4
Packit 1fb8d4
	if (!context->ServicePrincipalName.Buffer)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(context->ServicePrincipalName.Buffer, ServicePrincipalName,
Packit 1fb8d4
	           context->ServicePrincipalName.Length + 2);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	char* name = TargetName;
Packit 1fb8d4
	DWORD nSize = 0;
Packit 1fb8d4
	CHAR* computerName = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!name)
Packit 1fb8d4
	{
Packit Service 5a9772
		if (GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize) ||
Packit Service 5a9772
		    GetLastError() != ERROR_MORE_DATA)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		computerName = calloc(nSize, sizeof(CHAR));
Packit 1fb8d4
Packit 1fb8d4
		if (!computerName)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize))
Packit 1fb8d4
		{
Packit 1fb8d4
			free(computerName);
Packit 1fb8d4
			return -1;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (nSize > MAX_COMPUTERNAME_LENGTH)
Packit 1fb8d4
			computerName[MAX_COMPUTERNAME_LENGTH] = '\0';
Packit 1fb8d4
Packit 1fb8d4
		name = computerName;
Packit 1fb8d4
Packit 1fb8d4
		if (!name)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		CharUpperA(name);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	context->TargetName.pvBuffer = NULL;
Packit Service 5a9772
	status = ConvertToUnicode(CP_UTF8, 0, name, -1, (LPWSTR*)&context->TargetName.pvBuffer, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (status <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!TargetName)
Packit 1fb8d4
			free(name);
Packit 1fb8d4
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	context->TargetName.cbBuffer = (USHORT)((status - 1) * 2);
Packit 1fb8d4
Packit 1fb8d4
	if (!TargetName)
Packit 1fb8d4
		free(name);
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static NTLM_CONTEXT* ntlm_ContextNew(void)
Packit 1fb8d4
{
Packit 1fb8d4
	HKEY hKey;
Packit 1fb8d4
	LONG status;
Packit 1fb8d4
	DWORD dwType;
Packit 1fb8d4
	DWORD dwSize;
Packit 1fb8d4
	DWORD dwValue;
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit Service 5a9772
	context = (NTLM_CONTEXT*)calloc(1, sizeof(NTLM_CONTEXT));
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	context->NTLMv2 = TRUE;
Packit 1fb8d4
	context->UseMIC = FALSE;
Packit 1fb8d4
	context->SendVersionInfo = TRUE;
Packit 1fb8d4
	context->SendSingleHostData = FALSE;
Packit 1fb8d4
	context->SendWorkstationName = TRUE;
Packit 1fb8d4
	context->NegotiateKeyExchange = TRUE;
Packit 1fb8d4
	context->UseSamFileDatabase = TRUE;
Packit 1fb8d4
	status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WINPR_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
Packit 1fb8d4
Packit 1fb8d4
	if (status == ERROR_SUCCESS)
Packit 1fb8d4
	{
Packit Service 5a9772
		if (RegQueryValueEx(hKey, _T("NTLMv2"), NULL, &dwType, (BYTE*)&dwValue, &dwSize) ==
Packit Service 5a9772
		    ERROR_SUCCESS)
Packit 1fb8d4
			context->NTLMv2 = dwValue ? 1 : 0;
Packit 1fb8d4
Packit Service 5a9772
		if (RegQueryValueEx(hKey, _T("UseMIC"), NULL, &dwType, (BYTE*)&dwValue, &dwSize) ==
Packit Service 5a9772
		    ERROR_SUCCESS)
Packit 1fb8d4
			context->UseMIC = dwValue ? 1 : 0;
Packit 1fb8d4
Packit Service 5a9772
		if (RegQueryValueEx(hKey, _T("SendVersionInfo"), NULL, &dwType, (BYTE*)&dwValue, &dwSize) ==
Packit Service 5a9772
		    ERROR_SUCCESS)
Packit 1fb8d4
			context->SendVersionInfo = dwValue ? 1 : 0;
Packit 1fb8d4
Packit Service 5a9772
		if (RegQueryValueEx(hKey, _T("SendSingleHostData"), NULL, &dwType, (BYTE*)&dwValue,
Packit 1fb8d4
		                    &dwSize) == ERROR_SUCCESS)
Packit 1fb8d4
			context->SendSingleHostData = dwValue ? 1 : 0;
Packit 1fb8d4
Packit Service 5a9772
		if (RegQueryValueEx(hKey, _T("SendWorkstationName"), NULL, &dwType, (BYTE*)&dwValue,
Packit 1fb8d4
		                    &dwSize) == ERROR_SUCCESS)
Packit 1fb8d4
			context->SendWorkstationName = dwValue ? 1 : 0;
Packit 1fb8d4
Packit Service 5a9772
		if (RegQueryValueEx(hKey, _T("WorkstationName"), NULL, &dwType, NULL, &dwSize) ==
Packit Service 5a9772
		    ERROR_SUCCESS)
Packit 1fb8d4
		{
Packit Service 5a9772
			char* workstation = (char*)malloc(dwSize + 1);
Packit 1fb8d4
Packit 1fb8d4
			if (!workstation)
Packit 1fb8d4
			{
Packit 1fb8d4
				free(context);
Packit 1fb8d4
				return NULL;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit Service 5a9772
			status = RegQueryValueExA(hKey, "WorkstationName", NULL, &dwType, (BYTE*)workstation,
Packit Service 5a9772
			                          &dwSize);
Packit 1fb8d4
			workstation[dwSize] = '\0';
Packit 1fb8d4
Packit 1fb8d4
			if (ntlm_SetContextWorkstation(context, workstation) < 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				free(workstation);
Packit 1fb8d4
				free(context);
Packit 1fb8d4
				return NULL;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			free(workstation);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		RegCloseKey(hKey);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/*
Packit 1fb8d4
	 * Extended Protection is enabled by default in Windows 7,
Packit 1fb8d4
	 * but enabling it in WinPR breaks TS Gateway at this point
Packit 1fb8d4
	 */
Packit 1fb8d4
	context->SuppressExtendedProtection = FALSE;
Packit 1fb8d4
	status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\LSA"), 0,
Packit 1fb8d4
	                      KEY_READ | KEY_WOW64_64KEY, &hKey);
Packit 1fb8d4
Packit 1fb8d4
	if (status == ERROR_SUCCESS)
Packit 1fb8d4
	{
Packit Service 5a9772
		if (RegQueryValueEx(hKey, _T("SuppressExtendedProtection"), NULL, &dwType, (BYTE*)&dwValue,
Packit 1fb8d4
		                    &dwSize) == ERROR_SUCCESS)
Packit 1fb8d4
			context->SuppressExtendedProtection = dwValue ? 1 : 0;
Packit 1fb8d4
Packit 1fb8d4
		RegCloseKey(hKey);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	context->NegotiateFlags = 0;
Packit 1fb8d4
	context->LmCompatibilityLevel = 3;
Packit 1fb8d4
	context->state = NTLM_STATE_INITIAL;
Packit 1fb8d4
	FillMemory(context->MachineID, sizeof(context->MachineID), 0xAA);
Packit 1fb8d4
Packit 1fb8d4
	if (context->NTLMv2)
Packit 1fb8d4
		context->UseMIC = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	return context;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void ntlm_ContextFree(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	winpr_RC4_Free(context->SendRc4Seal);
Packit 1fb8d4
	winpr_RC4_Free(context->RecvRc4Seal);
Packit 1fb8d4
	sspi_SecBufferFree(&context->NegotiateMessage);
Packit 1fb8d4
	sspi_SecBufferFree(&context->ChallengeMessage);
Packit 1fb8d4
	sspi_SecBufferFree(&context->AuthenticateMessage);
Packit 1fb8d4
	sspi_SecBufferFree(&context->ChallengeTargetInfo);
Packit 1fb8d4
	sspi_SecBufferFree(&context->TargetName);
Packit 1fb8d4
	sspi_SecBufferFree(&context->NtChallengeResponse);
Packit 1fb8d4
	sspi_SecBufferFree(&context->LmChallengeResponse);
Packit 1fb8d4
	free(context->ServicePrincipalName.Buffer);
Packit 1fb8d4
	free(context->Workstation.Buffer);
Packit 1fb8d4
	free(context);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(
Packit Service 5a9772
    SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
Packit Service 5a9772
    void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
Packit Service 5a9772
    PTimeStamp ptsExpiry)
Packit 1fb8d4
{
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials;
Packit 1fb8d4
	SEC_WINNT_AUTH_IDENTITY* identity;
Packit 1fb8d4
Packit Service 5a9772
	if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && (fCredentialUse != SECPKG_CRED_INBOUND) &&
Packit 1fb8d4
	    (fCredentialUse != SECPKG_CRED_BOTH))
Packit 1fb8d4
	{
Packit 1fb8d4
		return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	credentials = sspi_CredentialsNew();
Packit 1fb8d4
Packit 1fb8d4
	if (!credentials)
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit 1fb8d4
	credentials->fCredentialUse = fCredentialUse;
Packit 1fb8d4
	credentials->pGetKeyFn = pGetKeyFn;
Packit 1fb8d4
	credentials->pvGetKeyArgument = pvGetKeyArgument;
Packit Service 5a9772
	identity = (SEC_WINNT_AUTH_IDENTITY*)pAuthData;
Packit 1fb8d4
Packit 1fb8d4
	if (identity)
Packit 1fb8d4
		sspi_CopyAuthIdentity(&(credentials->identity), identity);
Packit 1fb8d4
Packit Service 5a9772
	sspi_SecureHandleSetLowerPointer(phCredential, (void*)credentials);
Packit Service 5a9772
	sspi_SecureHandleSetUpperPointer(phCredential, (void*)NTLM_PACKAGE_NAME);
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(
Packit Service 5a9772
    SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
Packit Service 5a9772
    void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
Packit Service 5a9772
    PTimeStamp ptsExpiry)
Packit 1fb8d4
{
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials;
Packit 1fb8d4
	SEC_WINNT_AUTH_IDENTITY* identity;
Packit 1fb8d4
Packit Service 5a9772
	if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && (fCredentialUse != SECPKG_CRED_INBOUND) &&
Packit 1fb8d4
	    (fCredentialUse != SECPKG_CRED_BOTH))
Packit 1fb8d4
	{
Packit 1fb8d4
		return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	credentials = sspi_CredentialsNew();
Packit 1fb8d4
Packit 1fb8d4
	if (!credentials)
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit 1fb8d4
	credentials->fCredentialUse = fCredentialUse;
Packit 1fb8d4
	credentials->pGetKeyFn = pGetKeyFn;
Packit 1fb8d4
	credentials->pvGetKeyArgument = pvGetKeyArgument;
Packit Service 5a9772
	identity = (SEC_WINNT_AUTH_IDENTITY*)pAuthData;
Packit 1fb8d4
Packit 1fb8d4
	if (identity)
Packit 1fb8d4
		sspi_CopyAuthIdentity(&(credentials->identity), identity);
Packit 1fb8d4
Packit Service 5a9772
	sspi_SecureHandleSetLowerPointer(phCredential, (void*)credentials);
Packit Service 5a9772
	sspi_SecureHandleSetUpperPointer(phCredential, (void*)NTLM_PACKAGE_NAME);
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential)
Packit 1fb8d4
{
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials;
Packit 1fb8d4
Packit 1fb8d4
	if (!phCredential)
Packit 1fb8d4
		return SEC_E_INVALID_HANDLE;
Packit 1fb8d4
Packit Service 5a9772
	credentials = (SSPI_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
Packit 1fb8d4
Packit 1fb8d4
	if (!credentials)
Packit 1fb8d4
		return SEC_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	sspi_CredentialsFree(credentials);
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(PCredHandle phCredential,
Packit Service 5a9772
                                                                  ULONG ulAttribute, void* pBuffer)
Packit 1fb8d4
{
Packit 1fb8d4
	if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
Packit 1fb8d4
	{
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return SEC_E_UNSUPPORTED_FUNCTION;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredential,
Packit Service 5a9772
                                                                  ULONG ulAttribute, void* pBuffer)
Packit 1fb8d4
{
Packit 1fb8d4
	return ntlm_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa374707
Packit 1fb8d4
 */
Packit Service 5a9772
static SECURITY_STATUS SEC_ENTRY
Packit Service 5a9772
ntlm_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
Packit Service 5a9772
                           ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
Packit Service 5a9772
                           PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
Packit 1fb8d4
{
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit 1fb8d4
	SECURITY_STATUS status;
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials;
Packit 1fb8d4
	PSecBuffer input_buffer;
Packit 1fb8d4
	PSecBuffer output_buffer;
Packit Service 5a9772
	context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
	{
Packit 1fb8d4
		context = ntlm_ContextNew();
Packit 1fb8d4
Packit 1fb8d4
		if (!context)
Packit 1fb8d4
			return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
		context->server = TRUE;
Packit 1fb8d4
Packit 1fb8d4
		if (fContextReq & ASC_REQ_CONFIDENTIALITY)
Packit 1fb8d4
			context->confidentiality = TRUE;
Packit 1fb8d4
Packit Service 5a9772
		credentials = (SSPI_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
Packit 1fb8d4
		context->credentials = credentials;
Packit 1fb8d4
		ntlm_SetContextTargetName(context, NULL);
Packit 1fb8d4
		sspi_SecureHandleSetLowerPointer(phNewContext, context);
Packit Service 5a9772
		sspi_SecureHandleSetUpperPointer(phNewContext, (void*)NTLM_PACKAGE_NAME);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (context->state == NTLM_STATE_INITIAL)
Packit 1fb8d4
	{
Packit 1fb8d4
		context->state = NTLM_STATE_NEGOTIATE;
Packit 1fb8d4
Packit 1fb8d4
		if (!pInput)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		if (pInput->cBuffers < 1)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
Packit 1fb8d4
Packit 1fb8d4
		if (!input_buffer)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		if (input_buffer->cbBuffer < 1)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		status = ntlm_read_NegotiateMessage(context, input_buffer);
Packit 1fb8d4
Packit 1fb8d4
		if (context->state == NTLM_STATE_CHALLENGE)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!pOutput)
Packit 1fb8d4
				return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
			if (pOutput->cBuffers < 1)
Packit 1fb8d4
				return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
			output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
Packit 1fb8d4
Packit 1fb8d4
			if (!output_buffer->BufferType)
Packit 1fb8d4
				return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
			if (output_buffer->cbBuffer < 1)
Packit 1fb8d4
				return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
			return ntlm_write_ChallengeMessage(context, output_buffer);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		return SEC_E_OUT_OF_SEQUENCE;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (context->state == NTLM_STATE_AUTHENTICATE)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!pInput)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		if (pInput->cBuffers < 1)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
Packit 1fb8d4
Packit 1fb8d4
		if (!input_buffer)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		if (input_buffer->cbBuffer < 1)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		status = ntlm_read_AuthenticateMessage(context, input_buffer);
Packit 1fb8d4
Packit 1fb8d4
		if (pOutput)
Packit 1fb8d4
		{
Packit 1fb8d4
			ULONG i;
Packit 1fb8d4
Packit 1fb8d4
			for (i = 0; i < pOutput->cBuffers; i++)
Packit 1fb8d4
			{
Packit 1fb8d4
				pOutput->pBuffers[i].cbBuffer = 0;
Packit 1fb8d4
				pOutput->pBuffers[i].BufferType = SECBUFFER_TOKEN;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		return status;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return SEC_E_OUT_OF_SEQUENCE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_ImpersonateSecurityContext(PCtxtHandle phContext)
Packit 1fb8d4
{
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(
Packit Service 5a9772
    PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
Packit Service 5a9772
    ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
Packit Service 5a9772
    PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
Packit 1fb8d4
{
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit 1fb8d4
	SECURITY_STATUS status;
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials;
Packit 1fb8d4
	PSecBuffer input_buffer = NULL;
Packit 1fb8d4
	PSecBuffer output_buffer = NULL;
Packit 1fb8d4
	PSecBuffer channel_bindings = NULL;
Packit Service 5a9772
	context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
	{
Packit 1fb8d4
		context = ntlm_ContextNew();
Packit 1fb8d4
Packit 1fb8d4
		if (!context)
Packit 1fb8d4
			return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
		if (fContextReq & ISC_REQ_CONFIDENTIALITY)
Packit 1fb8d4
			context->confidentiality = TRUE;
Packit 1fb8d4
Packit Service 5a9772
		credentials = (SSPI_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
Packit 1fb8d4
		context->credentials = credentials;
Packit 1fb8d4
Packit 1fb8d4
		if (context->Workstation.Length < 1)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (ntlm_SetContextWorkstation(context, NULL) < 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				ntlm_ContextFree(context);
Packit 1fb8d4
				return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (ntlm_SetContextServicePrincipalNameW(context, pszTargetName) < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			ntlm_ContextFree(context);
Packit 1fb8d4
			return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		sspi_SecureHandleSetLowerPointer(phNewContext, context);
Packit Service 5a9772
		sspi_SecureHandleSetUpperPointer(phNewContext, (void*)NTLM_PACKAGE_NAME);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if ((!pInput) || (context->state == NTLM_STATE_AUTHENTICATE))
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!pOutput)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		if (pOutput->cBuffers < 1)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
Packit 1fb8d4
Packit 1fb8d4
		if (!output_buffer)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		if (output_buffer->cbBuffer < 1)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		if (context->state == NTLM_STATE_INITIAL)
Packit 1fb8d4
			context->state = NTLM_STATE_NEGOTIATE;
Packit 1fb8d4
Packit 1fb8d4
		if (context->state == NTLM_STATE_NEGOTIATE)
Packit 1fb8d4
			return ntlm_write_NegotiateMessage(context, output_buffer);
Packit 1fb8d4
Packit 1fb8d4
		return SEC_E_OUT_OF_SEQUENCE;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		if (pInput->cBuffers < 1)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
Packit 1fb8d4
Packit 1fb8d4
		if (!input_buffer)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		if (input_buffer->cbBuffer < 1)
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
		channel_bindings = sspi_FindSecBuffer(pInput, SECBUFFER_CHANNEL_BINDINGS);
Packit 1fb8d4
Packit 1fb8d4
		if (channel_bindings)
Packit 1fb8d4
		{
Packit 1fb8d4
			context->Bindings.BindingsLength = channel_bindings->cbBuffer;
Packit Service 5a9772
			context->Bindings.Bindings = (SEC_CHANNEL_BINDINGS*)channel_bindings->pvBuffer;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (context->state == NTLM_STATE_CHALLENGE)
Packit 1fb8d4
		{
Packit 1fb8d4
			status = ntlm_read_ChallengeMessage(context, input_buffer);
Packit 1fb8d4
Packit 1fb8d4
			if (!pOutput)
Packit 1fb8d4
				return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
			if (pOutput->cBuffers < 1)
Packit 1fb8d4
				return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
			output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
Packit 1fb8d4
Packit 1fb8d4
			if (!output_buffer)
Packit 1fb8d4
				return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
			if (output_buffer->cbBuffer < 1)
Packit 1fb8d4
				return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
			if (context->state == NTLM_STATE_AUTHENTICATE)
Packit 1fb8d4
				return ntlm_write_AuthenticateMessage(context, output_buffer);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		return SEC_E_OUT_OF_SEQUENCE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return SEC_E_OUT_OF_SEQUENCE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa375512%28v=vs.85%29.aspx
Packit 1fb8d4
 */
Packit Service 5a9772
static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(
Packit Service 5a9772
    PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq,
Packit Service 5a9772
    ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
Packit Service 5a9772
    PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
Packit 1fb8d4
{
Packit 1fb8d4
	SECURITY_STATUS status;
Packit 1fb8d4
	SEC_WCHAR* pszTargetNameW = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (pszTargetName)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (ConvertToUnicode(CP_UTF8, 0, pszTargetName, -1, &pszTargetNameW, 0) <= 0)
Packit 1fb8d4
			return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	status = ntlm_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq,
Packit Service 5a9772
	                                         Reserved1, TargetDataRep, pInput, Reserved2,
Packit Service 5a9772
	                                         phNewContext, pOutput, pfContextAttr, ptsExpiry);
Packit 1fb8d4
	free(pszTargetNameW);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext,
Packit Service 5a9772
                                                        PSecBufferDesc pToken)
Packit 1fb8d4
{
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit 1fb8d4
	SECURITY_STATUS status = SEC_E_OK;
Packit Service 5a9772
	context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return SEC_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if (context->server)
Packit 1fb8d4
	{
Packit 1fb8d4
		status = ntlm_server_AuthenticateComplete(context);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375354 */
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
Packit 1fb8d4
{
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit Service 5a9772
	context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return SEC_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	ntlm_ContextFree(context);
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_computeProofValue(NTLM_CONTEXT* ntlm, SecBuffer* ntproof)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* blob;
Packit 1fb8d4
	SecBuffer* target = &ntlm->ChallengeTargetInfo;
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(ntproof, 36 + target->cbBuffer))
Packit 1fb8d4
		return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
	blob = (BYTE*)ntproof->pvBuffer;
Packit 1fb8d4
	CopyMemory(blob, ntlm->ServerChallenge, 8); /* Server challenge. */
Packit Service 5a9772
	blob[8] = 1;                                /* Response version. */
Packit 1fb8d4
	blob[9] = 1; /* Highest response version understood by the client. */
Packit 1fb8d4
	/* Reserved 6B. */
Packit Service 5a9772
	CopyMemory(&blob[16], ntlm->Timestamp, 8);       /* Time. */
Packit 1fb8d4
	CopyMemory(&blob[24], ntlm->ClientChallenge, 8); /* Client challenge. */
Packit 1fb8d4
	/* Reserved 4B. */
Packit 1fb8d4
	/* Server name. */
Packit 1fb8d4
	CopyMemory(&blob[36], target->pvBuffer, target->cbBuffer);
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_computeMicValue(NTLM_CONTEXT* ntlm, SecBuffer* micvalue)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* blob;
Packit 1fb8d4
	ULONG msgSize = ntlm->NegotiateMessage.cbBuffer + ntlm->ChallengeMessage.cbBuffer +
Packit 1fb8d4
	                ntlm->AuthenticateMessage.cbBuffer;
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(micvalue, msgSize))
Packit 1fb8d4
		return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit Service 5a9772
	blob = (BYTE*)micvalue->pvBuffer;
Packit 1fb8d4
	CopyMemory(blob, ntlm->NegotiateMessage.pvBuffer, ntlm->NegotiateMessage.cbBuffer);
Packit 1fb8d4
	blob += ntlm->NegotiateMessage.cbBuffer;
Packit 1fb8d4
	CopyMemory(blob, ntlm->ChallengeMessage.pvBuffer, ntlm->ChallengeMessage.cbBuffer);
Packit 1fb8d4
	blob += ntlm->ChallengeMessage.cbBuffer;
Packit 1fb8d4
	CopyMemory(blob, ntlm->AuthenticateMessage.pvBuffer, ntlm->AuthenticateMessage.cbBuffer);
Packit 1fb8d4
	blob += ntlm->MessageIntegrityCheckOffset;
Packit 1fb8d4
	ZeroMemory(blob, 16);
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa379337/ */
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext,
Packit Service 5a9772
                                                              ULONG ulAttribute, void* pBuffer)
Packit 1fb8d4
{
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit 1fb8d4
Packit 1fb8d4
	if (!phContext)
Packit 1fb8d4
		return SEC_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if (!pBuffer)
Packit 1fb8d4
		return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit Service 5a9772
	context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
Packit 1fb8d4
Packit 1fb8d4
	if (ulAttribute == SECPKG_ATTR_SIZES)
Packit 1fb8d4
	{
Packit Service 5a9772
		SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*)pBuffer;
Packit 1fb8d4
		ContextSizes->cbMaxToken = 2010;
Packit Service 5a9772
		ContextSizes->cbMaxSignature = 16;    /* the size of expected signature is 16 bytes */
Packit Service 5a9772
		ContextSizes->cbBlockSize = 0;        /* no padding */
Packit 1fb8d4
		ContextSizes->cbSecurityTrailer = 16; /* no security trailer appended in NTLM
Packit Service 5a9772
		                            contrary to Kerberos */
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_IDENTITY)
Packit 1fb8d4
	{
Packit 1fb8d4
		int status;
Packit 1fb8d4
		char* UserA = NULL;
Packit 1fb8d4
		char* DomainA = NULL;
Packit 1fb8d4
		SSPI_CREDENTIALS* credentials;
Packit Service 5a9772
		SecPkgContext_AuthIdentity* AuthIdentity = (SecPkgContext_AuthIdentity*)pBuffer;
Packit 1fb8d4
		context->UseSamFileDatabase = FALSE;
Packit 1fb8d4
		credentials = context->credentials;
Packit 1fb8d4
		ZeroMemory(AuthIdentity, sizeof(SecPkgContext_AuthIdentity));
Packit 1fb8d4
		UserA = AuthIdentity->User;
Packit 1fb8d4
Packit 1fb8d4
		if (credentials->identity.UserLength > 0)
Packit 1fb8d4
		{
Packit Service 5a9772
			status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)credentials->identity.User,
Packit Service 5a9772
			                            credentials->identity.UserLength, &UserA, 256, NULL, NULL);
Packit 1fb8d4
Packit 1fb8d4
			if (status <= 0)
Packit 1fb8d4
				return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		DomainA = AuthIdentity->Domain;
Packit 1fb8d4
Packit 1fb8d4
		if (credentials->identity.DomainLength > 0)
Packit 1fb8d4
		{
Packit Service 5a9772
			status =
Packit Service 5a9772
			    ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)credentials->identity.Domain,
Packit Service 5a9772
			                       credentials->identity.DomainLength, &DomainA, 256, NULL, NULL);
Packit 1fb8d4
Packit 1fb8d4
			if (status <= 0)
Packit 1fb8d4
				return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_NTPROOF_VALUE)
Packit 1fb8d4
	{
Packit 1fb8d4
		return ntlm_computeProofValue(context, (SecBuffer*)pBuffer);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_RANDKEY)
Packit 1fb8d4
	{
Packit 1fb8d4
		SecBuffer* randkey;
Packit Service 5a9772
		randkey = (SecBuffer*)pBuffer;
Packit 1fb8d4
Packit 1fb8d4
		if (!sspi_SecBufferAlloc(randkey, 16))
Packit 1fb8d4
			return (SEC_E_INSUFFICIENT_MEMORY);
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(randkey->pvBuffer, context->EncryptedRandomSessionKey, 16);
Packit 1fb8d4
		return (SEC_E_OK);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MIC)
Packit 1fb8d4
	{
Packit 1fb8d4
		SecBuffer* mic;
Packit 1fb8d4
		NTLM_AUTHENTICATE_MESSAGE* message;
Packit Service 5a9772
		mic = (SecBuffer*)pBuffer;
Packit 1fb8d4
		message = &context->AUTHENTICATE_MESSAGE;
Packit 1fb8d4
Packit 1fb8d4
		if (!sspi_SecBufferAlloc(mic, 16))
Packit 1fb8d4
			return (SEC_E_INSUFFICIENT_MEMORY);
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(mic->pvBuffer, message->MessageIntegrityCheck, 16);
Packit 1fb8d4
		return (SEC_E_OK);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MIC_VALUE)
Packit 1fb8d4
	{
Packit Service 5a9772
		return ntlm_computeMicValue(context, (SecBuffer*)pBuffer);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return SEC_E_UNSUPPORTED_FUNCTION;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext,
Packit Service 5a9772
                                                              ULONG ulAttribute, void* pBuffer)
Packit 1fb8d4
{
Packit 1fb8d4
	return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(PCtxtHandle phContext,
Packit Service 5a9772
                                                            ULONG ulAttribute, void* pBuffer,
Packit Service 5a9772
                                                            ULONG cbBuffer)
Packit 1fb8d4
{
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit 1fb8d4
Packit 1fb8d4
	if (!phContext)
Packit 1fb8d4
		return SEC_E_INVALID_HANDLE;
Packit 1fb8d4
Packit 1fb8d4
	if (!pBuffer)
Packit 1fb8d4
		return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit Service 5a9772
	context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
Packit 1fb8d4
Packit 1fb8d4
	if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_HASH)
Packit 1fb8d4
	{
Packit Service 5a9772
		SecPkgContext_AuthNtlmHash* AuthNtlmHash = (SecPkgContext_AuthNtlmHash*)pBuffer;
Packit 1fb8d4
Packit 1fb8d4
		if (cbBuffer < sizeof(SecPkgContext_AuthNtlmHash))
Packit 1fb8d4
			return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
		if (AuthNtlmHash->Version == 1)
Packit 1fb8d4
			CopyMemory(context->NtlmHash, AuthNtlmHash->NtlmHash, 16);
Packit 1fb8d4
		else if (AuthNtlmHash->Version == 2)
Packit 1fb8d4
			CopyMemory(context->NtlmV2Hash, AuthNtlmHash->NtlmHash, 16);
Packit 1fb8d4
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_SAM_FILE)
Packit 1fb8d4
	{
Packit Service 5a9772
		const char* filename = (char*)pBuffer;
Packit 1fb8d4
		free(context->SamFile);
Packit 1fb8d4
		context->SamFile = NULL;
Packit 1fb8d4
Packit 1fb8d4
		if (filename)
Packit 1fb8d4
		{
Packit 1fb8d4
			context->SamFile = _strdup(filename);
Packit 1fb8d4
Packit 1fb8d4
			if (!context->SamFile)
Packit 1fb8d4
				return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MESSAGE)
Packit 1fb8d4
	{
Packit Service 5a9772
		SecPkgContext_AuthNtlmMessage* AuthNtlmMessage = (SecPkgContext_AuthNtlmMessage*)pBuffer;
Packit 1fb8d4
Packit 1fb8d4
		if (cbBuffer < sizeof(SecPkgContext_AuthNtlmMessage))
Packit 1fb8d4
			return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
		if (AuthNtlmMessage->type == 1)
Packit 1fb8d4
		{
Packit 1fb8d4
			sspi_SecBufferFree(&context->NegotiateMessage);
Packit 1fb8d4
Packit 1fb8d4
			if (!sspi_SecBufferAlloc(&context->NegotiateMessage, AuthNtlmMessage->length))
Packit 1fb8d4
				return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit Service 5a9772
			CopyMemory(context->NegotiateMessage.pvBuffer, AuthNtlmMessage->buffer,
Packit Service 5a9772
			           AuthNtlmMessage->length);
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (AuthNtlmMessage->type == 2)
Packit 1fb8d4
		{
Packit 1fb8d4
			sspi_SecBufferFree(&context->ChallengeMessage);
Packit 1fb8d4
Packit 1fb8d4
			if (!sspi_SecBufferAlloc(&context->ChallengeMessage, AuthNtlmMessage->length))
Packit 1fb8d4
				return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit Service 5a9772
			CopyMemory(context->ChallengeMessage.pvBuffer, AuthNtlmMessage->buffer,
Packit Service 5a9772
			           AuthNtlmMessage->length);
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (AuthNtlmMessage->type == 3)
Packit 1fb8d4
		{
Packit 1fb8d4
			sspi_SecBufferFree(&context->AuthenticateMessage);
Packit 1fb8d4
Packit 1fb8d4
			if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, AuthNtlmMessage->length))
Packit 1fb8d4
				return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit Service 5a9772
			CopyMemory(context->AuthenticateMessage.pvBuffer, AuthNtlmMessage->buffer,
Packit Service 5a9772
			           AuthNtlmMessage->length);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_TIMESTAMP)
Packit 1fb8d4
	{
Packit Service 5a9772
		SecPkgContext_AuthNtlmTimestamp* AuthNtlmTimestamp =
Packit Service 5a9772
		    (SecPkgContext_AuthNtlmTimestamp*)pBuffer;
Packit 1fb8d4
Packit 1fb8d4
		if (cbBuffer < sizeof(SecPkgContext_AuthNtlmTimestamp))
Packit 1fb8d4
			return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
		if (AuthNtlmTimestamp->ChallengeOrResponse)
Packit 1fb8d4
			CopyMemory(context->ChallengeTimestamp, AuthNtlmTimestamp->Timestamp, 8);
Packit 1fb8d4
		else
Packit 1fb8d4
			CopyMemory(context->Timestamp, AuthNtlmTimestamp->Timestamp, 8);
Packit 1fb8d4
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE)
Packit 1fb8d4
	{
Packit 1fb8d4
		SecPkgContext_AuthNtlmClientChallenge* AuthNtlmClientChallenge =
Packit Service 5a9772
		    (SecPkgContext_AuthNtlmClientChallenge*)pBuffer;
Packit 1fb8d4
Packit 1fb8d4
		if (cbBuffer < sizeof(SecPkgContext_AuthNtlmClientChallenge))
Packit 1fb8d4
			return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(context->ClientChallenge, AuthNtlmClientChallenge->ClientChallenge, 8);
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE)
Packit 1fb8d4
	{
Packit 1fb8d4
		SecPkgContext_AuthNtlmServerChallenge* AuthNtlmServerChallenge =
Packit Service 5a9772
		    (SecPkgContext_AuthNtlmServerChallenge*)pBuffer;
Packit 1fb8d4
Packit 1fb8d4
		if (cbBuffer < sizeof(SecPkgContext_AuthNtlmServerChallenge))
Packit 1fb8d4
			return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(context->ServerChallenge, AuthNtlmServerChallenge->ServerChallenge, 8);
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_HASH_CB)
Packit 1fb8d4
	{
Packit 1fb8d4
		context->HashCallback = (psPeerComputeNtlmHash)pBuffer;
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_HASH_CB_DATA)
Packit 1fb8d4
	{
Packit 1fb8d4
		context->HashCallbackArg = pBuffer;
Packit 1fb8d4
		return SEC_E_OK;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return SEC_E_UNSUPPORTED_FUNCTION;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesA(PCtxtHandle phContext,
Packit Service 5a9772
                                                            ULONG ulAttribute, void* pBuffer,
Packit Service 5a9772
                                                            ULONG cbBuffer)
Packit 1fb8d4
{
Packit 1fb8d4
	return ntlm_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext)
Packit 1fb8d4
{
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
Packit Service 5a9772
                                                     PSecBufferDesc pMessage, ULONG MessageSeqNo)
Packit 1fb8d4
{
Packit 1fb8d4
	int index;
Packit 1fb8d4
	int length;
Packit 1fb8d4
	void* data;
Packit 1fb8d4
	UINT32 SeqNo;
Packit 1fb8d4
	UINT32 value;
Packit 1fb8d4
	BYTE digest[WINPR_MD5_DIGEST_LENGTH];
Packit 1fb8d4
	BYTE checksum[8];
Packit 1fb8d4
	BYTE* signature;
Packit 1fb8d4
	ULONG version = 1;
Packit 1fb8d4
	WINPR_HMAC_CTX* hmac;
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit 1fb8d4
	PSecBuffer data_buffer = NULL;
Packit 1fb8d4
	PSecBuffer signature_buffer = NULL;
Packit 1fb8d4
	SeqNo = MessageSeqNo;
Packit Service 5a9772
	context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
Packit 1fb8d4
Packit Service 5a9772
	for (index = 0; index < (int)pMessage->cBuffers; index++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA)
Packit 1fb8d4
			data_buffer = &pMessage->pBuffers[index];
Packit 1fb8d4
		else if (pMessage->pBuffers[index].BufferType == SECBUFFER_TOKEN)
Packit 1fb8d4
			signature_buffer = &pMessage->pBuffers[index];
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!data_buffer)
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
	if (!signature_buffer)
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
	/* Copy original data buffer */
Packit 1fb8d4
	length = data_buffer->cbBuffer;
Packit 1fb8d4
	data = malloc(length);
Packit 1fb8d4
Packit 1fb8d4
	if (!data)
Packit 1fb8d4
		return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(data, data_buffer->pvBuffer, length);
Packit 1fb8d4
	/* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */
Packit 1fb8d4
	hmac = winpr_HMAC_New();
Packit 1fb8d4
Packit Service 5a9772
	if (hmac &&
Packit Service 5a9772
	    winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->SendSigningKey, WINPR_MD5_DIGEST_LENGTH))
Packit 1fb8d4
	{
Packit 1fb8d4
		Data_Write_UINT32(&value, SeqNo);
Packit Service 5a9772
		winpr_HMAC_Update(hmac, (void*)&value, 4);
Packit Service 5a9772
		winpr_HMAC_Update(hmac, (void*)data, length);
Packit 1fb8d4
		winpr_HMAC_Final(hmac, digest, WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
		winpr_HMAC_Free(hmac);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		winpr_HMAC_Free(hmac);
Packit 1fb8d4
		free(data);
Packit 1fb8d4
		return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Encrypt message using with RC4, result overwrites original buffer */
Packit 1fb8d4
Packit 1fb8d4
	if (context->confidentiality)
Packit Service 5a9772
		winpr_RC4_Update(context->SendRc4Seal, length, (BYTE*)data, (BYTE*)data_buffer->pvBuffer);
Packit 1fb8d4
	else
Packit 1fb8d4
		CopyMemory(data_buffer->pvBuffer, data, length);
Packit 1fb8d4
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "Data Buffer (length = %d)", length);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, data, length);
Packit Service 5a9772
	WLog_DBG(TAG, "Encrypted Data Buffer (length = %" PRIu32 ")", data_buffer->cbBuffer);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, data_buffer->pvBuffer, data_buffer->cbBuffer);
Packit 1fb8d4
#endif
Packit 1fb8d4
	free(data);
Packit 1fb8d4
	/* RC4-encrypt first 8 bytes of digest */
Packit 1fb8d4
	winpr_RC4_Update(context->SendRc4Seal, 8, digest, checksum);
Packit Service 5a9772
	signature = (BYTE*)signature_buffer->pvBuffer;
Packit 1fb8d4
	/* Concatenate version, ciphertext and sequence number to build signature */
Packit 1fb8d4
	Data_Write_UINT32(signature, version);
Packit Service 5a9772
	CopyMemory(&signature[4], (void*)checksum, 8);
Packit 1fb8d4
	Data_Write_UINT32(&signature[12], SeqNo);
Packit 1fb8d4
	context->SendSeqNum++;
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit Service 5a9772
	WLog_DBG(TAG, "Signature (length = %" PRIu32 ")", signature_buffer->cbBuffer);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, signature_buffer->pvBuffer, signature_buffer->cbBuffer);
Packit 1fb8d4
#endif
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage,
Packit Service 5a9772
                                                     ULONG MessageSeqNo, PULONG pfQOP)
Packit 1fb8d4
{
Packit 1fb8d4
	int index;
Packit 1fb8d4
	int length;
Packit 1fb8d4
	void* data;
Packit 1fb8d4
	UINT32 SeqNo;
Packit 1fb8d4
	UINT32 value;
Packit 1fb8d4
	BYTE digest[WINPR_MD5_DIGEST_LENGTH];
Packit 1fb8d4
	BYTE checksum[8];
Packit 1fb8d4
	UINT32 version = 1;
Packit 1fb8d4
	WINPR_HMAC_CTX* hmac;
Packit 1fb8d4
	NTLM_CONTEXT* context;
Packit 1fb8d4
	BYTE expected_signature[WINPR_MD5_DIGEST_LENGTH];
Packit 1fb8d4
	PSecBuffer data_buffer = NULL;
Packit 1fb8d4
	PSecBuffer signature_buffer = NULL;
Packit Service 5a9772
	SeqNo = (UINT32)MessageSeqNo;
Packit Service 5a9772
	context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
Packit 1fb8d4
Packit Service 5a9772
	for (index = 0; index < (int)pMessage->cBuffers; index++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA)
Packit 1fb8d4
			data_buffer = &pMessage->pBuffers[index];
Packit 1fb8d4
		else if (pMessage->pBuffers[index].BufferType == SECBUFFER_TOKEN)
Packit 1fb8d4
			signature_buffer = &pMessage->pBuffers[index];
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!data_buffer)
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
	if (!signature_buffer)
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
Packit 1fb8d4
	/* Copy original data buffer */
Packit 1fb8d4
	length = data_buffer->cbBuffer;
Packit 1fb8d4
	data = malloc(length);
Packit 1fb8d4
Packit 1fb8d4
	if (!data)
Packit 1fb8d4
		return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(data, data_buffer->pvBuffer, length);
Packit 1fb8d4
Packit 1fb8d4
	/* Decrypt message using with RC4, result overwrites original buffer */
Packit 1fb8d4
Packit 1fb8d4
	if (context->confidentiality)
Packit Service 5a9772
		winpr_RC4_Update(context->RecvRc4Seal, length, (BYTE*)data, (BYTE*)data_buffer->pvBuffer);
Packit 1fb8d4
	else
Packit 1fb8d4
		CopyMemory(data_buffer->pvBuffer, data, length);
Packit 1fb8d4
Packit 1fb8d4
	/* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */
Packit 1fb8d4
	hmac = winpr_HMAC_New();
Packit 1fb8d4
Packit Service 5a9772
	if (hmac &&
Packit Service 5a9772
	    winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->RecvSigningKey, WINPR_MD5_DIGEST_LENGTH))
Packit 1fb8d4
	{
Packit 1fb8d4
		Data_Write_UINT32(&value, SeqNo);
Packit Service 5a9772
		winpr_HMAC_Update(hmac, (void*)&value, 4);
Packit Service 5a9772
		winpr_HMAC_Update(hmac, (void*)data_buffer->pvBuffer, data_buffer->cbBuffer);
Packit 1fb8d4
		winpr_HMAC_Final(hmac, digest, WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
		winpr_HMAC_Free(hmac);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		winpr_HMAC_Free(hmac);
Packit 1fb8d4
		free(data);
Packit 1fb8d4
		return SEC_E_INSUFFICIENT_MEMORY;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "Encrypted Data Buffer (length = %d)", length);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, data, length);
Packit Service 5a9772
	WLog_DBG(TAG, "Data Buffer (length = %" PRIu32 ")", data_buffer->cbBuffer);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, data_buffer->pvBuffer, data_buffer->cbBuffer);
Packit 1fb8d4
#endif
Packit 1fb8d4
	free(data);
Packit 1fb8d4
	/* RC4-encrypt first 8 bytes of digest */
Packit 1fb8d4
	winpr_RC4_Update(context->RecvRc4Seal, 8, digest, checksum);
Packit 1fb8d4
	/* Concatenate version, ciphertext and sequence number to build signature */
Packit 1fb8d4
	Data_Write_UINT32(expected_signature, version);
Packit Service 5a9772
	CopyMemory(&expected_signature[4], (void*)checksum, 8);
Packit 1fb8d4
	Data_Write_UINT32(&expected_signature[12], SeqNo);
Packit 1fb8d4
	context->RecvSeqNum++;
Packit 1fb8d4
Packit 1fb8d4
	if (memcmp(signature_buffer->pvBuffer, expected_signature, 16) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* signature verification failed! */
Packit 1fb8d4
		WLog_ERR(TAG, "signature verification failed, something nasty is going on!");
Packit Service 5a9772
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
		WLog_ERR(TAG, "Expected Signature:");
Packit 1fb8d4
		winpr_HexDump(TAG, WLOG_ERROR, expected_signature, 16);
Packit 1fb8d4
		WLog_ERR(TAG, "Actual Signature:");
Packit Service 5a9772
		winpr_HexDump(TAG, WLOG_ERROR, (BYTE*)signature_buffer->pvBuffer, 16);
Packit Service 5a9772
#endif
Packit 1fb8d4
		return SEC_E_MESSAGE_ALTERED;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
Packit Service 5a9772
                                                    PSecBufferDesc pMessage, ULONG MessageSeqNo)
Packit 1fb8d4
{
Packit 1fb8d4
	return SEC_E_UNSUPPORTED_FUNCTION;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
Packit Service 5a9772
                                                      PSecBufferDesc pMessage, ULONG MessageSeqNo,
Packit Service 5a9772
                                                      PULONG pfQOP)
Packit 1fb8d4
{
Packit 1fb8d4
	return SEC_E_UNSUPPORTED_FUNCTION;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
const SecurityFunctionTableA NTLM_SecurityFunctionTableA = {
Packit Service 5a9772
	1,                                /* dwVersion */
Packit Service 5a9772
	NULL,                             /* EnumerateSecurityPackages */
Packit 1fb8d4
	ntlm_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */
Packit Service 5a9772
	ntlm_AcquireCredentialsHandleA,   /* AcquireCredentialsHandle */
Packit Service 5a9772
	ntlm_FreeCredentialsHandle,       /* FreeCredentialsHandle */
Packit Service 5a9772
	NULL,                             /* Reserved2 */
Packit Service 5a9772
	ntlm_InitializeSecurityContextA,  /* InitializeSecurityContext */
Packit Service 5a9772
	ntlm_AcceptSecurityContext,       /* AcceptSecurityContext */
Packit Service 5a9772
	ntlm_CompleteAuthToken,           /* CompleteAuthToken */
Packit Service 5a9772
	ntlm_DeleteSecurityContext,       /* DeleteSecurityContext */
Packit Service 5a9772
	NULL,                             /* ApplyControlToken */
Packit Service 5a9772
	ntlm_QueryContextAttributesA,     /* QueryContextAttributes */
Packit Service 5a9772
	ntlm_ImpersonateSecurityContext,  /* ImpersonateSecurityContext */
Packit Service 5a9772
	ntlm_RevertSecurityContext,       /* RevertSecurityContext */
Packit Service 5a9772
	ntlm_MakeSignature,               /* MakeSignature */
Packit Service 5a9772
	ntlm_VerifySignature,             /* VerifySignature */
Packit Service 5a9772
	NULL,                             /* FreeContextBuffer */
Packit Service 5a9772
	NULL,                             /* QuerySecurityPackageInfo */
Packit Service 5a9772
	NULL,                             /* Reserved3 */
Packit Service 5a9772
	NULL,                             /* Reserved4 */
Packit Service 5a9772
	NULL,                             /* ExportSecurityContext */
Packit Service 5a9772
	NULL,                             /* ImportSecurityContext */
Packit Service 5a9772
	NULL,                             /* AddCredentials */
Packit Service 5a9772
	NULL,                             /* Reserved8 */
Packit Service 5a9772
	NULL,                             /* QuerySecurityContextToken */
Packit Service 5a9772
	ntlm_EncryptMessage,              /* EncryptMessage */
Packit Service 5a9772
	ntlm_DecryptMessage,              /* DecryptMessage */
Packit Service 5a9772
	ntlm_SetContextAttributesA,       /* SetContextAttributes */
Packit 1fb8d4
};
Packit 1fb8d4
Packit Service 5a9772
const SecurityFunctionTableW NTLM_SecurityFunctionTableW = {
Packit Service 5a9772
	1,                                /* dwVersion */
Packit Service 5a9772
	NULL,                             /* EnumerateSecurityPackages */
Packit 1fb8d4
	ntlm_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */
Packit Service 5a9772
	ntlm_AcquireCredentialsHandleW,   /* AcquireCredentialsHandle */
Packit Service 5a9772
	ntlm_FreeCredentialsHandle,       /* FreeCredentialsHandle */
Packit Service 5a9772
	NULL,                             /* Reserved2 */
Packit Service 5a9772
	ntlm_InitializeSecurityContextW,  /* InitializeSecurityContext */
Packit Service 5a9772
	ntlm_AcceptSecurityContext,       /* AcceptSecurityContext */
Packit Service 5a9772
	ntlm_CompleteAuthToken,           /* CompleteAuthToken */
Packit Service 5a9772
	ntlm_DeleteSecurityContext,       /* DeleteSecurityContext */
Packit Service 5a9772
	NULL,                             /* ApplyControlToken */
Packit Service 5a9772
	ntlm_QueryContextAttributesW,     /* QueryContextAttributes */
Packit Service 5a9772
	ntlm_ImpersonateSecurityContext,  /* ImpersonateSecurityContext */
Packit Service 5a9772
	ntlm_RevertSecurityContext,       /* RevertSecurityContext */
Packit Service 5a9772
	ntlm_MakeSignature,               /* MakeSignature */
Packit Service 5a9772
	ntlm_VerifySignature,             /* VerifySignature */
Packit Service 5a9772
	NULL,                             /* FreeContextBuffer */
Packit Service 5a9772
	NULL,                             /* QuerySecurityPackageInfo */
Packit Service 5a9772
	NULL,                             /* Reserved3 */
Packit Service 5a9772
	NULL,                             /* Reserved4 */
Packit Service 5a9772
	NULL,                             /* ExportSecurityContext */
Packit Service 5a9772
	NULL,                             /* ImportSecurityContext */
Packit Service 5a9772
	NULL,                             /* AddCredentials */
Packit Service 5a9772
	NULL,                             /* Reserved8 */
Packit Service 5a9772
	NULL,                             /* QuerySecurityContextToken */
Packit Service 5a9772
	ntlm_EncryptMessage,              /* EncryptMessage */
Packit Service 5a9772
	ntlm_DecryptMessage,              /* DecryptMessage */
Packit Service 5a9772
	ntlm_SetContextAttributesA,       /* SetContextAttributes */
Packit 1fb8d4
};
Packit 1fb8d4
Packit Service 5a9772
const SecPkgInfoA NTLM_SecPkgInfoA = {
Packit Service 5a9772
	0x00082B37,             /* fCapabilities */
Packit Service 5a9772
	1,                      /* wVersion */
Packit Service 5a9772
	0x000A,                 /* wRPCID */
Packit Service 5a9772
	0x00000B48,             /* cbMaxToken */
Packit Service 5a9772
	"NTLM",                 /* Name */
Packit 1fb8d4
	"NTLM Security Package" /* Comment */
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static WCHAR NTLM_SecPkgInfoW_Name[] = { 'N', 'T', 'L', 'M', '\0' };
Packit 1fb8d4
Packit Service 5a9772
static WCHAR NTLM_SecPkgInfoW_Comment[] = {
Packit Service 5a9772
	'N', 'T', 'L', 'M', ' ', 'S', 'e', 'c', 'u', 'r', 'i',
Packit Service 5a9772
	't', 'y', ' ', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\0'
Packit 1fb8d4
};
Packit 1fb8d4
Packit Service 5a9772
const SecPkgInfoW NTLM_SecPkgInfoW = {
Packit Service 5a9772
	0x00082B37,              /* fCapabilities */
Packit Service 5a9772
	1,                       /* wVersion */
Packit Service 5a9772
	0x000A,                  /* wRPCID */
Packit Service 5a9772
	0x00000B48,              /* cbMaxToken */
Packit Service 5a9772
	NTLM_SecPkgInfoW_Name,   /* Name */
Packit 1fb8d4
	NTLM_SecPkgInfoW_Comment /* Comment */
Packit 1fb8d4
};