libwinpr-sspi: add Schannel EncryptMessage/DecryptMessage tests
This commit is contained in:
parent
59084a09ba
commit
03ef822d0c
@ -35,11 +35,15 @@ typedef struct _LSA_UNICODE_STRING
|
||||
* http://msdn.microsoft.com/en-us/library/bb625963.aspx
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#define SECURITY_MANDATORY_UNTRUSTED_RID 0x0000
|
||||
#define SECURITY_MANDATORY_LOW_RID 0x1000
|
||||
#define SECURITY_MANDATORY_MEDIUM_RID 0x2000
|
||||
#define SECURITY_MANDATORY_HIGH_RID 0x3000
|
||||
#define SECURITY_MANDATORY_SYSTEM_RID 0x4000
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_SECURITY_H */
|
||||
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/schannel.h>
|
||||
|
||||
HANDLE g_ClientEvent = NULL;
|
||||
HANDLE g_ServerEvent = NULL;
|
||||
BOOL g_ClientWait = FALSE;
|
||||
BOOL g_ServerWait = FALSE;
|
||||
|
||||
@ -20,6 +18,139 @@ HANDLE g_ClientWritePipe = NULL;
|
||||
HANDLE g_ServerReadPipe = NULL;
|
||||
HANDLE g_ServerWritePipe = NULL;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext, BYTE* buffer, UINT32 length)
|
||||
{
|
||||
BYTE* ioBuffer;
|
||||
UINT32 ioBufferLength;
|
||||
BYTE* pMessageBuffer;
|
||||
SecBuffer Buffers[4];
|
||||
SecBufferDesc Message;
|
||||
SECURITY_STATUS status;
|
||||
DWORD NumberOfBytesWritten;
|
||||
SecPkgContext_StreamSizes StreamSizes;
|
||||
|
||||
ZeroMemory(&StreamSizes, sizeof(SecPkgContext_StreamSizes));
|
||||
status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
|
||||
|
||||
ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer;
|
||||
ioBuffer = (BYTE*) malloc(ioBufferLength);
|
||||
ZeroMemory(ioBuffer, ioBufferLength);
|
||||
|
||||
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 = NULL;
|
||||
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%08X\n", status);
|
||||
|
||||
printf("EncryptMessage output: cBuffers: %d [0]: %d / %d [1]: %d / %d [2]: %d / %d [3]: %d / %d\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);
|
||||
|
||||
printf("Client > Server (%d)\n", ioBufferLength);
|
||||
winpr_HexDump(ioBuffer, ioBufferLength);
|
||||
|
||||
if (!WriteFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesWritten, NULL))
|
||||
{
|
||||
printf("schannel_send: failed to write to pipe\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext, BYTE* buffer, UINT32 length)
|
||||
{
|
||||
BYTE* ioBuffer;
|
||||
UINT32 ioBufferLength;
|
||||
BYTE* pMessageBuffer;
|
||||
SecBuffer Buffers[4];
|
||||
SecBufferDesc Message;
|
||||
SECURITY_STATUS status;
|
||||
DWORD NumberOfBytesRead;
|
||||
SecPkgContext_StreamSizes StreamSizes;
|
||||
|
||||
ZeroMemory(&StreamSizes, sizeof(SecPkgContext_StreamSizes));
|
||||
status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
|
||||
|
||||
ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer;
|
||||
ioBuffer = (BYTE*) malloc(ioBufferLength);
|
||||
ZeroMemory(ioBuffer, ioBufferLength);
|
||||
|
||||
if (!ReadFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesRead, NULL))
|
||||
{
|
||||
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 = NULL;
|
||||
Buffers[1].cbBuffer = 0;
|
||||
Buffers[1].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
Buffers[2].pvBuffer = NULL;
|
||||
Buffers[2].cbBuffer = 0;
|
||||
Buffers[2].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
Buffers[3].pvBuffer = NULL;
|
||||
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, NULL);
|
||||
|
||||
printf("DecryptMessage status: 0x%08X\n", status);
|
||||
|
||||
printf("DecryptMessage output: cBuffers: %d [0]: %d / %d [1]: %d / %d [2]: %d / %d [3]: %d / %d\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);
|
||||
|
||||
printf("Decrypted Message (%d)\n", Message.pBuffers[1].cbBuffer);
|
||||
winpr_HexDump((BYTE*) Message.pBuffers[1].pvBuffer, Message.pBuffers[1].cbBuffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* schannel_test_server_thread(void* arg)
|
||||
{
|
||||
BOOL extraData;
|
||||
@ -72,7 +203,11 @@ static void* schannel_test_server_thread(void* arg)
|
||||
//return NULL;
|
||||
}
|
||||
|
||||
#ifdef CERT_FIND_HAS_PRIVATE_KEY
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL);
|
||||
#else
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
|
||||
#endif
|
||||
|
||||
if (!pCertContext)
|
||||
{
|
||||
@ -110,6 +245,8 @@ static void* schannel_test_server_thread(void* arg)
|
||||
}
|
||||
|
||||
extraData = FALSE;
|
||||
g_ServerWait = TRUE;
|
||||
|
||||
lpTokenIn = (BYTE*) malloc(cbMaxToken);
|
||||
lpTokenOut = (BYTE*) malloc(cbMaxToken);
|
||||
|
||||
@ -121,9 +258,6 @@ static void* schannel_test_server_thread(void* arg)
|
||||
{
|
||||
if (!extraData)
|
||||
{
|
||||
WaitForSingleObject(g_ServerEvent, INFINITE);
|
||||
ResetEvent(g_ServerEvent);
|
||||
|
||||
if (g_ServerWait)
|
||||
{
|
||||
if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
|
||||
@ -137,7 +271,9 @@ static void* schannel_test_server_thread(void* arg)
|
||||
NumberOfBytesRead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extraData = FALSE;
|
||||
g_ServerWait = TRUE;
|
||||
|
||||
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
|
||||
SecBuffer_in[0].pvBuffer = lpTokenIn;
|
||||
@ -162,13 +298,7 @@ static void* schannel_test_server_thread(void* arg)
|
||||
status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL,
|
||||
&SecBufferDesc_in, fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
printf("AcceptSecurityContext SEC_E_OK, TLS connection complete\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
{
|
||||
printf("AcceptSecurityContext unexpected status: 0x%08X\n", status);
|
||||
return NULL;
|
||||
@ -176,7 +306,9 @@ static void* schannel_test_server_thread(void* arg)
|
||||
|
||||
NumberOfBytesWritten = 0;
|
||||
|
||||
if (status == SEC_I_CONTINUE_NEEDED)
|
||||
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");
|
||||
@ -199,28 +331,33 @@ static void* schannel_test_server_thread(void* arg)
|
||||
{
|
||||
pSecBuffer = &SecBufferDesc_out.pBuffers[0];
|
||||
|
||||
printf("Server > Client (%d)\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
g_ClientWait = TRUE;
|
||||
SetEvent(g_ClientEvent);
|
||||
|
||||
if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
|
||||
if (pSecBuffer->cbBuffer > 0)
|
||||
{
|
||||
printf("failed to write to client pipe\n");
|
||||
return NULL;
|
||||
printf("Server > Client (%d)\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
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);
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
printf("Server Handshake Complete\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
|
||||
do
|
||||
{
|
||||
schannel_recv(table, g_ServerReadPipe, &context, test_DummyMessage, sizeof(test_DummyMessage));
|
||||
}
|
||||
while(1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -254,9 +391,6 @@ 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);
|
||||
|
||||
@ -376,13 +510,9 @@ int TestSchannel(int argc, char* argv[])
|
||||
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))
|
||||
@ -396,6 +526,7 @@ int TestSchannel(int argc, char* argv[])
|
||||
NumberOfBytesRead = 0;
|
||||
}
|
||||
|
||||
g_ClientWait = TRUE;
|
||||
printf("NumberOfBytesRead: %d\n", NumberOfBytesRead);
|
||||
|
||||
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
|
||||
@ -421,7 +552,7 @@ int TestSchannel(int argc, char* argv[])
|
||||
status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"),
|
||||
fContextReq, 0, 0, &SecBufferDesc_in, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
|
||||
if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
{
|
||||
printf("InitializeSecurityContext unexpected status: 0x%08X\n", status);
|
||||
return -1;
|
||||
@ -429,7 +560,9 @@ int TestSchannel(int argc, char* argv[])
|
||||
|
||||
NumberOfBytesWritten = 0;
|
||||
|
||||
if (status == SEC_I_CONTINUE_NEEDED)
|
||||
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");
|
||||
@ -443,25 +576,31 @@ int TestSchannel(int argc, char* argv[])
|
||||
{
|
||||
pSecBuffer = &SecBufferDesc_out.pBuffers[0];
|
||||
|
||||
printf("Client > Server (%d)\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
g_ServerWait = TRUE;
|
||||
SetEvent(g_ServerEvent);
|
||||
|
||||
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
|
||||
if (pSecBuffer->cbBuffer > 0)
|
||||
{
|
||||
printf("failed to write to server pipe\n");
|
||||
return -1;
|
||||
printf("Client > Server (%d)\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
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 (status == SEC_E_OK)
|
||||
{
|
||||
printf("Client Handshake Complete\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(1);
|
||||
|
||||
do
|
||||
{
|
||||
schannel_send(table, g_ServerWritePipe, &context, test_DummyMessage, sizeof(test_DummyMessage));
|
||||
Sleep(1000 * 10);
|
||||
}
|
||||
while(1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user