From 6a34b95f02848f75057f5e913e500115643fde5d Mon Sep 17 00:00:00 2001 From: Andrea Diamantini Date: Mon, 22 Mar 2010 02:46:24 +0100 Subject: First SSL support. checking metadata missing.. --- src/CMakeLists.txt | 1 + src/sslinfodialog_p.h | 107 +++++++++++++++++++++++++ src/webpage.cpp | 175 +++++++++++++++++++++++++++++++++++------ src/webpage.h | 7 +- src/websslinfo.cpp | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/websslinfo.h | 73 +++++++++++++++++ 6 files changed, 548 insertions(+), 26 deletions(-) create mode 100644 src/sslinfodialog_p.h create mode 100644 src/websslinfo.cpp create mode 100644 src/websslinfo.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d41ebfe0..bc4e91c8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,7 @@ SET( rekonq_KDEINIT_SRCS webinspectorpanel.cpp webpage.cpp webpluginfactory.cpp + websslinfo.cpp websnap.cpp webview.cpp webtab.cpp diff --git a/src/sslinfodialog_p.h b/src/sslinfodialog_p.h new file mode 100644 index 00000000..44d3ab7c --- /dev/null +++ b/src/sslinfodialog_p.h @@ -0,0 +1,107 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000-2003 George Staikos + * Copyright (C) 2000 Malte Starostik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef SSLINFODIALOG_P_H +#define SSLINFODIALOG_P_H + +#include + +#include +#include + +// NOTE: We need a copy of this header file is needed here because it +// is never installed by default by KIO. + +/** + * KDE SSL Information Dialog + * + * This class creates a dialog that can be used to display information about + * an SSL session. + * + * There are NO GUARANTEES that KSslInfoDialog will remain binary compatible/ + * Contact staikos@kde.org for details if needed. + * + * @author George Staikos + * @see KSSL + * @short KDE SSL Information Dialog + */ +class KDE_EXPORT KSslInfoDialog : public KDialog +{ +Q_OBJECT + +public: + /** + * Construct a KSSL Information Dialog + * + * @param parent the parent widget + */ + explicit KSslInfoDialog(QWidget *parent = 0); + + /** + * Destroy this dialog + */ + virtual ~KSslInfoDialog(); + + /** + * Tell the dialog if the connection has portions that may not be + * secure (ie. a mixture of secure and insecure frames) + * + * @param isIt true if security is in question + */ + void setSecurityInQuestion(bool isIt); + + /** + * Set information to display about the SSL connection. + * + * @param certificateChain the certificate chain leading from the certificate + * authority to the peer. + * @param ip the ip of the remote host + * @param host the remote hostname + * @param sslProtocol the version of SSL in use (SSLv2, SSLv3, TLSv1) + * @param cipher the cipher in use + * @param usedBits the used bits of the key + * @param bits the key size of the cipher in use + * @param validationErrors errors validating the certificates, if any + */ + void setSslInfo(const QList &certificateChain, + const QString &ip, const QString &host, + const QString &sslProtocol, const QString &cipher, + int usedBits, int bits, + const QList > &validationErrors); + + void setMainPartEncrypted(bool); + void setAuxiliaryPartsEncrypted(bool); + + static QList > errorsFromString(const QString &s); + +private Q_SLOTS: + void launchConfig(); + void displayFromChain(int); + +private: + void updateWhichPartsEncrypted(); + + class KSslInfoDialogPrivate; + KSslInfoDialogPrivate* const d; +}; + +#endif // SSLINFODIALOG_P_H diff --git a/src/webpage.cpp b/src/webpage.cpp index 0e7b3d8a..395e9073 100644 --- a/src/webpage.cpp +++ b/src/webpage.cpp @@ -45,6 +45,8 @@ #include "networkaccessmanager.h" #include "adblockmanager.h" +#include "sslinfodialog_p.h" + // KDE Includes #include #include @@ -73,6 +75,32 @@ // Defines #define QL1S(x) QLatin1String(x) +#define QL1C(x) QLatin1Char(x) + + +// Returns true if the scheme and domain of the two urls match... +static bool domainSchemeMatch(const QUrl& u1, const QUrl& u2) +{ + if (u1.scheme() != u2.scheme()) + return false; + + QStringList u1List = u1.host().split(QL1C('.'), QString::SkipEmptyParts); + QStringList u2List = u2.host().split(QL1C('.'), QString::SkipEmptyParts); + + if (qMin(u1List.count(), u2List.count()) < 2) + return false; // better safe than sorry... + + while (u1List.count() > 2) + u1List.removeFirst(); + + while (u2List.count() > 2) + u2List.removeFirst(); + + return (u1List == u2List); +} + + +// --------------------------------------------------------------------------------- WebPage::WebPage(QWidget *parent) @@ -92,6 +120,14 @@ WebPage::WebPage(QWidget *parent) setNetworkAccessManager(manager); + // activate ssl warnings + setSessionMetaData("ssl_activate_warnings", "TRUE"); + + // Override the 'Accept' header sent by QtWebKit which favors XML over HTML! + // Setting the accept meta-data to null will force kio_http to use its own + // default settings for this header. + setSessionMetaData(QL1S("accept"), QString()); + // ----- Web Plugin Factory setPluginFactory(new WebPluginFactory(this)); @@ -100,7 +136,7 @@ WebPage::WebPage(QWidget *parent) connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool))); // protocol handler signals - connect(&m_protHandler, SIGNAL(downloadUrl(const KUrl &)), this, SLOT(downloadUrl(const KUrl &))); + connect(&_protHandler, SIGNAL(downloadUrl(const KUrl &)), this, SLOT(downloadUrl(const KUrl &))); } @@ -112,21 +148,54 @@ WebPage::~WebPage() bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type) { - // advise users on resubmitting data - if(type == QWebPage::NavigationTypeFormResubmitted) + if(frame) { - int risp = KMessageBox::warningContinueCancel(view(), - i18n("Are you sure you want to send your data again?"), - i18n("Resend form data") ); - if(risp == KMessageBox::Cancel) + if ( _protHandler.preHandling(request, frame) ) + { return false; + } + + switch (type) + { + case QWebPage::NavigationTypeLinkClicked: + if (_sslInfo.isValid() ) + { + setRequestMetaData("ssl_was_in_use", "TRUE"); + } + break; + + case QWebPage::NavigationTypeFormSubmitted: + break; + + case QWebPage::NavigationTypeFormResubmitted: + if( KMessageBox::warningContinueCancel(view(), + i18n("Are you sure you want to send your data again?"), + i18n("Resend form data") + ) + == KMessageBox::Cancel) + { + return false; + } + break; + + case QWebPage::NavigationTypeReload: + case QWebPage::NavigationTypeBackOrForward: + case QWebPage::NavigationTypeOther: + break; + + default: + break; + } + + if(frame == mainFrame()) + { + setRequestMetaData("main_frame_request", "TRUE"); + } + else + { + setRequestMetaData("main_frame_request", "FALSE"); + } } - - if ( frame && m_protHandler.preHandling(request, frame) ) - { - return false; - } - return KWebPage::acceptNavigationRequest(frame, request, type); } @@ -197,38 +266,67 @@ void WebPage::handleUnsupportedContent(QNetworkReply *reply) } -void WebPage::loadFinished(bool) +void WebPage::loadFinished(bool ok) { + if(!ok) + return; + Application::adblockManager()->applyHidingRules(this); + QStringList list = ReKonfig::walletBlackList(); + // KWallet Integration - // TODO: Add check for sites exempt from automatic form filling... - if (wallet()) + if ( wallet() + && !list.contains( mainFrame()->url().toString() ) + ) { wallet()->fillFormData(mainFrame()); } + + // TODO: implement me! + if(_sslInfo.isValid()) + { + // show an icon in the urlbar + } + else + { + // hide the icon in the urlbar + } } void WebPage::manageNetworkErrors(QNetworkReply *reply) { Q_ASSERT(reply); - - WebView *v = 0; + QWebFrame* frame = qobject_cast(reply->request().originatingObject()); + const bool isMainFrameRequest = (frame == mainFrame()); - // NOTE - // These are not all networkreply errors, + if ( isMainFrameRequest + && _sslInfo.isValid() + && !domainSchemeMatch(reply->url(), _sslInfo.url()) + ) + { + //kDebug() << "Reseting cached SSL info..."; + _sslInfo = WebSslInfo(); + } + + // NOTE: These are not all networkreply errors, // but just that supported directly by KIO - switch( reply->error() ) { - case QNetworkReply::NoError: // no error. Simple :) + case QNetworkReply::NoError: // no error. Simple :) + if ( isMainFrameRequest && !_sslInfo.isValid() ) + { + // Obtain and set the SSL information if any... + _sslInfo.fromMetaData(reply->attribute(static_cast(KIO::AccessManager::MetaData))); + _sslInfo.setUrl(reply->url()); + } break; case QNetworkReply::UnknownNetworkError: // unknown network-related error detected - if( m_protHandler.postHandling(reply->request(), mainFrame()) ) + if( _protHandler.postHandling(reply->request(), mainFrame()) ) break; case QNetworkReply::ContentAccessDenied: // access to remote content denied (similar to HTTP error 401) @@ -247,8 +345,7 @@ void WebPage::manageNetworkErrors(QNetworkReply *reply) // don't bother on elements loading errors: // we'll manage just main url page ones - v = qobject_cast(view()); - if( reply->url() != v->url() ) + if( !isMainFrameRequest ) break; mainFrame()->setHtml( errorPage(reply), reply->url() ); @@ -398,3 +495,31 @@ void WebPage::downloadAllContentsWithKGet() kget.call("importLinks", QVariant(contents.toList())); } } + + +void WebPage::showSSLInfo() +{ + if (_sslInfo.isValid()) + { + QPointer dlg = new KSslInfoDialog ( view() ); + dlg->setSslInfo( _sslInfo.certificateChain(), + _sslInfo.peerAddress().toString(), + mainFrame()->url().host(), + _sslInfo.protocol(), + _sslInfo.ciphers(), + _sslInfo.usedChiperBits(), + _sslInfo.supportedChiperBits(), + KSslInfoDialog::errorsFromString( _sslInfo.certificateErrors() ) + ); + + dlg->open(); + delete dlg; + } + else + { + KMessageBox::information( 0, + i18n("The SSL information for this site appears to be corrupt."), + i18nc("Secure Sockets Layer", "SSL") + ); + } +} diff --git a/src/webpage.h b/src/webpage.h index 76927725..42d5f586 100644 --- a/src/webpage.h +++ b/src/webpage.h @@ -37,6 +37,7 @@ #include "rekonqprivate_export.h" #include "protocolhandler.h" #include "newtabpage.h" +#include "websslinfo.h" // KDE Includes #include @@ -57,6 +58,8 @@ public: explicit WebPage(QWidget *parent = 0); ~WebPage(); + void showSSLInfo(); + public slots: void manageNetworkErrors(QNetworkReply *reply); virtual void downloadRequest(const QNetworkRequest &request); @@ -78,7 +81,9 @@ private slots: private: QString errorPage(QNetworkReply *); - ProtocolHandler m_protHandler; + ProtocolHandler _protHandler; + + WebSslInfo _sslInfo; }; #endif diff --git a/src/websslinfo.cpp b/src/websslinfo.cpp new file mode 100644 index 00000000..ffc4918f --- /dev/null +++ b/src/websslinfo.cpp @@ -0,0 +1,211 @@ +/* + * This file is part of the KDE project. + * + * Copyright (C) 2009 Dawit Alemayehu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "websslinfo.h" + +#include + + +class WebSslInfo::WebSslInfoPrivate +{ +public: + WebSslInfoPrivate() + : usedCipherBits(0), supportedCipherBits(0) {} + + QUrl url; + QString ciphers; + QString protocol; + QString certErrors; + QHostAddress peerAddress; + QHostAddress parentAddress; + QList certificateChain; + + int usedCipherBits; + int supportedCipherBits; +}; + +WebSslInfo::WebSslInfo() + :d(new WebSslInfo::WebSslInfoPrivate) +{ +} + +WebSslInfo::WebSslInfo(const WebSslInfo& other) + :d(new WebSslInfo::WebSslInfoPrivate) +{ + *this = other; +} + +WebSslInfo::~WebSslInfo() +{ + delete d; + d = 0; +} + +bool WebSslInfo::isValid() const +{ + return !d->peerAddress.isNull(); +} + +QUrl WebSslInfo::url() const +{ + return d->url; +} + +QHostAddress WebSslInfo::parentAddress() const +{ + return d->parentAddress; +} + +QHostAddress WebSslInfo::peerAddress() const +{ + return d->peerAddress; +} + +QString WebSslInfo::protocol() const +{ + return d->protocol; +} + +QString WebSslInfo::ciphers() const +{ + return d->ciphers; +} + +QString WebSslInfo::certificateErrors() const +{ + return d->certErrors; +} + +int WebSslInfo::supportedChiperBits () const +{ + return d->supportedCipherBits; +} + +int WebSslInfo::usedChiperBits () const +{ + return d->usedCipherBits; +} + +QList WebSslInfo::certificateChain() const +{ + return d->certificateChain; +} + +WebSslInfo& WebSslInfo::operator=(const WebSslInfo& other) +{ + d->ciphers = other.d->ciphers; + d->protocol = other.d->protocol; + d->certErrors = other.d->certErrors; + d->peerAddress = other.d->peerAddress; + d->parentAddress = other.d->parentAddress; + d->certificateChain = other.d->certificateChain; + + d->usedCipherBits = other.d->usedCipherBits; + d->supportedCipherBits = other.d->supportedCipherBits; + d->url = other.d->url; + + return *this; +} + +QVariant WebSslInfo::toMetaData() const +{ + if (isValid()) { + QMap data; + data.insert("ssl_in_use", true); + data.insert("ssl_peer_ip", d->peerAddress.toString()); + data.insert("ssl_parent_ip", d->parentAddress.toString()); + data.insert("ssl_protocol_version", d->protocol); + data.insert("ssl_cipher", d->ciphers); + data.insert("ssl_cert_errors", d->certErrors); + data.insert("ssl_cipher_used_bits", d->usedCipherBits); + data.insert("ssl_cipher_bits", d->supportedCipherBits); + QByteArray certChain; + Q_FOREACH(const QSslCertificate& cert, d->certificateChain) + certChain += cert.toPem(); + data.insert("ssl_peer_chain", certChain); + return data; + } + + return QVariant(); +} + +void WebSslInfo::fromMetaData(const QVariant& value) +{ + if (value.isValid() && value.type() == QVariant::Map) { + QMap metaData = value.toMap(); + if (metaData.value("ssl_in_use", false).toBool()) { + setCertificateChain(metaData.value("ssl_peer_chain").toByteArray()); + setPeerAddress(metaData.value("ssl_peer_ip").toString()); + setParentAddress(metaData.value("ssl_parent_ip").toString()); + setProtocol(metaData.value("ssl_protocol_version").toString()); + setCiphers(metaData.value("ssl_cipher").toString()); + setCertificateErrors(metaData.value("ssl_cert_errors").toString()); + setUsedCipherBits(metaData.value("ssl_cipher_used_bits").toString()); + setSupportedCipherBits(metaData.value("ssl_cipher_bits").toString()); + } + } +} + +void WebSslInfo::setUrl (const QUrl &url) +{ + d->url = url; +} + +void WebSslInfo::setPeerAddress(const QString& address) +{ + d->peerAddress = address; +} + +void WebSslInfo::setParentAddress(const QString& address) +{ + d->parentAddress = address; +} + +void WebSslInfo::setProtocol(const QString& protocol) +{ + d->protocol = protocol; +} + +void WebSslInfo::setCertificateChain(const QByteArray& chain) +{ + d->certificateChain = QSslCertificate::fromData(chain); +} + +void WebSslInfo::setCiphers(const QString& ciphers) +{ + d->ciphers = ciphers; +} + +void WebSslInfo::setUsedCipherBits(const QString& bits) +{ + d->usedCipherBits = bits.toInt(); +} + +void WebSslInfo::setSupportedCipherBits(const QString& bits) +{ + d->supportedCipherBits = bits.toInt(); +} + +void WebSslInfo::setCertificateErrors(const QString& certErrors) +{ + d->certErrors = certErrors; +} diff --git a/src/websslinfo.h b/src/websslinfo.h new file mode 100644 index 00000000..433cf053 --- /dev/null +++ b/src/websslinfo.h @@ -0,0 +1,73 @@ +/* + * This file is part of the KDE project. + * + * Copyright (C) 2009 Dawit Alemayehu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef WEBSSLINFO_H +#define WEBSSLINFO_H + +#include + +#include +#include +#include +#include +#include + + +class WebSslInfo +{ +public: + WebSslInfo(); + WebSslInfo(const WebSslInfo&); + virtual ~WebSslInfo(); + + bool isValid() const; + QUrl url() const; + QHostAddress peerAddress() const; + QHostAddress parentAddress() const; + QString ciphers() const; + QString protocol() const; + QString certificateErrors() const; + int supportedChiperBits () const; + int usedChiperBits () const; + QList certificateChain() const; + + QVariant toMetaData() const; + void fromMetaData (const QVariant &); + + void setUrl (const QUrl &url); + WebSslInfo& operator = (const WebSslInfo&); + +protected: + void setCiphers(const QString& ciphers); + void setProtocol(const QString& protocol); + void setPeerAddress(const QString& address); + void setParentAddress(const QString& address); + void setCertificateChain(const QByteArray& chain); + void setCertificateErrors(const QString& certErrors); + void setUsedCipherBits(const QString& bits); + void setSupportedCipherBits(const QString& bits); + +private: + class WebSslInfoPrivate; + WebSslInfoPrivate* d; +}; + +#endif // WEBSSLINFO_H -- cgit v1.2.1