From 93e450793ce289925dfd1d5e3b2d14e781f8dfd4 Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Tue, 30 Sep 2014 22:31:17 -0400 Subject: SSL: implement public key pinning Option --pinnedpubkey takes a path to a public key in DER format and only connect if it matches (currently only implemented with OpenSSL). Provides CURLOPT_PINNEDPUBLICKEY for curl_easy_setopt(). Extract a public RSA key from a website like so: openssl s_client -connect google.com:443 2>&1 < /dev/null | \ sed -n '/-----BEGIN/,/-----END/p' | openssl x509 -noout -pubkey \ | openssl rsa -pubin -outform DER > google.com.der --- src/tool_cfgable.c | 1 + src/tool_cfgable.h | 1 + src/tool_getparam.c | 6 ++++++ src/tool_help.c | 1 + src/tool_operate.c | 3 +++ 5 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index 2fdae073f..bd8707e57 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -101,6 +101,7 @@ static void free_config_fields(struct OperationConfig *config) Curl_safefree(config->cacert); Curl_safefree(config->capath); Curl_safefree(config->crlfile); + Curl_safefree(config->pinnedpubkey); Curl_safefree(config->key); Curl_safefree(config->key_type); Curl_safefree(config->key_passwd); diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 4ef269026..11a6a98e0 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -110,6 +110,7 @@ struct OperationConfig { char *cacert; char *capath; char *crlfile; + char *pinnedpubkey; char *key; char *key_type; char *key_passwd; diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 588a20723..bf025e4e8 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -215,6 +215,7 @@ static const struct LongShort aliases[]= { {"Em", "tlsauthtype", TRUE}, {"En", "ssl-allow-beast", FALSE}, {"Eo", "login-options", TRUE}, + {"Ep", "pinnedpubkey", TRUE}, {"f", "fail", FALSE}, {"F", "form", TRUE}, {"Fs", "form-string", TRUE}, @@ -1353,6 +1354,11 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ GetStr(&config->login_options, nextarg); break; + case 'p': /* Pinned public key DER file */ + /* Pinned public key DER file */ + GetStr(&config->pinnedpubkey, nextarg); + break; + default: /* certificate file */ { char *certname, *passphrase; diff --git a/src/tool_help.c b/src/tool_help.c index c255be0b9..2b26c58af 100644 --- a/src/tool_help.c +++ b/src/tool_help.c @@ -152,6 +152,7 @@ static const char *const helptext[] = { " --oauth2-bearer TOKEN OAuth 2 Bearer Token (IMAP, POP3, SMTP)", " -o, --output FILE Write to FILE instead of stdout", " --pass PASS Pass phrase for the private key (SSL/SSH)", + " --pinnedpubkey FILE Public key (DER) to verify peer against (OpenSSL)", " --post301 " "Do not switch to GET after following a 301 redirect (H)", " --post302 " diff --git a/src/tool_operate.c b/src/tool_operate.c index fd2fd6ddd..488fb08c4 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1025,6 +1025,9 @@ static CURLcode operate_do(struct GlobalConfig *global, if(config->crlfile) my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile); + if(config->pinnedpubkey) + my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey); + if(curlinfo->features & CURL_VERSION_SSL) { if(config->insecure_ok) { my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); -- cgit v1.2.3