c++ - 使用 C++ 的安全套接字连接

标签 c++ windows ssl schannel

我正在尝试让 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;
}

最佳答案

CtxtHandle* contexthandle; 更改为 CtxtHandle contexthandle; 而不是 contexthandle&contexthandle 传递给你的 InitializeSecurityContextA() 调用。

关于c++ - 使用 C++ 的安全套接字连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22295796/

相关文章:

windows - Luasql 和 SQLite?

ssl - 如何在 Neo4j 中使用 SSL 证书而不是自签名证书(或 snakeoil.cert)

ssl - Firebase 托管是否受益于 CloudFlare?

java - 如何在新的(未弃用的)SSLSocketFactory 中加载私钥密码?

c++ - 关于这个智能指针类

c++ - 需要更清楚地使用静态依赖项编译共享二进制文件的语法

c# - 寻找发音正确性

c++ - 无论传递了迭代器类型/指针,指向元素的地址

c++ - 将 LPTSTR 转换为字符串

windows - Git difftool 不启动外部 DiffMerge 程序