diff options
| author | Felix (xq) Queißner <git@mq32.de> | 2020-06-20 00:42:46 +0200 |
|---|---|---|
| committer | Felix (xq) Queißner <git@mq32.de> | 2020-06-20 00:42:46 +0200 |
| commit | cf3b60ea29526417a35734a4ae4f5a7b0d5560d5 (patch) | |
| tree | 1ff3846f2b10ddce0e883adf41ba35f7139945af /src | |
| parent | bdfd6ba6874ca1a7bcfa4ed075e686bfd119dc7e (diff) | |
| download | kristall-cf3b60ea29526417a35734a4ae4f5a7b0d5560d5.tar.gz | |
Adds new feature: Auto-enable and host matching for client certificates
Diffstat (limited to 'src')
| -rw-r--r-- | src/browsertab.cpp | 83 | ||||
| -rw-r--r-- | src/browsertab.hpp | 1 | ||||
| -rw-r--r-- | src/cryptoidentity.cpp | 29 | ||||
| -rw-r--r-- | src/cryptoidentity.hpp | 6 | ||||
| -rw-r--r-- | src/identitycollection.cpp | 15 | ||||
| -rw-r--r-- | src/identitycollection.hpp | 3 |
6 files changed, 123 insertions, 14 deletions
diff --git a/src/browsertab.cpp b/src/browsertab.cpp index 3d16e08..0fe0af6 100644 --- a/src/browsertab.cpp +++ b/src/browsertab.cpp @@ -767,18 +767,7 @@ bool BrowserTab::trySetClientCertificate(const QString &query) return false; } - this->current_identity = dialog.identity(); - - if (not current_identity.isValid()) - { - QMessageBox::warning(this, "Kristall", "Failed to generate temporary crypto-identitiy"); - this->disableClientCertificate(); - return false; - } - - this->ui->enable_client_cert_button->setChecked(true); - - return true; + return this->enableClientCertificate(dialog.identity()); } void BrowserTab::resetClientCertificate() @@ -826,7 +815,7 @@ bool BrowserTab::startRequest(const QUrl &url, ProtocolHandler::RequestOptions o auto answer = QMessageBox::question( this, "Kristall", - QString("You requested a %1-URL with a client certificate, but these are not supported for this scheme. Continue?").arg(url.scheme()) + tr("You requested a %1-URL with a client certificate, but these are not supported for this scheme. Continue?").arg(url.scheme()) ); if(answer != QMessageBox::Yes) return false; @@ -840,7 +829,22 @@ bool BrowserTab::startRequest(const QUrl &url, ProtocolHandler::RequestOptions o auto answer = QMessageBox::question( this, "Kristall", - "You want to visit a new host, but have a client certificate enabled. This may be a risk to expose your identity to another host.\r\nDo you want to keep the certificate enabled?", + tr("You want to visit a new host, but have a client certificate enabled. This may be a risk to expose your identity to another host.\r\nDo you want to keep the certificate enabled?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No + ); + if(answer != QMessageBox::Yes) { + this->disableClientCertificate(); + } + } + + if(this->current_identity.isValid() and this->current_identity.isHostFiltered(url)) { + auto answer = QMessageBox::question( + this, + "Kristall", + tr("Your client certificate has a host filter enabled and this site does not match the host filter.\r\nNew URL: %1\r\nHost Filter: %2\r\nDo you want to keep the certificate enabled?") + .arg(url.toString(QUrl::FullyEncoded)) + .arg(this->current_identity.host_filter), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); @@ -848,6 +852,44 @@ bool BrowserTab::startRequest(const QUrl &url, ProtocolHandler::RequestOptions o this->disableClientCertificate(); } } + else if(not this->current_identity.isValid()) { + for(auto ident_ptr : global_identities.allIdentities()) + { + if(ident_ptr->isAutomaticallyEnabledOn(url)) { + + auto answer = QMessageBox::question( + this, + "Kristall", + tr("An automatic client certificate was detected for this site:\r\n%1\r\nDo you want to enable that certificate?") + .arg(ident_ptr->display_name), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No + ); + if(answer != QMessageBox::Yes) { + break; + } + + enableClientCertificate(*ident_ptr); + + break; + } + } + } + + if(this->current_identity.isValid()) { + if(not this->current_handler->enableClientCertificate(this->current_identity)) { + auto answer = QMessageBox::question( + this, + "Kristall", + tr("You requested a %1-URL with a client certificate, but these are not supported for this scheme. Continue?").arg(url.scheme()) + ); + if(answer != QMessageBox::Yes) + return false; + this->disableClientCertificate(); + } + } else { + this->disableClientCertificate(); + } this->is_internal_location = (url.scheme() == "about"); this->current_location = url; @@ -858,6 +900,19 @@ bool BrowserTab::startRequest(const QUrl &url, ProtocolHandler::RequestOptions o return this->current_handler->startRequest(url, options); } +bool BrowserTab::enableClientCertificate(const CryptoIdentity &ident) +{ + if (not ident.isValid()) + { + QMessageBox::warning(this, "Kristall", "Failed to generate temporary crypto-identitiy"); + this->disableClientCertificate(); + return false; + } + this->current_identity = ident; + this->ui->enable_client_cert_button->setChecked(true); + return true; +} + void BrowserTab::disableClientCertificate() { for(auto & handler : this->protocol_handlers) { diff --git a/src/browsertab.hpp b/src/browsertab.hpp index 7429fa2..e491f9e 100644 --- a/src/browsertab.hpp +++ b/src/browsertab.hpp @@ -129,6 +129,7 @@ private: bool startRequest(QUrl const & url, ProtocolHandler::RequestOptions options); + bool enableClientCertificate(CryptoIdentity const & ident); void disableClientCertificate(); public: diff --git a/src/cryptoidentity.cpp b/src/cryptoidentity.cpp index 921a422..2d9db59 100644 --- a/src/cryptoidentity.cpp +++ b/src/cryptoidentity.cpp @@ -1,2 +1,31 @@ #include "cryptoidentity.hpp" +#include <QUrl> +#include <QRegExp> +#include <cassert> + +bool CryptoIdentity::isHostFiltered(const QUrl &url) const +{ + if(this->host_filter.isEmpty()) + return false; + + QString url_text = url.toString(QUrl::FullyEncoded); + + QRegExp pattern { this->host_filter, Qt::CaseInsensitive, QRegExp::Wildcard }; + + return not pattern.exactMatch(url_text); +} + +bool CryptoIdentity::isAutomaticallyEnabledOn(const QUrl &url) const +{ + if(this->host_filter.isEmpty()) + return false; + if(not this->auto_enable) + return false; + + QString url_text = url.toString(QUrl::FullyEncoded); + + QRegExp pattern { this->host_filter, Qt::CaseInsensitive, QRegExp::Wildcard }; + + return pattern.exactMatch(url_text); +} diff --git a/src/cryptoidentity.hpp b/src/cryptoidentity.hpp index b693427..9c35cd0 100644 --- a/src/cryptoidentity.hpp +++ b/src/cryptoidentity.hpp @@ -35,6 +35,12 @@ struct CryptoIdentity bool isValid() const { return (not this->certificate.isNull()) and (not this->private_key.isNull()); } + + //! returns true if a host does not match the filter criterion + bool isHostFiltered(QUrl const & url) const; + + //! returns true when the identity should be enabled on url + bool isAutomaticallyEnabledOn(QUrl const & url) const; }; #endif // CRYPTOIDENTITIY_HPP diff --git a/src/identitycollection.cpp b/src/identitycollection.cpp index 2590cdf..1a39e76 100644 --- a/src/identitycollection.cpp +++ b/src/identitycollection.cpp @@ -244,6 +244,21 @@ bool IdentityCollection::deleteGroup(const QString &group_name) return false; } +QVector<const CryptoIdentity *> IdentityCollection::allIdentities() const +{ + QVector<const CryptoIdentity *> identities; + + for(auto const & group : this->root.children) + { + for(auto const & ident : group->children) + { + identities.append(&ident->as<IdentityNode>().identity); + } + } + + return identities; +} + QModelIndex IdentityCollection::index(int row, int column, const QModelIndex &parent) const { if (not hasIndex(row, column, parent)) diff --git a/src/identitycollection.hpp b/src/identitycollection.hpp index eecf3a4..7db879e 100644 --- a/src/identitycollection.hpp +++ b/src/identitycollection.hpp @@ -66,6 +66,9 @@ public: bool canDeleteGroup(QString const & group_name); bool deleteGroup(QString const & group_name); + //! Returns a list of non-mutable references to all contained identities + QVector<CryptoIdentity const *> allIdentities() const; + public: // Header: // QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; |
