我正在尝试让 SSL/TLS 连接在 Windows 中工作。现在我正在使用 Schannel,但我不确定这是正确的方法。这是我的代码。InitializeSecurityContextA() 函数引发异常
#include "windows.h"
#pragma comment(lib, "ws2_32.lib")
#define SECURITY_WIN32
#include <SChannel.h>
#include <security.h>
int CALLBACK WinMain(HINSTANCE currentinstance, HINSTANCE previousinstance, LPSTR BS1, int BS2) {
// Initialize Winsock 2.0
WSADATA versioninfo;
WSAStartup (0x0202, &versioninfo);
// Load Security DLL
HMODULE securitydllmodule = LoadLibrary("Secur32.dll");
// Initialize Schannel
INIT_SECURITY_INTERFACE initsecurtyinterfacefunction = (INIT_SECURITY_INTERFACE)GetProcAddress(securitydllmodule, "InitSecurityInterfaceA");
PSecurityFunctionTable schannel = initsecurtyinterfacefunction();
if (!schannel)
MessageBox(0, "Failed to initialize schannel", "Message", MB_TASKMODAL | MB_OK);
else
MessageBox(0, "initialized schannel", "Message", MB_TASKMODAL | MB_OK);
// Setup Schannel Credentials
DWORD protocol = SP_PROT_TLS1;
SCHANNEL_CRED schannelcredentials;
ZeroMemory(&schannelcredentials, sizeof(schannelcredentials));
schannelcredentials.dwVersion = SCHANNEL_CRED_VERSION;
schannelcredentials.grbitEnabledProtocols = protocol;
schannelcredentials.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
schannelcredentials.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
// Get Client Credentials handle
CredHandle clientcredentials;
SECURITY_STATUS securitystatus = schannel->AcquireCredentialsHandleA(
0,
UNISP_NAME_A,
SECPKG_CRED_OUTBOUND,
0,
&schannelcredentials,
0,
0,
&clientcredentials,
0
);
if (securitystatus != SEC_E_OK)
MessageBox(0, "Failed to get credenetials", "Message", MB_TASKMODAL | MB_OK);
else
MessageBox(0, "Got client credenetials", "Message", MB_TASKMODAL | MB_OK);
// Connect to Google
SOCKET mysocket = socket(PF_INET, SOCK_STREAM, 0);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(443);
hostent *hp = gethostbyname("www.google.com");
memcpy(&sin.sin_addr, hp->h_addr, 4);
if (connect(mysocket, (struct sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR)
MessageBox(0, "Error connecting", "Message", MB_TASKMODAL | MB_OK);
else
MessageBox(0, "Connected", "Message", MB_TASKMODAL | MB_OK);
// Perform Handshake:
DWORD sspiflags = (
ISC_REQ_SEQUENCE_DETECT
| ISC_REQ_REPLAY_DETECT
| ISC_REQ_CONFIDENTIALITY
| ISC_RET_EXTENDED_ERROR
| ISC_REQ_ALLOCATE_MEMORY
| ISC_REQ_STREAM
);
SecBuffer OutBuffers[1];
OutBuffers[0].pvBuffer = 0;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].cbBuffer = 0;
SecBufferDesc OutBuffer;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
OutBuffer.ulVersion = SECBUFFER_VERSION;
DWORD sspioutflags;
CtxtHandle* contexthandle;
SECURITY_STATUS scRet = schannel->InitializeSecurityContextA(
&clientcredentials,
0,
"www.google.com",
sspiflags,
0,
SECURITY_NATIVE_DREP,
0,
0,
contexthandle,
&OutBuffer,
&sspioutflags,
0
);
if (scRet != SEC_I_CONTINUE_NEEDED)
MessageBox(0, "Error Initializing Security Context", "Message", MB_TASKMODAL | MB_OK);
else
MessageBox(0, "Security Context Initialized", "Message", MB_TASKMODAL | MB_OK);
// Done
MessageBox(0, "Done", "Message", MB_TASKMODAL | MB_OK);
return 0;
}