[PATCH] Add some more schannel tests

Mikko Rasa tdb at tdb.fi
Tue Sep 7 10:46:16 CDT 2010


---
 dlls/secur32/tests/schannel.c |  307 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 306 insertions(+), 1 deletions(-)

diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c
index 82e27db..c9527e9 100644
--- a/dlls/secur32/tests/schannel.c
+++ b/dlls/secur32/tests/schannel.c
@@ -24,16 +24,22 @@
 #define SECURITY_WIN32
 #include <security.h>
 #include <schannel.h>
+#include <winsock2.h>
 
 #include "wine/test.h"
 
-static HMODULE secdll, crypt32dll;
+static HMODULE secdll, crypt32dll, wsockdll;
 
 static ACQUIRE_CREDENTIALS_HANDLE_FN_A pAcquireCredentialsHandleA;
 static ENUMERATE_SECURITY_PACKAGES_FN_A pEnumerateSecurityPackagesA;
 static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
 static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
 static QUERY_CREDENTIALS_ATTRIBUTES_FN_A pQueryCredentialsAttributesA;
+static INITIALIZE_SECURITY_CONTEXT_FN_A pInitializeSecurityContextA;
+static QUERY_CONTEXT_ATTRIBUTES_FN_A pQueryContextAttributesA;
+static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
+static DECRYPT_MESSAGE_FN pDecryptMessage;
+static ENCRYPT_MESSAGE_FN pEncryptMessage;
 
 static PCCERT_CONTEXT (WINAPI *pCertCreateCertificateContext)(DWORD,const BYTE*,DWORD);
 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT);
@@ -44,6 +50,12 @@ static BOOL (WINAPI *pCryptDestroyKey)(HCRYPTKEY);
 static BOOL (WINAPI *pCryptImportKey)(HCRYPTPROV,CONST BYTE*,DWORD,HCRYPTKEY,DWORD,HCRYPTKEY*);
 static BOOL (WINAPI *pCryptReleaseContext)(HCRYPTPROV,ULONG_PTR);
 
+static int (WINAPI *pWSAStartup)(WORD,LPWSADATA);
+static SOCKET (WINAPI *psocket)(int,int,int);
+static int (WINAPI *pconnect)(SOCKET,const struct sockaddr*,int);
+static int (WINAPI *precv)(SOCKET,char*,int,int);
+static int (WINAPI *psend)(SOCKET,const char*,int,int);
+
 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
@@ -116,6 +128,10 @@ static void InitFunctionPtrs(void)
     if(!secdll)
         secdll = LoadLibraryA("security.dll");
     advapi32dll = GetModuleHandleA("advapi32.dll");
+    wsockdll = LoadLibraryA("ws2_32.dll");
+
+    if(!wsockdll)
+		printf("Couldn't open ws2_32.dll\n");
 
 #define GET_PROC(h, func)  p ## func = (void*)GetProcAddress(h, #func)
 
@@ -126,6 +142,11 @@ static void InitFunctionPtrs(void)
         GET_PROC(secdll, FreeContextBuffer);
         GET_PROC(secdll, FreeCredentialsHandle);
         GET_PROC(secdll, QueryCredentialsAttributesA);
+        GET_PROC(secdll, InitializeSecurityContextA);
+        GET_PROC(secdll, QueryContextAttributesA);
+        GET_PROC(secdll, DeleteSecurityContext);
+        GET_PROC(secdll, DecryptMessage);
+        GET_PROC(secdll, EncryptMessage);
     }
 
     GET_PROC(advapi32dll, CryptAcquireContextW);
@@ -137,6 +158,12 @@ static void InitFunctionPtrs(void)
     GET_PROC(crypt32dll, CertSetCertificateContextProperty);
     GET_PROC(crypt32dll, CertCreateCertificateContext);
 
+	GET_PROC(wsockdll, WSAStartup);
+	GET_PROC(wsockdll, socket);
+	GET_PROC(wsockdll, connect);
+	GET_PROC(wsockdll, send);
+	GET_PROC(wsockdll, recv);
+
 #undef GET_PROC
 }
 
@@ -454,11 +481,289 @@ static void testAcquireSecurityContext(void)
     }
 }
 
+static const char http_request[] = "HEAD /mail/ HTTP/1.1\r\nHost: mail.google.com\r\nConnection: close\r\n\r\n";
+
+static void init_cred(SCHANNEL_CRED *cred)
+{
+	cred->dwVersion = SCHANNEL_CRED_VERSION;
+	cred->cCreds = 0;
+	cred->paCred = 0;
+	cred->hRootStore = NULL;
+	cred->cMappers = 0;
+	cred->aphMappers = NULL;
+	cred->cSupportedAlgs = 0;
+	cred->palgSupportedAlgs = NULL;
+	cred->grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
+	cred->dwMinimumCipherStrength = 0;
+	cred->dwMaximumCipherStrength = 0;
+	cred->dwSessionLifespan = 0;
+	cred->dwFlags = 0;
+}
+
+static void init_buffers(SecBufferDesc *desc, unsigned count, unsigned size)
+{
+	unsigned i;
+
+	desc->ulVersion = SECBUFFER_VERSION;
+	desc->cBuffers = count;
+	desc->pBuffers = malloc(count*sizeof(SecBuffer));
+
+	for(i=0; i<count; ++i)
+	{
+		desc->pBuffers[i].cbBuffer = 0;
+		desc->pBuffers[i].pvBuffer = NULL;
+		desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
+	}
+
+	desc->pBuffers[0].cbBuffer = size;
+	desc->pBuffers[0].pvBuffer = malloc(size);
+}
+
+static void reset_buffers(SecBufferDesc *desc)
+{
+	unsigned i;
+
+	for(i=0; i<desc->cBuffers; ++i)
+	{
+		desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
+		if(i>0)
+		{
+			desc->pBuffers[i].cbBuffer = 0;
+			desc->pBuffers[i].pvBuffer = NULL;
+		}
+	}
+}
+
+static void free_buffers(SecBufferDesc *desc)
+{
+	free(desc->pBuffers[0].pvBuffer);
+	free(desc->pBuffers);
+}
+
+static int receive_data(SOCKET sock, SecBuffer *buf)
+{
+	unsigned received = 0;
+
+	while(1)
+	{
+		unsigned char *data = buf->pvBuffer;
+		unsigned expected = 0;
+		int ret;
+
+		ret = precv(sock, (char *)data+received, buf->cbBuffer-received, 0);
+		if(ret==-1)
+		{
+			skip("recv failed\n");
+			return -1;
+		}
+		else if(ret==0)
+		{
+			skip("connection closed\n");
+			return -1;
+		}
+		received += ret;
+
+		while(expected<received)
+		{
+			unsigned frame_size = 5 + ((data[3]<<8) | data[4]);
+			expected += frame_size;
+			data += frame_size;
+		}
+
+		if(expected==received)
+			break;
+	}
+
+	buf->cbBuffer = received;
+
+	return received;
+}
+
+static void test_communication(void)
+{
+	int ret;
+
+	WSADATA wsa_data;
+	SOCKET sock;
+	struct sockaddr_in addr;
+
+	SECURITY_STATUS status;
+	ULONG attrs;
+
+	SCHANNEL_CRED cred;
+	CredHandle cred_handle;
+	CtxtHandle context;
+	SecPkgContext_StreamSizes sizes;
+
+	SecBufferDesc buffers[2];
+	SecBuffer *buf;
+	unsigned buf_size = 4000;
+	char *data;
+	unsigned data_size;
+
+	if(!pWSAStartup || !psocket || !pconnect || !precv || !psend)
+	{
+		skip("Required winsock functions not available\n");
+		return;
+	}
+
+	if(!pAcquireCredentialsHandleA || !pFreeCredentialsHandle ||
+		!pInitializeSecurityContextA || !pDeleteSecurityContext ||
+		!pQueryContextAttributesA || !pDecryptMessage || pEncryptMessage)
+	{
+		skip("Required secur32 functions not available\n");
+		return;
+	}
+
+	// Create a socket and connect to mail.google.com
+	ret = pWSAStartup(0x0202, &wsa_data);
+	if(ret)
+	{
+		skip("Can't init winsock 2.2\n");
+		return;
+	}
+
+	sock = psocket(AF_INET, SOCK_STREAM, 0);
+	if(sock==SOCKET_ERROR)
+	{
+		skip("Can't create socket\n");
+		return;
+	}
+
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = htonl(0xD1558712);
+	addr.sin_port = htons(443);
+	ret = pconnect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+	if(ret==SOCKET_ERROR)
+	{
+		skip("Can't connect to mail.google.com\n");
+		return;
+	}
+
+	// Create client credentials
+	init_cred(&cred);
+	cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
+
+	status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
+		&cred, NULL, NULL, &cred_handle, NULL);
+	ok(status == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", status);
+
+	// Initialize the connection
+	init_buffers(&buffers[0], 4, buf_size);
+	init_buffers(&buffers[1], 4, buf_size);
+
+	buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
+	status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
+		ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+		0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
+	ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
+
+	while(status==SEC_I_CONTINUE_NEEDED)
+	{
+		buf = &buffers[0].pBuffers[0];
+		psend(sock, buf->pvBuffer, buf->cbBuffer, 0);
+		buf->cbBuffer = buf_size;
+
+		buf = &buffers[1].pBuffers[0];
+		ret = receive_data(sock, buf);
+		if(ret==-1)
+			return;
+
+		buf->BufferType = SECBUFFER_TOKEN;
+
+		status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+			ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+			0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
+		buffers[1].pBuffers[0].cbBuffer = buf_size;
+	}
+
+	ok(status == SEC_E_OK, "InitializeSecurityContext failed: %08x\n", status);
+
+	pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
+
+	reset_buffers(&buffers[0]);
+
+	// Send a simple request so we get data for testing DecryptMessage
+	buf = &buffers[0].pBuffers[0];
+	data = buf->pvBuffer;
+	buf->BufferType = SECBUFFER_STREAM_HEADER;
+	buf->cbBuffer = sizes.cbHeader;
+	++buf;
+	buf->BufferType = SECBUFFER_DATA;
+	buf->pvBuffer = data + sizes.cbHeader;
+	buf->cbBuffer = sizeof(http_request) - 1;
+	memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
+	++buf;
+	buf->BufferType = SECBUFFER_STREAM_TRAILER;
+	buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
+	buf->cbBuffer = sizes.cbTrailer;
+
+	status = pEncryptMessage(&context, 0, &buffers[0], 0);
+	ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
+	if(status != SEC_E_OK)
+		return;
+
+	buf = &buffers[0].pBuffers[0];
+	psend(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
+
+	reset_buffers(&buffers[0]);
+	buf->cbBuffer = buf_size;
+	data_size = receive_data(sock, buf);
+
+	// Too few buffers
+	--buffers[0].cBuffers;
+	status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+	ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+	// No data buffer
+	++buffers[0].cBuffers;
+	status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+	ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+	// Two data buffers
+	buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
+	buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
+	status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+	ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+	// Too few empty buffers
+	buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
+	status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+	ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+	// Incomplete data
+	buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
+	--buffers[0].pBuffers[0].cbBuffer;
+	status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+	ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
+	ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
+	ok(buffers[0].pBuffers[0].cbBuffer == 1, "Expected first buffer to be a single byte\n");
+
+	buffers[0].pBuffers[0].cbBuffer = data_size;
+	buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
+	buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
+	status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+	ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
+	ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
+	ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
+	ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected first buffer to be SECBUFFER_STREAM_TRAILER\n");
+
+	data = buffers[0].pBuffers[1].pvBuffer;
+	data[buffers[0].pBuffers[1].cbBuffer] = 0;
+
+	pDeleteSecurityContext(&context);
+	pFreeCredentialsHandle(&cred_handle);
+
+	free_buffers(&buffers[0]);
+	free_buffers(&buffers[1]);
+}
+
 START_TEST(schannel)
 {
     InitFunctionPtrs();
 
     testAcquireSecurityContext();
+    test_communication();
 
     if(secdll)
         FreeLibrary(secdll);
-- 
1.7.1




More information about the wine-patches mailing list