⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emptypacketschecker.cpp

📁 DescriptionThis adds some support for SSL renegotiation over V1.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	SecBuffer Buffers[4];
	BufferDesc.cBuffers = _countof(Buffers);
	BufferDesc.pBuffers = Buffers;
	BufferDesc.ulVersion = SECBUFFER_VERSION;

	Buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
	Buffers[0].pvBuffer = pCompositeInBuffer;
	Buffers[0].cbBuffer = Sizes.cbHeader;

	Buffers[1].BufferType = SECBUFFER_DATA;
	Buffers[1].pvBuffer = pCompositeInBuffer + Sizes.cbHeader;
	Buffers[1].cbBuffer = cbData;

	Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
	Buffers[2].pvBuffer = pCompositeInBuffer + Sizes.cbHeader + cbData;
	Buffers[2].cbBuffer = Sizes.cbTrailer;

	Buffers[3].BufferType = SECBUFFER_EMPTY;
	
	// Encrypt the message.
	scRet = EncryptMessage(phContext, 0, &BufferDesc, 0);

	if (scRet != SEC_E_OK)
	{
		error("failure encrypting message: 0x%x\n", scRet);
		goto cleanup;
	}

	ULONG cbEncryptedData = Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer;

	verbose("%5d raw bytes being sent on socket.\n", cbData);
	cbData = send(s, pCompositeInBuffer, cbEncryptedData, 0);
	if(cbData == SOCKET_ERROR || cbData == 0)
	{
		error("failure sending data: 0x%x\n", WSAGetLastError());
		goto cleanup;
	}

	result = true;

cleanup:
	if (pCompositeInBuffer) LocalFree(pCompositeInBuffer);

	return result;
}
int DecryptingRecv(SOCKET s, PCtxtHandle phContext, char * pBuffer, int cbBufferSize, char * pExtraData, int cbExtraDataSize, int * pcbExtraData, bool * pbEmptyPacketsDetected)
{
	int result = 0;

	SECURITY_STATUS scRet;

	// Find certain important buffer sizes
	SecPkgContext_StreamSizes Sizes;
	scRet = QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &Sizes);
	if(scRet != SEC_E_OK)
	{
		error("0x%x reading SECPKG_ATTR_STREAM_SIZES\n", scRet);
		goto cleanup;
	}
	ULONG nMaxPacketTotalSize = Sizes.cbHeader + Sizes.cbMaximumMessage + Sizes.cbTrailer;

	ULONG cbMessageSize = nMaxPacketTotalSize;
	char* pMessage = (char*)LocalAlloc(LMEM_FIXED, cbMessageSize);
	if (pMessage == NULL)
	{
		oom;
		goto cleanup;
	}
	
	// Initialize security buffers
	SecBufferDesc BufferDesc;
	SecBuffer Buffers[4];
	BufferDesc.cBuffers = _countof(Buffers);
	BufferDesc.pBuffers = Buffers;
	BufferDesc.ulVersion = SECBUFFER_VERSION;

	SecBuffer * pDataBuffer;
	SecBuffer * pExtraBuffer;

	// Mark the position of where the actual data buffer will go, and fill up any extra data from earlier.
	memcpy_s(pMessage, cbMessageSize, pExtraData, *pcbExtraData);
	ULONG cbMessage = *pcbExtraData;

	do
	{
		do
		{
			Buffers[0].BufferType = SECBUFFER_DATA;
			Buffers[0].pvBuffer = pMessage;
			Buffers[0].cbBuffer = 0;

			Buffers[1].BufferType = SECBUFFER_EMPTY;
			Buffers[2].BufferType = SECBUFFER_EMPTY;
			Buffers[3].BufferType = SECBUFFER_EMPTY;

			if (cbMessage > 0)
			{
				Buffers[0].cbBuffer = cbMessage;
				scRet = DecryptMessage(phContext, &BufferDesc, 0, NULL);
			}

			if (cbMessage == 0 || scRet == SEC_E_INCOMPLETE_MESSAGE)
			{
				if (scRet == SEC_E_INCOMPLETE_MESSAGE)
				{
					verbose("incomplete message received, calling recv again.\n");
				}
				int bytes_read = recv(s, pMessage + cbMessage, cbMessageSize - cbMessage, 0);
				if (bytes_read == 0 || bytes_read == SOCKET_ERROR)
				{
					error("socket unexpectedly closed.\n");
					goto cleanup;
				}
				else
				{
					verbose("%5d raw bytes received from socket.\n", bytes_read);
				}
				cbMessage += bytes_read;
				scRet = SEC_E_INCOMPLETE_MESSAGE;
			}
		} while (scRet == SEC_E_INCOMPLETE_MESSAGE);

		if (scRet != SEC_E_OK && scRet != SEC_I_CONTEXT_EXPIRED)
		{
			error("DecryptMessage failed with error code 0x%x\n", scRet);
			result = SOCKET_ERROR;
			goto cleanup;
		}

		pDataBuffer = NULL;
		pExtraBuffer = NULL;
		for (ULONG i = 0; i < BufferDesc.cBuffers; i++)
		{
			switch(BufferDesc.pBuffers[i].BufferType)
			{
				case SECBUFFER_DATA:
					pDataBuffer = &BufferDesc.pBuffers[i];
					break;
				case SECBUFFER_EXTRA:
					pExtraBuffer = &BufferDesc.pBuffers[i];
					break;
			}
		}

		// If we decrypted an "empty" packet, prepare to decrypt another one so we get something useful.
		if (pDataBuffer->cbBuffer == 0)
		{
			*pbEmptyPacketsDetected = true;
			if (pExtraBuffer)
			{
				verbose("%5d bytes in decrypted packet (EMPTY).  But some more data is waiting for decryption.\n", 0);
				//  move the extra buffer into the data buffer in preparation to try decrypting again.
				memmove_s(pMessage, cbMessageSize, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer);
				cbMessage = pExtraBuffer->cbBuffer;
			}
			else
			{
				verbose("%5d bytes in decrypted packet (EMPTY).  No extra data.  Waiting for more...\n", 0);
				// No extra buffer, but set to an empty state and listen for more.
				cbMessage = 0;
			}
		}
	} while (pDataBuffer->cbBuffer == 0); // loop until we get a non-empty encrypted packet.

    if (scRet == SEC_I_CONTEXT_EXPIRED)
    {
        verbose("The server closed the security context.\n");
        result = 0;
        *pcbExtraData = 0;
    }
    else
    {
        verbose("%5d bytes in decrypted packet.\n", pDataBuffer->cbBuffer);

	    // copy decrypted buffer into caller's buffer
	    memcpy_s(pBuffer, cbBufferSize, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
	    result = pDataBuffer->cbBuffer;

	    // Copy the extra bytes buffer into the caller's extra bytes buffer
	    if (pExtraBuffer)
	    {
		    memcpy_s(pExtraData, cbExtraDataSize, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer);
		    *pcbExtraData = pExtraBuffer->cbBuffer;
	    }
	    else
	    {
		    *pcbExtraData = 0;
	    }
    }

cleanup:
	if (pMessage) LocalFree(pMessage);

	return result;
}
bool ReceiveResponse(SOCKET s, PCtxtHandle phContext, bool * pbEmptyPacketsDetected)
{
	bool result = false;
	*pbEmptyPacketsDetected = false;
	char * pExtraData = NULL;
	char* pMessage = NULL;

	SECURITY_STATUS scRet;

	// Find certain important buffer sizes
	SecPkgContext_StreamSizes Sizes;
	scRet = QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &Sizes);
	if(scRet != SEC_E_OK)
	{
		error("0x%x reading SECPKG_ATTR_STREAM_SIZES\n", scRet);
		goto cleanup;
	}
	ULONG nMaxPacketTotalSize = Sizes.cbHeader + Sizes.cbMaximumMessage + Sizes.cbTrailer;

	ULONG cbMessageSize = max(nMaxPacketTotalSize, 1024*1024);
	pMessage = (char*)LocalAlloc(LMEM_FIXED, cbMessageSize);
	if (pMessage == NULL)
	{
		oom;
		goto cleanup;
	}
	
	int cbExtraData = 0; // number of valid characters in the buffer
	ULONG cbExtraDataSize = nMaxPacketTotalSize;  // size of allocated buffer
	pExtraData = (char*)LocalAlloc(LMEM_FIXED, cbExtraDataSize);
	if (pExtraData == NULL)
	{
		oom;
		goto cleanup;
	}

	ULONG cbTotalRead = 0;
	ULONG cbExpectedContentLength = 1;
	BOOL bContentLengthParsed = false;
	ULONG cbHeadersLength = 0;
	BOOL bHeadersEndFound = false;
    BOOL bStreaming = false;
	while (cbTotalRead - cbHeadersLength < cbExpectedContentLength)
	{
		ULONG cbMessage = DecryptingRecv(
			s, phContext, 
			pMessage + cbTotalRead, cbMessageSize - cbTotalRead, 
			pExtraData, cbExtraDataSize, &cbExtraData, 
			pbEmptyPacketsDetected);
		if (cbMessage == SOCKET_ERROR || cbMessage == 0)
		{
            if (bStreaming && cbMessage == 0)
            {
                verbose("Streaming end of data found.\n");
                break;
            }
            else
            {
		        error("failed read operation.\n");
		        return false;
            }
		}
		cbTotalRead += cbMessage;
		pMessage[cbTotalRead] = 0; // add null terminator since HTTP doesn't do that for us
        if (bStreaming)
        {
            cbExpectedContentLength = cbTotalRead - cbHeadersLength + 1;
        }
		// Look for the content length header if we haven't found it yet.
		if (!bContentLengthParsed && !bStreaming)
		{
			char* pszContentLengthHeader = strstr(pMessage, CONTENT_LENGTH_HEADER);
			if (pszContentLengthHeader)
			{
				cbExpectedContentLength = atol(pszContentLengthHeader + strlen(CONTENT_LENGTH_HEADER));
				bContentLengthParsed = true;
				verbose("Found %s%d\n", CONTENT_LENGTH_HEADER, cbExpectedContentLength);
			}
			else
			{
				cbExpectedContentLength = cbTotalRead - cbHeadersLength + 1; // keep looking
			}
		}
		if (!bHeadersEndFound)
		{
			char* pszEndHeaderIndex = strstr(pMessage, "\r\n\r\n");
			if (pszEndHeaderIndex)
			{
				bHeadersEndFound = true;
				cbHeadersLength = pszEndHeaderIndex + 4 - pMessage;
                bStreaming = !bContentLengthParsed;
			}
		}
		if (!bHeadersEndFound)
		{
			cbHeadersLength = cbTotalRead;
		}
	}

	verbose("%5d bytes in decrypted packet.\n", cbTotalRead/*, pMessage*/);

	result = true;

cleanup:
	if (pMessage) LocalFree(pMessage);
	if (pExtraData) LocalFree(pExtraData);

	return result;
}

int _tmain(int argc, wchar_t* argv[])
{
	CredHandle hCredential;
	CtxtHandle hContext;
	SOCKET socket = INVALID_SOCKET;
	SecInvalidateHandle(&hCredential);
	SecInvalidateHandle(&hContext);
	wchar_t* pwzHost = NULL;
	u_short nPort;
	wchar_t* pwzRequestUrl = NULL;
	bool bEmptyPacketsDetected;
	int nReturnCode = RETURN_CODE_ERROR;

	if (argc != 2)
	{
		printf("USAGE: %S https://<urltotest>\n", argv[0]);
		nReturnCode = RETURN_CODE_USAGE;
		goto cleanup;
	}
	if (!ParseCommandLine(argv[1], &pwzHost, &nPort, &pwzRequestUrl))
	{
		nReturnCode = RETURN_CODE_USAGE_ERROR;
		goto cleanup;
	}

	if (!InitializeCredential(&hCredential)) goto cleanup;
	if (!InitializeSockets()) goto cleanup;
	if (!ConnectSocket(socket, pwzHost, nPort)) goto cleanup;
	if (!Handshake(socket, pwzHost, &hCredential, &hContext)) goto cleanup;
	if (!SendRequest(socket, pwzHost, pwzRequestUrl, &hContext)) goto cleanup;
	if (!ReceiveResponse(socket, &hContext, &bEmptyPacketsDetected)) goto cleanup;

	printf("--------\nTest completed: empty encryption packets %s detected.\n", 
		bEmptyPacketsDetected ? "WERE" : "WERE NOT");
	if (bEmptyPacketsDetected)
	{
		printf("This may cause compatibility issues with .NET Compact Framework versions\n2.0 SP2 (and earlier) and 3.5 RTM.\n");
	}

cleanup:

	if (SecIsValidHandle(&hContext))
	{
		DeleteSecurityContext(&hContext);
		SecInvalidateHandle(&hContext);
	}
	if (socket != INVALID_SOCKET)
	{
		closesocket(socket);
	}
	WSACleanup();

	if (SecIsValidHandle(&hCredential))
	{
		FreeCredentialsHandle(&hCredential);
		SecInvalidateHandle(&hCredential);
	}

	if (pwzHost) delete pwzHost;
	if (pwzRequestUrl) delete pwzRequestUrl;

	return nReturnCode;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -