Click here to Skip to main content
Click here to Skip to main content

One Click SSL Certificate Registration using WinHTTP

, 29 Feb 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
Register self-signed SSL certificates from a remote web browser.

Introduction

Have you ever needed to install a self-signed certificate into the IE Certificate Cache from a 'remote' web browser? Here is some sample code which might make things easier.

Background

HTTPS testing can often be a pain. Every time you browse to your test web server, a challenge dialog appears, the SSL certificate is out of date, etc. Next, you want someone else to test your application. Ideally, they can run a self-registering program to make things simpler.

Using the code

The code is simple. The steps are simple. Open an HTTPS connection to a web server, get the SSL certificate, and install the certificate into the Certificate Cache. The provided code relies on the Windows HTTP Services interfaces as well as some Cryptography API calls. The function CwinHttpsCertDlg::Register() opens a WinHTTP session, creates a connection, and sends a request. At this point, we query the request for the certificate. The certificate is then placed in a Certificate Store.

Note: for the sake of this sample code, the certificate in placed in the "Root" store. Please be careful when adding certificates to your cache, remove them when testing is complete. Protect your keys!

Here are some excerpts from the code to 'get' a certificate from a web server:

    DWORD dwFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID|
        SECURITY_FLAG_IGNORE_CERT_DATE_INVALID|
        SECURITY_FLAG_IGNORE_UNKNOWN_CA;

        // open a session handle
    hSession = WinHttpOpen( szUserAgent,
        WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
        WINHTTP_NO_PROXY_NAME,
        WINHTTP_NO_PROXY_BYPASS, 0 );

    // connect to a web server
    hConnect = WinHttpConnect( hSession,
        m_csServer,
        INTERNET_DEFAULT_HTTPS_PORT,
        0 );

    // open a request handle
    hRequest = WinHttpOpenRequest( hConnect,
        L"GET",
        L"",
        NULL,
        WINHTTP_NO_REFERER,
        WINHTTP_DEFAULT_ACCEPT_TYPES,
        WINHTTP_FLAG_SECURE ); 

    // important - set security to ignore 'bad' certs
    bRet = WinHttpSetOption(
        hRequest,
        WINHTTP_OPTION_SECURITY_FLAGS,
        &dwFlags,
        sizeof(DWORD)
    );

    // send the request
    bRet = WinHttpSendRequest( hRequest,
        WINHTTP_NO_ADDITIONAL_HEADERS,
        0,
        WINHTTP_NO_REQUEST_DATA,
        0,
        0,
        0 );

    // get a handle on the certificate
    bRet = WinHttpQueryOption(
        hRequest,
        WINHTTP_OPTION_SERVER_CERT_CONTEXT,
        &pCert,
        &dwLen
    );

We now have a handle to a certificate, load the certificate into a store:

    // open a certificate store
     hCertStore = CertOpenStore( CERT_STORE_PROV_SYSTEM,
        0,
        0,
        CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
        L"Root"); 

    // add the certificate
    bRet =  CertAddCertificateContextToStore(
        hCertStore,
        pCert,
        CERT_STORE_ADD_REPLACE_EXISTING,
        NULL
    );

    // release the certificate
    CertFreeCertificateContext(pCert);

    // close the store
    bRet = CertCloseStore( hCertStore, 0 );

Finally, you might be able to use the following script to generate certificates. It's a bash script for a *NIX box with OpenSSL installed.

    #!/bin/bash

    #Generate ssl certificate
    PREFIX="foxbat.swiftview.com"

    #cd /opt/apache/conf
    mkdir ssl
    cd ssl
    openssl genrsa 1024 > ${PREFIX}.key
    chmod 600 ${PREFIX}.key
    openssl req -new -key ${PREFIX}.key  > ${PREFIX}.csr
    openssl req -x509 -days 365 -key ${PREFIX}.key -in ${PREFIX}.csr  > ${PREFIX}.crt
    echo "Add the following lines to httpd.conf"
    echo "SSLCertificateFile /opt/apache/conf/ssl/${PREFIX}.crt"
    echo "SSLCertificateKeyFile /opt/apache/conf/ssl/${PREFIX}.key"

certs.png

Points of interest

One annoying issue with this code, the Platform SDK did not contain the WinHTTP headers for libs. You will need to install a newer version of the SDK to make this compile correctly.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

KeithPirkl

United States United States
No Biography provided

Comments and Discussions

 
Questionhey,Man,how about using wininet? Pinmemberariesj2w3-Aug-10 17:57 
General#include <Winhttp.h> Pinmemberariesj2w29-Jul-10 21:24 
GeneralRe: #include [modified] PinmemberKeithAPirkl30-Jul-10 5:47 
GeneralRe: #include Pinmemberariesj2w3-Aug-10 16:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150331.1 | Last Updated 29 Feb 2008
Article Copyright 2008 by KeithPirkl
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid