# HG changeset patch # User Andre Heinecke # Date 1409593733 -7200 # Node ID 0570b1e562c21450dd39002690520b8f6aac5b9a # Parent 405c97ca4ab072c95d0e0146afa55d1d66deb042 (issue90) Add curl patches for the problems we had with curl. diff -r 405c97ca4ab0 -r 0570b1e562c2 INSTALL --- 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 ===================== diff -r 405c97ca4ab0 -r 0570b1e562c2 patches/0001-Implement-CURLOPT_SSLVERSION-for-polarssl.patch --- /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 +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 + diff -r 405c97ca4ab0 -r 0570b1e562c2 patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch --- /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 +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, /* , if used */ + STRING_PASSWORD, /* , if used */ + STRING_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 + diff -r 405c97ca4ab0 -r 0570b1e562c2 patches/0003-Add-possibility-to-fore-polarssl-ciphersuites.patch --- /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 +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 +