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
+

http://wald.intevation.org/projects/trustbridge/