📄 emptypacketschecker.cpp
字号:
/****************************************************************
* 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 + -