changeset 999:daa9448b64f5

(issue90) Use certificate pinning and forced ciphersuites for curl
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 01 Sep 2014 19:49:54 +0200
parents 0570b1e562c2
children c6c8f4ce48f8
files ui/sslconnection_curl.cpp ui/tests/downloadertest.cpp
diffstat 2 files changed, 56 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/ui/sslconnection_curl.cpp	Mon Sep 01 19:48:53 2014 +0200
+++ b/ui/sslconnection_curl.cpp	Mon Sep 01 19:49:54 2014 +0200
@@ -7,6 +7,8 @@
  */
 
 #include "sslconnection_curl.h"
+
+#include <polarssl/ssl.h>
 #include <QSaveFile>
 
 #define CONNECTION_DEBUG
@@ -24,7 +26,25 @@
         return;
     }
 
+#ifdef RELEASE_BUILD
     if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 1L) != CURLE_OK) {
+#else
+    /* For testing we do not have to trust the issuer. This should not
+     * be dangerous as we pin the peer certificate directly. */
+    if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 0L) != CURLE_OK) {
+#endif
+        /* Should be default anyway */
+        qDebug() << "Setting verifypeer failed";
+        return;
+    }
+
+#ifdef RELEASE_BUILD
+    if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, 1L) != CURLE_OK) {
+#else
+    /* For testing we do not have to trust host. This should not
+     * be dangerous as we pin the peer certificate directly. */
+    if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, 0L) != CURLE_OK) {
+#endif
         /* Should be default anyway */
         qDebug() << "Setting verifypeer failed";
         return;
@@ -35,6 +55,13 @@
         return;
     }
 
+#ifdef RELEASE_BUILD
+    if (curl_easy_setopt(mCurl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2) != CURLE_OK) {
+        qDebug() << "Setting ssl version failed.";
+        return;
+    }
+#endif
+
     mCertFile.open();
     if (mCertFile.write(mPinnedCert) != mPinnedCert.size()) {
         qDebug() << "Failed to write temporary certificate";
@@ -44,10 +71,17 @@
 
     if (curl_easy_setopt(mCurl, CURLOPT_CAINFO,
                 mCertFile.fileName().toUtf8().constData()) != CURLE_OK) {
-        qDebug() << "Failed to write temporary certificate";
+        qDebug() << "Failed to set ca certificate";
         return;
     }
 
+    /* If the build fails here maybe you probably forgot to apply the
+     * trustbridge patches to curl */
+    if (curl_easy_setopt(mCurl, CURLOPT_PEERCERT,
+                mCertFile.fileName().toUtf8().constData()) != CURLE_OK) {
+        qDebug() << "Failed set peer certificate.";
+        return;
+    }
     mInitialized = true;
 
 #ifdef CONNECTION_DEBUG
@@ -84,6 +118,10 @@
             mErrorState = InvalidCertificate;
             return -1;
         }
+        if (retval == CURLE_SSL_CONNECT_ERROR) {
+            mErrorState = SSLHandshakeFailed;
+            return -1;
+        }
 
         mErrorState = NoConnection;
         return -1;
@@ -226,5 +264,14 @@
 }
 
 void SSLConnectionCurl::setCiphersuites(int ciphers[]) {
-    qDebug() << "Set ciphersuites not supported.";
+    QStringList cipher_list;
+    for (int i = 0; ciphers[i] != 0; i++) {
+        cipher_list << ssl_get_ciphersuite_name(ciphers[i]);
+    }
+
+    if (curl_easy_setopt(mCurl, CURLOPT_SSL_CIPHER_LIST,
+                cipher_list.join(":").toLatin1().constData()) != CURLE_OK) {
+        qDebug() << "Failed to set cipher list";
+        return;
+    }
 }
--- a/ui/tests/downloadertest.cpp	Mon Sep 01 19:48:53 2014 +0200
+++ b/ui/tests/downloadertest.cpp	Mon Sep 01 19:49:54 2014 +0200
@@ -148,22 +148,22 @@
 
     QVERIFY(error == SSLConnection::NoConnection);
 }
+static int accept_ciphers[] = {
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+    0
+};
 
 void DownloaderTest::testForcedCiphers()
 {
     Downloader* downloader = new Downloader(this,
-            QString::fromLatin1("https://files.intevation.de:443"),
+            QString::fromLatin1(SERVER_URL),
             QByteArray(), /* Use default testing certificate */
             QDateTime::currentDateTime(),
             QDateTime::fromString("2010", "YYYY"),
             "/users/aheinecke/development/TrustBridge-development.exe",
             "/users/aheinecke/development/zertifikatsliste.txt");
-    int accept_ciphers[] = {
-        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
-        TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-        TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
-        0
-    };
 
     downloader->setCiphersuites(accept_ciphers);
 

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