summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/MainController.cpp6
-rw-r--r--Swift/Controllers/Storages/CertificateStorageTrustChecker.h12
-rw-r--r--Swift/Controllers/UIInterfaces/LoginWindow.h2
-rw-r--r--Swift/QtUI/QtLoginWindow.cpp21
-rw-r--r--Swift/QtUI/QtLoginWindow.h2
-rw-r--r--Swift/QtUI/QtMainWindow.cpp8
-rw-r--r--Swift/QtUI/QtMainWindow.h1
-rw-r--r--Swiften/Client/ClientSession.cpp9
-rw-r--r--Swiften/Client/ClientSession.h2
-rw-r--r--Swiften/TLS/BlindCertificateTrustChecker.h2
-rw-r--r--Swiften/TLS/CertificateTrustChecker.h6
11 files changed, 43 insertions, 28 deletions
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 40b4ded..cb43057 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -559,9 +559,9 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro
}
bool forceReconnectAfterCertificateTrust = false;
if (!certificateErrorMessage.empty()) {
- Certificate::ref certificate = certificateTrustChecker_->getLastCertificate();
- if (loginWindow_->askUserToTrustCertificatePermanently(certificateErrorMessage, certificate)) {
- certificateStorage_->addCertificate(certificate);
+ std::vector<Certificate::ref> certificates = certificateTrustChecker_->getLastCertificateChain();
+ if (!certificates.empty() && loginWindow_->askUserToTrustCertificatePermanently(certificateErrorMessage, certificates)) {
+ certificateStorage_->addCertificate(certificates[0]);
forceReconnectAfterCertificateTrust = true;
}
else {
diff --git a/Swift/Controllers/Storages/CertificateStorageTrustChecker.h b/Swift/Controllers/Storages/CertificateStorageTrustChecker.h
index 40838dd..a73590a 100644
--- a/Swift/Controllers/Storages/CertificateStorageTrustChecker.h
+++ b/Swift/Controllers/Storages/CertificateStorageTrustChecker.h
@@ -18,17 +18,17 @@ namespace Swift {
CertificateStorageTrustChecker(CertificateStorage* storage) : storage(storage) {
}
- virtual bool isCertificateTrusted(Certificate::ref certificate) {
- lastCertificate = certificate;
- return storage->hasCertificate(certificate);
+ virtual bool isCertificateTrusted(Certificate::ref, const std::vector<Certificate::ref>& certificateChain) {
+ lastCertificateChain = std::vector<Certificate::ref>(certificateChain.begin(), certificateChain.end());
+ return certificateChain.empty() ? false : storage->hasCertificate(certificateChain[0]);
}
- Certificate::ref getLastCertificate() const {
- return lastCertificate;
+ const std::vector<Certificate::ref>& getLastCertificateChain() const {
+ return lastCertificateChain;
}
private:
CertificateStorage* storage;
- Certificate::ref lastCertificate;
+ std::vector<Certificate::ref> lastCertificateChain;
};
}
diff --git a/Swift/Controllers/UIInterfaces/LoginWindow.h b/Swift/Controllers/UIInterfaces/LoginWindow.h
index bbbbe35..f1c2ce1 100644
--- a/Swift/Controllers/UIInterfaces/LoginWindow.h
+++ b/Swift/Controllers/UIInterfaces/LoginWindow.h
@@ -31,7 +31,7 @@ namespace Swift {
virtual void setLoginAutomatically(bool loginAutomatically) = 0;
virtual void quit() = 0;
/** Blocking request whether a cert should be permanently trusted.*/
- virtual bool askUserToTrustCertificatePermanently(const std::string& message, Certificate::ref) = 0;
+ virtual bool askUserToTrustCertificatePermanently(const std::string& message, const std::vector<Certificate::ref>& certificateChain) = 0;
boost::signal<void ()> onCancelLoginRequest;
boost::signal<void ()> onQuitRequest;
diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp
index 094f96c..42ebe39 100644
--- a/Swift/QtUI/QtLoginWindow.cpp
+++ b/Swift/QtUI/QtLoginWindow.cpp
@@ -506,20 +506,25 @@ void QtLoginWindow::moveEvent(QMoveEvent*) {
emit geometryChanged();
}
-bool QtLoginWindow::askUserToTrustCertificatePermanently(const std::string& message, Certificate::ref certificate) {
+bool QtLoginWindow::askUserToTrustCertificatePermanently(const std::string& message, const std::vector<Certificate::ref>& certificates) {
QMessageBox dialog(this);
dialog.setText(tr("The certificate presented by the server is not valid."));
dialog.setInformativeText(P2QSTRING(message) + "\n\n" + tr("Would you like to permanently trust this certificate? This must only be done if you know it is correct."));
- QString detailedText = tr("Subject: %1").arg(P2QSTRING(certificate->getSubjectName())) + "\n";
- detailedText += tr("SHA-1 Fingerprint: %1").arg(P2QSTRING(certificate->getSHA1Fingerprint()));
- dialog.setDetailedText(detailedText);
-
- dialog.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+ dialog.addButton("Show Certificate", QMessageBox::HelpRole);
+ dialog.addButton(QMessageBox::Yes);
+ dialog.addButton(QMessageBox::No);
dialog.setDefaultButton(QMessageBox::No);
-
- return dialog.exec() == QMessageBox::Yes;
+ while (true) {
+ int result = dialog.exec();
+ if (result == QMessageBox::Yes || result == QMessageBox::No) {
+ return result == QMessageBox::Yes;
+ }
+ // FIXME: This isn't very nice, because the dialog disappears every time. We actually need a real
+ // dialog with a custom button.
+ QtMainWindow::openCertificateDialog(certificates, &dialog);
+ }
}
}
diff --git a/Swift/QtUI/QtLoginWindow.h b/Swift/QtUI/QtLoginWindow.h
index 8f50a35..572902e 100644
--- a/Swift/QtUI/QtLoginWindow.h
+++ b/Swift/QtUI/QtLoginWindow.h
@@ -48,7 +48,7 @@ namespace Swift {
virtual void setLoginAutomatically(bool loginAutomatically);
virtual void setIsLoggingIn(bool loggingIn);
void selectUser(const std::string& user);
- bool askUserToTrustCertificatePermanently(const std::string& message, Certificate::ref certificate);
+ bool askUserToTrustCertificatePermanently(const std::string& message, const std::vector<Certificate::ref>& certificate);
void hide();
QtMenus getMenus() const;
virtual void quit();
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 547f22b..ec05684 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -273,10 +273,14 @@ void QtMainWindow::setStreamEncryptionStatus(bool tlsInPlaceAndValid) {
}
void QtMainWindow::openCertificateDialog(const std::vector<Certificate::ref>& chain) {
+ openCertificateDialog(chain, this);
+}
+
+void QtMainWindow::openCertificateDialog(const std::vector<Certificate::ref>& chain, QWidget* parent) {
#if defined(SWIFTEN_PLATFORM_MACOSX)
- CocoaUIHelpers::displayCertificateChainAsSheet(this, chain);
+ CocoaUIHelpers::displayCertificateChainAsSheet(parent, chain);
#elif defined(SWIFTEN_PLATFORM_WINDOWS)
- WinUIHelpers::displayCertificateChainAsSheet(this,chain);
+ WinUIHelpers::displayCertificateChainAsSheet(parent, chain);
#else
#pragma message ("No certificate dialog available on this platform.")
#endif
diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h
index c725d08..25d9ace 100644
--- a/Swift/QtUI/QtMainWindow.h
+++ b/Swift/QtUI/QtMainWindow.h
@@ -47,6 +47,7 @@ namespace Swift {
void setConnecting();
void setStreamEncryptionStatus(bool tlsInPlaceAndValid);
void openCertificateDialog(const std::vector<Certificate::ref>& chain);
+ static void openCertificateDialog(const std::vector<Certificate::ref>& chain, QWidget* parent);
QtEventWindow* getEventWindow();
QtChatListWindow* getChatListWindow();
void setRosterModel(Roster* roster);
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index 8be8a8c..c2dc3ae 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -371,9 +371,10 @@ void ClientSession::handleTLSEncrypted() {
checkState(Encrypting);
Certificate::ref certificate = stream->getPeerCertificate();
+ std::vector<Certificate::ref> certificateChain = stream->getPeerCertificateChain();
boost::shared_ptr<CertificateVerificationError> verificationError = stream->getPeerCertificateVerificationError();
if (verificationError) {
- checkTrustOrFinish(certificate, verificationError);
+ checkTrustOrFinish(certificate, certificateChain, verificationError);
}
else {
ServerIdentityVerifier identityVerifier(localJID);
@@ -381,13 +382,13 @@ void ClientSession::handleTLSEncrypted() {
continueAfterTLSEncrypted();
}
else {
- checkTrustOrFinish(certificate, boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity));
+ checkTrustOrFinish(certificate, certificateChain, boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity));
}
}
}
-void ClientSession::checkTrustOrFinish(Certificate::ref certificate, boost::shared_ptr<CertificateVerificationError> error) {
- if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificate)) {
+void ClientSession::checkTrustOrFinish(Certificate::ref certificate, const std::vector<Certificate::ref>& certificateChain, boost::shared_ptr<CertificateVerificationError> error) {
+ if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificate, certificateChain)) {
continueAfterTLSEncrypted();
}
else {
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h
index b67b23d..9c4b980 100644
--- a/Swiften/Client/ClientSession.h
+++ b/Swiften/Client/ClientSession.h
@@ -154,7 +154,7 @@ namespace Swift {
void handleStanzaAcked(boost::shared_ptr<Stanza> stanza);
void ack(unsigned int handledStanzasCount);
void continueAfterTLSEncrypted();
- void checkTrustOrFinish(Certificate::ref certificate, boost::shared_ptr<CertificateVerificationError> error);
+ void checkTrustOrFinish(Certificate::ref certificate, const std::vector<Certificate::ref>& certificateChain, boost::shared_ptr<CertificateVerificationError> error);
private:
JID localJID;
diff --git a/Swiften/TLS/BlindCertificateTrustChecker.h b/Swiften/TLS/BlindCertificateTrustChecker.h
index 3177322..9ed7ff2 100644
--- a/Swiften/TLS/BlindCertificateTrustChecker.h
+++ b/Swiften/TLS/BlindCertificateTrustChecker.h
@@ -19,7 +19,7 @@ namespace Swift {
*/
class BlindCertificateTrustChecker : public CertificateTrustChecker {
public:
- virtual bool isCertificateTrusted(Certificate::ref) {
+ virtual bool isCertificateTrusted(Certificate::ref, const std::vector<Certificate::ref>&) {
return true;
}
};
diff --git a/Swiften/TLS/CertificateTrustChecker.h b/Swiften/TLS/CertificateTrustChecker.h
index 06c0c32..91cc530 100644
--- a/Swiften/TLS/CertificateTrustChecker.h
+++ b/Swiften/TLS/CertificateTrustChecker.h
@@ -10,6 +10,7 @@
#include <string>
#include <Swiften/TLS/Certificate.h>
+#include <vector>
namespace Swift {
/**
@@ -23,7 +24,10 @@ namespace Swift {
* This method is called to find out whether a certificate is
* trusted. This usually happens when a certificate's validation
* fails, to check whether to proceed with the connection or not.
+ *
+ * certificateChain contains the chain of certificates, if available.
+ * This chain includes certificate.
*/
- virtual bool isCertificateTrusted(Certificate::ref certificate) = 0;
+ virtual bool isCertificateTrusted(Certificate::ref certificate, const std::vector<Certificate::ref>& certificateChain) = 0;
};
}