Mercurial > trustbridge
view patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch @ 1059:f638eb1f3b0f
(issue46) Add debug option for trustbridge-admin
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 09 Sep 2014 18:00:37 +0200 |
parents | 0570b1e562c2 |
children | 93325618ac7b |
line wrap: on
line source
From c57d951c3bda8b1ca66cac45dfd6270fa34b01d3 Mon Sep 17 00:00:00 2001 From: Andre Heinecke <aheinecke@intevation.de> Date: Mon, 1 Sep 2014 16:55:40 +0200 Subject: [PATCH 2/3] Add CURLOPT_PEERCERT option to pin a peer cert 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 | 42 ++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 53 insertions(+), 2 deletions(-) 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 89c3fd5..b089cdf 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 e18cadf..2c40e36 100644 --- a/lib/vtls/polarssl.c +++ b/lib/vtls/polarssl.c @@ -360,6 +360,7 @@ polarssl_connect_step2(struct connectdata *conn, #ifdef HAS_ALPN const char* next_protocol; #endif + const x509_crt *peer_cert = NULL; char errorbuf[128]; memset(errorbuf, 0, sizeof(errorbuf)); @@ -419,12 +420,49 @@ polarssl_connect_step2(struct connectdata *conn, return CURLE_PEER_FAILED_VERIFICATION; } - if(ssl_get_peer_cert(&(connssl->ssl))) { + peer_cert = ssl_get_peer_cert(&(connssl->ssl)); + if(peer_cert) { + if(data->set.str[STRING_SSL_PEERCERT]) { + x509_crt pinned_cert; + unsigned int i; + + /* Handle pinned certificate */ + x509_crt_init(&pinned_cert); + ret = x509_crt_parse_file(&pinned_cert, + data->set.str[STRING_SSL_PEERCERT]); + + if(ret) { +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "Error reading peer cert file %s - PolarSSL: (-0x%04X) %s", + data->set.str[STRING_SSL_PEERCERT], -ret, errorbuf); + + x509_crt_free(&pinned_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + + if (peer_cert->raw.len == 0 || + peer_cert->raw.len != pinned_cert.raw.len) { + failf(data, "Error validating peer certificate. Size does " + "not match the certificate set with PEERCERT option.\n"); + x509_crt_free(&pinned_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + for (i = 0; i < peer_cert->raw.len; i++) { + if (peer_cert->raw.p[i] != pinned_cert.raw.p[i]) { + failf(data, "Error validating peer certificate. Does " + "not match the certificate set with PEERCERT option.\n"); + return CURLE_PEER_FAILED_VERIFICATION; + } + } + } + /* If the session was resumed, there will be no peer certs */ memset(buffer, 0, sizeof(buffer)); if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ", - ssl_get_peer_cert(&(connssl->ssl))) != -1) + peer_cert) != -1) infof(data, "Dumping cert info:\n%s\n", buffer); } -- 1.9.1