// // main.cpp // CURL Certificates Mac // // Created by Christian Schmitz on 11.03.19. // Copyright © 2019 Christian Schmitz. All rights reserved. // #include #include #include #include #include #include typedef std::vector X509Vector; static X509Vector *trustedCertificateList; void PrintCertificate(X509 *cert) { if (cert) { BIO* bp = BIO_new(BIO_s_mem()); if (bp) { int ee = X509_print(bp, cert); if (ee == 1) { BUF_MEM *bptr = nil; BIO_get_mem_ptr(bp, &bptr); if (bptr) { printf("%s\n", bptr->data); } } BIO_free(bp); } } } static int InitTrustedCertificateList() { if (trustedCertificateList == NULL) { trustedCertificateList = new X509Vector(); SecKeychainSearchRef search = NULL; // The first argument being NULL indicates the user's current keychain list OSStatus status = SecKeychainSearchCreateFromAttributes(NULL, kSecCertificateItemClass, NULL, &search); if (status != errSecSuccess) { // DebugMessage("SecKeychainSearchCreateFromAttributes fsailed", status); } else { SecKeychainItemRef searchItem = NULL; while (SecKeychainSearchCopyNext(search, &searchItem) != errSecItemNotFound) { SecKeychainAttributeList attrList = {0,0}; CSSM_DATA certData; status = SecKeychainItemCopyContent(searchItem, NULL, &attrList, (UInt32 *)(&certData.Length), (void **)(&certData.Data)); if (status != errSecSuccess) { // DebugMessage("SecKeychainItemCopyContent failed", status); CFRelease(searchItem); continue; } else { const unsigned char *p = certData.Data; const unsigned char **pp = &p; X509 *opensslCertificate = d2i_X509(0, (pp), certData.Length); if (opensslCertificate == 0) { printf("A certificate could not be converted"); } else { trustedCertificateList->push_back(opensslCertificate); } } SecKeychainItemFreeContent(&attrList, certData.Data); CFRelease(searchItem); } CFRelease(search); } } if (trustedCertificateList) { int count = (int) trustedCertificateList->size(); return count; } return 0; } static void setupSslContext(SSL_CTX* context) { 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) { 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 main(int argc, const char * argv[]) { // insert code here... curl_global_init(0); 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; }