Mercurial > trustbridge
view ui/sslconnection_curl.cpp @ 966:9783e32e215f
(issue89) Use platform specific help url.
Windows needs the file prefix to detect that c:/ is meant to
be a local file.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Thu, 28 Aug 2014 12:56:56 +0200 |
parents | 879a634d0a40 |
children | 6a3d284b9c16 |
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=2) * and comes with ABSOLUTELY NO WARRANTY! * See LICENSE.txt for details. */ #include "sslconnection_curl.h" #include <QSaveFile> #define CONNECTION_DEBUG SSLConnectionCurl::SSLConnectionCurl(const QString& url, const QByteArray& certificate): SSLConnection (url, certificate), mCurl (NULL) { if (certificate.isEmpty()) { /* Security: curl does not support leaf certificate pinning. So * while the bare connection pins the certificate directly the * curl implementation pins the issuer of the peer certificate * * CURLINFO_TLS_SESSION is also not implmented for polarssl * so there is no way to obtain / verify peer certificate manually * at this point. **/ #ifdef RELEASE_BUILD #error "Curl release build is not supported at this moment." #else QFile certResource(":certs/geotrust"); #endif certResource.open(QFile::ReadOnly); mPinnedCert = certResource.readAll(); certResource.close(); } curl_global_init(CURL_GLOBAL_DEFAULT); mCurl = curl_easy_init(); if (!mCurl) { qDebug() << "Failed to initialize curl"; return; } if (curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 1L) != CURLE_OK) { /* Should be default anyway */ qDebug() << "Setting verifypeer failed"; return; } if (curl_easy_setopt(mCurl, CURLOPT_ERRORBUFFER, mErrBuf) != CURLE_OK) { qDebug() << "Setting errorbuf failed"; return; } mCertFile.open(); if (mCertFile.write(mPinnedCert) != mPinnedCert.size()) { qDebug() << "Failed to write temporary certificate"; return; } mCertFile.close(); if (curl_easy_setopt(mCurl, CURLOPT_CAINFO, mCertFile.fileName().toUtf8().constData()) != CURLE_OK) { qDebug() << "Failed to write temporary certificate"; return; } mInitialized = true; #ifdef CONNECTION_DEBUG curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1L); #endif } SSLConnectionCurl::~SSLConnectionCurl() { if (mCurl) { curl_easy_cleanup (mCurl); } if (mInitialized) { mCertFile.close(); } curl_global_cleanup(); } int SSLConnectionCurl::connect() { CURLcode retval; if (curl_easy_setopt(mCurl, CURLOPT_URL, mUrl.toEncoded().constData()) != CURLE_OK) { qDebug() << "Failed to set URL"; return -1; } if (curl_easy_setopt(mCurl, CURLOPT_CONNECT_ONLY, 1L) != CURLE_OK) { qDebug() << "Failed to set connect only option"; return -1; } retval = curl_easy_perform(mCurl); if (retval != CURLE_OK) { qDebug() << "Failed to connect: " << mErrBuf << " retval: " << retval; if (retval == CURLE_PEER_FAILED_VERIFICATION) { mErrorState = InvalidCertificate; return -1; } mErrorState = NoConnection; return -1; } mConnected = true; return 0; } /* Globally do this as we can't pass this to the c function */ size_t ssl_curl_max_write, ssl_curl_written; size_t write_data(void *ptr, size_t size, size_t nmemb, QSaveFile *fp) { qDebug() << "Writing size: " << size << " * " << nmemb; if (ssl_curl_max_write < ssl_curl_written) { qDebug() << "Aborting write. Too much data."; return 0; } size_t written = fp->write((const char *)ptr, size * nmemb); if (written != size * nmemb) { qDebug() << "Failed to write data. Written: " << written << " requested: " << size * nmemb; return 0; } ssl_curl_written += written; return written; } bool SSLConnectionCurl::downloadFile(const QString &resource, const QString &fileName, size_t maxSize) { QSaveFile outputFile(fileName); ssl_curl_written = 0; ssl_curl_max_write = maxSize; // Open / Create the file to write to. if (!outputFile.open(QIODevice::WriteOnly)) { qDebug() << "Failed to open file"; return false; } QUrl urlCopy = mUrl; urlCopy.setPath(resource); if (curl_easy_setopt(mCurl, CURLOPT_URL, urlCopy.toEncoded().constData()) != CURLE_OK) { qDebug() << "Failed to set URL"; return false; } if (curl_easy_setopt(mCurl, CURLOPT_CONNECT_ONLY, 0L) != CURLE_OK) { qDebug() << "Failed to set connect"; return false; } if (curl_easy_setopt(mCurl, CURLOPT_HEADER, 0L) != CURLE_OK) { qDebug() << "Failed to set header"; return false; } if (curl_easy_setopt(mCurl, CURLOPT_NOBODY, 0L) != CURLE_OK) { qDebug() << "Failed to set no body"; return false; } if (curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, write_data) != CURLE_OK) { qDebug() << "Failed to set write function"; return false; } if (curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, &outputFile) != CURLE_OK) { qDebug() << "Failed to set write function"; return false; } if (curl_easy_perform (mCurl) != CURLE_OK) { qDebug() << "Failed to perform download."; return false; } if (!outputFile.commit()) { qDebug() << "Failed to commit data to filesystem."; return false; } return true; } QDateTime SSLConnectionCurl::getLastModifiedHeader(const QString &resource) { QUrl urlCopy = mUrl; urlCopy.setPath(resource); if (curl_easy_setopt(mCurl, CURLOPT_URL, urlCopy.toEncoded().constData()) != CURLE_OK) { qDebug() << "Failed to set URL"; return QDateTime(); } if (curl_easy_setopt(mCurl, CURLOPT_CONNECT_ONLY, 0L) != CURLE_OK) { qDebug() << "Failed to set connect"; return QDateTime(); } if (curl_easy_setopt(mCurl, CURLOPT_HEADER, 1L) != CURLE_OK) { qDebug() << "Failed to set header"; return QDateTime(); } if (curl_easy_setopt(mCurl, CURLOPT_NOBODY, 1L) != CURLE_OK) { qDebug() << "Failed to set no body"; return QDateTime(); } if (curl_easy_setopt(mCurl, CURLOPT_FILETIME, 1L) != CURLE_OK) { qDebug() << "Failed to set filetime"; return QDateTime(); } if (curl_easy_perform (mCurl) != CURLE_OK) { qDebug() << "Failed to perform last modified check."; return QDateTime(); } long filetime = 0; if (curl_easy_getinfo (mCurl, CURLINFO_FILETIME, &filetime) != CURLE_OK) { qDebug() << "Failed to get filetime"; return QDateTime(); } if (filetime == -1) { qDebug() << "Invalid Time"; return QDateTime(); } return QDateTime::fromTime_t(filetime); } void SSLConnectionCurl::setProxy(const QUrl& proxyUrl) { if (curl_easy_setopt(mCurl, CURLOPT_PROXY, proxyUrl.toEncoded().constData()) != CURLE_OK) { qDebug() << "Failed to set proxy"; return; } qDebug() << "Set proxy to: " << proxyUrl; }