Mercurial > trustbridge
view patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch @ 1164:c13ac2c9851d
(issue106) Reference relevant issue in fixme
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Fri, 19 Sep 2014 10:49:37 +0200 |
parents | 93325618ac7b |
children |
line wrap: on
line source
From e5c7feec5151299975fe03184cc322ea51fb45c2 Mon Sep 17 00:00:00 2001 From: Andre Heinecke <aheinecke@intevation.de> Date: Fri, 12 Sep 2014 13:01:07 +0200 Subject: [PATCH 2/2] Add CURLOPT_PEERCERT option to pin a peer cert This is only implemented for a specific usecase with polarssl --- include/curl/curl.h | 3 +++ include/curl/typecheck-gcc.h | 1 + lib/url.c | 8 ++++++++ lib/urldata.h | 1 + lib/vtls/polarssl.c | 41 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+) diff --git a/include/curl/curl.h b/include/curl/curl.h index d40b2db..20a9d82 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1611,6 +1611,9 @@ typedef enum { /* Pass in a bitmask of "header options" */ CINIT(HEADEROPT, LONG, 229), + /* Peer certificate */ + CINIT(PEERCERT, OBJECTPOINT, 230), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h index 69d41a2..241529d 100644 --- a/include/curl/typecheck-gcc.h +++ b/include/curl/typecheck-gcc.h @@ -258,6 +258,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ (option) == CURLOPT_CRLFILE || \ (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_PEERCERT || \ (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ (option) == CURLOPT_SSH_KNOWNHOSTS || \ (option) == CURLOPT_MAIL_FROM || \ diff --git a/lib/url.c b/lib/url.c index 67126ab3..5721ee2 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2015,6 +2015,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT], va_arg(param, char *)); break; + case CURLOPT_PEERCERT: + /* + * Set peer certificate file + * to check peer certificate against + */ + result = setstropt(&data->set.str[STRING_SSL_PEERCERT], + va_arg(param, char *)); + break; case CURLOPT_TELNETOPTIONS: /* * Set a linked list of telnet options diff --git a/lib/urldata.h b/lib/urldata.h index 8594c2f..a6dc1ae 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1391,6 +1391,7 @@ enum dupstring { STRING_USERAGENT, /* User-Agent string */ STRING_SSL_CRLFILE, /* crl file to check certificate */ STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ + STRING_SSL_PEERCERT, /* issuer cert file to check certificate */ STRING_USERNAME, /* <username>, if used */ STRING_PASSWORD, /* <password>, if used */ STRING_OPTIONS, /* <options>, if used */ diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c index 08dc4c6..8f34901 100644 --- a/lib/vtls/polarssl.c +++ b/lib/vtls/polarssl.c @@ -403,6 +403,44 @@ polarssl_connect_step1(struct connectdata *conn, return CURLE_OK; } +static int +pinned_verify(void *pinned_cert_file_name, x509_crt *crt, + int depth, int *flags) +{ + x509_crt pinned_cert; + x509_crt *leaf = crt; + unsigned int i; + int ret; + + if (pinned_cert_file_name == NULL || crt == NULL) { + *flags |= BADCERT_NOT_TRUSTED; + return *flags; + } + + x509_crt_init(&pinned_cert); + ret = x509_crt_parse_file(&pinned_cert, pinned_cert_file_name); + + if(ret) { + x509_crt_free(&pinned_cert); + *flags |= BADCERT_NOT_TRUSTED; + return *flags; + } + + while (leaf->next) { + leaf = leaf->next; + } + + ret = memcmp(pinned_cert.raw.p, leaf->raw.p, pinned_cert.raw.len); + x509_crt_free(&pinned_cert); + if (ret == 0) { + *flags = 0; + return 0; + } + + *flags |= BADCERT_NOT_TRUSTED; + return *flags; +} + static CURLcode polarssl_connect_step2(struct connectdata *conn, int sockindex) @@ -422,6 +460,9 @@ polarssl_connect_step2(struct connectdata *conn, conn->recv[sockindex] = polarssl_recv; conn->send[sockindex] = polarssl_send; + if(data->set.str[STRING_SSL_PEERCERT]) + ssl_set_verify (&connssl->ssl, pinned_verify, data->set.str[STRING_SSL_PEERCERT]); + for(;;) { if(!(ret = ssl_handshake(&connssl->ssl))) break; -- 1.9.1