// // main.cpp // CURL Certificates Win // // Created by Christian Schmitz on 11.03.19. // Copyright © 2019 Christian Schmitz. All rights reserved. // #include "stdafx.h" #include #include #include #include #include #include "CURL_idn_win32.h" #define nullptr 0 #include // Upon the recent request just find some code snippets that should give you an idea how to load the certificates from the Windows CA Store into the OpenSSL context of libcurl. // (Just note that I stripped a lot of things in order to remove Qt dependencies and our class names) typedef std::vector X509Vector; static X509Vector *trustedCertificateList; static void addCertificatesForStore(LPCWSTR name) { HCERTSTORE storeHandle = CertOpenSystemStoreW(NULL, name); if (storeHandle == nullptr) { printf("CertOpenSystemStoreW failed for: %s\n", name); return; } PCCERT_CONTEXT windowsCertificate = CertEnumCertificatesInStore(storeHandle, nullptr); while (windowsCertificate != nullptr) { const BYTE *p = windowsCertificate->pbCertEncoded; const BYTE **pp = &p; X509 *opensslCertificate = d2i_X509(nullptr, const_cast(pp), windowsCertificate->cbCertEncoded); if (opensslCertificate == nullptr) { printf("A certificate could not be converted"); } else { trustedCertificateList->push_back(opensslCertificate); } windowsCertificate = CertEnumCertificatesInStore(storeHandle, windowsCertificate); } CertCloseStore(storeHandle, 0); } static int InitTrustedCertificateList() { printf("%s\n", __FUNCTION__); if (trustedCertificateList == NULL) { trustedCertificateList = new X509Vector(); addCertificatesForStore(L"CA"); addCertificatesForStore(L"AuthRoot"); addCertificatesForStore(L"ROOT"); } if (trustedCertificateList) { int count = (int) trustedCertificateList->size(); printf("count: %d\n", count); return count; } return 0; } static void setupSslContext(SSL_CTX* context) { printf("%s\n", __FUNCTION__); InitTrustedCertificateList(); if (trustedCertificateList != NULL) { X509_STORE* certStore = SSL_CTX_get_cert_store(context); for (X509Vector::iterator it = trustedCertificateList->begin(); it != trustedCertificateList->end(); it++) { X509 *x509 = *it; X509_STORE_add_cert(certStore, x509); } } } static int sslContextFunction(void* curl, void* sslctx, void* userdata) { printf("%s\n", __FUNCTION__); setupSslContext(reinterpret_cast(sslctx)); return CURLE_OK; } int _curl_debug_callback(CURL *handle, /* the handle/transfer this concerns */ curl_infotype type, /* what kind of data */ char *data, /* points to the data */ size_t size, /* size of the data pointed to */ void *userptr) /* whatever the user please */ { switch (type) { case CURLINFO_TEXT: { printf("%s", data); } case CURLINFO_HEADER_IN: /* 1 */ case CURLINFO_HEADER_OUT: /* 2 */ case CURLINFO_DATA_IN: /* 3 */ case CURLINFO_DATA_OUT: /* 4 */ case CURLINFO_END: case CURLINFO_SSL_DATA_IN: case CURLINFO_SSL_DATA_OUT: default: { // ignore } } return 0; } size_t _write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) { printf("%s", ptr); return size * nmemb; } int _tmain(int argc, _TCHAR* argv[]) { // insert code here... curl_global_init(CURL_GLOBAL_ALL); int c = InitTrustedCertificateList(); printf("%d certificates found.\n", c); CURL *h = curl_easy_init(); curl_easy_setopt(h, CURLOPT_DEBUGFUNCTION, _curl_debug_callback); curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, _write_callback); curl_easy_setopt(h, CURLOPT_URL, "https://monkeybreadsoftware.de/cgi-bin/getip.cgi"); curl_easy_setopt(h, CURLOPT_VERBOSE, 1); if (1) { curl_easy_setopt(h, CURLOPT_SSL_CTX_FUNCTION, sslContextFunction); curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 2); curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 1); } else { curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0); } int e = curl_easy_perform(h); printf("curl_easy_perform result: %d\n", e); curl_easy_cleanup(h); return 0; }