Mercurial > trustbridge
diff patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch @ 1008:2fb6071c6669
Merged
author | Emanuel Schuetze <emanuel@intevation.de> |
---|---|
date | Tue, 02 Sep 2014 11:55:15 +0200 |
parents | 0570b1e562c2 |
children | 93325618ac7b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch Tue Sep 02 11:55:15 2014 +0200 @@ -0,0 +1,138 @@ +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 +