Merge pull request #1896 from awakecoding/sspi
WinPR SSPI Cleanup + Hardening
This commit is contained in:
commit
33b4407314
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 =
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
@ -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 */
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
@ -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 */
|
||||
|
289
winpr/libwinpr/sspi/sspi_export.c
Normal file
289
winpr/libwinpr/sspi/sspi_export.c
Normal 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);
|
||||
}
|
1442
winpr/libwinpr/sspi/sspi_winpr.c
Normal file
1442
winpr/libwinpr/sspi/sspi_winpr.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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 */
|
@ -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}
|
||||
|
8
winpr/libwinpr/sspi/test/TestCredSSP.c
Normal file
8
winpr/libwinpr/sspi/test/TestCredSSP.c
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/sspi.h>
|
||||
|
||||
int TestCredSSP(int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -319,7 +319,7 @@ int WLog_ParseFilters()
|
||||
{
|
||||
char* p;
|
||||
char* env;
|
||||
int count;
|
||||
DWORD count;
|
||||
DWORD nSize;
|
||||
int status;
|
||||
char** strs;
|
||||
|
Loading…
Reference in New Issue
Block a user