Merge pull request #1896 from awakecoding/sspi

WinPR SSPI Cleanup + Hardening
This commit is contained in:
Marc-André Moreau 2014-06-10 18:16:51 -04:00
commit 33b4407314
34 changed files with 4459 additions and 1822 deletions

View File

@ -85,11 +85,7 @@
#define WITH_DEBUG_CREDSSP
#endif
#ifdef WITH_NATIVE_SSPI
#define NLA_PKG_NAME NTLMSP_NAME
#else
#define NLA_PKG_NAME NTLMSP_NAME
#endif
#define NLA_PKG_NAME NEGOSSP_NAME
#define TERMSRV_SPN_PREFIX "TERMSRV/"
@ -267,24 +263,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
if (credssp_ntlm_client_init(credssp) == 0)
return 0;
#ifdef WITH_NATIVE_SSPI
{
HMODULE hSSPI;
INIT_SECURITY_INTERFACE InitSecurityInterface;
PSecurityFunctionTable pSecurityInterface = NULL;
hSSPI = LoadLibrary(_T("secur32.dll"));
#ifdef UNICODE
InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW");
#else
InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
#endif
credssp->table = (*InitSecurityInterface)();
}
#else
credssp->table = InitSecurityInterface();
#endif
credssp->table = InitSecurityInterfaceEx(0);
status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo);
@ -337,17 +316,25 @@ int credssp_client_authenticate(rdpCredssp* credssp)
SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_buffer_desc : NULL,
0, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration);
if (have_input_buffer && (input_buffer.pvBuffer != NULL))
if (have_input_buffer && (input_buffer.pvBuffer))
{
free(input_buffer.pvBuffer);
input_buffer.pvBuffer = NULL;
}
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK))
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{
if (credssp->table->CompleteAuthToken != NULL)
if (credssp->table->CompleteAuthToken)
credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
}
if (status == SEC_E_OK)
{
have_pub_key_auth = TRUE;
if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK)
@ -357,11 +344,6 @@ int credssp_client_authenticate(rdpCredssp* credssp)
}
credssp_encrypt_public_key_echo(credssp);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
}
/* send authentication token to server */
@ -469,11 +451,6 @@ int credssp_server_authenticate(rdpCredssp* credssp)
if (credssp_ntlm_server_init(credssp) == 0)
return 0;
#ifdef WITH_NATIVE_SSPI
if (!credssp->SspiModule)
credssp->SspiModule = _tcsdup(_T("secur32.dll"));
#endif
if (credssp->SspiModule)
{
HMODULE hSSPI;
@ -493,14 +470,12 @@ int credssp_server_authenticate(rdpCredssp* credssp)
pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
#endif
credssp->table = (*pInitSecurityInterface)();
credssp->table = pInitSecurityInterface();
}
#ifndef WITH_NATIVE_SSPI
else
{
credssp->table = InitSecurityInterface();
credssp->table = InitSecurityInterfaceEx(0);
}
#endif
status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo);
@ -597,7 +572,7 @@ int credssp_server_authenticate(rdpCredssp* credssp)
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{
if (credssp->table->CompleteAuthToken != NULL)
if (credssp->table->CompleteAuthToken)
credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc);
if (status == SEC_I_COMPLETE_NEEDED)
@ -1385,7 +1360,7 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings*
{
rdpCredssp* credssp;
credssp = (rdpCredssp*) malloc(sizeof(rdpCredssp));
credssp = (rdpCredssp*) calloc(1, sizeof(rdpCredssp));
if (credssp)
{
@ -1394,8 +1369,6 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings*
DWORD dwType;
DWORD dwSize;
ZeroMemory(credssp, sizeof(rdpCredssp));
credssp->instance = instance;
credssp->settings = settings;
credssp->server = settings->ServerMode;

View File

@ -541,6 +541,10 @@ static void* xf_peer_main_loop(void* arg)
settings->RemoteFxCodec = TRUE;
settings->ColorDepth = 32;
settings->NlaSecurity = FALSE;
settings->TlsSecurity = TRUE;
settings->RdpSecurity = FALSE;
client->Capabilities = xf_peer_capabilities;
client->PostConnect = xf_peer_post_connect;
client->Activate = xf_peer_activate;

View File

@ -67,9 +67,6 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/winpr/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/winpr/config.h)
add_subdirectory(include)
add_subdirectory(libwinpr)

View File

@ -29,7 +29,22 @@
#include <wincrypt.h>
#else
#endif
#ifndef ALG_TYPE_RESERVED7
#define ALG_TYPE_RESERVED7 (7 << 9)
#endif
#if (NTDDI_VERSION <= 0x05010200)
#define ALG_SID_SHA_256 12
#define ALG_SID_SHA_384 13
#define ALG_SID_SHA_512 14
#define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
#define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384)
#define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512)
#endif
#ifndef _WIN32
/* ncrypt.h */
@ -60,7 +75,6 @@ typedef ULONG_PTR NCRYPT_SECRET_HANDLE;
#define ALG_TYPE_STREAM (4 << 9)
#define ALG_TYPE_DH (5 << 9)
#define ALG_TYPE_SECURECHANNEL (6 << 9)
#define ALG_TYPE_RESERVED7 (7 << 9)
#define ALG_SID_ANY (0)
@ -74,8 +88,6 @@ typedef ULONG_PTR NCRYPT_SECRET_HANDLE;
#define ALG_SID_DSS_PKCS 1
#define ALG_SID_DSS_DMS 2
#define ALG_SID_ECDSA 3
#define ALG_SID_DES 1
#define ALG_SID_3DES 3
#define ALG_SID_DESX 4
@ -192,7 +204,6 @@ typedef ULONG_PTR NCRYPT_SECRET_HANDLE;
#define CALG_ECDH (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_ECDH)
#define CALG_ECMQV (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_ECMQV)
#define CALG_ECDSA (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_ECDSA)
typedef struct _CRYPTOAPI_BLOB
{
@ -594,5 +605,10 @@ BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, L
#endif
#ifndef ALG_SID_ECSDA
#define ALG_SID_ECDSA 3
#define CALG_ECDSA (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_ECDSA)
#endif
#endif /* WINPR_CRYPTO_H */

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* Security Support Provider Interface (SSPI)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,37 +20,23 @@
#ifndef WINPR_SSPI_H
#define WINPR_SSPI_H
#include <winpr/config.h>
#include <wchar.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/windows.h>
#include <winpr/security.h>
#define _NO_KSECDD_IMPORT_ 1
#ifdef _WIN32
#include <tchar.h>
#include <winerror.h>
#ifdef WITH_NATIVE_SSPI
#define SECURITY_WIN32
#include <sspi.h>
#include <security.h>
#else
#define WINPR_SSPI
#define SEC_ENTRY __stdcall
#endif
#else
#define WINPR_SSPI
#endif
#ifdef WINPR_SSPI
#ifndef _WIN32
#ifndef SEC_ENTRY
#define SEC_ENTRY
@ -266,7 +252,7 @@ typedef SecPkgInfoW* PSecPkgInfoW;
#define SECPKG_ATTR_NEGO_STATUS 32
#define SECPKG_ATTR_CONTEXT_DELETED 33
#ifdef WINPR_SSPI
#ifndef _WIN32
struct _SecPkgContext_AccessToken
{
@ -593,7 +579,7 @@ typedef SecPkgCredentials_NamesW* PSecPkgCredentials_NamesW;
#define SEC_WINNT_AUTH_IDENTITY_ANSI 0x1
#define SEC_WINNT_AUTH_IDENTITY_UNICODE 0x2
#ifdef WINPR_SSPI
#ifndef _WIN32
typedef struct _SEC_WINNT_AUTH_IDENTITY_W
{
@ -679,7 +665,7 @@ typedef CtxtHandle* PCtxtHandle;
#define SECBUFFER_READONLY_WITH_CHECKSUM 0x10000000
#define SECBUFFER_RESERVED 0x60000000
#ifdef WINPR_SSPI
#ifndef _WIN32
struct _SecBuffer
{
@ -1000,8 +986,7 @@ WINPR_API SECURITY_STATUS SEC_ENTRY VerifySignature(PCtxtHandle phContext, PSecB
}
#endif
#endif // WINPR_SSPI
#endif
#ifdef __cplusplus
extern "C" {
@ -1009,14 +994,56 @@ extern "C" {
/* Custom API */
#define SECPKG_ATTR_AUTH_IDENTITY 1001
#define SECPKG_ATTR_AUTH_PASSWORD 1002
#define SECPKG_ATTR_AUTH_NTLM_HASH 1003
struct _SecPkgContext_AuthIdentity
{
char User[256 + 1];
char Domain[256 + 1];
};
typedef struct _SecPkgContext_AuthIdentity SecPkgContext_AuthIdentity;
struct _SecPkgContext_AuthPassword
{
char Password[256 + 1];
};
typedef struct _SecPkgContext_AuthPassword SecPkgContext_AuthPassword;
struct _SecPkgContext_AuthNtlmHash
{
BYTE NtlmHash[16];
};
typedef struct _SecPkgContext_AuthNtlmHash SecPkgContext_AuthNtlmHash;
#define SSPI_INTERFACE_WINPR 0x00000001
#define SSPI_INTERFACE_NATIVE 0x00000002
typedef PSecurityFunctionTableA (SEC_ENTRY * INIT_SECURITY_INTERFACE_EX_A)(DWORD flags);
typedef PSecurityFunctionTableW (SEC_ENTRY * INIT_SECURITY_INTERFACE_EX_W)(DWORD flags);
WINPR_API void sspi_GlobalInit(void);
WINPR_API void sspi_GlobalFinish(void);
WINPR_API void sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size);
WINPR_API void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size);
WINPR_API void sspi_SecBufferFree(PSecBuffer SecBuffer);
WINPR_API void sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* domain, char* password);
WINPR_API void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDENTITY* srcIdentity);
WINPR_API int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, const char* password);
WINPR_API int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDENTITY* srcIdentity);
WINPR_API const char* GetSecurityStatusString(SECURITY_STATUS status);
WINPR_API SecurityFunctionTableW* SEC_ENTRY InitSecurityInterfaceExW(DWORD flags);
WINPR_API SecurityFunctionTableA* SEC_ENTRY InitSecurityInterfaceExA(DWORD flags);
#ifdef UNICODE
#define InitSecurityInterfaceEx InitSecurityInterfaceExW
#define INIT_SECURITY_INTERFACE_EX INIT_SECURITY_INTERFACE_EX_W
#else
#define InitSecurityInterfaceEx InitSecurityInterfaceExA
#define INIT_SECURITY_INTERFACE_EX INIT_SECURITY_INTERFACE_EX_A
#endif
#ifdef __cplusplus
}

View File

@ -62,8 +62,10 @@ WINPR_API BOOL TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZon
#endif
// GetDynamicTimeZoneInformation is provided by the SDK if _WIN32_WINNT >= 0x0600 in SDKs above 7.1A
// and incorrectly if _WIN32_WINNT >= 0x0501 in older SDKs
/*
* GetDynamicTimeZoneInformation is provided by the SDK if _WIN32_WINNT >= 0x0600 in SDKs above 7.1A
* and incorrectly if _WIN32_WINNT >= 0x0501 in older SDKs
*/
#if !defined(_WIN32) || (defined(_WIN32) && (defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0600 || !defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0501)) /* Windows Vista */
WINPR_API DWORD GetDynamicTimeZoneInformation(PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation);

View File

@ -25,6 +25,7 @@
#include <wctype.h>
#include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/print.h>
#ifndef _WIN32
@ -303,7 +304,15 @@ int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
allocate = TRUE;
if (allocate)
*lpWideCharStr = (LPWSTR) malloc(cchWideChar * sizeof(WCHAR));
{
*lpWideCharStr = (LPWSTR) calloc(cchWideChar, sizeof(WCHAR));
if (!(*lpWideCharStr))
{
//SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
}
status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr, cchWideChar);
@ -342,15 +351,22 @@ int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int
if (allocate)
{
*lpMultiByteStr = (LPSTR) malloc(cbMultiByte + 1);
ZeroMemory(*lpMultiByteStr, cbMultiByte + 1);
*lpMultiByteStr = (LPSTR) calloc(1, cbMultiByte + 1);
if (!(*lpMultiByteStr))
{
//SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
}
status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar,
*lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
if (status != cbMultiByte)
if ((status != cbMultiByte) && allocate)
{
status = 0;
}
if ((status <= 0) && allocate)
{

View File

@ -193,7 +193,6 @@ static void* named_pipe_single_thread(void* arg)
{
HANDLE servers[TESTNUMPIPESST];
HANDLE clients[TESTNUMPIPESST];
WINPR_NAMED_PIPE* p;
char sndbuf[PIPE_BUFFER_SIZE];
char rcvbuf[PIPE_BUFFER_SIZE];
DWORD dwRead;
@ -201,6 +200,9 @@ static void* named_pipe_single_thread(void* arg)
int i;
int numPipes;
BOOL bSuccess = FALSE;
#ifndef _WIN32
WINPR_NAMED_PIPE* p;
#endif
numPipes = TESTNUMPIPESST;
@ -220,6 +222,7 @@ static void* named_pipe_single_thread(void* arg)
}
}
#ifndef _WIN32
for (i = 0; i < numPipes; i++)
{
p = (WINPR_NAMED_PIPE*)servers[i];
@ -252,6 +255,7 @@ static void* named_pipe_single_thread(void* arg)
goto out;
}
}
#endif
for (i = 0; i < numPipes; i++)
{
@ -269,9 +273,11 @@ static void* named_pipe_single_thread(void* arg)
}
}
#ifndef _WIN32
for (i = 0; i < numPipes; i++)
{
p = servers[i];
if (p->clientfd < 1)
{
printf("%s: Unexpected client fd value for pipe #%d (%d is not > 0)\n",
@ -279,7 +285,7 @@ static void* named_pipe_single_thread(void* arg)
goto out;
}
if (p->ServerMode == TRUE)
if (p->ServerMode)
{
printf("%s: Unexpected ServerMode value for pipe #%d (1 instead of 0)\n",
__FUNCTION__, i);
@ -291,11 +297,12 @@ static void* named_pipe_single_thread(void* arg)
{
/* Test writing from clients to servers */
memset(sndbuf, 0, sizeof(sndbuf));
memset(rcvbuf, 0, sizeof(rcvbuf));
snprintf(sndbuf, sizeof(sndbuf), "CLIENT->SERVER ON PIPE #%05d", i);
ZeroMemory(sndbuf, sizeof(sndbuf));
ZeroMemory(rcvbuf, sizeof(rcvbuf));
sprintf_s(sndbuf, sizeof(sndbuf), "CLIENT->SERVER ON PIPE #%05d", i);
p = servers[i];
if (!WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) ||
dwWritten != sizeof(sndbuf))
{
@ -319,9 +326,9 @@ static void* named_pipe_single_thread(void* arg)
/* Test writing from servers to clients */
memset(sndbuf, 0, sizeof(sndbuf));
memset(rcvbuf, 0, sizeof(rcvbuf));
snprintf(sndbuf, sizeof(sndbuf), "SERVER->CLIENT ON PIPE #%05d", i);
ZeroMemory(sndbuf, sizeof(sndbuf));
ZeroMemory(rcvbuf, sizeof(rcvbuf));
sprintf_s(sndbuf, sizeof(sndbuf), "SERVER->CLIENT ON PIPE #%05d", i);
p = servers[i];
if (!WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) ||
@ -345,6 +352,7 @@ static void* named_pipe_single_thread(void* arg)
goto out;
}
}
#endif
/**
* After DisconnectNamedPipe on server end

View File

@ -43,20 +43,21 @@ set(${MODULE_PREFIX}_CREDSSP_SRCS
set(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_CREDSSP_SRCS}
sspi_winpr.c
sspi_winpr.h
sspi_export.c
sspi.c
sspi.h)
if(NOT WITH_NATIVE_SSPI)
set(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_NTLM_SRCS}
${${MODULE_PREFIX}_KERBEROS_SRCS}
${${MODULE_PREFIX}_NEGOTIATE_SRCS}
${${MODULE_PREFIX}_SCHANNEL_SRCS}
${${MODULE_PREFIX}_SRCS})
endif()
set(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_NTLM_SRCS}
${${MODULE_PREFIX}_KERBEROS_SRCS}
${${MODULE_PREFIX}_NEGOTIATE_SRCS}
${${MODULE_PREFIX}_SCHANNEL_SRCS}
${${MODULE_PREFIX}_SRCS})
if(MSVC AND (NOT MONOLITHIC_BUILD))
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def)
#set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def)
endif()
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
@ -80,7 +81,7 @@ endif()
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
MODULE winpr
MODULES winpr-crt winpr-sysinfo winpr-registry winpr-crypto winpr-utils)
MODULES winpr-crt winpr-sysinfo winpr-registry winpr-crypto winpr-library winpr-utils)
if(MONOLITHIC_BUILD)
set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* Credential Security Support Provider (CredSSP)
*
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2010-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,7 +35,7 @@ SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextW(PCredHandle phCrede
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
@ -44,22 +44,24 @@ SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCrede
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
CREDSSP_CONTEXT* context;
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
context = sspi_SecureHandleGetLowerPointer(phContext);
context = (CREDSSP_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = credssp_ContextNew();
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!context)
return SEC_E_INSUFFICIENT_MEMORY;
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) CREDSSP_PACKAGE_NAME);
}
return SEC_E_OK;
}
CREDSSP_CONTEXT* credssp_ContextNew()
@ -68,10 +70,8 @@ CREDSSP_CONTEXT* credssp_ContextNew()
context = (CREDSSP_CONTEXT*) calloc(1, sizeof(CREDSSP_CONTEXT));
if (context != NULL)
{
}
if (!context)
return NULL;
return context;
}
@ -99,19 +99,23 @@ SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleW(SEC_WCHAR* pszPrinci
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND)
{
credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INSUFFICIENT_MEMORY;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
@ -122,21 +126,21 @@ SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincip
return SEC_E_OK;
}
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{
if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
return SEC_E_OK;
}
@ -146,12 +150,12 @@ SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCred
SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
if (!phCredential)
return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials)
return SEC_E_INVALID_HANDLE;
@ -163,22 +167,22 @@ SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential
SECURITY_STATUS SEC_ENTRY credssp_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY credssp_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY credssp_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY credssp_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
const SecurityFunctionTableA CREDSSP_SecurityFunctionTableA =

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -41,145 +41,195 @@
char* NTLM_PACKAGE_NAME = "NTLM";
void ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation)
int ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation)
{
char *ws = Workstation;
int status;
DWORD nSize = 0;
char* ws = Workstation;
if (!Workstation)
{
GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize);
ws = malloc(nSize);
GetComputerNameExA(ComputerNameNetBIOS, ws, &nSize);
ws = (char*) malloc(nSize);
if (!ws)
return -1;
if (!GetComputerNameExA(ComputerNameNetBIOS, ws, &nSize))
return 0;
}
context->Workstation.Length = ConvertToUnicode(CP_UTF8, 0,
ws, -1, &context->Workstation.Buffer, 0) - 1;
context->Workstation.Buffer = NULL;
status = ConvertToUnicode(CP_UTF8, 0, ws, -1, &context->Workstation.Buffer, 0);
free(ws);
if (status <= 0)
return -1;
context->Workstation.Length = (USHORT) (status - 1);
context->Workstation.Length *= 2;
if (!Workstation)
free(Workstation);
return 1;
}
void ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePrincipalName)
int ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePrincipalName)
{
context->ServicePrincipalName.Length = _wcslen(ServicePrincipalName) * 2;
if (!ServicePrincipalName)
{
context->ServicePrincipalName.Buffer = NULL;
return;
context->ServicePrincipalName.Length = 0;
return 1;
}
context->ServicePrincipalName.Length = _wcslen(ServicePrincipalName) * 2;
context->ServicePrincipalName.Buffer = (PWSTR) malloc(context->ServicePrincipalName.Length + 2);
if (!context->ServicePrincipalName.Buffer)
return -1;
CopyMemory(context->ServicePrincipalName.Buffer, ServicePrincipalName, context->ServicePrincipalName.Length + 2);
return 1;
}
void ntlm_SetContextServicePrincipalNameA(NTLM_CONTEXT* context, char* ServicePrincipalName)
int ntlm_SetContextServicePrincipalNameA(NTLM_CONTEXT* context, char* ServicePrincipalName)
{
context->ServicePrincipalName.Length = ConvertToUnicode(CP_UTF8, 0,
ServicePrincipalName, -1, &context->ServicePrincipalName.Buffer, 0) - 1;
context->ServicePrincipalName.Length *= 2;
int status;
context->ServicePrincipalName.Buffer = NULL;
status = ConvertToUnicode(CP_UTF8, 0, ServicePrincipalName, -1, &context->ServicePrincipalName.Buffer, 0);
if (status <= 0)
return -1;
context->ServicePrincipalName.Length = (USHORT) ((status - 1) * 2);
return 1;
}
void ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName)
int ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName)
{
char *name = TargetName;
int status;
DWORD nSize = 0;
char* name = TargetName;
if (!TargetName)
{
GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize);
name = malloc(nSize);
GetComputerNameExA(ComputerNameDnsHostname, name, &nSize);
if (!GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize))
return -1;
name = (char*) malloc(nSize);
if (!name)
return -1;
if (!GetComputerNameExA(ComputerNameDnsHostname, name, &nSize))
return -1;
CharUpperA(TargetName);
}
context->TargetName.cbBuffer = ConvertToUnicode(CP_UTF8, 0,
name, -1, (LPWSTR*) &context->TargetName.pvBuffer, 0) - 1;
context->TargetName.cbBuffer *= 2;
context->TargetName.pvBuffer = NULL;
status = ConvertToUnicode(CP_UTF8, 0, name, -1, (LPWSTR*) &context->TargetName.pvBuffer, 0);
if (status <= 0)
return -1;
context->TargetName.cbBuffer = (USHORT) ((status - 1) * 2);
if (!TargetName)
free(name);
return 1;
}
NTLM_CONTEXT* ntlm_ContextNew()
{
HKEY hKey;
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
NTLM_CONTEXT* context;
context = (NTLM_CONTEXT*) malloc(sizeof(NTLM_CONTEXT));
ZeroMemory(context, sizeof(NTLM_CONTEXT));
context = (NTLM_CONTEXT*) calloc(1, sizeof(NTLM_CONTEXT));
if (context != NULL)
if (!context)
return NULL;
context->NTLMv2 = TRUE;
context->UseMIC = FALSE;
context->SendVersionInfo = TRUE;
context->SendSingleHostData = FALSE;
context->SendWorkstationName = TRUE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\WinPR\\NTLM"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
HKEY hKey;
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
if (RegQueryValueEx(hKey, _T("NTLMv2"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->NTLMv2 = dwValue ? 1 : 0;
context->NTLMv2 = TRUE;
context->UseMIC = FALSE;
context->SendVersionInfo = TRUE;
context->SendSingleHostData = FALSE;
context->SendWorkstationName = TRUE;
if (RegQueryValueEx(hKey, _T("UseMIC"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->UseMIC = dwValue ? 1 : 0;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\WinPR\\NTLM"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (RegQueryValueEx(hKey, _T("SendVersionInfo"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendVersionInfo = dwValue ? 1 : 0;
if (status == ERROR_SUCCESS)
if (RegQueryValueEx(hKey, _T("SendSingleHostData"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendSingleHostData = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("SendWorkstationName"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendWorkstationName = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("WorkstationName"), NULL, &dwType, NULL, &dwSize) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("NTLMv2"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->NTLMv2 = dwValue ? 1 : 0;
char* workstation = (char*) malloc(dwSize + 1);
if (RegQueryValueEx(hKey, _T("UseMIC"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->UseMIC = dwValue ? 1 : 0;
if (!workstation)
return NULL;
if (RegQueryValueEx(hKey, _T("SendVersionInfo"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendVersionInfo = dwValue ? 1 : 0;
status = RegQueryValueExA(hKey, "WorkstationName", NULL, &dwType, (BYTE*) workstation, &dwSize);
workstation[dwSize] = '\0';
if (RegQueryValueEx(hKey, _T("SendSingleHostData"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendSingleHostData = dwValue ? 1 : 0;
if (ntlm_SetContextWorkstation(context, workstation) < 0)
return NULL;
if (RegQueryValueEx(hKey, _T("SendWorkstationName"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendWorkstationName = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("WorkstationName"), NULL, &dwType, NULL, &dwSize) == ERROR_SUCCESS)
{
char* workstation = (char*) malloc(dwSize + 1);
status = RegQueryValueExA(hKey, "WorkstationName", NULL, &dwType, (BYTE*) workstation, &dwSize);
workstation[dwSize] = '\0';
ntlm_SetContextWorkstation(context, workstation);
free(workstation);
}
RegCloseKey(hKey);
free(workstation);
}
/*
* Extended Protection is enabled by default in Windows 7,
* but enabling it in WinPR breaks TS Gateway at this point
*/
context->SuppressExtendedProtection = FALSE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\LSA"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("SuppressExtendedProtection"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SuppressExtendedProtection = dwValue ? 1 : 0;
RegCloseKey(hKey);
}
context->NegotiateFlags = 0;
context->LmCompatibilityLevel = 3;
context->state = NTLM_STATE_INITIAL;
memset(context->MachineID, 0xAA, sizeof(context->MachineID));
if (context->NTLMv2)
context->UseMIC = TRUE;
RegCloseKey(hKey);
}
/*
* Extended Protection is enabled by default in Windows 7,
* but enabling it in WinPR breaks TS Gateway at this point
*/
context->SuppressExtendedProtection = FALSE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\LSA"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("SuppressExtendedProtection"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SuppressExtendedProtection = dwValue ? 1 : 0;
RegCloseKey(hKey);
}
context->NegotiateFlags = 0;
context->LmCompatibilityLevel = 3;
context->state = NTLM_STATE_INITIAL;
FillMemory(context->MachineID, sizeof(context->MachineID), 0xAA);
if (context->NTLMv2)
context->UseMIC = TRUE;
return context;
}
@ -197,10 +247,6 @@ void ntlm_ContextFree(NTLM_CONTEXT* context)
sspi_SecBufferFree(&context->LmChallengeResponse);
free(context->ServicePrincipalName.Buffer);
free(context->identity.User);
free(context->identity.Password);
free(context->identity.Domain);
free(context->Workstation.Buffer);
free(context);
}
@ -209,39 +255,32 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND)
if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
(fCredentialUse != SECPKG_CRED_INBOUND) &&
(fCredentialUse != SECPKG_CRED_BOTH))
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity != NULL)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK;
return SEC_E_INVALID_PARAMETER;
}
else if (fCredentialUse == SECPKG_CRED_INBOUND)
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
credentials = sspi_CredentialsNew();
if (identity)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
else
ZeroMemory(&(credentials->identity), sizeof(SEC_WINNT_AUTH_IDENTITY));
if (!credentials)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
return SEC_E_OK;
}
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity)
sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK;
}
@ -250,49 +289,44 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND)
if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
(fCredentialUse != SECPKG_CRED_INBOUND) &&
(fCredentialUse != SECPKG_CRED_BOTH))
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity != NULL)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK;
return SEC_E_INVALID_PARAMETER;
}
else if (fCredentialUse == SECPKG_CRED_INBOUND)
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
credentials = sspi_CredentialsNew();
if (identity != NULL)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
if (!credentials)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
return SEC_E_OK;
}
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity)
sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
if (!phCredential)
return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials)
return SEC_E_INVALID_HANDLE;
@ -326,7 +360,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
{
NTLM_CONTEXT* context;
SECURITY_STATUS status;
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
PSecBuffer input_buffer;
PSecBuffer output_buffer;
@ -339,13 +373,13 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
if (!context)
return SEC_E_INSUFFICIENT_MEMORY;
context->server = 1;
context->server = TRUE;
if (fContextReq & ASC_REQ_CONFIDENTIALITY)
context->confidentiality = 1;
context->confidentiality = TRUE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
context->credentials = credentials;
ntlm_SetContextTargetName(context, NULL);
@ -414,7 +448,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
if (pOutput)
{
int i;
ULONG i;
for (i = 0; i < pOutput->cBuffers; i++)
{
@ -441,7 +475,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
{
NTLM_CONTEXT* context;
SECURITY_STATUS status;
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
PSecBuffer input_buffer = NULL;
PSecBuffer output_buffer = NULL;
PSecBuffer channel_bindings = NULL;
@ -456,15 +490,19 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
return SEC_E_INSUFFICIENT_MEMORY;
if (fContextReq & ISC_REQ_CONFIDENTIALITY)
context->confidentiality = 1;
context->confidentiality = TRUE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
context->credentials = credentials;
if (context->Workstation.Length < 1)
ntlm_SetContextWorkstation(context, NULL);
{
if (ntlm_SetContextWorkstation(context, NULL) < 0)
return SEC_E_INTERNAL_ERROR;
}
ntlm_SetContextServicePrincipalNameW(context, pszTargetName);
sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
if (ntlm_SetContextServicePrincipalNameW(context, pszTargetName) < 0)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NTLM_PACKAGE_NAME);
@ -554,20 +592,39 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti
SECURITY_STATUS status;
SEC_WCHAR* pszTargetNameW = NULL;
if (pszTargetName != NULL)
if (pszTargetName)
{
ConvertToUnicode(CP_UTF8, 0, pszTargetName, -1, &pszTargetNameW, 0);
if (ConvertToUnicode(CP_UTF8, 0, pszTargetName, -1, &pszTargetNameW, 0) <= 0)
return SEC_E_INTERNAL_ERROR;
}
status = ntlm_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq,
Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
if (pszTargetNameW != NULL)
if (pszTargetNameW)
free(pszTargetNameW);
return status;
}
SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
{
NTLM_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
return SEC_E_INVALID_HANDLE;
if (context->server)
{
status = ntlm_server_AuthenticateComplete(context);
}
return status;
}
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375354 */
SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
@ -588,12 +645,16 @@ SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NTLM_CONTEXT* context;
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (ulAttribute == SECPKG_ATTR_SIZES)
{
SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer;
@ -605,6 +666,35 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL
return SEC_E_OK;
}
else if (ulAttribute == SECPKG_ATTR_AUTH_IDENTITY)
{
int status;
char* UserA = NULL;
char* DomainA = NULL;
SSPI_CREDENTIALS* credentials;
SecPkgContext_AuthIdentity* AuthIdentity = (SecPkgContext_AuthIdentity*) pBuffer;
credentials = context->credentials;
ZeroMemory(AuthIdentity, sizeof(SecPkgContext_AuthIdentity));
UserA = AuthIdentity->User;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) credentials->identity.User,
credentials->identity.UserLength,
&UserA, 256, NULL, NULL);
if (status <= 0)
return SEC_E_INTERNAL_ERROR;
DomainA = AuthIdentity->Domain;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) credentials->identity.Domain,
credentials->identity.DomainLength,
&DomainA, 256, NULL, NULL);
if (status <= 0)
return SEC_E_INTERNAL_ERROR;
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
}
@ -614,6 +704,38 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, UL
return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
}
SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NTLM_CONTEXT* context;
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INVALID_PARAMETER;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_HASH)
{
SecPkgContext_AuthNtlmHash* AuthNtlmHash = (SecPkgContext_AuthNtlmHash*) pBuffer;
if (cbBuffer < sizeof(SecPkgContext_AuthNtlmHash))
return SEC_E_INVALID_PARAMETER;
CopyMemory(context->NtlmHash, AuthNtlmHash->NtlmHash, 16);
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return ntlm_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
}
SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext)
{
return SEC_E_OK;
@ -654,20 +776,24 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
/* Copy original data buffer */
length = data_buffer->cbBuffer;
data = malloc(length);
if (!data)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(data, data_buffer->pvBuffer, length);
/* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */
HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac, context->SendSigningKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac, (void*) &(SeqNo), 4);
HMAC_Update(&hmac, data, length);
HMAC_Update(&hmac, (void*) data, length);
HMAC_Final(&hmac, digest, NULL);
HMAC_CTX_cleanup(&hmac);
/* Encrypt message using with RC4, result overwrites original buffer */
if (context->confidentiality)
RC4(&context->SendRc4Seal, length, data, data_buffer->pvBuffer);
RC4(&context->SendRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer);
else
CopyMemory(data_buffer->pvBuffer, data, length);
@ -719,7 +845,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
PSecBuffer signature_buffer = NULL;
SeqNo = (UINT32) MessageSeqNo;
context = sspi_SecureHandleGetLowerPointer(phContext);
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
for (index = 0; index < (int) pMessage->cBuffers; index++)
{
@ -738,12 +864,16 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
/* Copy original data buffer */
length = data_buffer->cbBuffer;
data = malloc(length);
if (!data)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(data, data_buffer->pvBuffer, length);
/* Decrypt message using with RC4, result overwrites original buffer */
if (context->confidentiality)
RC4(&context->RecvRc4Seal, length, data, data_buffer->pvBuffer);
RC4(&context->RecvRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer);
else
CopyMemory(data_buffer->pvBuffer, data, length);
@ -751,7 +881,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac, context->RecvSigningKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac, (void*) &(SeqNo), 4);
HMAC_Update(&hmac, data_buffer->pvBuffer, data_buffer->cbBuffer);
HMAC_Update(&hmac, (void*) data_buffer->pvBuffer, data_buffer->cbBuffer);
HMAC_Final(&hmac, digest, NULL);
HMAC_CTX_cleanup(&hmac);
@ -784,7 +914,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
fprintf(stderr, "Expected Signature:\n");
winpr_HexDump(expected_signature, 16);
fprintf(stderr, "Actual Signature:\n");
winpr_HexDump(signature_buffer->pvBuffer, 16);
winpr_HexDump((BYTE*) signature_buffer->pvBuffer, 16);
return SEC_E_MESSAGE_ALTERED;
}
@ -794,12 +924,12 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
@ -812,7 +942,7 @@ const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
NULL, /* Reserved2 */
ntlm_InitializeSecurityContextA, /* InitializeSecurityContext */
ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
ntlm_CompleteAuthToken, /* CompleteAuthToken */
ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
ntlm_QueryContextAttributesA, /* QueryContextAttributes */
@ -831,7 +961,7 @@ const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
NULL, /* QuerySecurityContextToken */
ntlm_EncryptMessage, /* EncryptMessage */
ntlm_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
ntlm_SetContextAttributesA, /* SetContextAttributes */
};
const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
@ -844,7 +974,7 @@ const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
NULL, /* Reserved2 */
ntlm_InitializeSecurityContextW, /* InitializeSecurityContext */
ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
ntlm_CompleteAuthToken, /* CompleteAuthToken */
ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
ntlm_QueryContextAttributesW, /* QueryContextAttributes */
@ -863,7 +993,7 @@ const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
NULL, /* QuerySecurityContextToken */
ntlm_EncryptMessage, /* EncryptMessage */
ntlm_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
ntlm_SetContextAttributesA, /* SetContextAttributes */
};
const SecPkgInfoA NTLM_SecPkgInfoA =

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,6 +23,8 @@
#include <winpr/sspi.h>
#include <winpr/windows.h>
#include <winpr/nt.h>
#include <time.h>
#include <openssl/des.h>
#include <openssl/md4.h>
@ -78,6 +80,7 @@ enum _NTLM_STATE
NTLM_STATE_NEGOTIATE,
NTLM_STATE_CHALLENGE,
NTLM_STATE_AUTHENTICATE,
NTLM_STATE_COMPLETION,
NTLM_STATE_FINAL
};
typedef enum _NTLM_STATE NTLM_STATE;
@ -226,6 +229,8 @@ struct _NTLM_CONTEXT
NTLM_STATE state;
int SendSeqNum;
int RecvSeqNum;
BYTE NtlmHash[16];
BYTE NtlmV2Hash[16];
BYTE MachineID[32];
BOOL SendVersionInfo;
BOOL confidentiality;
@ -241,7 +246,7 @@ struct _NTLM_CONTEXT
BOOL SendWorkstationName;
UNICODE_STRING Workstation;
UNICODE_STRING ServicePrincipalName;
SEC_WINNT_AUTH_IDENTITY identity;
SSPI_CREDENTIALS* credentials;
BYTE* ChannelBindingToken;
BYTE ChannelBindingsHash[16];
SecPkgContext_Bindings Bindings;
@ -258,6 +263,7 @@ struct _NTLM_CONTEXT
SecBuffer TargetName;
SecBuffer NtChallengeResponse;
SecBuffer LmChallengeResponse;
NTLMv2_RESPONSE NTLMv2Response;
BYTE Timestamp[8];
BYTE ChallengeTimestamp[8];
BYTE ServerChallenge[8];
@ -272,6 +278,7 @@ struct _NTLM_CONTEXT
BYTE ServerSigningKey[16];
BYTE ServerSealingKey[16];
BYTE MessageIntegrityCheck[16];
UINT32 MessageIntegrityCheckOffset;
};
typedef struct _NTLM_CONTEXT NTLM_CONTEXT;

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package (AV_PAIRs)
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -173,34 +173,45 @@ NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAv
return pAvPairCopy;
}
void ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
{
char* name;
int length;
int status;
DWORD nSize = 0;
GetComputerNameExA(type, NULL, &nSize);
name = malloc(nSize);
GetComputerNameExA(type, name, &nSize);
name = (char*) malloc(nSize);
if (!name)
return -1;
if (!GetComputerNameExA(type, name, &nSize))
return -1;
if (type == ComputerNameNetBIOS)
CharUpperA(name);
length = ConvertToUnicode(CP_UTF8, 0, name, -1, &pName->Buffer, 0);
status = ConvertToUnicode(CP_UTF8, 0, name, -1, &pName->Buffer, 0);
pName->Length = (length - 1) * 2;
if (status <= 0)
return status;
pName->Length = (USHORT) ((status - 1) * 2);
pName->MaximumLength = pName->Length;
free(name);
return 1;
}
void ntlm_free_unicode_string(PUNICODE_STRING string)
{
if (string != NULL)
if (string)
{
if (string->Length > 0)
{
if (string->Buffer != NULL)
if (string->Buffer)
free(string->Buffer);
string->Buffer = NULL;
@ -297,7 +308,7 @@ void ntlm_compute_single_host_data(NTLM_CONTEXT* context)
FillMemory(context->SingleHostData.MachineID, 32, 0xAA);
}
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
{
int length;
ULONG AvPairsCount;
@ -310,23 +321,33 @@ void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
UNICODE_STRING DnsComputerName;
NbDomainName.Buffer = NULL;
ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS);
if (ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS) < 0)
return -1;
NbComputerName.Buffer = NULL;
ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS);
if (ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS) < 0)
return -1;
DnsDomainName.Buffer = NULL;
ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain);
if (ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain) < 0)
return -1;
DnsComputerName.Buffer = NULL;
ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname);
if (ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname) < 0)
return -1;
AvPairsCount = 5;
AvPairsLength = NbDomainName.Length + NbComputerName.Length +
DnsDomainName.Length + DnsComputerName.Length + 8;
length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength);
sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length);
if (!sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length))
return -1;
pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
AvPairListSize = (ULONG) context->ChallengeTargetInfo.cbBuffer;
@ -342,9 +363,11 @@ void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
ntlm_free_unicode_string(&NbComputerName);
ntlm_free_unicode_string(&DnsDomainName);
ntlm_free_unicode_string(&DnsComputerName);
return 1;
}
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
{
ULONG size;
ULONG AvPairsCount;
@ -369,31 +392,31 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvDnsTreeName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsTreeName);
AvTimestamp = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvTimestamp);
if (AvNbDomainName != NULL)
if (AvNbDomainName)
{
AvPairsCount++; /* MsvAvNbDomainName */
AvPairsValueLength += AvNbDomainName->AvLen;
}
if (AvNbComputerName != NULL)
if (AvNbComputerName)
{
AvPairsCount++; /* MsvAvNbComputerName */
AvPairsValueLength += AvNbComputerName->AvLen;
}
if (AvDnsDomainName != NULL)
if (AvDnsDomainName)
{
AvPairsCount++; /* MsvAvDnsDomainName */
AvPairsValueLength += AvDnsDomainName->AvLen;
}
if (AvDnsComputerName != NULL)
if (AvDnsComputerName)
{
AvPairsCount++; /* MsvAvDnsComputerName */
AvPairsValueLength += AvDnsComputerName->AvLen;
}
if (AvDnsTreeName != NULL)
if (AvDnsTreeName)
{
AvPairsCount++; /* MsvAvDnsTreeName */
AvPairsValueLength += AvDnsTreeName->AvLen;
@ -448,22 +471,22 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
ntlm_av_pair_list_init(AuthenticateTargetInfo);
if (AvNbDomainName != NULL)
if (AvNbDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName);
if (AvNbComputerName != NULL)
if (AvNbComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName);
if (AvDnsDomainName != NULL)
if (AvDnsDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName);
if (AvDnsComputerName != NULL)
if (AvDnsComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName);
if (AvDnsTreeName != NULL)
if (AvDnsTreeName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName);
if (AvTimestamp != NULL)
if (AvTimestamp)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvTimestamp);
if (context->UseMIC)
@ -497,4 +520,6 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
ZeroMemory((void*) AvEOL, 4);
}
return 1;
}

View File

@ -35,7 +35,7 @@ NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId);
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId, PBYTE Value, UINT16 AvLen);
NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAvPair);
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
#endif /* WINPR_SSPI_NTLM_AV_PAIRS_H */

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package (Compute)
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,12 +32,15 @@
#include "ntlm_compute.h"
const char lm_magic[] = "KGS!@#$%";
const char LM_MAGIC[] = "KGS!@#$%";
static const char client_sign_magic[] = "session key to client-to-server signing key magic constant";
static const char server_sign_magic[] = "session key to server-to-client signing key magic constant";
static const char client_seal_magic[] = "session key to client-to-server sealing key magic constant";
static const char server_seal_magic[] = "session key to server-to-client sealing key magic constant";
static const char NTLM_CLIENT_SIGN_MAGIC[] = "session key to client-to-server signing key magic constant";
static const char NTLM_SERVER_SIGN_MAGIC[] = "session key to server-to-client signing key magic constant";
static const char NTLM_CLIENT_SEAL_MAGIC[] = "session key to client-to-server sealing key magic constant";
static const char NTLM_SERVER_SEAL_MAGIC[] = "session key to server-to-client sealing key magic constant";
static const BYTE NTLM_NULL_HASH[16] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/**
* Populate VERSION structure.\n
@ -66,13 +69,18 @@ void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo)
* @param s
*/
void ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo)
int ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo)
{
if (Stream_GetRemainingLength(s) < 8)
return -1;
Stream_Read_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
Stream_Read_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
Stream_Read_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */
Stream_Read(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
Stream_Read_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
return 1;
}
/**
@ -107,7 +115,7 @@ void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo)
fprintf(stderr, "\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent);
}
void ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
int ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
{
size_t size;
@ -121,10 +129,16 @@ void ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* cha
size = Stream_Length(s) - Stream_GetPosition(s);
challenge->AvPairs = (NTLM_AV_PAIR*) malloc(size);
if (!challenge->AvPairs)
return -1;
Stream_Read(s, challenge->AvPairs, size);
return 1;
}
void ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
int ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
{
ULONG length;
@ -138,57 +152,22 @@ void ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* ch
length = ntlm_av_pair_list_length(challenge->AvPairs);
Stream_Write(s, challenge->AvPairs, length);
return 1;
}
void ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
int ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
{
Stream_Read(s, response->Response, 16);
ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge));
return ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge));
}
void ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
int ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
{
Stream_Write(s, response->Response, 16);
ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
return ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
}
#if 0
/**
* Output Restriction_Encoding.\n
* Restriction_Encoding @msdn{cc236647}
* @param NTLM context
*/
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context)
{
wStream* s;
AV_PAIR* restrictions = &context->av_pairs->Restrictions;
BYTE machineID[32] =
"\x3A\x15\x8E\xA6\x75\x82\xD8\xF7\x3E\x06\xFA\x7A\xB4\xDF\xFD\x43"
"\x84\x6C\x02\x3A\xFD\x5A\x94\xFE\xCF\x97\x0F\x3D\x19\x2C\x38\x20";
restrictions->value = malloc(48);
restrictions->length = 48;
s = PStreamAllocAttach(restrictions->value, restrictions->length);
Stream_Write_UINT32(s, 48); /* Size */
Stream_Zero(s, 4); /* Z4 (set to zero) */
/* IntegrityLevel (bit 31 set to 1) */
Stream_Write_UINT8(s, 1);
Stream_Zero(s, 3);
Stream_Write_UINT32(s, 0x00002000); /* SubjectIntegrityLevel */
Stream_Write(s, machineID, 32); /* MachineID */
PStreamFreeDetach(s);
}
#endif
/**
* Get current time, in tenths of microseconds since midnight of January 1, 1601.
* @param[out] timestamp 64-bit little-endian timestamp
@ -224,20 +203,22 @@ void ntlm_generate_timestamp(NTLM_CONTEXT* context)
ntlm_current_time(context->Timestamp);
}
void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
{
WINPR_SAM* sam;
WINPR_SAM_ENTRY* entry;
SSPI_CREDENTIALS* credentials = context->credentials;
sam = SamOpen(1);
if (sam == NULL)
return;
sam = SamOpen(TRUE);
if (!sam)
return -1;
entry = SamLookupUserW(sam,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2);
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2);
if (entry != NULL)
if (entry)
{
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "NTLM Hash:\n");
@ -245,20 +226,20 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
#endif
NTOWFv2FromHashW(entry->NtHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
SamFreeEntry(sam, entry);
SamClose(sam);
return;
return 1;
}
entry = SamLookupUserW(sam,
(LPWSTR) context->identity.User, context->identity.UserLength * 2, NULL, 0);
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, NULL, 0);
if (entry != NULL)
if (entry)
{
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "NTLM Hash:\n");
@ -266,32 +247,44 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
#endif
NTOWFv2FromHashW(entry->NtHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
SamFreeEntry(sam, entry);
SamClose(sam);
return;
return 1;
}
else
{
fprintf(stderr, "Error: Could not find user in SAM database\n");
return 0;
}
SamClose(sam);
return 1;
}
void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
{
int status;
int i, hn, ln;
char* PasswordHash = NULL;
UINT32 PasswordHashLength = 0;
SSPI_CREDENTIALS* credentials = context->credentials;
/* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */
PasswordHashLength = context->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
ConvertFromUnicode(CP_UTF8, 0, context->identity.Password, PasswordHashLength, &PasswordHash, 0, NULL, NULL);
PasswordHashLength = credentials->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) credentials->identity.Password,
PasswordHashLength, &PasswordHash, 0, NULL, NULL);
if (status <= 0)
return -1;
CharUpperBuffA(PasswordHash, PasswordHashLength);
for (i = 0; i < 32; i += 2)
@ -302,62 +295,83 @@ void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
}
free(PasswordHash);
return 1;
}
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
{
if (context->identity.PasswordLength > 256)
SSPI_CREDENTIALS* credentials = context->credentials;
if (memcmp(context->NtlmHash, NTLM_NULL_HASH, 16) != 0)
{
BYTE PasswordHash[16];
/* Special case for WinPR: password hash */
ntlm_convert_password_hash(context, PasswordHash);
NTOWFv2FromHashW(PasswordHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2,
NTOWFv2FromHashW(context->NtlmHash,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
}
else if (context->identity.PasswordLength > 0)
else if (credentials->identity.PasswordLength > 256)
{
NTOWFv2W((LPWSTR) context->identity.Password, context->identity.PasswordLength * 2,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, (BYTE*) hash);
/* Special case for WinPR: password hash */
if (ntlm_convert_password_hash(context, context->NtlmHash) < 0)
return -1;
NTOWFv2FromHashW(context->NtlmHash,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
}
else if (credentials->identity.PasswordLength > 0)
{
NTOWFv2W((LPWSTR) credentials->identity.Password, credentials->identity.PasswordLength * 2,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash);
}
else
{
ntlm_fetch_ntlm_v2_hash(context, hash);
}
return 1;
}
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
{
char* response;
char value[16];
char ntlm_v2_hash[16];
BYTE* response;
BYTE value[16];
if (context->LmCompatibilityLevel < 2)
{
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24);
if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
return -1;
ZeroMemory(context->LmChallengeResponse.pvBuffer, 24);
return;
return 1;
}
/* Compute the NTLMv2 hash */
ntlm_compute_ntlm_v2_hash(context, ntlm_v2_hash);
if (ntlm_compute_ntlm_v2_hash(context, context->NtlmV2Hash) < 0)
return -1;
/* Concatenate the server and client challenges */
CopyMemory(value, context->ServerChallenge, 8);
CopyMemory(&value[8], context->ClientChallenge, 8);
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24);
response = (char*) context->LmChallengeResponse.pvBuffer;
if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
return -1;
response = (BYTE*) context->LmChallengeResponse.pvBuffer;
/* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) value, 16, (void*) response, NULL);
HMAC(EVP_md5(), (void*) context->NtlmV2Hash, 16, (BYTE*) value, 16, (BYTE*) response, NULL);
/* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */
CopyMemory(&response[16], context->ClientChallenge, 8);
return 1;
}
/**
@ -367,10 +381,9 @@ void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
* @param NTLM context
*/
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
{
BYTE* blob;
BYTE ntlm_v2_hash[16];
BYTE nt_proof_str[16];
SecBuffer ntlm_v2_temp;
SecBuffer ntlm_v2_temp_chal;
@ -378,13 +391,16 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
TargetInfo = &context->ChallengeTargetInfo;
sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28);
if (!sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28))
return -1;
ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
blob = (BYTE*) ntlm_v2_temp.pvBuffer;
/* Compute the NTLMv2 hash */
ntlm_compute_ntlm_v2_hash(context, (char*) ntlm_v2_hash);
if (ntlm_compute_ntlm_v2_hash(context, (BYTE*) context->NtlmV2Hash) < 0)
return -1;
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "Password (length = %d)\n", context->identity.PasswordLength * 2);
@ -404,7 +420,7 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
fprintf(stderr, "\n");
fprintf(stderr, "NTOWFv2, NTLMv2 Hash\n");
winpr_HexDump(ntlm_v2_hash, 16);
winpr_HexDump(context->NtlmV2Hash, 16);
fprintf(stderr, "\n");
#endif
@ -425,25 +441,33 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
#endif
/* Concatenate server challenge with temp */
sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8);
if (!sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8))
return -1;
blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer;
CopyMemory(blob, context->ServerChallenge, 8);
CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, ntlm_v2_temp_chal.pvBuffer,
ntlm_v2_temp_chal.cbBuffer, (void*) nt_proof_str, NULL);
HMAC(EVP_md5(), (BYTE*) context->NtlmV2Hash, 16, (BYTE*) ntlm_v2_temp_chal.pvBuffer,
ntlm_v2_temp_chal.cbBuffer, (BYTE*) nt_proof_str, NULL);
/* NtChallengeResponse, Concatenate NTProofStr with temp */
sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16);
if (!sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16))
return -1;
blob = (BYTE*) context->NtChallengeResponse.pvBuffer;
CopyMemory(blob, nt_proof_str, 16);
CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
/* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) nt_proof_str, 16, (void*) context->SessionBaseKey, NULL);
HMAC(EVP_md5(), (BYTE*) context->NtlmV2Hash, 16, (BYTE*) nt_proof_str, 16, (BYTE*) context->SessionBaseKey, NULL);
sspi_SecBufferFree(&ntlm_v2_temp);
sspi_SecBufferFree(&ntlm_v2_temp_chal);
return 1;
}
/**
@ -548,7 +572,7 @@ void ntlm_decrypt_random_session_key(NTLM_CONTEXT* context)
* @param signing_key Destination signing key
*/
void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, BYTE* signing_key)
int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, BYTE* signing_key)
{
int length;
BYTE* value;
@ -557,6 +581,9 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
length = 16 + sign_magic->cbBuffer;
value = (BYTE*) malloc(length);
if (!value)
return -1;
/* Concatenate ExportedSessionKey with sign magic */
CopyMemory(value, exported_session_key, 16);
CopyMemory(&value[16], sign_magic->pvBuffer, sign_magic->cbBuffer);
@ -566,6 +593,8 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
MD5_Final(signing_key, &md5);
free(value);
return 1;
}
/**
@ -576,10 +605,12 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
void ntlm_generate_client_signing_key(NTLM_CONTEXT* context)
{
SecBuffer sign_magic;
sign_magic.pvBuffer = (void*) client_sign_magic;
sign_magic.cbBuffer = sizeof(client_sign_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &sign_magic, context->ClientSigningKey);
SecBuffer signMagic;
signMagic.pvBuffer = (void*) NTLM_CLIENT_SIGN_MAGIC;
signMagic.cbBuffer = sizeof(NTLM_CLIENT_SIGN_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &signMagic, context->ClientSigningKey);
}
/**
@ -590,10 +621,12 @@ void ntlm_generate_client_signing_key(NTLM_CONTEXT* context)
void ntlm_generate_server_signing_key(NTLM_CONTEXT* context)
{
SecBuffer sign_magic;
sign_magic.pvBuffer = (void*) server_sign_magic;
sign_magic.cbBuffer = sizeof(server_sign_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &sign_magic, context->ServerSigningKey);
SecBuffer signMagic;
signMagic.pvBuffer = (void*) NTLM_SERVER_SIGN_MAGIC;
signMagic.cbBuffer = sizeof(NTLM_SERVER_SIGN_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &signMagic, context->ServerSigningKey);
}
/**
@ -604,13 +637,15 @@ void ntlm_generate_server_signing_key(NTLM_CONTEXT* context)
* @param sealing_key Destination sealing key
*/
void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key)
int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key)
{
BYTE* p;
MD5_CTX md5;
SecBuffer buffer;
sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer);
if (!sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer))
return -1;
p = (BYTE*) buffer.pvBuffer;
/* Concatenate ExportedSessionKey with seal magic */
@ -622,6 +657,8 @@ void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic
MD5_Final(sealing_key, &md5);
sspi_SecBufferFree(&buffer);
return 1;
}
/**
@ -632,10 +669,12 @@ void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic
void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context)
{
SecBuffer seal_magic;
seal_magic.pvBuffer = (void*) client_seal_magic;
seal_magic.cbBuffer = sizeof(client_seal_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &seal_magic, context->ClientSealingKey);
SecBuffer sealMagic;
sealMagic.pvBuffer = (void*) NTLM_CLIENT_SEAL_MAGIC;
sealMagic.cbBuffer = sizeof(NTLM_CLIENT_SEAL_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &sealMagic, context->ClientSealingKey);
}
/**
@ -646,10 +685,12 @@ void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context)
void ntlm_generate_server_sealing_key(NTLM_CONTEXT* context)
{
SecBuffer seal_magic;
seal_magic.pvBuffer = (void*) server_seal_magic;
seal_magic.cbBuffer = sizeof(server_seal_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &seal_magic, context->ServerSealingKey);
SecBuffer sealMagic;
sealMagic.pvBuffer = (void*) NTLM_SERVER_SEAL_MAGIC;
sealMagic.cbBuffer = sizeof(NTLM_SERVER_SEAL_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &sealMagic, context->ServerSealingKey);
}
/**
@ -690,9 +731,9 @@ void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context)
HMAC_CTX_init(&hmac_ctx);
HMAC_Init_ex(&hmac_ctx, context->ExportedSessionKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac_ctx, context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
HMAC_Update(&hmac_ctx, context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
HMAC_Final(&hmac_ctx, context->MessageIntegrityCheck, NULL);
HMAC_CTX_cleanup(&hmac_ctx);
}

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package (Compute)
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,24 +25,22 @@
#include "ntlm_av_pairs.h"
void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo);
void ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo);
int ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo);
void ntlm_write_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo);
void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo);
void ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
void ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
int ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
int ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context);
void ntlm_output_target_name(NTLM_CONTEXT* context);
void ntlm_output_channel_bindings(NTLM_CONTEXT* context);
void ntlm_current_time(BYTE* timestamp);
void ntlm_generate_timestamp(NTLM_CONTEXT* context);
void ntlm_compute_ntlm_hash(UINT16* password, UINT32 length, char* hash);
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash);
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context);
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash);
int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context);
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext);
void ntlm_generate_client_challenge(NTLM_CONTEXT* context);

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package (Message)
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,4 +29,6 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer);
SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer);
SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context);
#endif /* WINPR_SSPI_NTLM_MESSAGE_H */

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* Negotiate Security Package
*
* Copyright 2011-2012 Jiten Pathy
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,67 +28,27 @@
#include "../sspi.h"
extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;
char* NEGOTIATE_PACKAGE_NAME = "Negotiate";
SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
NEGOTIATE_CONTEXT* context;
CREDENTIALS* credentials;
PSecBuffer output_SecBuffer;
context = sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = negotiate_ContextNew();
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
}
if ((!pInput) && (context->state == NEGOTIATE_STATE_INITIAL))
{
if (!pOutput)
return SEC_E_INVALID_TOKEN;
if (pOutput->cBuffers < 1)
return SEC_E_INVALID_TOKEN;
output_SecBuffer = &pOutput->pBuffers[0];
if (output_SecBuffer->cbBuffer < 1)
return SEC_E_INSUFFICIENT_MEMORY;
}
return SEC_E_OK;
}
NEGOTIATE_CONTEXT* negotiate_ContextNew()
{
NEGOTIATE_CONTEXT* context;
context = (NEGOTIATE_CONTEXT*) calloc(1, sizeof(NEGOTIATE_CONTEXT));
if (context != NULL)
{
context->NegotiateFlags = 0;
context->state = NEGOTIATE_STATE_INITIAL;
}
if (!context)
return NULL;
context->NegotiateFlags = 0;
context->state = NEGOTIATE_STATE_INITIAL;
SecInvalidateHandle(&(context->SubContext));
context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA;
context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW;
return context;
}
@ -101,21 +61,262 @@ void negotiate_ContextFree(NEGOTIATE_CONTEXT* context)
free(context);
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
SECURITY_STATUS status;
NEGOTIATE_CONTEXT* context;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = negotiate_ContextNew();
if (!context)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
}
status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext),
pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
pOutput, pfContextAttr, ptsExpiry);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
SECURITY_STATUS status;
NEGOTIATE_CONTEXT* context;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = negotiate_ContextNew();
if (!context)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
}
status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext),
pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
pOutput, pfContextAttr, ptsExpiry);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext,
PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
{
SECURITY_STATUS status;
NEGOTIATE_CONTEXT* context;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = negotiate_ContextNew();
if (!context)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
}
status = context->sspiA->AcceptSecurityContext(phCredential, &(context->SubContext),
pInput, fContextReq, TargetDataRep, &(context->SubContext),
pOutput, pfContextAttr, ptsTimeStamp);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
return SEC_E_INVALID_HANDLE;
if (context->sspiW->CompleteAuthToken)
status = context->sspiW->CompleteAuthToken(phContext, pToken);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
return SEC_E_INVALID_HANDLE;
if (context->sspiW->DeleteSecurityContext)
status = context->sspiW->DeleteSecurityContext(&(context->SubContext));
negotiate_ContextFree(context);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_ImpersonateSecurityContext(PCtxtHandle phContext)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (context->sspiW->ImpersonateSecurityContext)
status = context->sspiW->ImpersonateSecurityContext(&(context->SubContext));
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (context->sspiW->RevertSecurityContext)
status = context->sspiW->RevertSecurityContext(&(context->SubContext));
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
return SEC_E_UNSUPPORTED_FUNCTION;
if (context->sspiW->QueryContextAttributesW)
status = context->sspiW->QueryContextAttributesW(&(context->SubContext), ulAttribute, pBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiA->QueryContextAttributesA)
status = context->sspiA->QueryContextAttributesA(&(context->SubContext), ulAttribute, pBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiW->SetContextAttributesW)
status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer, cbBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiA->SetContextAttributesA)
status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer, cbBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
(fCredentialUse != SECPKG_CRED_INBOUND) &&
(fCredentialUse != SECPKG_CRED_BOTH))
{
return SEC_E_INVALID_PARAMETER;
}
credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INTERNAL_ERROR;
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity)
sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME);
return SEC_E_OK;
}
@ -123,52 +324,54 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrinc
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND)
if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
(fCredentialUse != SECPKG_CRED_INBOUND) &&
(fCredentialUse != SECPKG_CRED_BOTH))
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
memcpy(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME);
return SEC_E_OK;
return SEC_E_INVALID_PARAMETER;
}
credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INTERNAL_ERROR;
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity)
sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME);
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{
if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
{
CREDENTIALS* credentials;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredential)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
if (!phCredential)
return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials)
return SEC_E_INVALID_HANDLE;
@ -180,22 +383,54 @@ SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredenti
SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
return SEC_E_OK;
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (context->sspiW->EncryptMessage)
status = context->sspiW->EncryptMessage(&(context->SubContext), fQOP, pMessage, MessageSeqNo);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{
return SEC_E_OK;
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (context->sspiW->DecryptMessage)
status = context->sspiW->DecryptMessage(&(context->SubContext), pMessage, MessageSeqNo, pfQOP);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
return SEC_E_OK;
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (context->sspiW->MakeSignature)
status = context->sspiW->MakeSignature(&(context->SubContext), fQOP, pMessage, MessageSeqNo);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{
return SEC_E_OK;
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (context->sspiW->VerifySignature)
status = context->sspiW->VerifySignature(&(context->SubContext), pMessage, MessageSeqNo, pfQOP);
return status;
}
const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
@ -207,13 +442,13 @@ const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
negotiate_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */
negotiate_InitializeSecurityContextA, /* InitializeSecurityContext */
NULL, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
NULL, /* DeleteSecurityContext */
negotiate_AcceptSecurityContext, /* AcceptSecurityContext */
negotiate_CompleteAuthToken, /* CompleteAuthToken */
negotiate_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
negotiate_QueryContextAttributes, /* QueryContextAttributes */
NULL, /* ImpersonateSecurityContext */
NULL, /* RevertSecurityContext */
negotiate_QueryContextAttributesA, /* QueryContextAttributes */
negotiate_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
negotiate_RevertSecurityContext, /* RevertSecurityContext */
negotiate_MakeSignature, /* MakeSignature */
negotiate_VerifySignature, /* VerifySignature */
NULL, /* FreeContextBuffer */
@ -227,7 +462,7 @@ const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
NULL, /* QuerySecurityContextToken */
negotiate_EncryptMessage, /* EncryptMessage */
negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
negotiate_SetContextAttributesA, /* SetContextAttributes */
};
const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
@ -239,13 +474,13 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
negotiate_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */
negotiate_InitializeSecurityContextW, /* InitializeSecurityContext */
NULL, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
NULL, /* DeleteSecurityContext */
negotiate_AcceptSecurityContext, /* AcceptSecurityContext */
negotiate_CompleteAuthToken, /* CompleteAuthToken */
negotiate_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
negotiate_QueryContextAttributes, /* QueryContextAttributes */
NULL, /* ImpersonateSecurityContext */
NULL, /* RevertSecurityContext */
negotiate_QueryContextAttributesW, /* QueryContextAttributes */
negotiate_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
negotiate_RevertSecurityContext, /* RevertSecurityContext */
negotiate_MakeSignature, /* MakeSignature */
negotiate_VerifySignature, /* VerifySignature */
NULL, /* FreeContextBuffer */
@ -259,7 +494,7 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
NULL, /* QuerySecurityContextToken */
negotiate_EncryptMessage, /* EncryptMessage */
negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
negotiate_SetContextAttributesW, /* SetContextAttributes */
};
const SecPkgInfoA NEGOTIATE_SecPkgInfoA =

View File

@ -40,8 +40,12 @@ struct _NEGOTIATE_CONTEXT
NEGOTIATE_STATE state;
UINT32 NegotiateFlags;
PCtxtHandle auth_ctx;
SEC_WINNT_AUTH_IDENTITY identity;
SecBuffer NegoInitMessage;
CtxtHandle SubContext;
SecurityFunctionTableA* sspiA;
SecurityFunctionTableW* sspiW;
};
typedef struct _NEGOTIATE_CONTEXT NEGOTIATE_CONTEXT;

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* Schannel Security Package
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* Schannel Security Package (OpenSSL)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -280,7 +280,7 @@ SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context
if (status > 0)
{
if (pBuffer->cbBuffer < status)
if (pBuffer->cbBuffer < (unsigned long) status)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
@ -339,7 +339,7 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context
if (status > 0)
{
if (pBuffer->cbBuffer < status)
if (pBuffer->cbBuffer < (unsigned long) status)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
@ -387,17 +387,17 @@ SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSec
if (status > 0)
{
offset = 0;
length = (pStreamHeaderBuffer->cbBuffer > status) ? status : pStreamHeaderBuffer->cbBuffer;
length = (pStreamHeaderBuffer->cbBuffer > (unsigned long) status) ? status : pStreamHeaderBuffer->cbBuffer;
CopyMemory(pStreamHeaderBuffer->pvBuffer, &context->ReadBuffer[offset], length);
status -= length;
offset += length;
length = (pStreamBodyBuffer->cbBuffer > status) ? status : pStreamBodyBuffer->cbBuffer;
length = (pStreamBodyBuffer->cbBuffer > (unsigned long) status) ? status : pStreamBodyBuffer->cbBuffer;
CopyMemory(pStreamBodyBuffer->pvBuffer, &context->ReadBuffer[offset], length);
status -= length;
offset += length;
length = (pStreamTrailerBuffer->cbBuffer > status) ? status : pStreamTrailerBuffer->cbBuffer;
length = (pStreamTrailerBuffer->cbBuffer > (unsigned long) status) ? status : pStreamTrailerBuffer->cbBuffer;
CopyMemory(pStreamTrailerBuffer->pvBuffer, &context->ReadBuffer[offset], length);
status -= length;
}

View File

@ -1,3 +1,34 @@
LIBRARY "libwinpr-sspi"
EXPORTS
AcceptSecurityContext
AcquireCredentialsHandleA
AcquireCredentialsHandleW
ApplyControlToken
CompleteAuthToken
DecryptMessage
DeleteSecurityContext
EncryptMessage
EnumerateSecurityPackagesA
EnumerateSecurityPackagesW
ExportSecurityContext
FreeContextBuffer
FreeCredentialsHandle
ImpersonateSecurityContext
ImportSecurityContextA
ImportSecurityContextW
InitSecurityInterfaceA
InitSecurityInterfaceW
InitializeSecurityContextA
InitializeSecurityContextW
MakeSignature
QueryContextAttributesA
QueryContextAttributesW
QueryCredentialsAttributesA
QueryCredentialsAttributesW
QuerySecurityContextToken
QuerySecurityPackageInfoA
QuerySecurityPackageInfoW
RevertSecurityContext
VerifySignature
InitSecurityInterfaceExA
InitSecurityInterfaceExW

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* Security Support Provider Interface (SSPI)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,20 +28,22 @@
#define SSPI_CREDENTIALS_HASH_LENGTH_FACTOR 64
struct _CREDENTIALS
struct _SSPI_CREDENTIALS
{
DWORD flags;
ULONG fCredentialUse;
SEC_GET_KEY_FN pGetKeyFn;
void* pvGetKeyArgument;
SEC_WINNT_AUTH_IDENTITY identity;
};
typedef struct _CREDENTIALS CREDENTIALS;
typedef struct _SSPI_CREDENTIALS SSPI_CREDENTIALS;
CREDENTIALS* sspi_CredentialsNew(void);
void sspi_CredentialsFree(CREDENTIALS* credentials);
SSPI_CREDENTIALS* sspi_CredentialsNew(void);
void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials);
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType);
SecHandle* sspi_SecureHandleAlloc(void);
void sspi_SecureHandleInit(SecHandle* handle);
void sspi_SecureHandleInvalidate(SecHandle* handle);
void* sspi_SecureHandleGetLowerPointer(SecHandle* handle);
void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer);
@ -81,4 +83,6 @@ enum SecurityFunctionTableIndex
SetContextAttributesIndex = 28
};
#include "sspi_winpr.h"
#endif /* WINPR_SSPI_PRIVATE_H */

View File

@ -0,0 +1,289 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Security Support Provider Interface (SSPI)
*
* Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef _WIN32
#define SEC_ENTRY __stdcall
#define SSPI_EXPORT __declspec(dllexport)
#else
#define SEC_ENTRY
#define SSPI_EXPORT
#endif
typedef long LONG;
typedef unsigned long ULONG;
typedef LONG SECURITY_STATUS;
/**
* Standard SSPI API
*/
/* Package Management */
extern SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesW(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesW(void* pcPackages, void* ppPackageInfo)
{
return sspi_EnumerateSecurityPackagesW(pcPackages, ppPackageInfo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesA(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesA(void* pcPackages, void* ppPackageInfo)
{
return sspi_EnumerateSecurityPackagesA(pcPackages, ppPackageInfo);
}
extern void* SEC_ENTRY sspi_InitSecurityInterfaceW(void);
SSPI_EXPORT void* SEC_ENTRY InitSecurityInterfaceW(void)
{
return sspi_InitSecurityInterfaceW();
}
extern void* SEC_ENTRY sspi_InitSecurityInterfaceA(void);
SSPI_EXPORT void* SEC_ENTRY InitSecurityInterfaceA(void)
{
return sspi_InitSecurityInterfaceA();
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoW(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW(void* pszPackageName, void* ppPackageInfo)
{
return sspi_QuerySecurityPackageInfoW(pszPackageName, ppPackageInfo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoA(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoA(void* pszPackageName, void* ppPackageInfo)
{
return sspi_QuerySecurityPackageInfoA(pszPackageName, ppPackageInfo);
}
/* Credential Management */
extern SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleW(void*, void*, ULONG, void*, void*, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleW(void* pszPrincipal, void* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn,
void* pvGetKeyArgument, void* phCredential, void* ptsExpiry)
{
return sspi_AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse,
pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleA(void*, void*, ULONG, void*, void*, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleA(void* pszPrincipal, void* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn,
void* pvGetKeyArgument, void* phCredential, void* ptsExpiry)
{
return sspi_AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse,
pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ExportSecurityContext(void*, ULONG, void*, void**);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ExportSecurityContext(void* phContext, ULONG fFlags, void* pPackedContext, void** pToken)
{
return sspi_ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_FreeCredentialsHandle(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY FreeCredentialsHandle(void* phCredential)
{
return sspi_FreeCredentialsHandle(phCredential);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextW(void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImportSecurityContextW(void* pszPackage, void* pPackedContext, void* pToken, void* phContext)
{
return sspi_ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextA(void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImportSecurityContextA(void* pszPackage, void* pPackedContext, void* pToken, void* phContext)
{
return sspi_ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesW(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesW(void* phCredential, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesA(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesA(void* phCredential, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
}
/* Context Management */
extern SECURITY_STATUS SEC_ENTRY sspi_AcceptSecurityContext(void*, void*, void*, ULONG, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcceptSecurityContext(void* phCredential, void* phContext,
void* pInput, ULONG fContextReq, ULONG TargetDataRep, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsTimeStamp)
{
return sspi_AcceptSecurityContext(phCredential, phContext, pInput, fContextReq,
TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ApplyControlToken(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ApplyControlToken(void* phContext, void* pInput)
{
return sspi_ApplyControlToken(phContext, pInput);
}
extern SECURITY_STATUS SEC_ENTRY sspi_CompleteAuthToken(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY CompleteAuthToken(void* phContext, void* pToken)
{
return sspi_CompleteAuthToken(phContext, pToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_DeleteSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY DeleteSecurityContext(void* phContext)
{
return sspi_DeleteSecurityContext(phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_FreeContextBuffer(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY FreeContextBuffer(void* pvContextBuffer)
{
return sspi_FreeContextBuffer(pvContextBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImpersonateSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImpersonateSecurityContext(void* phContext)
{
return sspi_ImpersonateSecurityContext(phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextW(void*, void*, void*, ULONG, ULONG, ULONG,
void*, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW(void* phCredential, void* phContext,
void* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
void* pInput, ULONG Reserved2, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsExpiry)
{
return sspi_InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq, Reserved1,
TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextA(void*, void*, void*, ULONG, ULONG, ULONG,
void*, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY InitializeSecurityContextA(void* phCredential, void* phContext,
void* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
void* pInput, ULONG Reserved2, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsExpiry)
{
return sspi_InitializeSecurityContextA(phCredential, phContext, pszTargetName, fContextReq, Reserved1,
TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesW(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryContextAttributesW(void* phContext, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesA(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryContextAttributesA(void* phContext, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryContextAttributesA(phContext, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityContextToken(void*, void**);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityContextToken(void* phContext, void** phToken)
{
return sspi_QuerySecurityContextToken(phContext, phToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesW(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY SetContextAttributesW(void* phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return sspi_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesA(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY SetContextAttributesA(void* phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return sspi_SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_RevertSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY RevertSecurityContext(void* phContext)
{
return sspi_RevertSecurityContext(phContext);
}
/* Message Support */
extern SECURITY_STATUS SEC_ENTRY sspi_DecryptMessage(void*, void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY DecryptMessage(void* phContext, void* pMessage, ULONG MessageSeqNo, void* pfQOP)
{
return sspi_DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
}
extern SECURITY_STATUS SEC_ENTRY sspi_EncryptMessage(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EncryptMessage(void* phContext, ULONG fQOP, void* pMessage, ULONG MessageSeqNo)
{
return sspi_EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_MakeSignature(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY MakeSignature(void* phContext, ULONG fQOP, void* pMessage, ULONG MessageSeqNo)
{
return sspi_MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_VerifySignature(void*, void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY VerifySignature(void* phContext, void* pMessage, ULONG MessageSeqNo, void* pfQOP)
{
return sspi_VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/**
* WinPR: Windows Portable Runtime
* config.h definitions for installable headers
* Security Support Provider Interface (SSPI)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,16 +17,12 @@
* limitations under the License.
*/
#ifndef WINPR_CONFIG_H
#define WINPR_CONFIG_H
#ifndef WINPR_SSPI_WINPR_H
#define WINPR_SSPI_WINPR_H
/*
* This generated config.h header is meant for installation, which is why
* all definitions MUST be prefixed to avoid conflicting with third-party
* libraries. Only add configurable definitions which really must be used
* from installable headers, such as the base type definition types.
*/
#include <winpr/sspi.h>
#cmakedefine WITH_NATIVE_SSPI
SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void);
SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void);
#endif /* WINPR_CONFIG_H */
#endif /* WINPR_SSPI_WINPR_H */

View File

@ -9,8 +9,9 @@ set(${MODULE_PREFIX}_TESTS
TestEnumerateSecurityPackages.c
TestInitializeSecurityContext.c
TestAcquireCredentialsHandle.c
TestNTLM.c
)
TestCredSSP.c
TestSchannel.c
TestNTLM.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}

View File

@ -0,0 +1,8 @@
#include <winpr/crt.h>
#include <winpr/sspi.h>
int TestCredSSP(int argc, char* argv[])
{
return 0;
}

View File

@ -1,59 +1,546 @@
#include <winpr/crt.h>
#include <winpr/sspi.h>
#include <winpr/print.h>
BYTE test_Certificate[] =
"\x30\x82\x02\x09\x30\x82\x01\x76\xa0\x03\x02\x01\x02\x02\x10\xcb"
"\x69\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30"
"\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x30\x16\x31\x14\x30\x12"
"\x06\x03\x55\x04\x03\x13\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38"
"\x52\x32\x30\x1e\x17\x0d\x31\x32\x31\x31\x31\x37\x30\x30\x35\x39"
"\x32\x31\x5a\x17\x0d\x33\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35"
"\x39\x5a\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x44"
"\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x30\x81\x9f\x30\x0d\x06"
"\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00"
"\x30\x81\x89\x02\x81\x81\x00\x9b\x00\xf8\x1a\x2d\x37\xc6\x8d\xa1"
"\x39\x91\x46\xf3\x6a\x1b\xf9\x60\x6c\xb3\x6c\xa0\xac\xed\x85\xe0"
"\x3f\xdc\x92\x86\x36\xbd\x64\xbf\x36\x51\xdb\x57\x3a\x8a\x82\x6b"
"\xd8\x94\x17\x7b\xd3\x91\x11\x98\xef\x19\x06\x52\x30\x03\x73\x67"
"\xc8\xed\x8e\xfa\x0b\x3d\x4c\xc9\x10\x63\x9f\xcf\xb4\xcf\x39\xd8"
"\xfe\x99\xeb\x5b\x11\xf2\xfc\xfa\x86\x24\xd9\xff\xd9\x19\xf5\x69"
"\xb4\xdf\x5a\x5a\xc4\x94\xb4\xb0\x07\x25\x97\x13\xad\x7e\x38\x14"
"\xfb\xd6\x33\x65\x6f\xe6\xf7\x48\x4b\x2d\xb3\x51\x2e\x6d\xc7\xea"
"\x11\x76\x9a\x2b\xf0\x00\x4d\x02\x03\x01\x00\x01\xa3\x60\x30\x5e"
"\x30\x13\x06\x03\x55\x1d\x25\x04\x0c\x30\x0a\x06\x08\x2b\x06\x01"
"\x05\x05\x07\x03\x01\x30\x47\x06\x03\x55\x1d\x01\x04\x40\x30\x3e"
"\x80\x10\xeb\x65\x26\x03\x95\x4b\xd6\xc0\x54\x75\x78\x7c\xb6\x2a"
"\xa1\xbb\xa1\x18\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13"
"\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x82\x10\xcb\x69"
"\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30\x09"
"\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x03\x81\x81\x00\x7b\xfa\xfe"
"\xee\x74\x05\xac\xbb\x79\xe9\xda\xca\x00\x44\x96\x94\x71\x92\xb1"
"\xdb\xc9\x9b\x71\x29\xc0\xe4\x28\x5e\x6a\x50\x99\xcd\xa8\x17\xe4"
"\x56\xb9\xef\x7f\x02\x7d\x96\xa3\x48\x14\x72\x75\x2f\xb0\xb5\x87"
"\xee\x55\xe9\x6a\x6d\x28\x3c\xc1\xfd\x00\xe4\x76\xe3\x80\x88\x78"
"\x26\x0d\x6c\x8c\xb8\x64\x61\x63\xb7\x13\x3a\xab\xc7\xdd\x1d\x0a"
"\xd7\x15\x45\xa1\xd6\xd9\x34\xc7\x21\x48\xfb\x43\x87\x38\xda\x1f"
"\x50\x47\xb1\xa5\x5c\x47\xed\x04\x44\x97\xd3\xac\x74\x2d\xeb\x09"
"\x77\x59\xbf\xa3\x54\x5b\xde\x42\xd5\x23\x5a\x71\x9f";
#define TEST_SSPI_INTERFACE SSPI_INTERFACE_WINPR
BYTE test_Certificate_SHA256Hash[] =
"\xea\x05\xfe\xfe\xcc\x6b\x0b\xd5\x71\xdb\xbc\x5b\xaa\x3e\xd4\x53"
"\x86\xd0\x44\x68\x35\xf7\xb7\x4c\x85\x62\x1b\x99\x83\x47\x5f\x95";
static const char* TEST_NTLM_USER = "Username";
static const char* TEST_NTLM_DOMAIN = "Domain";
static const char* TEST_NTLM_PASSWORD = "P4ss123!";
BYTE test_ChannelBindings_MD5Hash[] =
"\x65\x86\xE9\x9D\x81\xC2\xFC\x98\x4E\x47\x17\x2F\xD4\xDD\x03\x10";
//static const char* TEST_NTLM_HASH_STRING = "d5922a65c4d5c082ca444af1be0001db";
int test_ntlm_channel_binding_token()
static const BYTE TEST_NTLM_HASH[16] =
{ 0xd5, 0x92, 0x2a, 0x65, 0xc4, 0xd5, 0xc0, 0x82, 0xca, 0x44, 0x4a, 0xf1, 0xbe, 0x00, 0x01, 0xdb };
//#define NTLM_PACKAGE_NAME NEGOSSP_NAME
#define NTLM_PACKAGE_NAME NTLMSP_NAME
struct _TEST_NTLM_CLIENT
{
CtxtHandle context;
ULONG cbMaxToken;
ULONG fContextReq;
ULONG pfContextAttr;
TimeStamp expiration;
PSecBuffer pBuffer;
SecBuffer inputBuffer[2];
SecBuffer outputBuffer[2];
BOOL haveContext;
BOOL haveInputBuffer;
LPTSTR ServicePrincipalName;
SecBufferDesc inputBufferDesc;
SecBufferDesc outputBufferDesc;
CredHandle credentials;
BOOL confidentiality;
SecPkgInfo* pPackageInfo;
SecurityFunctionTable* table;
SEC_WINNT_AUTH_IDENTITY identity;
};
typedef struct _TEST_NTLM_CLIENT TEST_NTLM_CLIENT;
return 0;
int test_ntlm_client_init(TEST_NTLM_CLIENT* ntlm, const char* user, const char* domain, const char* password)
{
SECURITY_STATUS status;
SecInvalidateHandle(&(ntlm->context));
ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE);
sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password);
status = ntlm->table->QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &ntlm->pPackageInfo);
if (status != SEC_E_OK)
{
fprintf(stderr, "QuerySecurityPackageInfo status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1;
}
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration);
if (status != SEC_E_OK)
{
fprintf(stderr, "AcquireCredentialsHandle status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1;
}
ntlm->haveContext = FALSE;
ntlm->haveInputBuffer = FALSE;
ZeroMemory(&ntlm->inputBuffer, sizeof(SecBuffer));
ZeroMemory(&ntlm->outputBuffer, sizeof(SecBuffer));
ntlm->fContextReq = 0;
#if 0
/* HTTP authentication flags */
ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY;
#endif
/* NLA authentication flags */
ntlm->fContextReq |= ISC_REQ_MUTUAL_AUTH;
ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY;
ntlm->fContextReq |= ISC_REQ_USE_SESSION_KEY;
return 1;
}
void test_ntlm_client_uninit(TEST_NTLM_CLIENT* ntlm)
{
if (!ntlm)
return;
if (ntlm->outputBuffer[0].pvBuffer)
{
free(ntlm->outputBuffer[0].pvBuffer);
ntlm->outputBuffer[0].pvBuffer = NULL;
}
free(ntlm->identity.User);
free(ntlm->identity.Domain);
free(ntlm->identity.Password);
free(ntlm->ServicePrincipalName);
if (ntlm->table)
{
ntlm->table->FreeCredentialsHandle(&ntlm->credentials);
ntlm->table->FreeContextBuffer(ntlm->pPackageInfo);
ntlm->table->DeleteSecurityContext(&ntlm->context);
}
}
/**
* SSPI Client Ceremony
*
* --------------
* ( Client Begin )
* --------------
* |
* |
* \|/
* -----------+--------------
* | AcquireCredentialsHandle |
* --------------------------
* |
* |
* \|/
* -------------+--------------
* +---------------> / InitializeSecurityContext /
* | ----------------------------
* | |
* | |
* | \|/
* --------------------------- ---------+------------- ----------------------
* / Receive blob from server / < Received security blob? > --Yes-> / Send blob to server /
* -------------+------------- ----------------------- ----------------------
* /|\ | |
* | No |
* Yes \|/ |
* | ------------+----------- |
* +---------------- < Received Continue Needed > <-----------------+
* ------------------------
* |
* No
* \|/
* ------+-------
* ( Client End )
* --------------
*/
int test_ntlm_client_authenticate(TEST_NTLM_CLIENT* ntlm)
{
SECURITY_STATUS status;
if (ntlm->outputBuffer[0].pvBuffer)
{
free(ntlm->outputBuffer[0].pvBuffer);
ntlm->outputBuffer[0].pvBuffer = NULL;
}
ntlm->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->outputBufferDesc.cBuffers = 1;
ntlm->outputBufferDesc.pBuffers = ntlm->outputBuffer;
ntlm->outputBuffer[0].BufferType = SECBUFFER_TOKEN;
ntlm->outputBuffer[0].cbBuffer = ntlm->cbMaxToken;
ntlm->outputBuffer[0].pvBuffer = malloc(ntlm->outputBuffer[0].cbBuffer);
if (!ntlm->outputBuffer[0].pvBuffer)
return -1;
if (ntlm->haveInputBuffer)
{
ntlm->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->inputBufferDesc.cBuffers = 1;
ntlm->inputBufferDesc.pBuffers = ntlm->inputBuffer;
ntlm->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
}
if ((!ntlm) || (!ntlm->table))
{
fprintf(stderr, "ntlm_authenticate: invalid ntlm context\n");
return -1;
}
status = ntlm->table->InitializeSecurityContext(&ntlm->credentials,
(ntlm->haveContext) ? &ntlm->context : NULL,
(ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : NULL,
ntlm->fContextReq, 0, SECURITY_NATIVE_DREP,
(ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : NULL,
0, &ntlm->context, &ntlm->outputBufferDesc,
&ntlm->pfContextAttr, &ntlm->expiration);
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{
if (ntlm->table->CompleteAuthToken)
ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
}
if (ntlm->haveInputBuffer)
{
free(ntlm->inputBuffer[0].pvBuffer);
}
ntlm->haveInputBuffer = TRUE;
ntlm->haveContext = TRUE;
return (status == SEC_I_CONTINUE_NEEDED) ? 1 : 0;
}
TEST_NTLM_CLIENT* test_ntlm_client_new()
{
TEST_NTLM_CLIENT* ntlm;
ntlm = (TEST_NTLM_CLIENT*) calloc(1, sizeof(TEST_NTLM_CLIENT));
if (!ntlm)
return NULL;
return ntlm;
}
void test_ntlm_client_free(TEST_NTLM_CLIENT* ntlm)
{
if (!ntlm)
return;
test_ntlm_client_uninit(ntlm);
free(ntlm);
}
struct _TEST_NTLM_SERVER
{
CtxtHandle context;
ULONG cbMaxToken;
ULONG fContextReq;
ULONG pfContextAttr;
TimeStamp expiration;
PSecBuffer pBuffer;
SecBuffer inputBuffer[2];
SecBuffer outputBuffer[2];
BOOL haveContext;
BOOL haveInputBuffer;
LPTSTR ServicePrincipalName;
SecBufferDesc inputBufferDesc;
SecBufferDesc outputBufferDesc;
CredHandle credentials;
BOOL confidentiality;
SecPkgInfo* pPackageInfo;
SecurityFunctionTable* table;
SEC_WINNT_AUTH_IDENTITY identity;
};
typedef struct _TEST_NTLM_SERVER TEST_NTLM_SERVER;
int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm)
{
SECURITY_STATUS status;
SecInvalidateHandle(&(ntlm->context));
ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE);
status = ntlm->table->QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &ntlm->pPackageInfo);
if (status != SEC_E_OK)
{
fprintf(stderr, "QuerySecurityPackageInfo status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1;
}
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL,
&ntlm->credentials, &ntlm->expiration);
if (status != SEC_E_OK)
{
fprintf(stderr, "AcquireCredentialsHandle status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1;
}
ntlm->haveContext = FALSE;
ntlm->haveInputBuffer = FALSE;
ZeroMemory(&ntlm->inputBuffer, sizeof(SecBuffer));
ZeroMemory(&ntlm->outputBuffer, sizeof(SecBuffer));
ntlm->fContextReq = 0;
/* NLA authentication flags */
ntlm->fContextReq |= ASC_REQ_MUTUAL_AUTH;
ntlm->fContextReq |= ASC_REQ_CONFIDENTIALITY;
ntlm->fContextReq |= ASC_REQ_CONNECTION;
ntlm->fContextReq |= ASC_REQ_USE_SESSION_KEY;
ntlm->fContextReq |= ASC_REQ_REPLAY_DETECT;
ntlm->fContextReq |= ASC_REQ_SEQUENCE_DETECT;
ntlm->fContextReq |= ASC_REQ_EXTENDED_ERROR;
return 1;
}
void test_ntlm_server_uninit(TEST_NTLM_SERVER* ntlm)
{
if (!ntlm)
return;
if (ntlm->outputBuffer[0].pvBuffer)
{
free(ntlm->outputBuffer[0].pvBuffer);
ntlm->outputBuffer[0].pvBuffer = NULL;
}
free(ntlm->identity.User);
free(ntlm->identity.Domain);
free(ntlm->identity.Password);
free(ntlm->ServicePrincipalName);
if (ntlm->table)
{
ntlm->table->FreeCredentialsHandle(&ntlm->credentials);
ntlm->table->FreeContextBuffer(ntlm->pPackageInfo);
ntlm->table->DeleteSecurityContext(&ntlm->context);
}
}
int test_ntlm_server_authenticate(TEST_NTLM_SERVER* ntlm)
{
SECURITY_STATUS status;
ntlm->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->inputBufferDesc.cBuffers = 1;
ntlm->inputBufferDesc.pBuffers = ntlm->inputBuffer;
ntlm->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
ntlm->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->outputBufferDesc.cBuffers = 1;
ntlm->outputBufferDesc.pBuffers = &ntlm->outputBuffer[0];
ntlm->outputBuffer[0].BufferType = SECBUFFER_TOKEN;
ntlm->outputBuffer[0].cbBuffer = ntlm->cbMaxToken;
ntlm->outputBuffer[0].pvBuffer = malloc(ntlm->outputBuffer[0].cbBuffer);
status = ntlm->table->AcceptSecurityContext(&ntlm->credentials,
ntlm->haveContext? &ntlm->context: NULL,
&ntlm->inputBufferDesc, ntlm->fContextReq, SECURITY_NATIVE_DREP, &ntlm->context,
&ntlm->outputBufferDesc, &ntlm->pfContextAttr, &ntlm->expiration);
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{
SecPkgContext_AuthIdentity AuthIdentity;
SecPkgContext_AuthNtlmHash AuthNtlmHash;
ZeroMemory(&AuthIdentity, sizeof(SecPkgContext_AuthIdentity));
ZeroMemory(&AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_AUTH_IDENTITY, &AuthIdentity);
if (status == SEC_E_OK)
{
if (strcmp(AuthIdentity.User, TEST_NTLM_USER) == 0)
{
CopyMemory(AuthNtlmHash.NtlmHash, TEST_NTLM_HASH, 16);
status = ntlm->table->SetContextAttributes(&ntlm->context,
SECPKG_ATTR_AUTH_NTLM_HASH, &AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
}
}
if (ntlm->table->CompleteAuthToken)
status = ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
}
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
{
fprintf(stderr, "AcceptSecurityContext status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1; /* Access Denied */
}
ntlm->haveContext = TRUE;
return (status == SEC_I_CONTINUE_NEEDED) ? 1 : 0;
}
TEST_NTLM_SERVER* test_ntlm_server_new()
{
TEST_NTLM_SERVER* ntlm;
ntlm = (TEST_NTLM_SERVER*) calloc(1, sizeof(TEST_NTLM_SERVER));
if (!ntlm)
return NULL;
return ntlm;
}
void test_ntlm_server_free(TEST_NTLM_SERVER* ntlm)
{
if (!ntlm)
return;
test_ntlm_server_uninit(ntlm);
free(ntlm);
}
int TestNTLM(int argc, char* argv[])
{
if (test_ntlm_channel_binding_token() < 0)
int status;
PSecBuffer pSecBuffer;
TEST_NTLM_CLIENT* client;
TEST_NTLM_SERVER* server;
/**
* Client Initialization
*/
client = test_ntlm_client_new();
status = test_ntlm_client_init(client, TEST_NTLM_USER, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD);
if (status < 0)
{
printf("test_ntlm_client_init failure\n");
return -1;
}
/**
* Server Initialization
*/
server = test_ntlm_server_new();
status = test_ntlm_server_init(server);
if (status < 0)
{
printf("test_ntlm_server_init failure\n");
return -1;
}
/**
* Client -> Negotiate Message
*/
status = test_ntlm_client_authenticate(client);
if (status < 0)
{
printf("test_ntlm_client_authenticate failure\n");
return -1;
}
pSecBuffer = &(client->outputBuffer[0]);
fprintf(stderr, "NTLM_NEGOTIATE (length = %d):\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
/**
* Server <- Negotiate Message
* Server -> Challenge Message
*/
server->haveInputBuffer = TRUE;
server->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
server->inputBuffer[0].pvBuffer = pSecBuffer->pvBuffer;
server->inputBuffer[0].cbBuffer = pSecBuffer->cbBuffer;
status = test_ntlm_server_authenticate(server);
if (status < 0)
{
printf("test_ntlm_server_authenticate failure\n");
return -1;
}
pSecBuffer = &(server->outputBuffer[0]);
fprintf(stderr, "NTLM_CHALLENGE (length = %d):\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
/**
* Client <- Challenge Message
* Client -> Authenticate Message
*/
client->haveInputBuffer = TRUE;
client->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
client->inputBuffer[0].pvBuffer = pSecBuffer->pvBuffer;
client->inputBuffer[0].cbBuffer = pSecBuffer->cbBuffer;
status = test_ntlm_client_authenticate(client);
if (status < 0)
{
printf("test_ntlm_client_authenticate failure\n");
return -1;
}
pSecBuffer = &(client->outputBuffer[0]);
fprintf(stderr, "NTLM_AUTHENTICATE (length = %d):\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
/**
* Server <- Authenticate Message
*/
server->haveInputBuffer = TRUE;
server->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
server->inputBuffer[0].pvBuffer = pSecBuffer->pvBuffer;
server->inputBuffer[0].cbBuffer = pSecBuffer->cbBuffer;
status = test_ntlm_server_authenticate(server);
if (status < 0)
{
printf("test_ntlm_server_authenticate failure\n");
return -1;
}
/**
* Cleanup & Termination
*/
test_ntlm_client_free(client);
test_ntlm_server_free(server);
return 0;
}

View File

@ -273,7 +273,7 @@ int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
printf("EncryptMessage status: 0x%08X\n", status);
printf("EncryptMessage output: cBuffers: %ld [0]: %lu / %lu [1]: %lu / %lu [2]: %lu / %lu [3]: %lu / %lu\n", Message.cBuffers,
printf("EncryptMessage output: cBuffers: %d [0]: %u / %u [1]: %u / %u [2]: %u / %u [3]: %u / %u\n", Message.cBuffers,
Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
@ -342,7 +342,7 @@ int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
printf("DecryptMessage status: 0x%08X\n", status);
printf("DecryptMessage output: cBuffers: %ld [0]: %lu / %lu [1]: %lu / %lu [2]: %lu / %lu [3]: %lu / %lu\n", Message.cBuffers,
printf("DecryptMessage output: cBuffers: %d [0]: %u / %u [1]: %u / %u [2]: %u / %u [3]: %u / %u\n", Message.cBuffers,
Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
@ -351,7 +351,7 @@ int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
if (status != SEC_E_OK)
return -1;
printf("Decrypted Message (%ld)\n", Message.pBuffers[1].cbBuffer);
printf("Decrypted Message (%d)\n", Message.pBuffers[1].cbBuffer);
winpr_HexDump((BYTE*) Message.pBuffers[1].pvBuffer, Message.pBuffers[1].cbBuffer);
if (memcmp(Message.pBuffers[1].pvBuffer, test_LastDummyMessage, sizeof(test_LastDummyMessage)) == 0)
@ -522,9 +522,9 @@ static void* schannel_test_server_thread(void* arg)
else if (status == SEC_E_INCOMPLETE_MESSAGE)
printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
printf("Server cBuffers: %lu pBuffers[0]: %lu type: %lu\n",
printf("Server cBuffers: %u pBuffers[0]: %u type: %u\n",
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
printf("Server Input cBuffers: %ld pBuffers[0]: %lu type: %lu pBuffers[1]: %lu type: %lu\n", SecBufferDesc_in.cBuffers,
printf("Server Input cBuffers: %d pBuffers[0]: %u type: %u pBuffers[1]: %u type: %u\n", SecBufferDesc_in.cBuffers,
SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType,
SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
@ -543,7 +543,7 @@ static void* schannel_test_server_thread(void* arg)
if (pSecBuffer->cbBuffer > 0)
{
printf("Server > Client (%ld)\n", pSecBuffer->cbBuffer);
printf("Server > Client (%d)\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
@ -615,7 +615,7 @@ int dump_test_certificate_files()
int TestSchannel(int argc, char* argv[])
{
int count;
int index;
DWORD index;
ALG_ID algId;
HANDLE thread;
BYTE* lpTokenIn;
@ -641,6 +641,8 @@ int TestSchannel(int argc, char* argv[])
SecPkgCred_CipherStrengths CipherStrengths;
SecPkgCred_SupportedProtocols SupportedProtocols;
return 0; /* disable by default - causes crash */
sspi_GlobalInit();
dump_test_certificate_files();
@ -713,7 +715,7 @@ int TestSchannel(int argc, char* argv[])
* 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203
*/
printf("SupportedAlgs: %ld\n", SupportedAlgs.cSupportedAlgs);
printf("SupportedAlgs: %d\n", SupportedAlgs.cSupportedAlgs);
for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++)
{
@ -734,7 +736,7 @@ int TestSchannel(int argc, char* argv[])
/* CipherStrengths: Minimum: 40 Maximum: 256 */
printf("CipherStrengths: Minimum: %ld Maximum: %ld\n",
printf("CipherStrengths: Minimum: %d Maximum: %d\n",
CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength);
ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols));
@ -748,7 +750,7 @@ int TestSchannel(int argc, char* argv[])
/* SupportedProtocols: 0x208A0 */
printf("SupportedProtocols: 0x%04lX\n", SupportedProtocols.grbitProtocol);
printf("SupportedProtocols: 0x%04X\n", SupportedProtocols.grbitProtocol);
fContextReq = ISC_REQ_STREAM |
ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
@ -781,7 +783,7 @@ int TestSchannel(int argc, char* argv[])
}
g_ClientWait = TRUE;
printf("NumberOfBytesRead: %ld\n", NumberOfBytesRead);
printf("NumberOfBytesRead: %d\n", NumberOfBytesRead);
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
SecBuffer_in[0].pvBuffer = lpTokenIn;
@ -821,9 +823,9 @@ int TestSchannel(int argc, char* argv[])
else if (status == SEC_E_INCOMPLETE_MESSAGE)
printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
printf("Client Output cBuffers: %ld pBuffers[0]: %ld type: %ld\n",
printf("Client Output cBuffers: %d pBuffers[0]: %d type: %d\n",
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
printf("Client Input cBuffers: %ld pBuffers[0]: %ld type: %ld pBuffers[1]: %ld type: %ld\n", SecBufferDesc_in.cBuffers,
printf("Client Input cBuffers: %d pBuffers[0]: %d type: %d pBuffers[1]: %d type: %d\n", SecBufferDesc_in.cBuffers,
SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType,
SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
@ -833,7 +835,7 @@ int TestSchannel(int argc, char* argv[])
if (pSecBuffer->cbBuffer > 0)
{
printf("Client > Server (%ld)\n", pSecBuffer->cbBuffer);
printf("Client > Server (%d)\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))

View File

@ -59,8 +59,10 @@ BOOL TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformati
#endif
// GetDynamicTimeZoneInformation is provided by the SDK if _WIN32_WINNT >= 0x0600 in SDKs above 7.1A
// and incorrectly if _WIN32_WINNT >= 0x0501 in older SDKs
/*
* GetDynamicTimeZoneInformation is provided by the SDK if _WIN32_WINNT >= 0x0600 in SDKs above 7.1A
* and incorrectly if _WIN32_WINNT >= 0x0501 in older SDKs
*/
#if !defined(_WIN32) || (defined(_WIN32) && (defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0600 || !defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0501)) /* Windows Vista */
DWORD GetDynamicTimeZoneInformation(PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation)

View File

@ -319,7 +319,7 @@ int WLog_ParseFilters()
{
char* p;
char* env;
int count;
DWORD count;
DWORD nSize;
int status;
char** strs;