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

📄 emptypacketschecker.cpp

📁 DescriptionThis adds some support for SSL renegotiation over V1.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************************
* Copyright (C) 2007 Microsoft Corporation
* Author: Andrew Arnott (http://blogs.msdn.com/andrewarnottms)
* This file is released under the Ms-PL license.
* The full text of this license can be retrieved from:
* http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx
* WARNING: This code is for demonstration purposes only and
* has not been security reviewed for production use.
* VERSION: 2
*****************************************************************/

#include "stdafx.h"

#define oom error("Out of memory.\n")
#define SecurityPackage L"Negotiate"
const char* CONTENT_LENGTH_HEADER = "Content-Length: ";

const int RETURN_CODE_USAGE = 1;
const int RETURN_CODE_USAGE_ERROR = 2;
const int RETURN_CODE_EMPTY_PACKETS_FOUND = 3;
const int RETURN_CODE_NO_EMPTY_PACKETS_FOUND = 4;
const int RETURN_CODE_ERROR = 5;

bool ParseCommandLine(wchar_t* url, wchar_t** ppszHost, u_short* pnPort, wchar_t** ppszPath)
{
	wchar_t* pszExpectedScheme = _T("https://");
	if (wcsstr(url, pszExpectedScheme) != url)
	{
		error("First parameter expected to start with '%S'.\n", pszExpectedScheme);
		return false;
	}
	wchar_t* pszHostStart = url + wcslen(pszExpectedScheme);
    wchar_t* pszPortStart = wcsstr(pszHostStart, L":");
    if (pszPortStart)
    {
        *pnPort = _wtoi(pszPortStart + 1);
    }
    else
    {
        *pnPort = 443;
    }
	wchar_t* pszPathSplitter = wcsstr(pszHostStart, L"/");
    wchar_t* pszHostStop = pszPortStart ? pszPortStart : pszPathSplitter;
	if (!pszPathSplitter)
	{
		error("First parameter expected to be a URL with a path on it.\n");
		return false;
	}
	// Extract host name
	ULONG cchHost = pszHostStop - pszHostStart + 1;
	*ppszHost = new wchar_t[cchHost];
	if (ppszHost == NULL)
	{
		oom;
		return false;
	}
	memcpy_s(*ppszHost, cchHost * sizeof(wchar_t), pszHostStart, (pszHostStop - pszHostStart) * sizeof(wchar_t));
	(*ppszHost)[pszHostStop - pszHostStart] = NULL; // null terminator
	// Extract path
	ULONG cchPath = wcslen(pszPathSplitter) + 1;
	*ppszPath = new wchar_t[cchPath];
	if (ppszPath == NULL)
	{
		oom;
		return false;
	}
	wcscpy_s(*ppszPath, cchPath, pszPathSplitter);
	return true;
}

bool InitializeCredential(PCredHandle phCredential)
{
	DWORD dwProtocol = 0;
	SEC_WCHAR* pszPrincipal = NULL;
	SEC_WCHAR* pszPackage = UNISP_NAME_W;
	unsigned long fCredentialUse = SECPKG_CRED_OUTBOUND;
	void* pvLogonID = NULL;
	void* pAuthData = NULL;
	SEC_GET_KEY_FN pGetKeyFn = NULL;
	void* pvGetKeyArgument = NULL;
	PTimeStamp ptsExpiry = NULL;
	SECURITY_STATUS result = AcquireCredentialsHandle(
		pszPrincipal, pszPackage, fCredentialUse, 
		pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, 
		phCredential, ptsExpiry);
	if (result != SEC_E_OK)
	{
		error("in call to AcquireCredentialsHandle: 0x%x\n", result);
		SecInvalidateHandle(phCredential);
		return false;
	}
	return true;
}

BOOL InitializeSockets()
{
	WSADATA wsaData;
	WORD version = MAKEWORD(2, 0);

	HRESULT result = WSAStartup(version, &wsaData);
	if (FAILED(result))
	{
		error("call to WSAStartup failed: 0x%x\n", result);
		return false;
	}

	return true;
}

bool ResolveHostname(const wchar_t * pwzHostname, in_addr * sin_addr)
{
	bool result = false;
	struct hostent *hp;

	size_t cbHostname = wcslen(pwzHostname) + 1;
	char * pszHostname = new char[cbHostname];
	size_t retValue;
	mbstate_t conversionstate;
	if (wcsrtombs_s(&retValue, pszHostname, cbHostname, &pwzHostname, wcslen(pwzHostname), &conversionstate) != 0)
	{
		error("Failure converting host name to multibyte string.\n");
		goto cleanup;
	}

	if((hp = gethostbyname(pszHostname)) == NULL)
	{
		error("0x%x returned by gethostbyname\n", WSAGetLastError());
		goto cleanup;
	}
	memcpy(sin_addr, hp->h_addr, 4);
	result = true;

cleanup:
	if (pszHostname) delete pszHostname;
	return result;
}


bool ConnectSocket(SOCKET& s, wchar_t* pwzHostname, u_short nPort)
{
	bool result = false;

	echo("Connecting to %S:%d\n", pwzHostname, nPort);
	s = socket(PF_INET, SOCK_STREAM, 0);
	if(s == INVALID_SOCKET)
	{
		error("0x%x creating socket\n", WSAGetLastError());
		goto cleanup;
	}

	struct sockaddr_in socket_structure;
	socket_structure.sin_family = AF_INET;
	socket_structure.sin_port = ntohs(nPort);
	if (!ResolveHostname(pwzHostname, &socket_structure.sin_addr))
	{
		error("Socket connection failed.\n");
		goto cleanup;
	}

	if(connect(s, (struct sockaddr *)&socket_structure, sizeof(socket_structure)) == SOCKET_ERROR)
	{
		error("0x%x connecting to \"%s\" (%s)\n", 
			WSAGetLastError(),
			pwzHostname,
			inet_ntoa(socket_structure.sin_addr));
		goto cleanup;
	}

	result = true;

cleanup:
	if (!result)
	{
		if (s != INVALID_SOCKET)
		{
			closesocket(s);
		}
	}

	return result;
}

bool Handshake(SOCKET s, wchar_t * pwzHostname, PCredHandle phCredential, PCtxtHandle phContext)
{
	SecBufferDesc   InBufferDesc;
	SecBuffer       InBuffers[2];
	InBufferDesc.cBuffers = _countof(InBuffers);
	InBufferDesc.pBuffers = InBuffers;
	InBufferDesc.ulVersion = SECBUFFER_VERSION;

	SecBufferDesc   OutBufferDesc;
	SecBuffer       OutBuffers[1];
	OutBufferDesc.cBuffers = _countof(OutBuffers);
	OutBufferDesc.pBuffers = OutBuffers;
	OutBufferDesc.ulVersion = SECBUFFER_VERSION;

	char *          InSecBuffer = NULL;
	char *          OutSecBuffer = NULL;

	TimeStamp       tsExpiry;
	ULONG m_byteOrder = SECURITY_NETWORK_DREP;
	ULONG requiredSecurity =
		ISC_REQ_SEQUENCE_DETECT   |
		ISC_REQ_REPLAY_DETECT     |
		ISC_REQ_CONFIDENTIALITY   |
		ISC_RET_EXTENDED_ERROR    |
		ISC_REQ_STREAM;
	ULONG actualSecurity;

	SECURITY_STATUS scRet;
	bool            success = false;

	// Figure out how large of a buffer to allocate for a token.
	PSecPkgInfo pPackageInfo;
	scRet = QuerySecurityPackageInfo(SecurityPackage, &pPackageInfo);
	ULONG cbMaxTokenSize = pPackageInfo->cbMaxToken;
	FreeContextBuffer(pPackageInfo);

	// Allocate a buffer large enough to hold the largest token.
	InSecBuffer = (char *) LocalAlloc(LMEM_FIXED, cbMaxTokenSize);
	OutSecBuffer = (char *) LocalAlloc(LMEM_FIXED, cbMaxTokenSize);
	if (!InSecBuffer || !OutSecBuffer)
	{
		oom;
		goto cleanup;
	}
	ULONG& cbInSecBuffer = InBuffers[0].cbBuffer;
	ULONG& cbOutSecBuffer = OutBuffers[0].cbBuffer;

	// Do some one-time initialization of the buffers
	InBuffers[0].BufferType = SECBUFFER_TOKEN;
	InBuffers[0].pvBuffer = InSecBuffer;
	InBuffers[1].BufferType = SECBUFFER_EMPTY;
	InBuffers[1].pvBuffer = NULL;
	InBuffers[1].cbBuffer = 0;
	
	SecInvalidateHandle(phContext);
	do
	{
		cbInSecBuffer = 0;
		BOOL bFirstTime = !SecIsValidHandle(phContext);
		int cbData;

		do
		{
			if (InBuffers[1].BufferType == SECBUFFER_EXTRA)
			{
				// The server sent more to the token than could be processed in a single
				// call to InitializeSecurityContext.  We move this extra data into the token
				// buffer and prepare to call the function again.
				InBuffers[1].pvBuffer = (byte*)InBuffers[0].pvBuffer + cbData - InBuffers[1].cbBuffer;
				MoveMemory(InSecBuffer, InBuffers[1].pvBuffer, InBuffers[1].cbBuffer);
				InBuffers[0].pvBuffer = InSecBuffer;
				InBuffers[0].cbBuffer = InBuffers[1].cbBuffer;
				InBuffers[0].BufferType = SECBUFFER_TOKEN;

				InBuffers[1].BufferType = SECBUFFER_EMPTY;
				InBuffers[1].pvBuffer = NULL;
				InBuffers[1].cbBuffer = 0;
			}
			else // don't try to read more data from the server (yet) if there was data in the extra buffer
			{
				// Read in response from server if we already said something to it.
				if (!bFirstTime)
				{
					cbData = recv(s, InSecBuffer + cbInSecBuffer, cbMaxTokenSize - cbInSecBuffer, 0);
					if(cbData == SOCKET_ERROR || cbData == 0)
					{
						error("failure sending data to server 0x%x\n", WSAGetLastError());
						goto cleanup;
					}
					verbose("%5d bytes of handshake data received.\n", cbData);
					cbInSecBuffer += cbData;

					InBuffers[0].BufferType = SECBUFFER_TOKEN;
					InBuffers[0].pvBuffer = InSecBuffer;
				}
			}

			// Prepare client token.
			OutBuffers[0].BufferType = SECBUFFER_TOKEN;
			OutBuffers[0].pvBuffer = OutSecBuffer;
			OutBuffers[0].cbBuffer = cbMaxTokenSize;

			// Prepare client token.
			scRet = InitializeSecurityContextW(
				phCredential, 
				bFirstTime ? NULL : phContext, 
				bFirstTime ? pwzHostname : NULL, 
				requiredSecurity, 
				0, 
				m_byteOrder, 
				bFirstTime ? NULL : &InBufferDesc, 
				0, 
				bFirstTime ? phContext : NULL, 
				&OutBufferDesc, 
				&actualSecurity, 
				&tsExpiry);
		} while (scRet == SEC_E_INCOMPLETE_MESSAGE);

		// Send token to server if there is a token.
		if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
		{
			cbData = send(s,
						  (const char*)OutBuffers[0].pvBuffer,
						  OutBuffers[0].cbBuffer,
						  0);

			if(cbData == SOCKET_ERROR || cbData == 0)
			{
				error("failure sending data to server 0x%x\n", WSAGetLastError());
				goto cleanup;
			}

			verbose("%5d bytes of handshake data sent.\n", cbData);
		}
	} while (scRet == SEC_I_CONTINUE_NEEDED);

	if (scRet != SEC_E_OK)
	{
		error("server handshake failed with error code 0x%x\n", scRet);
		goto cleanup;
	}

	success = true;

cleanup:

	if (InSecBuffer) LocalFree(InSecBuffer);
	if (OutSecBuffer) LocalFree(OutSecBuffer);

	if (!success)
	{
		if (SecIsValidHandle(phContext))
		{
			DeleteSecurityContext(phContext);
			SecInvalidateHandle(phContext);
		}
	}

	return success;
}
bool SendRequest(SOCKET s, wchar_t * pwzHostname, wchar_t * pwzPath, PCtxtHandle phContext)
{
	bool result = false;
	char * pCompositeInBuffer = NULL;

	// Find certain important buffer sizes
	SecPkgContext_StreamSizes Sizes;
	SECURITY_STATUS 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;

	// Allocate one large buffer that will contain the three individual input buffers.
	int cbCompositeInBuffer = nMaxPacketTotalSize;
	pCompositeInBuffer = (char*)LocalAlloc(LMEM_FIXED, cbCompositeInBuffer);
	if (pCompositeInBuffer == NULL) 
	{
		oom;
		goto cleanup;
	}
	ULONG cbData;
	cbData = sprintf_s(pCompositeInBuffer + Sizes.cbHeader, Sizes.cbMaximumMessage - 1, "GET %S HTTP/1.0\r\nHost: %S\r\n\r\n", pwzPath, pwzHostname);

	// Initialize security buffers
	SecBufferDesc BufferDesc;

⌨️ 快捷键说明

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