libwinpr-sspi: add more Schannel tests
This commit is contained in:
parent
985721d035
commit
f8b364d696
@ -23,7 +23,11 @@
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <wincrypt.h>
|
||||
|
||||
#else
|
||||
|
||||
#define GET_ALG_CLASS(x) (x & (7 << 13))
|
||||
#define GET_ALG_TYPE(x) (x & (15 << 9))
|
||||
|
@ -44,3 +44,6 @@ endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR")
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
3
winpr/libwinpr/crypto/test/.gitignore
vendored
Normal file
3
winpr/libwinpr/crypto/test/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
TestCrypto
|
||||
TestCrypto.c
|
||||
|
35
winpr/libwinpr/crypto/test/CMakeLists.txt
Normal file
35
winpr/libwinpr/crypto/test/CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
set(MODULE_NAME "TestCrypto")
|
||||
set(MODULE_PREFIX "TEST_CRYPTO")
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestCertEnumCertificatesInStore.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_DRIVER}
|
||||
${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
if(WIN32)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32 cryptui)
|
||||
endif()
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-crt winpr-crypto winpr-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
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")
|
||||
|
66
winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c
Normal file
66
winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
//#define WITH_CRYPTUI 1
|
||||
#endif
|
||||
|
||||
#ifdef WITH_CRYPTUI
|
||||
#include <cryptuiapi.h>
|
||||
#endif
|
||||
|
||||
int TestCertEnumCertificatesInStore(int argc, char* argv[])
|
||||
{
|
||||
int index;
|
||||
DWORD status;
|
||||
LPTSTR pszNameString;
|
||||
HCERTSTORE hCertStore = NULL;
|
||||
PCCERT_CONTEXT pCertContext = NULL;
|
||||
|
||||
/**
|
||||
* System Store Locations:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa388136/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Requires elevated rights:
|
||||
* hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, _T("Remote Desktop"));
|
||||
*/
|
||||
|
||||
hCertStore = CertOpenSystemStore((HCRYPTPROV_LEGACY) NULL, _T("MY"));
|
||||
// hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_CURRENT_USER, _T("MY"));
|
||||
|
||||
if (!hCertStore)
|
||||
{
|
||||
printf("Failed to open system store\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
while (pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext))
|
||||
{
|
||||
status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
|
||||
|
||||
pszNameString = (LPTSTR) malloc(status * sizeof(TCHAR));
|
||||
status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, status);
|
||||
|
||||
_tprintf(_T("Certificate #%d: %s\n"), index++, pszNameString);
|
||||
|
||||
#ifdef WITH_CRYPTUI
|
||||
CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pCertContext, NULL, NULL, 0, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!CertCloseStore(hCertStore, 0))
|
||||
{
|
||||
printf("Failed to close system store\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,17 +9,16 @@
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/schannel.h>
|
||||
|
||||
HANDLE g_ClientEvent = NULL;
|
||||
HANDLE g_ServerEvent = NULL;
|
||||
BOOL g_ClientWait = FALSE;
|
||||
BOOL g_ServerWait = FALSE;
|
||||
|
||||
HANDLE g_ClientReadPipe = NULL;
|
||||
HANDLE g_ClientWritePipe = NULL;
|
||||
HANDLE g_ServerReadPipe = NULL;
|
||||
HANDLE g_ServerWritePipe = NULL;
|
||||
|
||||
#ifndef _WIN32
|
||||
#define SCHANNEL_PKG_NAME SCHANNEL_NAME
|
||||
#else
|
||||
#define SCHANNEL_PKG_NAME UNISP_NAME
|
||||
#endif
|
||||
|
||||
static void* schannel_test_server_thread(void* arg)
|
||||
{
|
||||
BYTE* lpTokenIn;
|
||||
@ -31,6 +30,8 @@ static void* schannel_test_server_thread(void* arg)
|
||||
SCHANNEL_CRED cred;
|
||||
CtxtHandle context;
|
||||
CredHandle credentials;
|
||||
DWORD cchNameString;
|
||||
LPTSTR pszNameString;
|
||||
HCERTSTORE hCertStore;
|
||||
PCCERT_CONTEXT pCertContext;
|
||||
PSecBuffer pSecBuffer;
|
||||
@ -51,7 +52,7 @@ static void* schannel_test_server_thread(void* arg)
|
||||
|
||||
table = InitSecurityInterface();
|
||||
|
||||
status = QuerySecurityPackageInfo(SCHANNEL_PKG_NAME, &pPackageInfo);
|
||||
status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
@ -69,7 +70,7 @@ static void* schannel_test_server_thread(void* arg)
|
||||
//return NULL;
|
||||
}
|
||||
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL);
|
||||
|
||||
if (!pCertContext)
|
||||
{
|
||||
@ -77,6 +78,13 @@ static void* schannel_test_server_thread(void* arg)
|
||||
//return NULL;
|
||||
}
|
||||
|
||||
cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
|
||||
|
||||
pszNameString = (LPTSTR) malloc(status * sizeof(TCHAR));
|
||||
cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, cchNameString);
|
||||
|
||||
_tprintf(_T("Certificate Name: %s\n"), pszNameString);
|
||||
|
||||
ZeroMemory(&cred, sizeof(SCHANNEL_CRED));
|
||||
cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
|
||||
@ -90,7 +98,7 @@ static void* schannel_test_server_thread(void* arg)
|
||||
|
||||
cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER;
|
||||
|
||||
status = table->AcquireCredentialsHandle(NULL, SCHANNEL_PKG_NAME,
|
||||
status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME,
|
||||
SECPKG_CRED_INBOUND, NULL, &cred, NULL, NULL, &credentials, NULL);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
@ -102,25 +110,41 @@ static void* schannel_test_server_thread(void* arg)
|
||||
lpTokenIn = (BYTE*) malloc(cbMaxToken);
|
||||
lpTokenOut = (BYTE*) malloc(cbMaxToken);
|
||||
|
||||
fContextReq = ASC_REQ_STREAM |
|
||||
ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
|
||||
ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR;
|
||||
|
||||
do
|
||||
{
|
||||
WaitForSingleObject(g_ServerEvent, INFINITE);
|
||||
ResetEvent(g_ServerEvent);
|
||||
|
||||
if (g_ServerWait)
|
||||
{
|
||||
if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
|
||||
{
|
||||
printf("Failed to read from server pipe\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumberOfBytesRead = 0;
|
||||
}
|
||||
|
||||
printf("Server Received:\n");
|
||||
printf("Server Received %d bytes:\n", NumberOfBytesRead);
|
||||
winpr_HexDump(lpTokenIn, NumberOfBytesRead);
|
||||
|
||||
fContextReq = ASC_REQ_STREAM |
|
||||
ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
|
||||
ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR;
|
||||
|
||||
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 = NULL;
|
||||
SecBuffer_in[1].cbBuffer = 0;
|
||||
|
||||
SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
|
||||
SecBufferDesc_in.cBuffers = 1;
|
||||
SecBufferDesc_in.cBuffers = 2;
|
||||
SecBufferDesc_in.pBuffers = SecBuffer_in;
|
||||
|
||||
SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
|
||||
@ -132,24 +156,49 @@ static void* schannel_test_server_thread(void* arg)
|
||||
SecBufferDesc_out.pBuffers = SecBuffer_out;
|
||||
|
||||
status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL,
|
||||
&SecBufferDesc_in, fContextReq, SECURITY_NATIVE_DREP, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
&SecBufferDesc_in, fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
|
||||
if (status != SEC_I_CONTINUE_NEEDED)
|
||||
if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
{
|
||||
printf("AcceptSecurityContext unexpected status: 0x%08X\n", status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf("SecBufferDesc_out.cBuffers: %d\n", SecBufferDesc_out.cBuffers);
|
||||
NumberOfBytesWritten = 0;
|
||||
|
||||
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: %d pBuffers[0]: %d type: %d\n",
|
||||
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
|
||||
printf("Server Input cBuffers: %d pBuffers[1]: %d type: %d\n",
|
||||
SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
|
||||
|
||||
if (status != SEC_E_INCOMPLETE_MESSAGE)
|
||||
{
|
||||
pSecBuffer = &SecBufferDesc_out.pBuffers[0];
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
g_ClientWait = TRUE;
|
||||
SetEvent(g_ClientEvent);
|
||||
|
||||
if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
|
||||
{
|
||||
printf("failed to write to client pipe\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ClientWait = FALSE;
|
||||
SetEvent(g_ClientEvent);
|
||||
}
|
||||
|
||||
printf("Server wrote %d bytes\n", NumberOfBytesWritten);
|
||||
}
|
||||
while (1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -184,6 +233,9 @@ int TestSchannel(int argc, char* argv[])
|
||||
|
||||
sspi_GlobalInit();
|
||||
|
||||
g_ClientEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
g_ServerEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
SecInvalidateHandle(&context);
|
||||
SecInvalidateHandle(&credentials);
|
||||
|
||||
@ -203,7 +255,7 @@ int TestSchannel(int argc, char* argv[])
|
||||
|
||||
table = InitSecurityInterface();
|
||||
|
||||
status = QuerySecurityPackageInfo(SCHANNEL_PKG_NAME, &pPackageInfo);
|
||||
status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
@ -228,7 +280,7 @@ int TestSchannel(int argc, char* argv[])
|
||||
cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
|
||||
cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
|
||||
|
||||
status = table->AcquireCredentialsHandle(NULL, SCHANNEL_PKG_NAME,
|
||||
status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME,
|
||||
SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credentials, NULL);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
@ -302,12 +354,39 @@ int TestSchannel(int argc, char* argv[])
|
||||
ZeroMemory(&SecBufferDesc_in, sizeof(SecBufferDesc));
|
||||
ZeroMemory(&SecBufferDesc_out, sizeof(SecBufferDesc));
|
||||
|
||||
g_ClientWait = FALSE;
|
||||
SetEvent(g_ClientEvent);
|
||||
|
||||
do
|
||||
{
|
||||
WaitForSingleObject(g_ClientEvent, INFINITE);
|
||||
ResetEvent(g_ClientEvent);
|
||||
|
||||
if (g_ClientWait)
|
||||
{
|
||||
if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
|
||||
{
|
||||
printf("failed to read from server pipe\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumberOfBytesRead = 0;
|
||||
}
|
||||
|
||||
printf("NumberOfBytesRead: %d\n", NumberOfBytesRead);
|
||||
|
||||
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
|
||||
SecBuffer_in[0].pvBuffer = lpTokenIn;
|
||||
SecBuffer_in[0].cbBuffer = cbMaxToken;
|
||||
SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
|
||||
|
||||
SecBuffer_in[1].pvBuffer = NULL;
|
||||
SecBuffer_in[1].cbBuffer = 0;
|
||||
SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
|
||||
SecBufferDesc_in.cBuffers = 1;
|
||||
SecBufferDesc_in.cBuffers = 2;
|
||||
SecBufferDesc_in.pBuffers = SecBuffer_in;
|
||||
|
||||
SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
|
||||
@ -319,32 +398,49 @@ int TestSchannel(int argc, char* argv[])
|
||||
SecBufferDesc_out.pBuffers = SecBuffer_out;
|
||||
|
||||
status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"),
|
||||
fContextReq, SECURITY_NATIVE_DREP, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
fContextReq, 0, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
|
||||
if (status != SEC_I_CONTINUE_NEEDED)
|
||||
if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
{
|
||||
printf("InitializeSecurityContext unexpected status: 0x%08X\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("SecBufferDesc_out.cBuffers: %d\n", SecBufferDesc_out.cBuffers);
|
||||
NumberOfBytesWritten = 0;
|
||||
|
||||
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: %d pBuffers[0]: %d type: %d\n",
|
||||
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
|
||||
printf("Client Input cBuffers: %d pBuffers[1]: %d type: %d\n",
|
||||
SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
|
||||
|
||||
if (status != SEC_E_INCOMPLETE_MESSAGE)
|
||||
{
|
||||
pSecBuffer = &SecBufferDesc_out.pBuffers[0];
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
g_ServerWait = TRUE;
|
||||
SetEvent(g_ServerEvent);
|
||||
|
||||
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
|
||||
{
|
||||
printf("failed to write to server pipe\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ServerWait = FALSE;
|
||||
SetEvent(g_ServerEvent);
|
||||
}
|
||||
|
||||
printf("Client wrote %d bytes\n", NumberOfBytesWritten);
|
||||
|
||||
if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
|
||||
{
|
||||
printf("failed to read from server pipe\n");
|
||||
return -1;
|
||||
}
|
||||
while(1);
|
||||
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user