Search code examples
c++windowssslschannel

Secure Socket Connections using c++


I am trying to get SSL/TLS connections to work in windows. Right now I am using Schannel, but I am not sure this is the correct way to go about it. Here is my code. An exception is thrown at the InitializeSecurityContextA() function

#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;
}

Solution

  • Change CtxtHandle* contexthandle; to CtxtHandle contexthandle; and instead of contexthandle pass &contexthandle to your InitializeSecurityContextA() call.