changeset 998:0570b1e562c2

(issue90) Add curl patches for the problems we had with curl.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 01 Sep 2014 19:48:53 +0200
parents 405c97ca4ab0
children daa9448b64f5
files INSTALL patches/0001-Implement-CURLOPT_SSLVERSION-for-polarssl.patch patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch patches/0003-Add-possibility-to-fore-polarssl-ciphersuites.patch
diffstat 4 files changed, 275 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/INSTALL	Mon Sep 01 16:18:10 2014 +0200
+++ b/INSTALL	Mon Sep 01 19:48:53 2014 +0200
@@ -61,12 +61,21 @@
     cmake .. -DCMAKE_C_FLAGS=-fpic -DCMAKE_INSTALL_PREFIX=$YOURPREFIX
     make && make test && make install
 
+Trustbridge checkout:
+At this point you need a trustbridge checkout as curl needs to be patched
+to enable the certificate pinning and the force of SSL Ciphersuites when
+using polarssl.
+
+    hg clone https://wald.intevation.org/hg/trustbridge/
+
 Libcurl:
+
     wget http://curl.haxx.se/download/curl-7.37.1.tar.gz
     a32492a38c10a097344892f5fd2041e54698cb909696852311b1161e4aa979f3 curl-7.37.1.tar.gz
 
     tar -xf curl-7.37.1.tar.gz
     cd curl-7.37.1/
+    patch -p1 < ../trustbridge/patches/*.patch
     mkdir build
     cd build
 
@@ -84,7 +93,6 @@
 To compile the software you can use plain cmake. An out of source build is
 highly suggested. For build options see CMakeList.txt
 
-    hg clone https://wald.intevation.org/hg/trustbridge/
     cd trustbridge
     hg clone https://wald.intevation.org/hg/trustbridge/nss-cmake-static
     mkdir build-linux
@@ -171,13 +179,15 @@
     cp polarssl-1.3.7-gpl.tgz hiawatha-9.5/polarssl/polarssl.tgz
     cd hiawatha-9.5/polarssl
     sed -i 's/wget.*//' upgrade
-    ./upgrade 1.3.7
+    ./upgrade 1.3.8
     cd ..
     mkdir build
     cd build
     cmake .. -DCMAKE_INSTALL_PREFIX=$YOURPREFIX
     make && make install
 
+
+
 Osslsigncode (for binverify unit test)
 ======================================
 Osslsigncode is used to create PKCS#7 embedded signatures for Windows Authenticode
@@ -232,7 +242,7 @@
     cmake .. \
         -DCMAKE_PREFIX_PATH="$MXETARGET/qt5;$MXETARGET;" \
         -DCMAKE_TOOLCHAIN_FILE="$MXETARGET/share/cmake/mxe-conf.cmake" \
-        -DCMAKE_VERBOSE_MAKEFILE=True
+        -DCMAKE_VERBOSE_MAKEFILE=True -DUSE_CURL=OFF
 
 Runtime Depdendencies
 =====================
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/0001-Implement-CURLOPT_SSLVERSION-for-polarssl.patch	Mon Sep 01 19:48:53 2014 +0200
@@ -0,0 +1,47 @@
+From bebf7d617091042828fc5838170b35c42ab60396 Mon Sep 17 00:00:00 2001
+From: Andre Heinecke <aheinecke@intevation.de>
+Date: Mon, 1 Sep 2014 16:06:03 +0200
+Subject: [PATCH 1/3] Implement CURLOPT_SSLVERSION for polarssl
+
+    Forwards the setting as minimum ssl version to polarssl.
+    If the server does not support the requested version the
+    SSL Handshake will fail.
+---
+ lib/vtls/polarssl.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
+index f948486..e18cadf 100644
+--- a/lib/vtls/polarssl.c
++++ b/lib/vtls/polarssl.c
+@@ -270,6 +270,27 @@ polarssl_connect_step1(struct connectdata *conn,
+     return CURLE_SSL_CONNECT_ERROR;
+   }
+ 
++  if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) {
++    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
++                        SSL_MINOR_VERSION_0);
++    infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
++  }
++  else if(data->set.ssl.version == CURL_SSLVERSION_TLSv1_0) {
++    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
++                        SSL_MINOR_VERSION_1);
++    infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n");
++  }
++  else if(data->set.ssl.version == CURL_SSLVERSION_TLSv1_1) {
++    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
++                        SSL_MINOR_VERSION_2);
++    infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n");
++  }
++  else if(data->set.ssl.version == CURL_SSLVERSION_TLSv1_2) {
++    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
++                        SSL_MINOR_VERSION_3);
++    infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
++  }
++
+   ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
+   ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
+ 
+-- 
+1.9.1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch	Mon Sep 01 19:48:53 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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/0003-Add-possibility-to-fore-polarssl-ciphersuites.patch	Mon Sep 01 19:48:53 2014 +0200
@@ -0,0 +1,77 @@
+From 3dc7ab77759878778ae440a31304c736c1ef8cba Mon Sep 17 00:00:00 2001
+From: Andre Heinecke <aheinecke@intevation.de>
+Date: Mon, 1 Sep 2014 19:43:55 +0200
+Subject: [PATCH 3/3] Add possibility to fore polarssl ciphersuites.
+
+---
+ lib/vtls/polarssl.c | 40 ++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 38 insertions(+), 2 deletions(-)
+
+diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
+index 2c40e36..7e806bf 100644
+--- a/lib/vtls/polarssl.c
++++ b/lib/vtls/polarssl.c
+@@ -67,6 +67,8 @@
+ #define THREADING_SUPPORT
+ #endif
+ 
++#define MAX_CIPHERSUITES 255
++
+ #if defined(THREADING_SUPPORT)
+ static entropy_context entropy;
+ 
+@@ -129,7 +131,7 @@ static void polarssl_debug(void *context, int level, const char *line)
+ 
+ static Curl_recv polarssl_recv;
+ static Curl_send polarssl_send;
+-
++static int ciphersuites[MAX_CIPHERSUITES + 1];
+ 
+ static CURLcode
+ polarssl_connect_step1(struct connectdata *conn,
+@@ -300,7 +302,41 @@ polarssl_connect_step1(struct connectdata *conn,
+               net_recv, &conn->sock[sockindex],
+               net_send, &conn->sock[sockindex]);
+ 
+-  ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
++  if(!data->set.str[STRING_SSL_CIPHER_LIST])
++    ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
++  else {
++    /* Convert string input to polarssl cipher id's */
++    char *tmp,
++         *token,
++         *tok_buf;
++
++    memset(ciphersuites, 0, MAX_CIPHERSUITES + 1);
++
++    tmp = strdup (data->set.str[STRING_SSL_CIPHER_LIST]);
++    if(!tmp)
++      return CURLE_OUT_OF_MEMORY;
++
++    i = 0;
++    for (token = strtok_r(tmp, ":", &tok_buf);
++         token != NULL;
++         token = strtok_r(NULL, ":", &tok_buf)) {
++
++      ciphersuites[i] = ssl_get_ciphersuite_id(token);
++      if (!ciphersuites[i]) {
++        infof(data, "WARNING: failed to set cipher: %s\n", token);
++        /* Do not increase i as the first 0 is the end
++           of the list so we overwrite it with the next
++           valid cipher. Maybe we should fail? */
++        continue;
++      }
++      i++;
++    }
++    free(tmp);
++    /* Beware, polarssl does not make a copy of the ciphersuites
++       so the data needs to be valid during the call. */
++    ssl_set_ciphersuites(&connssl->ssl, ciphersuites);
++  }
++
+   if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
+     memcpy(&connssl->ssn, old_session, old_session_size);
+     infof(data, "PolarSSL re-using session\n");
+-- 
+1.9.1
+

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