nextcloud-desktop/src/mirall/sslerrordialog.cpp

222 lines
7.4 KiB
C++
Raw Normal View History

/*
* Copyright (C) by Klaas Freitag <freitag@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License
* for more details.
*/
2012-05-21 18:48:49 +04:00
#include "mirall/mirallconfigfile.h"
#include "mirall/utility.h"
#include "mirall/sslerrordialog.h"
2012-04-12 13:37:48 +04:00
#include <QtGui>
#include <QtNetwork>
2013-08-28 22:58:22 +04:00
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtWidgets>
#endif
#include "ui_sslerrordialog.h"
namespace Mirall
{
2013-08-28 22:58:22 +04:00
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
namespace Utility {
// Used for QSSLCertificate::subjectInfo which returns a QStringList in Qt5, but a QString in Qt4
QString escape(const QStringList &l) { return escape(l.join(';')); }
}
#endif
2013-10-24 02:29:08 +04:00
bool SslDialogErrorHandler::handleErrors(QList<QSslError> errors, QList<QSslCertificate> *certs, Account *account)
{
if (!certs) {
qDebug() << "Certs parameter required but is NULL!";
return false;
}
2013-10-24 02:29:08 +04:00
SslErrorDialog dlg(account);
// whether the failing certs have previously been accepted
if (dlg.checkFailingCertsKnown(errors)) {
*certs = dlg.unknownCerts();
2013-10-24 02:29:08 +04:00
return true;
}
// whether the user accepted the certs
2013-10-24 02:29:08 +04:00
if (dlg.exec() == QDialog::Accepted) {
if (dlg.trustConnection()) {
*certs = dlg.unknownCerts();
return true;
2013-10-24 02:29:08 +04:00
}
}
return false;
}
2013-08-28 22:58:22 +04:00
2013-10-24 02:29:08 +04:00
SslErrorDialog::SslErrorDialog(Account *account, QWidget *parent) :
QDialog(parent), _allTrusted(false), _ui(new Ui::SslErrorDialog), _account(account)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
_ui->setupUi( this );
setWindowTitle( tr("SSL Connection") );
2012-10-27 19:03:48 +04:00
QPushButton *okButton =
_ui->_dialogButtonBox->button( QDialogButtonBox::Ok );
2012-10-27 19:03:48 +04:00
QPushButton *cancelButton =
_ui->_dialogButtonBox->button( QDialogButtonBox::Cancel );
2012-10-27 19:03:48 +04:00
okButton->setEnabled(false);
connect(_ui->_cbTrustConnect, SIGNAL(clicked(bool)),
2012-10-27 19:03:48 +04:00
okButton, SLOT(setEnabled(bool)));
2012-04-12 13:37:48 +04:00
if( okButton ) {
okButton->setDefault(true);
connect( okButton, SIGNAL(clicked()),SLOT(accept()));
2012-10-27 19:03:48 +04:00
connect( cancelButton, SIGNAL(clicked()),SLOT(reject()));
2012-04-12 13:37:48 +04:00
}
}
SslErrorDialog::~SslErrorDialog()
{
delete _ui;
}
2012-04-12 13:37:48 +04:00
QString SslErrorDialog::styleSheet() const
{
2012-04-12 13:37:48 +04:00
const QString style = QLatin1String(
"#cert {margin-left: 5px;} "
"#ca_error { color:#a00011; margin-left:5px; margin-right:5px; }"
"#ca_error p { margin-top: 2px; margin-bottom:2px; }"
"#ccert { margin-left: 5px; }"
"#issuer { margin-left: 5px; }"
2012-10-24 03:42:25 +04:00
"tt { font-size: small; }"
2012-04-12 13:37:48 +04:00
);
return style;
}
#define QL(x) QLatin1String(x)
bool SslErrorDialog::checkFailingCertsKnown( const QList<QSslError> &errors )
2012-04-12 13:37:48 +04:00
{
// check if unknown certs caused errors.
_unknownCerts.clear();
QStringList errorStrings;
2013-10-24 02:29:08 +04:00
QList<QSslCertificate> trustedCerts = _account->approvedCerts();
2012-04-12 13:37:48 +04:00
for (int i = 0; i < errors.count(); ++i) {
QSslError error = errors.at(i);
if (trustedCerts.contains(error.certificate()) ||
_unknownCerts.contains(error.certificate() )) {
2012-04-12 13:37:48 +04:00
continue;
}
errorStrings += error.errorString();
if (!error.certificate().isNull()) {
_unknownCerts.append(error.certificate());
2012-04-12 13:37:48 +04:00
}
}
2012-04-12 13:37:48 +04:00
// if there are no errors left, all Certs were known.
if (errorStrings.isEmpty()) {
_allTrusted = true;
return true;
}
2012-04-12 13:37:48 +04:00
QString msg = QL("<html><head>");
msg += QL("<link rel='stylesheet' type='text/css' href='format.css'>");
msg += QL("</head><body>");
// loop over the unknown certs and line up their errors.
msg += QL("<h3>") + tr("Warnings about current SSL Connection:") + QL("</h3>");
msg += QL("<div id=\"ca_errors\">");
2012-05-21 18:48:49 +04:00
foreach( const QSslCertificate& cert, _unknownCerts ) {
2012-04-12 13:37:48 +04:00
msg += QL("<div id=\"ca_error\">");
// add the errors for this cert
foreach( QSslError err, errors ) {
if( err.certificate() == cert ) {
2012-08-17 19:13:17 +04:00
msg += QL("<p>") + err.errorString() + QL("</p>");
}
}
2012-04-12 13:37:48 +04:00
msg += QL("</div>");
msg += certDiv( cert );
if( _unknownCerts.count() > 1 ) {
msg += QL("<hr/>");
}
}
2012-04-12 13:37:48 +04:00
msg += QL("</div></body></html>");
qDebug() << "# # # # # # ";
qDebug() << msg;
QTextDocument *doc = new QTextDocument(0);
QString style = styleSheet();
qDebug() << "Style: " << style;
2012-08-17 19:13:17 +04:00
doc->addResource( QTextDocument::StyleSheetResource, QUrl( QL("format.css") ), style);
2012-04-12 13:37:48 +04:00
doc->setHtml( msg );
_ui->_tbErrors->setDocument( doc );
_ui->_tbErrors->show();
2012-04-12 13:37:48 +04:00
return false;
}
QString SslErrorDialog::certDiv( QSslCertificate cert ) const
{
QString msg;
2012-04-12 13:37:48 +04:00
msg += QL("<div id=\"cert\">");
2013-08-28 22:58:22 +04:00
msg += QL("<h3>") + tr("with Certificate %1").arg( Utility::escape(cert.subjectInfo( QSslCertificate::CommonName ))) + QL("</h3>");
2012-04-12 13:37:48 +04:00
msg += QL("<div id=\"ccert\">");
QStringList li;
2012-10-24 03:42:25 +04:00
QString org = Utility::escape(cert.subjectInfo( QSslCertificate::Organization));
QString unit = Utility::escape(cert.subjectInfo( QSslCertificate::OrganizationalUnitName));
QString country = Utility::escape(cert.subjectInfo( QSslCertificate::CountryName));
2012-10-24 03:42:25 +04:00
if (unit.isEmpty()) unit = tr("&lt;not specified&gt;");
if (org.isEmpty()) org = tr("&lt;not specified&gt;");
if (country.isEmpty()) country = tr("&lt;not specified&gt;");
li << tr("Organization: %1").arg(org);
li << tr("Unit: %1").arg(unit);
li << tr("Country: %1").arg(country);
2012-08-17 19:13:17 +04:00
msg += QL("<p>") + li.join(QL("<br/>")) + QL("</p>");
2012-04-12 13:37:48 +04:00
msg += QL("<p>");
2012-10-24 03:42:25 +04:00
QString md5sum = Utility::formatFingerprint(cert.digest(QCryptographicHash::Md5).toHex());
QString sha1sum = Utility::formatFingerprint(cert.digest(QCryptographicHash::Sha1).toHex());
msg += tr("Fingerprint (MD5): <tt>%1</tt>").arg(md5sum) + QL("<br/>");
msg += tr("Fingerprint (SHA1): <tt>%1</tt>").arg(sha1sum) + QL("<br/>");
2012-10-24 03:42:25 +04:00
msg += QL("<br/>");
2012-04-12 13:37:48 +04:00
msg += tr("Effective Date: %1").arg( cert.effectiveDate().toString()) + QL("<br/>");
msg += tr("Expiry Date: %1").arg( cert.expiryDate().toString()) + QL("</p>");
msg += QL("</div>" );
2013-08-28 22:58:22 +04:00
msg += QL("<h3>") + tr("Issuer: %1").arg(Utility::escape(cert.issuerInfo( QSslCertificate::CommonName))) + QL("</h3>");
2012-08-17 19:13:17 +04:00
msg += QL("<div id=\"issuer\">");
2012-04-12 13:37:48 +04:00
li.clear();
2013-08-28 22:58:22 +04:00
li << tr("Organization: %1").arg(Utility::escape(cert.issuerInfo( QSslCertificate::Organization)));
li << tr("Unit: %1").arg(Utility::escape(cert.issuerInfo( QSslCertificate::OrganizationalUnitName)));
li << tr("Country: %1").arg(Utility::escape(cert.issuerInfo( QSslCertificate::CountryName)));
2012-08-17 19:13:17 +04:00
msg += QL("<p>") + li.join(QL("<br/>")) + QL("</p>");
2012-04-12 13:37:48 +04:00
msg += QL("</div>" );
msg += QL("</div>" );
return msg;
}
2012-04-12 13:37:48 +04:00
bool SslErrorDialog::trustConnection()
{
if( _allTrusted ) return true;
bool stat = ( _ui->_cbTrustConnect->checkState() == Qt::Checked );
2012-04-12 13:37:48 +04:00
qDebug() << "SSL-Connection is trusted: " << stat;
return stat;
}
} // end namespace