Last active
February 14, 2019 07:41
-
-
Save jay/982b70e50bdd8a86415c to your computer and use it in GitHub Desktop.
Use libcurl and OpenSSL to show SSL negotiated cipher and version.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Use libcurl and OpenSSL to show SSL negotiated cipher and version. | |
Usage: ShowSSLInfo | |
curl-library mailing list thread: | |
'CURLINFO_TLS_SESSION with OPENSSL returns SSL_CTX instead of SSL' | |
http://curl.haxx.se/mail/lib-2015-09/0127.html | |
Copyright (C) 2015 Jay Satiro <raysatiro@yahoo.com> | |
http://curl.haxx.se/docs/copyright.html | |
https://gist.github.com/jay/982b70e50bdd8a86415c | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
/* http://curl.haxx.se/download.html */ | |
#include <curl/curl.h> | |
/* https://www.openssl.org/source/ */ | |
#include <openssl/ssl.h> | |
#undef FALSE | |
#define FALSE 0 | |
#undef TRUE | |
#define TRUE 1 | |
void ssl_info_callback(const SSL *s, int where, int ret) | |
{ | |
(void) ret; | |
if(where & SSL_CB_HANDSHAKE_DONE) { | |
const char *ver, *cipher; | |
fprintf(stderr, "Received SSL_CB_HANDSHAKE_DONE\n"); | |
switch(SSL_version(s)) { | |
case TLS1_2_VERSION: | |
ver = "TLSv1.2"; | |
break; | |
case TLS1_1_VERSION: | |
ver = "TLSv1.1"; | |
break; | |
case TLS1_VERSION: | |
ver = "TLSv1.0"; | |
break; | |
case SSL3_VERSION: | |
ver = "SSLv3"; | |
break; | |
case SSL2_VERSION: | |
ver = "SSLv2"; | |
break; | |
default: | |
ver = "unknown"; | |
break; | |
} | |
fprintf(stderr, "Version: %s\n", ver); | |
cipher = SSL_get_cipher(s); | |
if(!cipher) | |
cipher = "unknown"; | |
fprintf(stderr, "Cipher: %s\n\n", cipher); | |
} | |
return; | |
} | |
CURLcode ssl_ctx_callback(CURL *curl, void *ssl_ctx, void *userptr) | |
{ | |
(void)curl; | |
(void)userptr; | |
SSL_CTX_set_info_callback((SSL_CTX *)ssl_ctx, ssl_info_callback); | |
return CURLE_OK; | |
} | |
/* Retrieve url, show the SSL cipher and version. */ | |
int ShowSSLInfo(const char *url) | |
{ | |
int retcode = FALSE; | |
CURL *curl = NULL; | |
CURLcode res = CURLE_FAILED_INIT; | |
char errbuf[CURL_ERROR_SIZE] = { 0, }; | |
curl = curl_easy_init(); | |
if(!curl) { | |
fprintf(stderr, "Error: curl_easy_init failed.\n"); | |
goto cleanup; | |
} | |
/* CURLOPT_CAINFO | |
To verify SSL sites you may need to load a bundle of certificates. | |
You can download the default bundle here: | |
https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt | |
However your SSL backend might use a database in addition to or instead of | |
the bundle. | |
http://curl.haxx.se/docs/ssl-compared.html | |
*/ | |
curl_easy_setopt(curl, CURLOPT_CAINFO, "curl-ca-bundle.crt"); | |
curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, ssl_ctx_callback); | |
/* curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); */ | |
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); | |
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); /* HEAD request */ | |
curl_easy_setopt(curl, CURLOPT_HEADER, 1L); /* show headers */ | |
curl_easy_setopt(curl, CURLOPT_URL, url); | |
res = curl_easy_perform(curl); | |
if(res != CURLE_OK) { | |
size_t len = strlen(errbuf); | |
fprintf(stderr, "\nlibcurl: (%d) ", res); | |
if(len) | |
fprintf(stderr, "%s%s", errbuf, ((errbuf[len - 1] != '\n') ? "\n" : "")); | |
fprintf(stderr, "%s\n\n", curl_easy_strerror(res)); | |
goto cleanup; | |
} | |
retcode = TRUE; | |
cleanup: | |
curl_easy_cleanup(curl); | |
return retcode; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
curl_version_info_data *curlver = NULL; | |
if(argc != 2) { | |
fprintf(stderr, "Usage: ShowSSLInfo <url>\n"); | |
return EXIT_FAILURE; | |
} | |
if(curl_global_init(CURL_GLOBAL_ALL)) { | |
fprintf(stderr, "Fatal: The initialization of libcurl has failed.\n"); | |
return EXIT_FAILURE; | |
} | |
if(atexit(curl_global_cleanup)) { | |
fprintf(stderr, "Fatal: atexit failed to register curl_global_cleanup.\n"); | |
curl_global_cleanup(); | |
return EXIT_FAILURE; | |
} | |
curlver = curl_version_info(CURLVERSION_NOW); | |
if(!(curlver->features & CURL_VERSION_SSL) || !curlver->ssl_version || | |
strncmp("OpenSSL", curlver->ssl_version, 7)) { | |
fprintf(stderr, "Fatal: libcurl is not using OpenSSL.\n"); | |
return EXIT_FAILURE; | |
} | |
if(!ShowSSLInfo(argv[1])) { | |
fprintf(stderr, "Fatal: ShowSSLInfo failed.\n"); | |
return EXIT_FAILURE; | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment