Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
34
third_party/FreeRDP/winpr/libwinpr/sspi/test/CMakeLists.txt
vendored
Normal file
34
third_party/FreeRDP/winpr/libwinpr/sspi/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
set(MODULE_NAME "TestSspi")
|
||||
set(MODULE_PREFIX "TEST_SSPI")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestQuerySecurityPackageInfo.c TestEnumerateSecurityPackages.c TestInitializeSecurityContext.c
|
||||
TestAcquireCredentialsHandle.c TestCredSSP.c
|
||||
#TestSchannel.c
|
||||
TestNTLM.c
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
if(WIN32)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
61
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c
vendored
Normal file
61
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
static const char* test_User = "User";
|
||||
static const char* test_Domain = "Domain";
|
||||
static const char* test_Password = "Password";
|
||||
|
||||
int TestAcquireCredentialsHandle(int argc, char* argv[])
|
||||
{
|
||||
int rc = -1;
|
||||
SECURITY_STATUS status = 0;
|
||||
CredHandle credentials = WINPR_C_ARRAY_INIT;
|
||||
TimeStamp expiration;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
SecurityFunctionTable* table = nullptr;
|
||||
SecPkgCredentials_Names credential_names;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
sspi_GlobalInit();
|
||||
table = InitSecurityInterfaceEx(0);
|
||||
identity.User = (UINT16*)_strdup(test_User);
|
||||
identity.Domain = (UINT16*)_strdup(test_Domain);
|
||||
identity.Password = (UINT16*)_strdup(test_Password);
|
||||
|
||||
if (!identity.User || !identity.Domain || !identity.Password)
|
||||
goto fail;
|
||||
|
||||
identity.UserLength = strlen(test_User);
|
||||
identity.DomainLength = strlen(test_Domain);
|
||||
identity.PasswordLength = strlen(test_Password);
|
||||
identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
|
||||
status =
|
||||
table->AcquireCredentialsHandle(nullptr, NTLM_SSP_NAME, SECPKG_CRED_OUTBOUND, nullptr,
|
||||
&identity, nullptr, nullptr, &credentials, &expiration);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
goto fail;
|
||||
|
||||
status =
|
||||
table->QueryCredentialsAttributes(&credentials, SECPKG_CRED_ATTR_NAMES, &credential_names);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
|
||||
if (SecIsValidHandle(&credentials))
|
||||
table->FreeCredentialsHandle(&credentials);
|
||||
|
||||
free(identity.User);
|
||||
free(identity.Domain);
|
||||
free(identity.Password);
|
||||
sspi_GlobalFinish();
|
||||
return rc;
|
||||
}
|
||||
8
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestCredSSP.c
vendored
Normal file
8
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestCredSSP.c
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/sspi.h>
|
||||
|
||||
int TestCredSSP(int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
40
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestEnumerateSecurityPackages.c
vendored
Normal file
40
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestEnumerateSecurityPackages.c
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/tchar.h>
|
||||
|
||||
int TestEnumerateSecurityPackages(int argc, char* argv[])
|
||||
{
|
||||
ULONG cPackages = 0;
|
||||
SECURITY_STATUS status = 0;
|
||||
SecPkgInfo* pPackageInfo = nullptr;
|
||||
SecurityFunctionTable* table = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
sspi_GlobalInit();
|
||||
table = InitSecurityInterfaceEx(0);
|
||||
|
||||
status = table->EnumerateSecurityPackages(&cPackages, &pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
sspi_GlobalFinish();
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tprintf(_T("\nEnumerateSecurityPackages (%") _T(PRIu32) _T("):\n"), cPackages);
|
||||
|
||||
for (size_t index = 0; index < cPackages; index++)
|
||||
{
|
||||
_tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo[index].Name, pPackageInfo[index].Comment);
|
||||
}
|
||||
|
||||
table->FreeContextBuffer(pPackageInfo);
|
||||
sspi_GlobalFinish();
|
||||
|
||||
return 0;
|
||||
}
|
||||
116
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c
vendored
Normal file
116
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
static const char* test_User = "User";
|
||||
static const char* test_Domain = "Domain";
|
||||
static const char* test_Password = "Password";
|
||||
|
||||
int TestInitializeSecurityContext(int argc, char* argv[])
|
||||
{
|
||||
int rc = -1;
|
||||
UINT32 cbMaxLen = 0;
|
||||
UINT32 fContextReq = 0;
|
||||
void* output_buffer = nullptr;
|
||||
CtxtHandle context;
|
||||
ULONG pfContextAttr = 0;
|
||||
SECURITY_STATUS status = 0;
|
||||
CredHandle credentials = WINPR_C_ARRAY_INIT;
|
||||
TimeStamp expiration;
|
||||
PSecPkgInfo pPackageInfo = nullptr;
|
||||
SEC_WINNT_AUTH_IDENTITY identity = WINPR_C_ARRAY_INIT;
|
||||
SecurityFunctionTable* table = nullptr;
|
||||
PSecBuffer p_SecBuffer = nullptr;
|
||||
SecBuffer output_SecBuffer;
|
||||
SecBufferDesc output_SecBuffer_desc;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
sspi_GlobalInit();
|
||||
table = InitSecurityInterfaceEx(0);
|
||||
status = table->QuerySecurityPackageInfo(NTLM_SSP_NAME, &pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("QuerySecurityPackageInfo status: 0x%08" PRIX32 "\n", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cbMaxLen = pPackageInfo->cbMaxToken;
|
||||
identity.User = (UINT16*)_strdup(test_User);
|
||||
identity.Domain = (UINT16*)_strdup(test_Domain);
|
||||
identity.Password = (UINT16*)_strdup(test_Password);
|
||||
|
||||
if (!identity.User || !identity.Domain || !identity.Password)
|
||||
goto fail;
|
||||
|
||||
identity.UserLength = strlen(test_User);
|
||||
identity.DomainLength = strlen(test_Domain);
|
||||
identity.PasswordLength = strlen(test_Password);
|
||||
identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
|
||||
status =
|
||||
table->AcquireCredentialsHandle(nullptr, NTLM_SSP_NAME, SECPKG_CRED_OUTBOUND, nullptr,
|
||||
&identity, nullptr, nullptr, &credentials, &expiration);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("AcquireCredentialsHandle status: 0x%08" PRIX32 "\n", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY |
|
||||
ISC_REQ_DELEGATE;
|
||||
output_buffer = malloc(cbMaxLen);
|
||||
|
||||
if (!output_buffer)
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
output_SecBuffer_desc.ulVersion = 0;
|
||||
output_SecBuffer_desc.cBuffers = 1;
|
||||
output_SecBuffer_desc.pBuffers = &output_SecBuffer;
|
||||
output_SecBuffer.cbBuffer = cbMaxLen;
|
||||
output_SecBuffer.BufferType = SECBUFFER_TOKEN;
|
||||
output_SecBuffer.pvBuffer = output_buffer;
|
||||
status = table->InitializeSecurityContext(&credentials, nullptr, nullptr, fContextReq, 0, 0,
|
||||
nullptr, 0, &context, &output_SecBuffer_desc,
|
||||
&pfContextAttr, &expiration);
|
||||
|
||||
if (status != SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
printf("InitializeSecurityContext status: 0x%08" PRIX32 "\n", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printf("cBuffers: %" PRIu32 " ulVersion: %" PRIu32 "\n", output_SecBuffer_desc.cBuffers,
|
||||
output_SecBuffer_desc.ulVersion);
|
||||
p_SecBuffer = &output_SecBuffer_desc.pBuffers[0];
|
||||
printf("BufferType: 0x%08" PRIX32 " cbBuffer: %" PRIu32 "\n", p_SecBuffer->BufferType,
|
||||
p_SecBuffer->cbBuffer);
|
||||
status = table->DeleteSecurityContext(&context);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("DeleteSecurityContext status: 0x%08" PRIX32 "\n", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
free(identity.User);
|
||||
free(identity.Domain);
|
||||
free(identity.Password);
|
||||
free(output_buffer);
|
||||
|
||||
if (SecIsValidHandle(&credentials))
|
||||
table->FreeCredentialsHandle(&credentials);
|
||||
|
||||
table->FreeContextBuffer(pPackageInfo);
|
||||
sspi_GlobalFinish();
|
||||
return rc;
|
||||
}
|
||||
792
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestNTLM.c
vendored
Normal file
792
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestNTLM.c
vendored
Normal file
@@ -0,0 +1,792 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
struct test_input_t
|
||||
{
|
||||
const char* user;
|
||||
const char* domain;
|
||||
const char* pwd;
|
||||
const BYTE* ntlm;
|
||||
const BYTE* ntlmv2;
|
||||
BOOL dynamic;
|
||||
BOOL expected;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CtxtHandle context;
|
||||
ULONG cbMaxToken;
|
||||
ULONG fContextReq;
|
||||
ULONG pfContextAttr;
|
||||
TimeStamp expiration;
|
||||
PSecBuffer pBuffer;
|
||||
SecBuffer inputBuffer[2];
|
||||
SecBuffer outputBuffer[2];
|
||||
BOOL haveContext;
|
||||
BOOL haveInputBuffer;
|
||||
BOOL UseNtlmV2Hash;
|
||||
LPTSTR ServicePrincipalName;
|
||||
SecBufferDesc inputBufferDesc;
|
||||
SecBufferDesc outputBufferDesc;
|
||||
CredHandle credentials;
|
||||
BOOL confidentiality;
|
||||
SecPkgInfo* pPackageInfo;
|
||||
SecurityFunctionTable* table;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
} TEST_NTLM_SERVER;
|
||||
|
||||
static BYTE TEST_NTLM_TIMESTAMP[8] = { 0x33, 0x57, 0xbd, 0xb1, 0x07, 0x8b, 0xcf, 0x01 };
|
||||
|
||||
static BYTE TEST_NTLM_CLIENT_CHALLENGE[8] = { 0x20, 0xc0, 0x2b, 0x3d, 0xc0, 0x61, 0xa7, 0x73 };
|
||||
|
||||
static BYTE TEST_NTLM_SERVER_CHALLENGE[8] = { 0xa4, 0xf1, 0xba, 0xa6, 0x7c, 0xdc, 0x1a, 0x12 };
|
||||
|
||||
static BYTE TEST_NTLM_NEGOTIATE[] =
|
||||
"\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x06\x03\x80\x25\x00\x00\x00\x0f";
|
||||
|
||||
static BYTE TEST_NTLM_CHALLENGE[] =
|
||||
"\x4e\x54\x4c\x4d\x53\x53\x50\x00\x02\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x38\x00\x00\x00\x07\x82\x88\xa2\xa4\xf1\xba\xa6\x7c\xdc\x1a\x12"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x66\x00\x66\x00\x38\x00\x00\x00"
|
||||
"\x06\x03\x80\x25\x00\x00\x00\x0f\x02\x00\x0e\x00\x4e\x00\x45\x00"
|
||||
"\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x01\x00\x0e\x00\x4e\x00"
|
||||
"\x45\x00\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x04\x00\x1c\x00"
|
||||
"\x6c\x00\x61\x00\x62\x00\x2e\x00\x77\x00\x61\x00\x79\x00\x6b\x00"
|
||||
"\x2e\x00\x6c\x00\x6f\x00\x63\x00\x61\x00\x6c\x00\x03\x00\x0e\x00"
|
||||
"\x6e\x00\x65\x00\x77\x00\x79\x00\x65\x00\x61\x00\x72\x00\x07\x00"
|
||||
"\x08\x00\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x00\x00\x00\x00";
|
||||
|
||||
static BYTE TEST_NTLM_AUTHENTICATE[] =
|
||||
"\x4e\x54\x4c\x4d\x53\x53\x50\x00\x03\x00\x00\x00\x18\x00\x18\x00"
|
||||
"\x82\x00\x00\x00\x08\x01\x08\x01\x9a\x00\x00\x00\x0c\x00\x0c\x00"
|
||||
"\x58\x00\x00\x00\x10\x00\x10\x00\x64\x00\x00\x00\x0e\x00\x0e\x00"
|
||||
"\x74\x00\x00\x00\x00\x00\x00\x00\xa2\x01\x00\x00\x05\x82\x88\xa2"
|
||||
"\x06\x03\x80\x25\x00\x00\x00\x0f\x12\xe5\x5a\xf5\x80\xee\x3f\x29"
|
||||
"\xe1\xde\x90\x4d\x73\x77\x06\x25\x44\x00\x6f\x00\x6d\x00\x61\x00"
|
||||
"\x69\x00\x6e\x00\x55\x00\x73\x00\x65\x00\x72\x00\x6e\x00\x61\x00"
|
||||
"\x6d\x00\x65\x00\x4e\x00\x45\x00\x57\x00\x59\x00\x45\x00\x41\x00"
|
||||
"\x52\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x62\x14\x68\xc8\x98\x12"
|
||||
"\xe7\x39\xd8\x76\x1b\xe9\xf7\x54\xb5\xe3\x01\x01\x00\x00\x00\x00"
|
||||
"\x00\x00\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x20\xc0\x2b\x3d\xc0\x61"
|
||||
"\xa7\x73\x00\x00\x00\x00\x02\x00\x0e\x00\x4e\x00\x45\x00\x57\x00"
|
||||
"\x59\x00\x45\x00\x41\x00\x52\x00\x01\x00\x0e\x00\x4e\x00\x45\x00"
|
||||
"\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x04\x00\x1c\x00\x6c\x00"
|
||||
"\x61\x00\x62\x00\x2e\x00\x77\x00\x61\x00\x79\x00\x6b\x00\x2e\x00"
|
||||
"\x6c\x00\x6f\x00\x63\x00\x61\x00\x6c\x00\x03\x00\x0e\x00\x6e\x00"
|
||||
"\x65\x00\x77\x00\x79\x00\x65\x00\x61\x00\x72\x00\x07\x00\x08\x00"
|
||||
"\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x06\x00\x04\x00\x02\x00\x00\x00"
|
||||
"\x08\x00\x30\x00\x30\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"
|
||||
"\x00\x20\x00\x00\x1e\x10\xf5\x2c\x54\x2f\x2e\x77\x1c\x13\xbf\xc3"
|
||||
"\x3f\xe1\x7b\x28\x7e\x0b\x93\x5a\x39\xd2\xce\x12\xd7\xbd\x8c\x4e"
|
||||
"\x2b\xb5\x0b\xf5\x0a\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x1a\x00\x48\x00\x54\x00"
|
||||
"\x54\x00\x50\x00\x2f\x00\x72\x00\x77\x00\x2e\x00\x6c\x00\x6f\x00"
|
||||
"\x63\x00\x61\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00";
|
||||
|
||||
#define TEST_SSPI_INTERFACE SSPI_INTERFACE_WINPR
|
||||
|
||||
static const char* TEST_NTLM_USER = "Username";
|
||||
static const char* TEST_NTLM_DOMAIN = "Domain";
|
||||
static const char* TEST_NTLM_PASSWORD = "P4ss123!";
|
||||
|
||||
// static const char* TEST_NTLM_HASH_STRING = "d5922a65c4d5c082ca444af1be0001db";
|
||||
|
||||
static const BYTE TEST_NTLM_HASH[16] = { 0xd5, 0x92, 0x2a, 0x65, 0xc4, 0xd5, 0xc0, 0x82,
|
||||
0xca, 0x44, 0x4a, 0xf1, 0xbe, 0x00, 0x01, 0xdb };
|
||||
|
||||
// static const char* TEST_NTLM_HASH_V2_STRING = "4c7f706f7dde05a9d1a0f4e7ffe3bfb8";
|
||||
|
||||
static const BYTE TEST_NTLM_V2_HASH[16] = { 0x4c, 0x7f, 0x70, 0x6f, 0x7d, 0xde, 0x05, 0xa9,
|
||||
0xd1, 0xa0, 0xf4, 0xe7, 0xff, 0xe3, 0xbf, 0xb8 };
|
||||
|
||||
static const BYTE TEST_EMPTY_PWD_NTLM_HASH[] = { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
|
||||
0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 };
|
||||
|
||||
static const BYTE TEST_EMPTY_PWD_NTLM_V2_HASH[] = {
|
||||
0x0b, 0xce, 0x54, 0x87, 0x4e, 0x94, 0x20, 0x9e, 0x34, 0x48, 0x97, 0xc1, 0x60, 0x03, 0x6e, 0x3b
|
||||
};
|
||||
|
||||
#define NTLM_PACKAGE_NAME NTLM_SSP_NAME
|
||||
|
||||
typedef struct
|
||||
{
|
||||
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;
|
||||
} TEST_NTLM_CLIENT;
|
||||
|
||||
static int test_ntlm_client_init(TEST_NTLM_CLIENT* ntlm, const char* user, const char* domain,
|
||||
const char* password)
|
||||
{
|
||||
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
||||
|
||||
WINPR_ASSERT(ntlm);
|
||||
|
||||
SecInvalidateHandle(&(ntlm->context));
|
||||
ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE);
|
||||
if (!ntlm->table)
|
||||
return -1;
|
||||
const int rc = sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
status = ntlm->table->QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &ntlm->pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
(void)fprintf(stderr, "QuerySecurityPackageInfo status: %s (0x%08" PRIX32 ")\n",
|
||||
GetSecurityStatusString(status), status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
|
||||
status = ntlm->table->AcquireCredentialsHandle(nullptr, NTLM_PACKAGE_NAME, SECPKG_CRED_OUTBOUND,
|
||||
nullptr, &ntlm->identity, nullptr, nullptr,
|
||||
&ntlm->credentials, &ntlm->expiration);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
(void)fprintf(stderr, "AcquireCredentialsHandle status: %s (0x%08" PRIX32 ")\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 |= ISC_REQ_MUTUAL_AUTH;
|
||||
ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY;
|
||||
ntlm->fContextReq |= ISC_REQ_USE_SESSION_KEY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static 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 = nullptr;
|
||||
}
|
||||
|
||||
free(ntlm->identity.User);
|
||||
free(ntlm->identity.Domain);
|
||||
free(ntlm->identity.Password);
|
||||
free(ntlm->ServicePrincipalName);
|
||||
|
||||
if (ntlm->table)
|
||||
{
|
||||
SECURITY_STATUS status = ntlm->table->FreeCredentialsHandle(&ntlm->credentials);
|
||||
WINPR_ASSERT((status == SEC_E_OK) || (status == SEC_E_SECPKG_NOT_FOUND) ||
|
||||
(status == SEC_E_UNSUPPORTED_FUNCTION));
|
||||
|
||||
status = ntlm->table->FreeContextBuffer(ntlm->pPackageInfo);
|
||||
WINPR_ASSERT((status == SEC_E_OK) || (status = SEC_E_INVALID_HANDLE));
|
||||
|
||||
status = ntlm->table->DeleteSecurityContext(&ntlm->context);
|
||||
WINPR_ASSERT((status == SEC_E_OK) || (status == SEC_E_SECPKG_NOT_FOUND) ||
|
||||
(status == SEC_E_UNSUPPORTED_FUNCTION));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
* --------------
|
||||
*/
|
||||
static BOOL IsSecurityStatusError(SECURITY_STATUS status)
|
||||
{
|
||||
BOOL error = TRUE;
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case SEC_E_OK:
|
||||
case SEC_I_CONTINUE_NEEDED:
|
||||
case SEC_I_COMPLETE_NEEDED:
|
||||
case SEC_I_COMPLETE_AND_CONTINUE:
|
||||
case SEC_I_LOCAL_LOGON:
|
||||
case SEC_I_CONTEXT_EXPIRED:
|
||||
case SEC_I_INCOMPLETE_CREDENTIALS:
|
||||
case SEC_I_RENEGOTIATE:
|
||||
case SEC_I_NO_LSA_CONTEXT:
|
||||
case SEC_I_SIGNATURE_NEEDED:
|
||||
case SEC_I_NO_RENEGOTIATION:
|
||||
error = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int test_ntlm_client_authenticate(TEST_NTLM_CLIENT* ntlm)
|
||||
{
|
||||
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
||||
|
||||
WINPR_ASSERT(ntlm);
|
||||
if (ntlm->outputBuffer[0].pvBuffer)
|
||||
{
|
||||
free(ntlm->outputBuffer[0].pvBuffer);
|
||||
ntlm->outputBuffer[0].pvBuffer = nullptr;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
(void)fprintf(stderr, "ntlm_authenticate: invalid ntlm context\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = ntlm->table->InitializeSecurityContext(
|
||||
&ntlm->credentials, (ntlm->haveContext) ? &ntlm->context : nullptr,
|
||||
(ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : nullptr, ntlm->fContextReq, 0,
|
||||
SECURITY_NATIVE_DREP, (ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : nullptr, 0,
|
||||
&ntlm->context, &ntlm->outputBufferDesc, &ntlm->pfContextAttr, &ntlm->expiration);
|
||||
|
||||
if (IsSecurityStatusError(status))
|
||||
return -1;
|
||||
|
||||
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
|
||||
{
|
||||
if (ntlm->table->CompleteAuthToken)
|
||||
{
|
||||
SECURITY_STATUS rc =
|
||||
ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
|
||||
if (rc != SEC_E_OK)
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static TEST_NTLM_CLIENT* test_ntlm_client_new(void)
|
||||
{
|
||||
TEST_NTLM_CLIENT* ntlm = (TEST_NTLM_CLIENT*)calloc(1, sizeof(TEST_NTLM_CLIENT));
|
||||
|
||||
if (!ntlm)
|
||||
return nullptr;
|
||||
|
||||
return ntlm;
|
||||
}
|
||||
|
||||
static void test_ntlm_client_free(TEST_NTLM_CLIENT* ntlm)
|
||||
{
|
||||
if (!ntlm)
|
||||
return;
|
||||
|
||||
test_ntlm_client_uninit(ntlm);
|
||||
free(ntlm);
|
||||
}
|
||||
|
||||
static int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm)
|
||||
{
|
||||
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
||||
|
||||
WINPR_ASSERT(ntlm);
|
||||
|
||||
ntlm->UseNtlmV2Hash = TRUE;
|
||||
SecInvalidateHandle(&(ntlm->context));
|
||||
ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE);
|
||||
if (!ntlm->table)
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
|
||||
status = ntlm->table->QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &ntlm->pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
(void)fprintf(stderr, "QuerySecurityPackageInfo status: %s (0x%08" PRIX32 ")\n",
|
||||
GetSecurityStatusString(status), status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
|
||||
status = ntlm->table->AcquireCredentialsHandle(nullptr, NTLM_PACKAGE_NAME, SECPKG_CRED_INBOUND,
|
||||
nullptr, nullptr, nullptr, nullptr,
|
||||
&ntlm->credentials, &ntlm->expiration);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
(void)fprintf(stderr, "AcquireCredentialsHandle status: %s (0x%08" PRIX32 ")\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;
|
||||
}
|
||||
|
||||
static 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 = nullptr;
|
||||
}
|
||||
|
||||
free(ntlm->identity.User);
|
||||
free(ntlm->identity.Domain);
|
||||
free(ntlm->identity.Password);
|
||||
free(ntlm->ServicePrincipalName);
|
||||
|
||||
if (ntlm->table)
|
||||
{
|
||||
SECURITY_STATUS status = ntlm->table->FreeCredentialsHandle(&ntlm->credentials);
|
||||
WINPR_ASSERT(status == SEC_E_OK);
|
||||
status = ntlm->table->FreeContextBuffer(ntlm->pPackageInfo);
|
||||
WINPR_ASSERT(status == SEC_E_OK);
|
||||
status = ntlm->table->DeleteSecurityContext(&ntlm->context);
|
||||
WINPR_ASSERT(status == SEC_E_OK);
|
||||
}
|
||||
}
|
||||
|
||||
static int test_ntlm_server_authenticate(const struct test_input_t* targ, TEST_NTLM_SERVER* ntlm)
|
||||
{
|
||||
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
||||
|
||||
WINPR_ASSERT(ntlm);
|
||||
WINPR_ASSERT(targ);
|
||||
|
||||
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);
|
||||
|
||||
if (!ntlm->outputBuffer[0].pvBuffer)
|
||||
return -1;
|
||||
|
||||
status = ntlm->table->AcceptSecurityContext(
|
||||
&ntlm->credentials, ntlm->haveContext ? &ntlm->context : nullptr, &ntlm->inputBufferDesc,
|
||||
ntlm->fContextReq, SECURITY_NATIVE_DREP, &ntlm->context, &ntlm->outputBufferDesc,
|
||||
&ntlm->pfContextAttr, &ntlm->expiration);
|
||||
|
||||
if (status == SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
SecPkgContext_AuthNtlmHash AuthNtlmHash = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (ntlm->UseNtlmV2Hash)
|
||||
{
|
||||
AuthNtlmHash.Version = 2;
|
||||
CopyMemory(AuthNtlmHash.NtlmHash, targ->ntlmv2, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthNtlmHash.Version = 1;
|
||||
CopyMemory(AuthNtlmHash.NtlmHash, targ->ntlm, 16);
|
||||
}
|
||||
|
||||
status =
|
||||
ntlm->table->SetContextAttributes(&ntlm->context, SECPKG_ATTR_AUTH_NTLM_HASH,
|
||||
&AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
|
||||
}
|
||||
|
||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
|
||||
{
|
||||
(void)fprintf(stderr, "AcceptSecurityContext status: %s (0x%08" PRIX32 ")\n",
|
||||
GetSecurityStatusString(status), status);
|
||||
return -1; /* Access Denied */
|
||||
}
|
||||
|
||||
ntlm->haveContext = TRUE;
|
||||
return (status == SEC_I_CONTINUE_NEEDED) ? 1 : 0;
|
||||
}
|
||||
|
||||
static TEST_NTLM_SERVER* test_ntlm_server_new(void)
|
||||
{
|
||||
TEST_NTLM_SERVER* ntlm = (TEST_NTLM_SERVER*)calloc(1, sizeof(TEST_NTLM_SERVER));
|
||||
|
||||
if (!ntlm)
|
||||
return nullptr;
|
||||
|
||||
return ntlm;
|
||||
}
|
||||
|
||||
static void test_ntlm_server_free(TEST_NTLM_SERVER* ntlm)
|
||||
{
|
||||
if (!ntlm)
|
||||
return;
|
||||
|
||||
test_ntlm_server_uninit(ntlm);
|
||||
free(ntlm);
|
||||
}
|
||||
|
||||
static BOOL test_default(const struct test_input_t* arg)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
PSecBuffer pSecBuffer = nullptr;
|
||||
|
||||
WINPR_ASSERT(arg);
|
||||
|
||||
printf("testcase {user=%s, domain=%s, password=%s, dynamic=%s}\n", arg->user, arg->domain,
|
||||
arg->pwd, arg->dynamic ? "TRUE" : "FALSE");
|
||||
|
||||
/**
|
||||
* Client Initialization
|
||||
*/
|
||||
TEST_NTLM_CLIENT* client = test_ntlm_client_new();
|
||||
TEST_NTLM_SERVER* server = test_ntlm_server_new();
|
||||
|
||||
if (!client || !server)
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
int status = test_ntlm_client_init(client, arg->user, arg->domain, arg->pwd);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("test_ntlm_client_init failure\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server Initialization
|
||||
*/
|
||||
|
||||
status = test_ntlm_server_init(server);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("test_ntlm_server_init failure\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Client -> Negotiate Message
|
||||
*/
|
||||
status = test_ntlm_client_authenticate(client);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("test_ntlm_client_authenticate failure\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!arg->dynamic)
|
||||
{
|
||||
SecPkgContext_AuthNtlmTimestamp AuthNtlmTimestamp = WINPR_C_ARRAY_INIT;
|
||||
SecPkgContext_AuthNtlmClientChallenge AuthNtlmClientChallenge = WINPR_C_ARRAY_INIT;
|
||||
SecPkgContext_AuthNtlmServerChallenge AuthNtlmServerChallenge = WINPR_C_ARRAY_INIT;
|
||||
CopyMemory(AuthNtlmTimestamp.Timestamp, TEST_NTLM_TIMESTAMP, 8);
|
||||
AuthNtlmTimestamp.ChallengeOrResponse = TRUE;
|
||||
SECURITY_STATUS rc = client->table->SetContextAttributes(
|
||||
&client->context, SECPKG_ATTR_AUTH_NTLM_TIMESTAMP, &AuthNtlmTimestamp,
|
||||
sizeof(SecPkgContext_AuthNtlmTimestamp));
|
||||
WINPR_ASSERT((rc == SEC_E_OK) || (rc == SEC_E_SECPKG_NOT_FOUND));
|
||||
|
||||
AuthNtlmTimestamp.ChallengeOrResponse = FALSE;
|
||||
rc = client->table->SetContextAttributes(&client->context, SECPKG_ATTR_AUTH_NTLM_TIMESTAMP,
|
||||
&AuthNtlmTimestamp,
|
||||
sizeof(SecPkgContext_AuthNtlmTimestamp));
|
||||
WINPR_ASSERT((rc == SEC_E_OK) || (rc == SEC_E_SECPKG_NOT_FOUND));
|
||||
|
||||
CopyMemory(AuthNtlmClientChallenge.ClientChallenge, TEST_NTLM_CLIENT_CHALLENGE, 8);
|
||||
CopyMemory(AuthNtlmServerChallenge.ServerChallenge, TEST_NTLM_SERVER_CHALLENGE, 8);
|
||||
rc = client->table->SetContextAttributes(
|
||||
&client->context, SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE, &AuthNtlmClientChallenge,
|
||||
sizeof(SecPkgContext_AuthNtlmClientChallenge));
|
||||
WINPR_ASSERT((rc == SEC_E_OK) || (rc == SEC_E_SECPKG_NOT_FOUND));
|
||||
|
||||
rc = client->table->SetContextAttributes(
|
||||
&client->context, SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE, &AuthNtlmServerChallenge,
|
||||
sizeof(SecPkgContext_AuthNtlmServerChallenge));
|
||||
WINPR_ASSERT((rc == SEC_E_OK) || (rc == SEC_E_SECPKG_NOT_FOUND));
|
||||
}
|
||||
|
||||
pSecBuffer = &(client->outputBuffer[0]);
|
||||
|
||||
if (!arg->dynamic)
|
||||
{
|
||||
pSecBuffer->cbBuffer = sizeof(TEST_NTLM_NEGOTIATE) - 1;
|
||||
free(pSecBuffer->pvBuffer);
|
||||
pSecBuffer->pvBuffer = malloc(pSecBuffer->cbBuffer);
|
||||
|
||||
if (!pSecBuffer->pvBuffer)
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_NEGOTIATE, pSecBuffer->cbBuffer);
|
||||
}
|
||||
|
||||
(void)fprintf(stderr, "NTLM_NEGOTIATE (length = %" PRIu32 "):\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump("sspi.test", WLOG_DEBUG, (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(arg, server);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("test_ntlm_server_authenticate failure\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!arg->dynamic)
|
||||
{
|
||||
SecPkgContext_AuthNtlmTimestamp AuthNtlmTimestamp = WINPR_C_ARRAY_INIT;
|
||||
SecPkgContext_AuthNtlmClientChallenge AuthNtlmClientChallenge = WINPR_C_ARRAY_INIT;
|
||||
SecPkgContext_AuthNtlmServerChallenge AuthNtlmServerChallenge = WINPR_C_ARRAY_INIT;
|
||||
CopyMemory(AuthNtlmTimestamp.Timestamp, TEST_NTLM_TIMESTAMP, 8);
|
||||
AuthNtlmTimestamp.ChallengeOrResponse = TRUE;
|
||||
SECURITY_STATUS rc = client->table->SetContextAttributes(
|
||||
&server->context, SECPKG_ATTR_AUTH_NTLM_TIMESTAMP, &AuthNtlmTimestamp,
|
||||
sizeof(SecPkgContext_AuthNtlmTimestamp));
|
||||
WINPR_ASSERT(rc == SEC_E_OK);
|
||||
|
||||
AuthNtlmTimestamp.ChallengeOrResponse = FALSE;
|
||||
rc = client->table->SetContextAttributes(&server->context, SECPKG_ATTR_AUTH_NTLM_TIMESTAMP,
|
||||
&AuthNtlmTimestamp,
|
||||
sizeof(SecPkgContext_AuthNtlmTimestamp));
|
||||
WINPR_ASSERT(rc == SEC_E_OK);
|
||||
|
||||
CopyMemory(AuthNtlmClientChallenge.ClientChallenge, TEST_NTLM_CLIENT_CHALLENGE, 8);
|
||||
CopyMemory(AuthNtlmServerChallenge.ServerChallenge, TEST_NTLM_SERVER_CHALLENGE, 8);
|
||||
rc = server->table->SetContextAttributes(
|
||||
&server->context, SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE, &AuthNtlmClientChallenge,
|
||||
sizeof(SecPkgContext_AuthNtlmClientChallenge));
|
||||
WINPR_ASSERT(rc == SEC_E_OK);
|
||||
|
||||
rc = server->table->SetContextAttributes(
|
||||
&server->context, SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE, &AuthNtlmServerChallenge,
|
||||
sizeof(SecPkgContext_AuthNtlmServerChallenge));
|
||||
WINPR_ASSERT(rc == SEC_E_OK);
|
||||
}
|
||||
|
||||
pSecBuffer = &(server->outputBuffer[0]);
|
||||
|
||||
if (!arg->dynamic)
|
||||
{
|
||||
SecPkgContext_AuthNtlmMessage AuthNtlmMessage = WINPR_C_ARRAY_INIT;
|
||||
pSecBuffer->cbBuffer = sizeof(TEST_NTLM_CHALLENGE) - 1;
|
||||
free(pSecBuffer->pvBuffer);
|
||||
pSecBuffer->pvBuffer = malloc(pSecBuffer->cbBuffer);
|
||||
|
||||
if (!pSecBuffer->pvBuffer)
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_CHALLENGE, pSecBuffer->cbBuffer);
|
||||
AuthNtlmMessage.type = 2;
|
||||
AuthNtlmMessage.length = pSecBuffer->cbBuffer;
|
||||
AuthNtlmMessage.buffer = (BYTE*)pSecBuffer->pvBuffer;
|
||||
SECURITY_STATUS rc = server->table->SetContextAttributes(
|
||||
&server->context, SECPKG_ATTR_AUTH_NTLM_MESSAGE, &AuthNtlmMessage,
|
||||
sizeof(SecPkgContext_AuthNtlmMessage));
|
||||
if (rc != SEC_E_OK)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
(void)fprintf(stderr, "NTLM_CHALLENGE (length = %" PRIu32 "):\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump("sspi.test", WLOG_DEBUG, (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");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pSecBuffer = &(client->outputBuffer[0]);
|
||||
|
||||
if (!arg->dynamic)
|
||||
{
|
||||
pSecBuffer->cbBuffer = sizeof(TEST_NTLM_AUTHENTICATE) - 1;
|
||||
free(pSecBuffer->pvBuffer);
|
||||
pSecBuffer->pvBuffer = malloc(pSecBuffer->cbBuffer);
|
||||
|
||||
if (!pSecBuffer->pvBuffer)
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_AUTHENTICATE, pSecBuffer->cbBuffer);
|
||||
}
|
||||
|
||||
(void)fprintf(stderr, "NTLM_AUTHENTICATE (length = %" PRIu32 "):\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump("sspi.test", WLOG_DEBUG, (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(arg, server);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("test_ntlm_server_authenticate failure\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
|
||||
fail:
|
||||
/**
|
||||
* Cleanup & Termination
|
||||
*/
|
||||
test_ntlm_client_free(client);
|
||||
test_ntlm_server_free(server);
|
||||
|
||||
printf("testcase {user=%s, domain=%s, password=%s, dynamic=%s} returns %d\n", arg->user,
|
||||
arg->domain, arg->pwd, arg->dynamic ? "TRUE" : "FALSE", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestNTLM(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
const struct test_input_t inputs[] = {
|
||||
{ TEST_NTLM_USER, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD, TEST_NTLM_HASH, TEST_NTLM_V2_HASH,
|
||||
TRUE, TRUE },
|
||||
{ TEST_NTLM_USER, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD, TEST_NTLM_HASH, TEST_NTLM_V2_HASH,
|
||||
FALSE, TRUE },
|
||||
{ TEST_NTLM_USER, TEST_NTLM_DOMAIN, "", TEST_EMPTY_PWD_NTLM_HASH,
|
||||
TEST_EMPTY_PWD_NTLM_V2_HASH, TRUE, TRUE },
|
||||
{ TEST_NTLM_USER, TEST_NTLM_DOMAIN, nullptr, TEST_EMPTY_PWD_NTLM_HASH,
|
||||
TEST_EMPTY_PWD_NTLM_V2_HASH, TRUE, FALSE }
|
||||
};
|
||||
|
||||
int rc = 0;
|
||||
for (size_t x = 0; x < ARRAYSIZE(inputs); x++)
|
||||
{
|
||||
const struct test_input_t* cur = &inputs[x];
|
||||
const BOOL res = test_default(cur);
|
||||
if (res != cur->expected)
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
34
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c
vendored
Normal file
34
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/tchar.h>
|
||||
|
||||
int TestQuerySecurityPackageInfo(int argc, char* argv[])
|
||||
{
|
||||
int rc = 0;
|
||||
SECURITY_STATUS status = 0;
|
||||
SecPkgInfo* pPackageInfo = nullptr;
|
||||
SecurityFunctionTable* table = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
sspi_GlobalInit();
|
||||
table = InitSecurityInterfaceEx(0);
|
||||
|
||||
status = table->QuerySecurityPackageInfo(NTLM_SSP_NAME, &pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
rc = -1;
|
||||
else
|
||||
{
|
||||
_tprintf(_T("\nQuerySecurityPackageInfo:\n"));
|
||||
_tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo->Name, pPackageInfo->Comment);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
table->FreeContextBuffer(pPackageInfo);
|
||||
sspi_GlobalFinish();
|
||||
return rc;
|
||||
}
|
||||
854
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestSchannel.c
vendored
Normal file
854
third_party/FreeRDP/winpr/libwinpr/sspi/test/TestSchannel.c
vendored
Normal file
@@ -0,0 +1,854 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/pipe.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/schannel.h>
|
||||
|
||||
static BOOL g_ClientWait = FALSE;
|
||||
static BOOL g_ServerWait = FALSE;
|
||||
|
||||
static HANDLE g_ClientReadPipe = nullptr;
|
||||
static HANDLE g_ClientWritePipe = nullptr;
|
||||
static HANDLE g_ServerReadPipe = nullptr;
|
||||
static HANDLE g_ServerWritePipe = nullptr;
|
||||
|
||||
static const BYTE test_localhost_crt[1029] = {
|
||||
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
|
||||
0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43,
|
||||
0x79, 0x6A, 0x43, 0x43, 0x41, 0x62, 0x4B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x45,
|
||||
0x63, 0x61, 0x64, 0x63, 0x72, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47,
|
||||
0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, 0x41, 0x55, 0x4D, 0x52, 0x49, 0x77,
|
||||
0x45, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x77, 0x6C, 0x73, 0x0A, 0x62, 0x32, 0x4E,
|
||||
0x68, 0x62, 0x47, 0x68, 0x76, 0x63, 0x33, 0x51, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x4D,
|
||||
0x78, 0x4D, 0x44, 0x45, 0x78, 0x4D, 0x44, 0x59, 0x78, 0x4E, 0x7A, 0x55, 0x31, 0x57, 0x68, 0x63,
|
||||
0x4E, 0x4D, 0x54, 0x51, 0x78, 0x4D, 0x44, 0x45, 0x78, 0x4D, 0x44, 0x59, 0x78, 0x4E, 0x7A, 0x55,
|
||||
0x31, 0x57, 0x6A, 0x41, 0x55, 0x4D, 0x52, 0x49, 0x77, 0x45, 0x41, 0x59, 0x44, 0x0A, 0x56, 0x51,
|
||||
0x51, 0x44, 0x45, 0x77, 0x6C, 0x73, 0x62, 0x32, 0x4E, 0x68, 0x62, 0x47, 0x68, 0x76, 0x63, 0x33,
|
||||
0x51, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49,
|
||||
0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77,
|
||||
0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x33, 0x0A, 0x65,
|
||||
0x6E, 0x33, 0x68, 0x5A, 0x4F, 0x53, 0x33, 0x6B, 0x51, 0x2F, 0x55, 0x54, 0x30, 0x53, 0x45, 0x6C,
|
||||
0x30, 0x48, 0x6E, 0x50, 0x79, 0x64, 0x48, 0x75, 0x35, 0x39, 0x61, 0x69, 0x71, 0x64, 0x73, 0x64,
|
||||
0x53, 0x55, 0x74, 0x6E, 0x43, 0x41, 0x37, 0x46, 0x66, 0x74, 0x30, 0x4F, 0x36, 0x51, 0x79, 0x68,
|
||||
0x49, 0x71, 0x58, 0x7A, 0x30, 0x47, 0x32, 0x53, 0x76, 0x77, 0x4C, 0x54, 0x62, 0x79, 0x68, 0x0A,
|
||||
0x59, 0x54, 0x68, 0x31, 0x36, 0x78, 0x31, 0x72, 0x45, 0x48, 0x68, 0x31, 0x57, 0x47, 0x5A, 0x6D,
|
||||
0x36, 0x77, 0x64, 0x2B, 0x4B, 0x76, 0x38, 0x6B, 0x31, 0x6B, 0x2F, 0x36, 0x6F, 0x41, 0x2F, 0x4F,
|
||||
0x51, 0x76, 0x65, 0x61, 0x38, 0x6B, 0x63, 0x45, 0x64, 0x53, 0x72, 0x54, 0x64, 0x75, 0x71, 0x4A,
|
||||
0x33, 0x65, 0x66, 0x74, 0x48, 0x4A, 0x4A, 0x6E, 0x43, 0x4B, 0x30, 0x41, 0x62, 0x68, 0x34, 0x39,
|
||||
0x0A, 0x41, 0x47, 0x41, 0x50, 0x39, 0x79, 0x58, 0x77, 0x77, 0x59, 0x41, 0x6A, 0x51, 0x49, 0x52,
|
||||
0x6E, 0x38, 0x2B, 0x4F, 0x63, 0x63, 0x48, 0x74, 0x6F, 0x4E, 0x75, 0x75, 0x79, 0x52, 0x63, 0x6B,
|
||||
0x49, 0x50, 0x71, 0x75, 0x70, 0x78, 0x79, 0x31, 0x4A, 0x5A, 0x4B, 0x39, 0x64, 0x76, 0x76, 0x62,
|
||||
0x34, 0x79, 0x53, 0x6B, 0x49, 0x75, 0x7A, 0x62, 0x79, 0x50, 0x6F, 0x54, 0x41, 0x79, 0x61, 0x55,
|
||||
0x2B, 0x0A, 0x51, 0x72, 0x70, 0x34, 0x78, 0x67, 0x64, 0x4B, 0x46, 0x54, 0x70, 0x6B, 0x50, 0x46,
|
||||
0x34, 0x33, 0x6A, 0x32, 0x4D, 0x6D, 0x5A, 0x72, 0x46, 0x63, 0x42, 0x76, 0x79, 0x6A, 0x69, 0x35,
|
||||
0x6A, 0x4F, 0x37, 0x74, 0x66, 0x6F, 0x56, 0x61, 0x6B, 0x59, 0x47, 0x53, 0x2F, 0x4C, 0x63, 0x78,
|
||||
0x77, 0x47, 0x2B, 0x77, 0x51, 0x77, 0x63, 0x4F, 0x43, 0x54, 0x42, 0x45, 0x78, 0x2F, 0x7A, 0x31,
|
||||
0x53, 0x30, 0x0A, 0x37, 0x49, 0x2F, 0x6A, 0x62, 0x44, 0x79, 0x53, 0x4E, 0x68, 0x44, 0x35, 0x63,
|
||||
0x61, 0x63, 0x54, 0x75, 0x4E, 0x36, 0x50, 0x68, 0x33, 0x58, 0x30, 0x71, 0x70, 0x47, 0x73, 0x37,
|
||||
0x79, 0x50, 0x6B, 0x4E, 0x79, 0x69, 0x4A, 0x33, 0x57, 0x52, 0x69, 0x6C, 0x35, 0x75, 0x57, 0x73,
|
||||
0x4B, 0x65, 0x79, 0x63, 0x64, 0x71, 0x42, 0x4E, 0x72, 0x34, 0x75, 0x32, 0x62, 0x49, 0x52, 0x6E,
|
||||
0x63, 0x54, 0x51, 0x0A, 0x46, 0x72, 0x68, 0x73, 0x58, 0x39, 0x69, 0x77, 0x37, 0x35, 0x76, 0x75,
|
||||
0x53, 0x64, 0x35, 0x46, 0x39, 0x37, 0x56, 0x70, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A,
|
||||
0x4A, 0x44, 0x41, 0x69, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x64, 0x4A, 0x51, 0x51, 0x4D,
|
||||
0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42, 0x77, 0x4D, 0x42,
|
||||
0x4D, 0x41, 0x73, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49,
|
||||
0x45, 0x4D, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30,
|
||||
0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x49, 0x51, 0x66,
|
||||
0x75, 0x2F, 0x77, 0x39, 0x45, 0x34, 0x4C, 0x6F, 0x67, 0x30, 0x71, 0x35, 0x4B, 0x53, 0x38, 0x71,
|
||||
0x46, 0x78, 0x62, 0x36, 0x6F, 0x0A, 0x36, 0x31, 0x62, 0x35, 0x37, 0x6F, 0x6D, 0x6E, 0x46, 0x59,
|
||||
0x52, 0x34, 0x47, 0x43, 0x67, 0x33, 0x6F, 0x6A, 0x4F, 0x4C, 0x54, 0x66, 0x38, 0x7A, 0x6A, 0x4D,
|
||||
0x43, 0x52, 0x6D, 0x75, 0x59, 0x32, 0x76, 0x30, 0x4E, 0x34, 0x78, 0x66, 0x68, 0x69, 0x35, 0x4B,
|
||||
0x69, 0x59, 0x67, 0x64, 0x76, 0x4E, 0x4C, 0x4F, 0x33, 0x52, 0x42, 0x6D, 0x4E, 0x50, 0x76, 0x59,
|
||||
0x58, 0x50, 0x52, 0x46, 0x41, 0x76, 0x0A, 0x66, 0x61, 0x76, 0x66, 0x57, 0x75, 0x6C, 0x44, 0x31,
|
||||
0x64, 0x50, 0x36, 0x31, 0x69, 0x35, 0x62, 0x36, 0x59, 0x66, 0x56, 0x6C, 0x78, 0x62, 0x31, 0x61,
|
||||
0x57, 0x46, 0x37, 0x4C, 0x5A, 0x44, 0x32, 0x55, 0x6E, 0x63, 0x41, 0x6A, 0x37, 0x4E, 0x38, 0x78,
|
||||
0x38, 0x2B, 0x36, 0x58, 0x6B, 0x30, 0x6B, 0x63, 0x70, 0x58, 0x46, 0x38, 0x6C, 0x77, 0x58, 0x48,
|
||||
0x55, 0x57, 0x57, 0x55, 0x6D, 0x73, 0x2B, 0x0A, 0x4B, 0x56, 0x44, 0x34, 0x34, 0x39, 0x68, 0x6F,
|
||||
0x4D, 0x2B, 0x77, 0x4E, 0x4A, 0x49, 0x61, 0x4F, 0x52, 0x39, 0x4C, 0x46, 0x2B, 0x6B, 0x6F, 0x32,
|
||||
0x32, 0x37, 0x7A, 0x74, 0x37, 0x54, 0x41, 0x47, 0x64, 0x56, 0x35, 0x4A, 0x75, 0x7A, 0x71, 0x38,
|
||||
0x32, 0x2F, 0x6B, 0x75, 0x73, 0x6F, 0x65, 0x32, 0x69, 0x75, 0x57, 0x77, 0x54, 0x65, 0x42, 0x6C,
|
||||
0x53, 0x5A, 0x6E, 0x6B, 0x42, 0x38, 0x63, 0x64, 0x0A, 0x77, 0x4D, 0x30, 0x5A, 0x42, 0x58, 0x6D,
|
||||
0x34, 0x35, 0x48, 0x38, 0x6F, 0x79, 0x75, 0x36, 0x4A, 0x71, 0x59, 0x71, 0x45, 0x6D, 0x75, 0x4A,
|
||||
0x51, 0x64, 0x67, 0x79, 0x52, 0x2B, 0x63, 0x53, 0x53, 0x41, 0x7A, 0x2B, 0x4F, 0x32, 0x6D, 0x61,
|
||||
0x62, 0x68, 0x50, 0x5A, 0x65, 0x49, 0x76, 0x78, 0x65, 0x67, 0x6A, 0x6A, 0x61, 0x5A, 0x61, 0x46,
|
||||
0x4F, 0x71, 0x74, 0x73, 0x2B, 0x64, 0x33, 0x72, 0x39, 0x0A, 0x79, 0x71, 0x4A, 0x78, 0x67, 0x75,
|
||||
0x39, 0x43, 0x38, 0x39, 0x5A, 0x69, 0x33, 0x39, 0x57, 0x34, 0x38, 0x46, 0x66, 0x46, 0x63, 0x49,
|
||||
0x58, 0x4A, 0x4F, 0x6B, 0x39, 0x43, 0x4E, 0x46, 0x41, 0x2F, 0x69, 0x70, 0x54, 0x57, 0x6A, 0x74,
|
||||
0x74, 0x4E, 0x2F, 0x6B, 0x4F, 0x6B, 0x5A, 0x42, 0x70, 0x6F, 0x6A, 0x2F, 0x32, 0x6A, 0x4E, 0x45,
|
||||
0x62, 0x4F, 0x59, 0x7A, 0x7A, 0x6E, 0x4B, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
|
||||
0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D,
|
||||
0x2D, 0x2D, 0x2D, 0x2D, 0x0A
|
||||
};
|
||||
|
||||
static const BYTE test_localhost_key[1704] = {
|
||||
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41,
|
||||
0x54, 0x45, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45,
|
||||
0x76, 0x51, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47,
|
||||
0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, 0x42, 0x4B, 0x63, 0x77,
|
||||
0x67, 0x67, 0x53, 0x6A, 0x41, 0x67, 0x45, 0x41, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x33,
|
||||
0x65, 0x6E, 0x33, 0x68, 0x5A, 0x4F, 0x53, 0x33, 0x6B, 0x51, 0x2F, 0x55, 0x0A, 0x54, 0x30, 0x53,
|
||||
0x45, 0x6C, 0x30, 0x48, 0x6E, 0x50, 0x79, 0x64, 0x48, 0x75, 0x35, 0x39, 0x61, 0x69, 0x71, 0x64,
|
||||
0x73, 0x64, 0x53, 0x55, 0x74, 0x6E, 0x43, 0x41, 0x37, 0x46, 0x66, 0x74, 0x30, 0x4F, 0x36, 0x51,
|
||||
0x79, 0x68, 0x49, 0x71, 0x58, 0x7A, 0x30, 0x47, 0x32, 0x53, 0x76, 0x77, 0x4C, 0x54, 0x62, 0x79,
|
||||
0x68, 0x59, 0x54, 0x68, 0x31, 0x36, 0x78, 0x31, 0x72, 0x45, 0x48, 0x68, 0x31, 0x0A, 0x57, 0x47,
|
||||
0x5A, 0x6D, 0x36, 0x77, 0x64, 0x2B, 0x4B, 0x76, 0x38, 0x6B, 0x31, 0x6B, 0x2F, 0x36, 0x6F, 0x41,
|
||||
0x2F, 0x4F, 0x51, 0x76, 0x65, 0x61, 0x38, 0x6B, 0x63, 0x45, 0x64, 0x53, 0x72, 0x54, 0x64, 0x75,
|
||||
0x71, 0x4A, 0x33, 0x65, 0x66, 0x74, 0x48, 0x4A, 0x4A, 0x6E, 0x43, 0x4B, 0x30, 0x41, 0x62, 0x68,
|
||||
0x34, 0x39, 0x41, 0x47, 0x41, 0x50, 0x39, 0x79, 0x58, 0x77, 0x77, 0x59, 0x41, 0x6A, 0x0A, 0x51,
|
||||
0x49, 0x52, 0x6E, 0x38, 0x2B, 0x4F, 0x63, 0x63, 0x48, 0x74, 0x6F, 0x4E, 0x75, 0x75, 0x79, 0x52,
|
||||
0x63, 0x6B, 0x49, 0x50, 0x71, 0x75, 0x70, 0x78, 0x79, 0x31, 0x4A, 0x5A, 0x4B, 0x39, 0x64, 0x76,
|
||||
0x76, 0x62, 0x34, 0x79, 0x53, 0x6B, 0x49, 0x75, 0x7A, 0x62, 0x79, 0x50, 0x6F, 0x54, 0x41, 0x79,
|
||||
0x61, 0x55, 0x2B, 0x51, 0x72, 0x70, 0x34, 0x78, 0x67, 0x64, 0x4B, 0x46, 0x54, 0x70, 0x6B, 0x0A,
|
||||
0x50, 0x46, 0x34, 0x33, 0x6A, 0x32, 0x4D, 0x6D, 0x5A, 0x72, 0x46, 0x63, 0x42, 0x76, 0x79, 0x6A,
|
||||
0x69, 0x35, 0x6A, 0x4F, 0x37, 0x74, 0x66, 0x6F, 0x56, 0x61, 0x6B, 0x59, 0x47, 0x53, 0x2F, 0x4C,
|
||||
0x63, 0x78, 0x77, 0x47, 0x2B, 0x77, 0x51, 0x77, 0x63, 0x4F, 0x43, 0x54, 0x42, 0x45, 0x78, 0x2F,
|
||||
0x7A, 0x31, 0x53, 0x30, 0x37, 0x49, 0x2F, 0x6A, 0x62, 0x44, 0x79, 0x53, 0x4E, 0x68, 0x44, 0x35,
|
||||
0x0A, 0x63, 0x61, 0x63, 0x54, 0x75, 0x4E, 0x36, 0x50, 0x68, 0x33, 0x58, 0x30, 0x71, 0x70, 0x47,
|
||||
0x73, 0x37, 0x79, 0x50, 0x6B, 0x4E, 0x79, 0x69, 0x4A, 0x33, 0x57, 0x52, 0x69, 0x6C, 0x35, 0x75,
|
||||
0x57, 0x73, 0x4B, 0x65, 0x79, 0x63, 0x64, 0x71, 0x42, 0x4E, 0x72, 0x34, 0x75, 0x32, 0x62, 0x49,
|
||||
0x52, 0x6E, 0x63, 0x54, 0x51, 0x46, 0x72, 0x68, 0x73, 0x58, 0x39, 0x69, 0x77, 0x37, 0x35, 0x76,
|
||||
0x75, 0x0A, 0x53, 0x64, 0x35, 0x46, 0x39, 0x37, 0x56, 0x70, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41,
|
||||
0x45, 0x43, 0x67, 0x67, 0x45, 0x41, 0x42, 0x36, 0x6A, 0x6C, 0x65, 0x48, 0x4E, 0x74, 0x32, 0x50,
|
||||
0x77, 0x46, 0x58, 0x53, 0x65, 0x79, 0x42, 0x4A, 0x63, 0x4C, 0x2B, 0x55, 0x74, 0x35, 0x71, 0x46,
|
||||
0x54, 0x38, 0x34, 0x68, 0x72, 0x48, 0x77, 0x6F, 0x39, 0x68, 0x62, 0x66, 0x59, 0x47, 0x6F, 0x6E,
|
||||
0x44, 0x59, 0x0A, 0x66, 0x70, 0x47, 0x2B, 0x32, 0x52, 0x30, 0x50, 0x62, 0x43, 0x63, 0x4B, 0x35,
|
||||
0x30, 0x46, 0x61, 0x4A, 0x46, 0x36, 0x71, 0x63, 0x56, 0x4A, 0x4E, 0x75, 0x52, 0x36, 0x48, 0x71,
|
||||
0x2B, 0x43, 0x55, 0x4A, 0x74, 0x48, 0x35, 0x39, 0x48, 0x48, 0x37, 0x62, 0x68, 0x6A, 0x39, 0x62,
|
||||
0x64, 0x78, 0x45, 0x6D, 0x6F, 0x48, 0x30, 0x4A, 0x76, 0x68, 0x45, 0x76, 0x67, 0x4D, 0x2F, 0x55,
|
||||
0x38, 0x42, 0x51, 0x0A, 0x65, 0x57, 0x4F, 0x4E, 0x68, 0x78, 0x50, 0x73, 0x69, 0x73, 0x6D, 0x57,
|
||||
0x6B, 0x78, 0x61, 0x5A, 0x6F, 0x6C, 0x72, 0x32, 0x69, 0x44, 0x56, 0x72, 0x7A, 0x54, 0x37, 0x55,
|
||||
0x4A, 0x71, 0x6A, 0x74, 0x59, 0x49, 0x74, 0x67, 0x2B, 0x37, 0x59, 0x43, 0x32, 0x70, 0x55, 0x58,
|
||||
0x6B, 0x64, 0x49, 0x35, 0x4A, 0x4D, 0x67, 0x6C, 0x44, 0x47, 0x4D, 0x52, 0x5A, 0x35, 0x55, 0x5A,
|
||||
0x48, 0x75, 0x63, 0x7A, 0x0A, 0x41, 0x56, 0x2B, 0x71, 0x77, 0x77, 0x33, 0x65, 0x45, 0x52, 0x74,
|
||||
0x78, 0x44, 0x50, 0x61, 0x61, 0x61, 0x34, 0x54, 0x39, 0x50, 0x64, 0x33, 0x44, 0x31, 0x6D, 0x62,
|
||||
0x71, 0x58, 0x66, 0x75, 0x45, 0x68, 0x42, 0x6D, 0x33, 0x51, 0x6F, 0x2B, 0x75, 0x7A, 0x51, 0x32,
|
||||
0x36, 0x76, 0x73, 0x66, 0x48, 0x75, 0x56, 0x76, 0x61, 0x39, 0x38, 0x32, 0x4F, 0x6A, 0x41, 0x55,
|
||||
0x6A, 0x6E, 0x64, 0x30, 0x70, 0x0A, 0x77, 0x43, 0x53, 0x6E, 0x42, 0x49, 0x48, 0x67, 0x70, 0x73,
|
||||
0x30, 0x79, 0x61, 0x45, 0x50, 0x63, 0x37, 0x46, 0x78, 0x39, 0x71, 0x45, 0x63, 0x6D, 0x33, 0x70,
|
||||
0x7A, 0x41, 0x56, 0x31, 0x69, 0x72, 0x31, 0x4E, 0x4E, 0x63, 0x51, 0x47, 0x55, 0x45, 0x75, 0x45,
|
||||
0x6C, 0x4A, 0x78, 0x76, 0x2B, 0x69, 0x57, 0x34, 0x6D, 0x35, 0x70, 0x7A, 0x4C, 0x6A, 0x64, 0x53,
|
||||
0x63, 0x49, 0x30, 0x59, 0x45, 0x73, 0x0A, 0x4D, 0x61, 0x33, 0x78, 0x32, 0x79, 0x48, 0x74, 0x6E,
|
||||
0x77, 0x79, 0x65, 0x4C, 0x4D, 0x54, 0x4B, 0x6C, 0x72, 0x46, 0x4B, 0x70, 0x55, 0x4E, 0x4A, 0x62,
|
||||
0x78, 0x73, 0x35, 0x32, 0x62, 0x5A, 0x4B, 0x71, 0x49, 0x56, 0x33, 0x33, 0x4A, 0x53, 0x34, 0x41,
|
||||
0x51, 0x4B, 0x42, 0x67, 0x51, 0x44, 0x73, 0x4C, 0x54, 0x49, 0x68, 0x35, 0x59, 0x38, 0x4C, 0x2F,
|
||||
0x48, 0x33, 0x64, 0x74, 0x68, 0x63, 0x62, 0x0A, 0x53, 0x43, 0x45, 0x77, 0x32, 0x64, 0x42, 0x49,
|
||||
0x76, 0x49, 0x79, 0x54, 0x7A, 0x39, 0x53, 0x72, 0x62, 0x33, 0x58, 0x37, 0x37, 0x41, 0x77, 0x57,
|
||||
0x45, 0x4C, 0x53, 0x4D, 0x49, 0x57, 0x53, 0x50, 0x55, 0x43, 0x4B, 0x54, 0x49, 0x70, 0x6A, 0x4D,
|
||||
0x73, 0x6E, 0x7A, 0x6B, 0x46, 0x67, 0x32, 0x32, 0x59, 0x32, 0x53, 0x75, 0x47, 0x38, 0x4C, 0x72,
|
||||
0x50, 0x6D, 0x76, 0x73, 0x46, 0x4A, 0x34, 0x30, 0x0A, 0x32, 0x67, 0x35, 0x44, 0x55, 0x6C, 0x59,
|
||||
0x33, 0x59, 0x6D, 0x53, 0x4F, 0x46, 0x61, 0x45, 0x4A, 0x54, 0x70, 0x55, 0x47, 0x44, 0x4D, 0x79,
|
||||
0x65, 0x33, 0x74, 0x36, 0x4F, 0x30, 0x6C, 0x63, 0x51, 0x41, 0x66, 0x79, 0x6D, 0x58, 0x66, 0x41,
|
||||
0x38, 0x74, 0x50, 0x42, 0x48, 0x6A, 0x5A, 0x78, 0x56, 0x61, 0x38, 0x78, 0x78, 0x52, 0x5A, 0x6E,
|
||||
0x56, 0x43, 0x31, 0x41, 0x62, 0x75, 0x49, 0x49, 0x52, 0x0A, 0x6E, 0x77, 0x72, 0x4E, 0x46, 0x2B,
|
||||
0x42, 0x6F, 0x53, 0x4B, 0x55, 0x41, 0x73, 0x78, 0x2B, 0x46, 0x75, 0x35, 0x5A, 0x4A, 0x4B, 0x4F,
|
||||
0x66, 0x79, 0x4D, 0x51, 0x4B, 0x42, 0x67, 0x51, 0x44, 0x47, 0x34, 0x50, 0x52, 0x39, 0x2F, 0x58,
|
||||
0x58, 0x6B, 0x51, 0x54, 0x36, 0x6B, 0x7A, 0x4B, 0x64, 0x34, 0x50, 0x6C, 0x50, 0x4D, 0x63, 0x2B,
|
||||
0x4B, 0x51, 0x79, 0x4C, 0x45, 0x6C, 0x4B, 0x39, 0x71, 0x47, 0x0A, 0x41, 0x6D, 0x6E, 0x2F, 0x31,
|
||||
0x68, 0x64, 0x69, 0x57, 0x57, 0x4F, 0x52, 0x57, 0x46, 0x62, 0x32, 0x38, 0x30, 0x4D, 0x77, 0x76,
|
||||
0x77, 0x41, 0x64, 0x78, 0x72, 0x66, 0x65, 0x4C, 0x57, 0x4D, 0x57, 0x32, 0x66, 0x76, 0x4C, 0x59,
|
||||
0x4B, 0x66, 0x6C, 0x4F, 0x35, 0x50, 0x51, 0x44, 0x59, 0x67, 0x4B, 0x4A, 0x78, 0x35, 0x79, 0x50,
|
||||
0x37, 0x52, 0x64, 0x38, 0x2F, 0x64, 0x50, 0x79, 0x5A, 0x59, 0x36, 0x0A, 0x7A, 0x56, 0x37, 0x47,
|
||||
0x47, 0x6B, 0x51, 0x5A, 0x42, 0x4B, 0x36, 0x79, 0x74, 0x61, 0x66, 0x32, 0x35, 0x44, 0x50, 0x67,
|
||||
0x50, 0x72, 0x32, 0x77, 0x73, 0x59, 0x4D, 0x43, 0x6C, 0x53, 0x74, 0x6C, 0x56, 0x74, 0x72, 0x6D,
|
||||
0x4F, 0x78, 0x59, 0x55, 0x56, 0x77, 0x42, 0x59, 0x4F, 0x69, 0x36, 0x45, 0x62, 0x50, 0x69, 0x6B,
|
||||
0x78, 0x47, 0x48, 0x5A, 0x70, 0x59, 0x6F, 0x5A, 0x5A, 0x70, 0x68, 0x4A, 0x0A, 0x4E, 0x61, 0x38,
|
||||
0x4F, 0x4C, 0x31, 0x69, 0x77, 0x75, 0x51, 0x4B, 0x42, 0x67, 0x51, 0x44, 0x42, 0x55, 0x55, 0x31,
|
||||
0x54, 0x79, 0x5A, 0x2B, 0x4A, 0x5A, 0x43, 0x64, 0x79, 0x72, 0x33, 0x58, 0x43, 0x63, 0x77, 0x77,
|
||||
0x58, 0x2F, 0x48, 0x49, 0x73, 0x31, 0x34, 0x6B, 0x4B, 0x42, 0x48, 0x68, 0x44, 0x79, 0x33, 0x78,
|
||||
0x37, 0x74, 0x50, 0x38, 0x2F, 0x6F, 0x48, 0x54, 0x6F, 0x72, 0x76, 0x79, 0x74, 0x0A, 0x41, 0x68,
|
||||
0x38, 0x4B, 0x36, 0x4B, 0x72, 0x43, 0x41, 0x75, 0x65, 0x50, 0x6D, 0x79, 0x32, 0x6D, 0x4F, 0x54,
|
||||
0x31, 0x54, 0x39, 0x6F, 0x31, 0x61, 0x47, 0x55, 0x49, 0x6C, 0x66, 0x38, 0x72, 0x76, 0x33, 0x2F,
|
||||
0x30, 0x45, 0x78, 0x67, 0x53, 0x6B, 0x57, 0x50, 0x6D, 0x4F, 0x41, 0x38, 0x35, 0x49, 0x32, 0x2F,
|
||||
0x58, 0x48, 0x65, 0x66, 0x71, 0x54, 0x6F, 0x45, 0x48, 0x30, 0x44, 0x65, 0x41, 0x4E, 0x0A, 0x7A,
|
||||
0x6C, 0x4B, 0x4C, 0x71, 0x79, 0x44, 0x56, 0x30, 0x42, 0x56, 0x4E, 0x76, 0x48, 0x42, 0x57, 0x79,
|
||||
0x32, 0x49, 0x51, 0x35, 0x62, 0x50, 0x42, 0x57, 0x76, 0x30, 0x37, 0x63, 0x34, 0x2B, 0x6A, 0x39,
|
||||
0x4E, 0x62, 0x57, 0x67, 0x64, 0x44, 0x43, 0x43, 0x35, 0x52, 0x6B, 0x4F, 0x6A, 0x70, 0x33, 0x4D,
|
||||
0x4E, 0x45, 0x58, 0x47, 0x56, 0x43, 0x69, 0x51, 0x51, 0x4B, 0x42, 0x67, 0x43, 0x7A, 0x4D, 0x0A,
|
||||
0x77, 0x65, 0x61, 0x62, 0x73, 0x50, 0x48, 0x68, 0x44, 0x4B, 0x5A, 0x38, 0x2F, 0x34, 0x43, 0x6A,
|
||||
0x73, 0x61, 0x62, 0x4E, 0x75, 0x41, 0x7A, 0x62, 0x57, 0x4B, 0x52, 0x42, 0x38, 0x37, 0x44, 0x61,
|
||||
0x58, 0x46, 0x78, 0x6F, 0x4D, 0x73, 0x35, 0x52, 0x79, 0x6F, 0x38, 0x55, 0x4D, 0x6B, 0x72, 0x67,
|
||||
0x30, 0x35, 0x4C, 0x6F, 0x67, 0x37, 0x4D, 0x78, 0x62, 0x33, 0x76, 0x61, 0x42, 0x34, 0x63, 0x2F,
|
||||
0x0A, 0x52, 0x57, 0x77, 0x7A, 0x38, 0x72, 0x34, 0x39, 0x70, 0x48, 0x64, 0x71, 0x68, 0x4F, 0x6D,
|
||||
0x63, 0x6C, 0x45, 0x77, 0x79, 0x4D, 0x34, 0x51, 0x79, 0x6A, 0x39, 0x52, 0x6D, 0x57, 0x62, 0x51,
|
||||
0x58, 0x54, 0x54, 0x45, 0x63, 0x2B, 0x35, 0x67, 0x54, 0x4B, 0x50, 0x4E, 0x53, 0x33, 0x6D, 0x70,
|
||||
0x4D, 0x54, 0x36, 0x39, 0x46, 0x45, 0x74, 0x2F, 0x35, 0x72, 0x4D, 0x52, 0x70, 0x4B, 0x2B, 0x52,
|
||||
0x68, 0x0A, 0x49, 0x32, 0x42, 0x58, 0x6B, 0x51, 0x71, 0x31, 0x36, 0x6E, 0x72, 0x31, 0x61, 0x45,
|
||||
0x4D, 0x6D, 0x64, 0x51, 0x42, 0x51, 0x79, 0x4B, 0x59, 0x4A, 0x6C, 0x30, 0x6C, 0x50, 0x68, 0x69,
|
||||
0x42, 0x2F, 0x75, 0x6C, 0x5A, 0x63, 0x72, 0x67, 0x4C, 0x70, 0x41, 0x6F, 0x47, 0x41, 0x65, 0x30,
|
||||
0x65, 0x74, 0x50, 0x4A, 0x77, 0x6D, 0x51, 0x46, 0x6B, 0x6A, 0x4D, 0x70, 0x66, 0x4D, 0x44, 0x61,
|
||||
0x4E, 0x34, 0x0A, 0x70, 0x7A, 0x71, 0x45, 0x51, 0x72, 0x52, 0x35, 0x4B, 0x35, 0x4D, 0x6E, 0x54,
|
||||
0x48, 0x76, 0x47, 0x67, 0x2F, 0x70, 0x6A, 0x57, 0x6A, 0x43, 0x57, 0x58, 0x56, 0x48, 0x67, 0x35,
|
||||
0x76, 0x36, 0x46, 0x6F, 0x5A, 0x48, 0x35, 0x6E, 0x59, 0x2B, 0x56, 0x2F, 0x57, 0x75, 0x57, 0x38,
|
||||
0x38, 0x6A, 0x6C, 0x4B, 0x53, 0x50, 0x6C, 0x77, 0x6A, 0x50, 0x7A, 0x41, 0x67, 0x7A, 0x47, 0x33,
|
||||
0x45, 0x41, 0x55, 0x0A, 0x71, 0x57, 0x6B, 0x42, 0x67, 0x30, 0x71, 0x75, 0x50, 0x4D, 0x72, 0x54,
|
||||
0x6B, 0x73, 0x69, 0x6E, 0x58, 0x50, 0x2B, 0x58, 0x6B, 0x51, 0x65, 0x46, 0x66, 0x58, 0x61, 0x33,
|
||||
0x38, 0x6A, 0x72, 0x70, 0x62, 0x4B, 0x46, 0x4F, 0x72, 0x7A, 0x49, 0x6F, 0x6A, 0x69, 0x65, 0x6C,
|
||||
0x4B, 0x55, 0x4D, 0x50, 0x4D, 0x78, 0x2F, 0x78, 0x70, 0x53, 0x6A, 0x63, 0x55, 0x42, 0x68, 0x62,
|
||||
0x4E, 0x34, 0x45, 0x54, 0x0A, 0x4F, 0x30, 0x66, 0x63, 0x57, 0x47, 0x6F, 0x61, 0x56, 0x50, 0x72,
|
||||
0x63, 0x6E, 0x38, 0x62, 0x58, 0x4D, 0x54, 0x45, 0x4E, 0x53, 0x31, 0x41, 0x3D, 0x0A, 0x2D, 0x2D,
|
||||
0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4B,
|
||||
0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A
|
||||
};
|
||||
|
||||
static const BYTE test_DummyMessage[64] = {
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD
|
||||
};
|
||||
|
||||
static const BYTE test_LastDummyMessage[64] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext,
|
||||
BYTE* buffer, UINT32 length)
|
||||
{
|
||||
BYTE* ioBuffer;
|
||||
UINT32 ioBufferLength;
|
||||
BYTE* pMessageBuffer;
|
||||
SecBuffer Buffers[4] = WINPR_C_ARRAY_INIT;
|
||||
SecBufferDesc Message;
|
||||
SECURITY_STATUS status;
|
||||
DWORD NumberOfBytesWritten;
|
||||
SecPkgContext_StreamSizes StreamSizes = WINPR_C_ARRAY_INIT;
|
||||
|
||||
status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
|
||||
ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer;
|
||||
ioBuffer = (BYTE*)calloc(1, ioBufferLength);
|
||||
if (!ioBuffer)
|
||||
return -1;
|
||||
pMessageBuffer = ioBuffer + StreamSizes.cbHeader;
|
||||
CopyMemory(pMessageBuffer, buffer, length);
|
||||
Buffers[0].pvBuffer = ioBuffer;
|
||||
Buffers[0].cbBuffer = StreamSizes.cbHeader;
|
||||
Buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
|
||||
Buffers[1].pvBuffer = pMessageBuffer;
|
||||
Buffers[1].cbBuffer = length;
|
||||
Buffers[1].BufferType = SECBUFFER_DATA;
|
||||
Buffers[2].pvBuffer = pMessageBuffer + length;
|
||||
Buffers[2].cbBuffer = StreamSizes.cbTrailer;
|
||||
Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
|
||||
Buffers[3].pvBuffer = nullptr;
|
||||
Buffers[3].cbBuffer = 0;
|
||||
Buffers[3].BufferType = SECBUFFER_EMPTY;
|
||||
Message.ulVersion = SECBUFFER_VERSION;
|
||||
Message.cBuffers = 4;
|
||||
Message.pBuffers = Buffers;
|
||||
ioBufferLength =
|
||||
Message.pBuffers[0].cbBuffer + Message.pBuffers[1].cbBuffer + Message.pBuffers[2].cbBuffer;
|
||||
status = table->EncryptMessage(phContext, 0, &Message, 0);
|
||||
printf("EncryptMessage status: 0x%08" PRIX32 "\n", status);
|
||||
printf("EncryptMessage output: cBuffers: %" PRIu32 " [0]: %" PRIu32 " / %" PRIu32
|
||||
" [1]: %" PRIu32 " / %" PRIu32 " [2]: %" PRIu32 " / %" PRIu32 " [3]: %" PRIu32
|
||||
" / %" PRIu32 "\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,
|
||||
Message.pBuffers[3].cbBuffer, Message.pBuffers[3].BufferType);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
return -1;
|
||||
|
||||
printf("Client > Server (%" PRIu32 ")\n", ioBufferLength);
|
||||
winpr_HexDump("sspi.test", WLOG_DEBUG, ioBuffer, ioBufferLength);
|
||||
|
||||
if (!WriteFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesWritten, nullptr))
|
||||
{
|
||||
printf("schannel_send: failed to write to pipe\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext)
|
||||
{
|
||||
BYTE* ioBuffer;
|
||||
UINT32 ioBufferLength;
|
||||
// BYTE* pMessageBuffer;
|
||||
SecBuffer Buffers[4] = WINPR_C_ARRAY_INIT;
|
||||
SecBufferDesc Message;
|
||||
SECURITY_STATUS status;
|
||||
DWORD NumberOfBytesRead;
|
||||
SecPkgContext_StreamSizes StreamSizes = WINPR_C_ARRAY_INIT;
|
||||
|
||||
status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
|
||||
ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer;
|
||||
ioBuffer = (BYTE*)calloc(1, ioBufferLength);
|
||||
if (!ioBuffer)
|
||||
return -1;
|
||||
|
||||
if (!ReadFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesRead, nullptr))
|
||||
{
|
||||
printf("schannel_recv: failed to read from pipe\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Buffers[0].pvBuffer = ioBuffer;
|
||||
Buffers[0].cbBuffer = NumberOfBytesRead;
|
||||
Buffers[0].BufferType = SECBUFFER_DATA;
|
||||
Buffers[1].pvBuffer = nullptr;
|
||||
Buffers[1].cbBuffer = 0;
|
||||
Buffers[1].BufferType = SECBUFFER_EMPTY;
|
||||
Buffers[2].pvBuffer = nullptr;
|
||||
Buffers[2].cbBuffer = 0;
|
||||
Buffers[2].BufferType = SECBUFFER_EMPTY;
|
||||
Buffers[3].pvBuffer = nullptr;
|
||||
Buffers[3].cbBuffer = 0;
|
||||
Buffers[3].BufferType = SECBUFFER_EMPTY;
|
||||
Message.ulVersion = SECBUFFER_VERSION;
|
||||
Message.cBuffers = 4;
|
||||
Message.pBuffers = Buffers;
|
||||
status = table->DecryptMessage(phContext, &Message, 0, nullptr);
|
||||
printf("DecryptMessage status: 0x%08" PRIX32 "\n", status);
|
||||
printf("DecryptMessage output: cBuffers: %" PRIu32 " [0]: %" PRIu32 " / %" PRIu32
|
||||
" [1]: %" PRIu32 " / %" PRIu32 " [2]: %" PRIu32 " / %" PRIu32 " [3]: %" PRIu32
|
||||
" / %" PRIu32 "\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,
|
||||
Message.pBuffers[3].cbBuffer, Message.pBuffers[3].BufferType);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
return -1;
|
||||
|
||||
printf("Decrypted Message (%" PRIu32 ")\n", Message.pBuffers[1].cbBuffer);
|
||||
winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*)Message.pBuffers[1].pvBuffer,
|
||||
Message.pBuffers[1].cbBuffer);
|
||||
|
||||
if (memcmp(Message.pBuffers[1].pvBuffer, test_LastDummyMessage,
|
||||
sizeof(test_LastDummyMessage)) == 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD WINAPI schannel_test_server_thread(LPVOID arg)
|
||||
{
|
||||
BOOL extraData;
|
||||
BYTE* lpTokenIn;
|
||||
BYTE* lpTokenOut;
|
||||
TimeStamp expiry;
|
||||
UINT32 cbMaxToken;
|
||||
UINT32 fContextReq;
|
||||
ULONG fContextAttr;
|
||||
SCHANNEL_CRED cred = WINPR_C_ARRAY_INIT;
|
||||
CtxtHandle context;
|
||||
CredHandle credentials;
|
||||
DWORD cchNameString;
|
||||
LPTSTR pszNameString;
|
||||
HCERTSTORE hCertStore;
|
||||
PCCERT_CONTEXT pCertContext;
|
||||
PSecBuffer pSecBuffer;
|
||||
SecBuffer SecBuffer_in[2] = WINPR_C_ARRAY_INIT;
|
||||
SecBuffer SecBuffer_out[2] = WINPR_C_ARRAY_INIT;
|
||||
SecBufferDesc SecBufferDesc_in;
|
||||
SecBufferDesc SecBufferDesc_out;
|
||||
DWORD NumberOfBytesRead;
|
||||
SECURITY_STATUS status;
|
||||
PSecPkgInfo pPackageInfo;
|
||||
PSecurityFunctionTable table;
|
||||
DWORD NumberOfBytesWritten;
|
||||
printf("Starting Server\n");
|
||||
SecInvalidateHandle(&context);
|
||||
SecInvalidateHandle(&credentials);
|
||||
table = InitSecurityInterface();
|
||||
status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("QuerySecurityPackageInfo failure: 0x%08" PRIX32 "\n", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cbMaxToken = pPackageInfo->cbMaxToken;
|
||||
hCertStore = CertOpenSystemStore(0, _T("MY"));
|
||||
|
||||
if (!hCertStore)
|
||||
{
|
||||
printf("Error opening system store\n");
|
||||
// return nullptr;
|
||||
}
|
||||
|
||||
#ifdef CERT_FIND_HAS_PRIVATE_KEY
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0,
|
||||
CERT_FIND_HAS_PRIVATE_KEY, nullptr, nullptr);
|
||||
#else
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY,
|
||||
nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
if (!pCertContext)
|
||||
{
|
||||
printf("Error finding certificate in store\n");
|
||||
// return nullptr;
|
||||
}
|
||||
|
||||
cchNameString =
|
||||
CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, nullptr, 0);
|
||||
pszNameString = (LPTSTR)malloc(cchNameString * sizeof(TCHAR));
|
||||
if (!pszNameString)
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr,
|
||||
pszNameString, cchNameString);
|
||||
_tprintf(_T("Certificate Name: %s\n"), pszNameString);
|
||||
cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
cred.cCreds = 1;
|
||||
cred.paCred = &pCertContext;
|
||||
cred.cSupportedAlgs = 0;
|
||||
cred.palgSupportedAlgs = nullptr;
|
||||
cred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER;
|
||||
cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER;
|
||||
status = table->AcquireCredentialsHandle(nullptr, SCHANNEL_NAME, SECPKG_CRED_INBOUND, nullptr,
|
||||
&cred, nullptr, nullptr, &credentials, nullptr);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("AcquireCredentialsHandle failure: 0x%08" PRIX32 "\n", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extraData = FALSE;
|
||||
g_ServerWait = TRUE;
|
||||
if (!(lpTokenIn = (BYTE*)malloc(cbMaxToken)))
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
if (!(lpTokenOut = (BYTE*)malloc(cbMaxToken)))
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
free(lpTokenIn);
|
||||
return 0;
|
||||
}
|
||||
fContextReq = ASC_REQ_STREAM | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
|
||||
ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR;
|
||||
|
||||
do
|
||||
{
|
||||
if (!extraData)
|
||||
{
|
||||
if (g_ServerWait)
|
||||
{
|
||||
if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, nullptr))
|
||||
{
|
||||
printf("Failed to read from server pipe\n");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumberOfBytesRead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extraData = FALSE;
|
||||
g_ServerWait = TRUE;
|
||||
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
|
||||
SecBuffer_in[0].pvBuffer = lpTokenIn;
|
||||
SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
|
||||
SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
|
||||
SecBuffer_in[1].pvBuffer = nullptr;
|
||||
SecBuffer_in[1].cbBuffer = 0;
|
||||
SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
|
||||
SecBufferDesc_in.cBuffers = 2;
|
||||
SecBufferDesc_in.pBuffers = SecBuffer_in;
|
||||
SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
|
||||
SecBuffer_out[0].pvBuffer = lpTokenOut;
|
||||
SecBuffer_out[0].cbBuffer = cbMaxToken;
|
||||
SecBufferDesc_out.ulVersion = SECBUFFER_VERSION;
|
||||
SecBufferDesc_out.cBuffers = 1;
|
||||
SecBufferDesc_out.pBuffers = SecBuffer_out;
|
||||
status = table->AcceptSecurityContext(
|
||||
&credentials, SecIsValidHandle(&context) ? &context : nullptr, &SecBufferDesc_in,
|
||||
fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
|
||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) &&
|
||||
(status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
{
|
||||
printf("AcceptSecurityContext unexpected status: 0x%08" PRIX32 "\n", status);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NumberOfBytesWritten = 0;
|
||||
|
||||
if (status == SEC_E_OK)
|
||||
printf("AcceptSecurityContext status: SEC_E_OK\n");
|
||||
else if (status == SEC_I_CONTINUE_NEEDED)
|
||||
printf("AcceptSecurityContext status: SEC_I_CONTINUE_NEEDED\n");
|
||||
else if (status == SEC_E_INCOMPLETE_MESSAGE)
|
||||
printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
|
||||
|
||||
printf("Server cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32 "\n",
|
||||
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer,
|
||||
SecBufferDesc_out.pBuffers[0].BufferType);
|
||||
printf("Server Input cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32
|
||||
" pBuffers[1]: %" PRIu32 " type: %" PRIu32 "\n",
|
||||
SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[0].cbBuffer,
|
||||
SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[1].cbBuffer,
|
||||
SecBufferDesc_in.pBuffers[1].BufferType);
|
||||
|
||||
if (SecBufferDesc_in.pBuffers[1].BufferType == SECBUFFER_EXTRA)
|
||||
{
|
||||
printf("AcceptSecurityContext SECBUFFER_EXTRA\n");
|
||||
pSecBuffer = &SecBufferDesc_in.pBuffers[1];
|
||||
CopyMemory(lpTokenIn, &lpTokenIn[NumberOfBytesRead - pSecBuffer->cbBuffer],
|
||||
pSecBuffer->cbBuffer);
|
||||
NumberOfBytesRead = pSecBuffer->cbBuffer;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status != SEC_E_INCOMPLETE_MESSAGE)
|
||||
{
|
||||
pSecBuffer = &SecBufferDesc_out.pBuffers[0];
|
||||
|
||||
if (pSecBuffer->cbBuffer > 0)
|
||||
{
|
||||
printf("Server > Client (%" PRIu32 ")\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*)pSecBuffer->pvBuffer,
|
||||
pSecBuffer->cbBuffer);
|
||||
|
||||
if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer,
|
||||
&NumberOfBytesWritten, nullptr))
|
||||
{
|
||||
printf("failed to write to client pipe\n");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
printf("Server Handshake Complete\n");
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
do
|
||||
{
|
||||
if (schannel_recv(table, g_ServerReadPipe, &context) < 0)
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_test_certificate_files(void)
|
||||
{
|
||||
FILE* fp;
|
||||
char* fullpath = nullptr;
|
||||
int ret = -1;
|
||||
|
||||
/*
|
||||
* Output Certificate File
|
||||
*/
|
||||
fullpath = GetCombinedPath("/tmp", "localhost.crt");
|
||||
if (!fullpath)
|
||||
return -1;
|
||||
|
||||
fp = winpr_fopen(fullpath, "w+");
|
||||
if (fp)
|
||||
{
|
||||
if (fwrite((void*)test_localhost_crt, sizeof(test_localhost_crt), 1, fp) != 1)
|
||||
goto out_fail;
|
||||
fclose(fp);
|
||||
fp = nullptr;
|
||||
}
|
||||
free(fullpath);
|
||||
|
||||
/*
|
||||
* Output Private Key File
|
||||
*/
|
||||
fullpath = GetCombinedPath("/tmp", "localhost.key");
|
||||
if (!fullpath)
|
||||
return -1;
|
||||
fp = winpr_fopen(fullpath, "w+");
|
||||
if (fp && fwrite((void*)test_localhost_key, sizeof(test_localhost_key), 1, fp) != 1)
|
||||
goto out_fail;
|
||||
|
||||
ret = 1;
|
||||
out_fail:
|
||||
free(fullpath);
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int TestSchannel(int argc, char* argv[])
|
||||
{
|
||||
int count;
|
||||
ALG_ID algId;
|
||||
HANDLE thread;
|
||||
BYTE* lpTokenIn;
|
||||
BYTE* lpTokenOut;
|
||||
TimeStamp expiry;
|
||||
UINT32 cbMaxToken;
|
||||
SCHANNEL_CRED cred = WINPR_C_ARRAY_INIT;
|
||||
UINT32 fContextReq;
|
||||
ULONG fContextAttr;
|
||||
CtxtHandle context;
|
||||
CredHandle credentials;
|
||||
SECURITY_STATUS status;
|
||||
PSecPkgInfo pPackageInfo;
|
||||
PSecBuffer pSecBuffer;
|
||||
PSecurityFunctionTable table;
|
||||
DWORD NumberOfBytesRead;
|
||||
DWORD NumberOfBytesWritten;
|
||||
SecPkgCred_SupportedAlgs SupportedAlgs = WINPR_C_ARRAY_INIT;
|
||||
SecPkgCred_CipherStrengths CipherStrengths = WINPR_C_ARRAY_INIT;
|
||||
SecPkgCred_SupportedProtocols SupportedProtocols = WINPR_C_ARRAY_INIT;
|
||||
return 0; /* disable by default - causes crash */
|
||||
sspi_GlobalInit();
|
||||
dump_test_certificate_files();
|
||||
SecInvalidateHandle(&context);
|
||||
SecInvalidateHandle(&credentials);
|
||||
|
||||
if (!CreatePipe(&g_ClientReadPipe, &g_ClientWritePipe, nullptr, 0))
|
||||
{
|
||||
printf("Failed to create client pipe\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!CreatePipe(&g_ServerReadPipe, &g_ServerWritePipe, nullptr, 0))
|
||||
{
|
||||
printf("Failed to create server pipe\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(thread = CreateThread(nullptr, 0, schannel_test_server_thread, nullptr, 0, nullptr)))
|
||||
{
|
||||
printf("Failed to create server thread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
table = InitSecurityInterface();
|
||||
status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("QuerySecurityPackageInfo failure: 0x%08" PRIX32 "\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cbMaxToken = pPackageInfo->cbMaxToken;
|
||||
cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
cred.cCreds = 0;
|
||||
cred.paCred = nullptr;
|
||||
cred.cSupportedAlgs = 0;
|
||||
cred.palgSupportedAlgs = nullptr;
|
||||
cred.grbitEnabledProtocols = SP_PROT_SSL3TLS1_CLIENTS;
|
||||
cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS;
|
||||
cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
|
||||
cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
|
||||
status = table->AcquireCredentialsHandle(nullptr, SCHANNEL_NAME, SECPKG_CRED_OUTBOUND, nullptr,
|
||||
&cred, nullptr, nullptr, &credentials, nullptr);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("AcquireCredentialsHandle failure: 0x%08" PRIX32 "\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status =
|
||||
table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_ALGS, &SupportedAlgs);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_ALGS failure: 0x%08" PRIX32 "\n",
|
||||
status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* SupportedAlgs: 15
|
||||
* 0x660E 0x6610 0x6801 0x6603 0x6601 0x8003 0x8004
|
||||
* 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203
|
||||
*/
|
||||
printf("SupportedAlgs: %" PRIu32 "\n", SupportedAlgs.cSupportedAlgs);
|
||||
|
||||
for (DWORD index = 0; index < SupportedAlgs.cSupportedAlgs; index++)
|
||||
{
|
||||
algId = SupportedAlgs.palgSupportedAlgs[index];
|
||||
printf("\t0x%08" PRIX32 " CLASS: %" PRIu32 " TYPE: %" PRIu32 " SID: %" PRIu32 "\n", algId,
|
||||
((GET_ALG_CLASS(algId)) >> 13), ((GET_ALG_TYPE(algId)) >> 9), GET_ALG_SID(algId));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_CIPHER_STRENGTHS,
|
||||
&CipherStrengths);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("QueryCredentialsAttributes SECPKG_ATTR_CIPHER_STRENGTHS failure: 0x%08" PRIX32 "\n",
|
||||
status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* CipherStrengths: Minimum: 40 Maximum: 256 */
|
||||
printf("CipherStrengths: Minimum: %" PRIu32 " Maximum: %" PRIu32 "\n",
|
||||
CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength);
|
||||
status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_PROTOCOLS,
|
||||
&SupportedProtocols);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_PROTOCOLS failure: 0x%08" PRIX32
|
||||
"\n",
|
||||
status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* SupportedProtocols: 0x208A0 */
|
||||
printf("SupportedProtocols: 0x%08" PRIX32 "\n", SupportedProtocols.grbitProtocol);
|
||||
fContextReq = ISC_REQ_STREAM | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
|
||||
ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR |
|
||||
ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY;
|
||||
if (!(lpTokenIn = (BYTE*)malloc(cbMaxToken)))
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (!(lpTokenOut = (BYTE*)malloc(cbMaxToken)))
|
||||
{
|
||||
printf("Memory allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
g_ClientWait = FALSE;
|
||||
|
||||
do
|
||||
{
|
||||
SecBuffer SecBuffer_in[2] = WINPR_C_ARRAY_INIT;
|
||||
SecBuffer SecBuffer_out[1] = WINPR_C_ARRAY_INIT;
|
||||
SecBufferDesc SecBufferDesc_in = WINPR_C_ARRAY_INIT;
|
||||
SecBufferDesc SecBufferDesc_out = WINPR_C_ARRAY_INIT;
|
||||
if (g_ClientWait)
|
||||
{
|
||||
if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, nullptr))
|
||||
{
|
||||
printf("failed to read from server pipe\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumberOfBytesRead = 0;
|
||||
}
|
||||
|
||||
g_ClientWait = TRUE;
|
||||
printf("NumberOfBytesRead: %" PRIu32 "\n", NumberOfBytesRead);
|
||||
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
|
||||
SecBuffer_in[0].pvBuffer = lpTokenIn;
|
||||
SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
|
||||
SecBuffer_in[1].pvBuffer = nullptr;
|
||||
SecBuffer_in[1].cbBuffer = 0;
|
||||
SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
|
||||
SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
|
||||
SecBufferDesc_in.cBuffers = 2;
|
||||
SecBufferDesc_in.pBuffers = SecBuffer_in;
|
||||
SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
|
||||
SecBuffer_out[0].pvBuffer = lpTokenOut;
|
||||
SecBuffer_out[0].cbBuffer = cbMaxToken;
|
||||
SecBufferDesc_out.ulVersion = SECBUFFER_VERSION;
|
||||
SecBufferDesc_out.cBuffers = 1;
|
||||
SecBufferDesc_out.pBuffers = SecBuffer_out;
|
||||
status = table->InitializeSecurityContext(
|
||||
&credentials, SecIsValidHandle(&context) ? &context : nullptr, _T("localhost"),
|
||||
fContextReq, 0, 0, &SecBufferDesc_in, 0, &context, &SecBufferDesc_out, &fContextAttr,
|
||||
&expiry);
|
||||
|
||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) &&
|
||||
(status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
{
|
||||
printf("InitializeSecurityContext unexpected status: 0x%08" PRIX32 "\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NumberOfBytesWritten = 0;
|
||||
|
||||
if (status == SEC_E_OK)
|
||||
printf("InitializeSecurityContext status: SEC_E_OK\n");
|
||||
else if (status == SEC_I_CONTINUE_NEEDED)
|
||||
printf("InitializeSecurityContext status: SEC_I_CONTINUE_NEEDED\n");
|
||||
else if (status == SEC_E_INCOMPLETE_MESSAGE)
|
||||
printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
|
||||
|
||||
printf("Client Output cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32 "\n",
|
||||
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer,
|
||||
SecBufferDesc_out.pBuffers[0].BufferType);
|
||||
printf("Client Input cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32
|
||||
" pBuffers[1]: %" PRIu32 " type: %" PRIu32 "\n",
|
||||
SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[0].cbBuffer,
|
||||
SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[1].cbBuffer,
|
||||
SecBufferDesc_in.pBuffers[1].BufferType);
|
||||
|
||||
if (status != SEC_E_INCOMPLETE_MESSAGE)
|
||||
{
|
||||
pSecBuffer = &SecBufferDesc_out.pBuffers[0];
|
||||
|
||||
if (pSecBuffer->cbBuffer > 0)
|
||||
{
|
||||
printf("Client > Server (%" PRIu32 ")\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*)pSecBuffer->pvBuffer,
|
||||
pSecBuffer->cbBuffer);
|
||||
|
||||
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer,
|
||||
&NumberOfBytesWritten, nullptr))
|
||||
{
|
||||
printf("failed to write to server pipe\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
printf("Client Handshake Complete\n");
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (schannel_send(table, g_ServerWritePipe, &context, test_DummyMessage,
|
||||
sizeof(test_DummyMessage)) < 0)
|
||||
break;
|
||||
|
||||
for (DWORD index = 0; index < sizeof(test_DummyMessage); index++)
|
||||
{
|
||||
BYTE b, ln, hn;
|
||||
b = test_DummyMessage[index];
|
||||
ln = (b & 0x0F);
|
||||
hn = ((b & 0xF0) >> 4);
|
||||
ln = (ln + 1) % 0xF;
|
||||
hn = (ln + 1) % 0xF;
|
||||
b = (ln | (hn << 4));
|
||||
test_DummyMessage[index] = b;
|
||||
}
|
||||
|
||||
Sleep(100);
|
||||
count++;
|
||||
} while (count < 3);
|
||||
|
||||
schannel_send(table, g_ServerWritePipe, &context, test_LastDummyMessage,
|
||||
sizeof(test_LastDummyMessage));
|
||||
(void)WaitForSingleObject(thread, INFINITE);
|
||||
sspi_GlobalFinish();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user