# HG changeset patch # User Andre Heinecke # Date 1409593794 -7200 # Node ID daa9448b64f5419b3611c8f812d9183be95aea71 # Parent 0570b1e562c21450dd39002690520b8f6aac5b9a (issue90) Use certificate pinning and forced ciphersuites for curl diff -r 0570b1e562c2 -r daa9448b64f5 ui/sslconnection_curl.cpp --- 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 #include #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; + } } diff -r 0570b1e562c2 -r daa9448b64f5 ui/tests/downloadertest.cpp --- 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);