comparison ui/sslconnection_curl.cpp @ 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 6a3d284b9c16
children 7dff5c0c569c
comparison
equal deleted inserted replaced
998:0570b1e562c2 999:daa9448b64f5
5 * and comes with ABSOLUTELY NO WARRANTY! 5 * and comes with ABSOLUTELY NO WARRANTY!
6 * See LICENSE.txt for details. 6 * See LICENSE.txt for details.
7 */ 7 */
8 8
9 #include "sslconnection_curl.h" 9 #include "sslconnection_curl.h"
10
11 #include <polarssl/ssl.h>
10 #include <QSaveFile> 12 #include <QSaveFile>
11 13
12 #define CONNECTION_DEBUG 14 #define CONNECTION_DEBUG
13 15
14 SSLConnectionCurl::SSLConnectionCurl(const QString& url, 16 SSLConnectionCurl::SSLConnectionCurl(const QString& url,
22 if (!mCurl) { 24 if (!mCurl) {
23 qDebug() << "Failed to initialize curl"; 25 qDebug() << "Failed to initialize curl";
24 return; 26 return;
25 } 27 }
26 28
29 #ifdef RELEASE_BUILD
27 if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 1L) != CURLE_OK) { 30 if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 1L) != CURLE_OK) {
31 #else
32 /* For testing we do not have to trust the issuer. This should not
33 * be dangerous as we pin the peer certificate directly. */
34 if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 0L) != CURLE_OK) {
35 #endif
28 /* Should be default anyway */ 36 /* Should be default anyway */
29 qDebug() << "Setting verifypeer failed"; 37 qDebug() << "Setting verifypeer failed";
30 return; 38 return;
31 } 39 }
32 40
41 #ifdef RELEASE_BUILD
42 if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, 1L) != CURLE_OK) {
43 #else
44 /* For testing we do not have to trust host. This should not
45 * be dangerous as we pin the peer certificate directly. */
46 if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, 0L) != CURLE_OK) {
47 #endif
48 /* Should be default anyway */
49 qDebug() << "Setting verifypeer failed";
50 return;
51 }
52
33 if (curl_easy_setopt(mCurl, CURLOPT_ERRORBUFFER, mErrBuf) != CURLE_OK) { 53 if (curl_easy_setopt(mCurl, CURLOPT_ERRORBUFFER, mErrBuf) != CURLE_OK) {
34 qDebug() << "Setting errorbuf failed"; 54 qDebug() << "Setting errorbuf failed";
35 return; 55 return;
36 } 56 }
57
58 #ifdef RELEASE_BUILD
59 if (curl_easy_setopt(mCurl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2) != CURLE_OK) {
60 qDebug() << "Setting ssl version failed.";
61 return;
62 }
63 #endif
37 64
38 mCertFile.open(); 65 mCertFile.open();
39 if (mCertFile.write(mPinnedCert) != mPinnedCert.size()) { 66 if (mCertFile.write(mPinnedCert) != mPinnedCert.size()) {
40 qDebug() << "Failed to write temporary certificate"; 67 qDebug() << "Failed to write temporary certificate";
41 return; 68 return;
42 } 69 }
43 mCertFile.close(); 70 mCertFile.close();
44 71
45 if (curl_easy_setopt(mCurl, CURLOPT_CAINFO, 72 if (curl_easy_setopt(mCurl, CURLOPT_CAINFO,
46 mCertFile.fileName().toUtf8().constData()) != CURLE_OK) { 73 mCertFile.fileName().toUtf8().constData()) != CURLE_OK) {
47 qDebug() << "Failed to write temporary certificate"; 74 qDebug() << "Failed to set ca certificate";
48 return; 75 return;
49 } 76 }
50 77
78 /* If the build fails here maybe you probably forgot to apply the
79 * trustbridge patches to curl */
80 if (curl_easy_setopt(mCurl, CURLOPT_PEERCERT,
81 mCertFile.fileName().toUtf8().constData()) != CURLE_OK) {
82 qDebug() << "Failed set peer certificate.";
83 return;
84 }
51 mInitialized = true; 85 mInitialized = true;
52 86
53 #ifdef CONNECTION_DEBUG 87 #ifdef CONNECTION_DEBUG
54 curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1L); 88 curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1L);
55 #endif 89 #endif
80 retval = curl_easy_perform(mCurl); 114 retval = curl_easy_perform(mCurl);
81 if (retval != CURLE_OK) { 115 if (retval != CURLE_OK) {
82 qDebug() << "Failed to connect: " << mErrBuf << " retval: " << retval; 116 qDebug() << "Failed to connect: " << mErrBuf << " retval: " << retval;
83 if (retval == CURLE_PEER_FAILED_VERIFICATION) { 117 if (retval == CURLE_PEER_FAILED_VERIFICATION) {
84 mErrorState = InvalidCertificate; 118 mErrorState = InvalidCertificate;
119 return -1;
120 }
121 if (retval == CURLE_SSL_CONNECT_ERROR) {
122 mErrorState = SSLHandshakeFailed;
85 return -1; 123 return -1;
86 } 124 }
87 125
88 mErrorState = NoConnection; 126 mErrorState = NoConnection;
89 return -1; 127 return -1;
224 return; 262 return;
225 } 263 }
226 } 264 }
227 265
228 void SSLConnectionCurl::setCiphersuites(int ciphers[]) { 266 void SSLConnectionCurl::setCiphersuites(int ciphers[]) {
229 qDebug() << "Set ciphersuites not supported."; 267 QStringList cipher_list;
230 } 268 for (int i = 0; ciphers[i] != 0; i++) {
269 cipher_list << ssl_get_ciphersuite_name(ciphers[i]);
270 }
271
272 if (curl_easy_setopt(mCurl, CURLOPT_SSL_CIPHER_LIST,
273 cipher_list.join(":").toLatin1().constData()) != CURLE_OK) {
274 qDebug() << "Failed to set cipher list";
275 return;
276 }
277 }

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