diff options
| -rw-r--r-- | Swift/Controllers/MainController.cpp | 6 | ||||
| -rw-r--r-- | Swift/Controllers/Storages/CertificateStorageTrustChecker.h | 12 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/LoginWindow.h | 2 | ||||
| -rw-r--r-- | Swift/QtUI/QtLoginWindow.cpp | 21 | ||||
| -rw-r--r-- | Swift/QtUI/QtLoginWindow.h | 2 | ||||
| -rw-r--r-- | Swift/QtUI/QtMainWindow.cpp | 8 | ||||
| -rw-r--r-- | Swift/QtUI/QtMainWindow.h | 1 | ||||
| -rw-r--r-- | Swiften/Client/ClientSession.cpp | 9 | ||||
| -rw-r--r-- | Swiften/Client/ClientSession.h | 2 | ||||
| -rw-r--r-- | Swiften/TLS/BlindCertificateTrustChecker.h | 2 | ||||
| -rw-r--r-- | Swiften/TLS/CertificateTrustChecker.h | 6 | 
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;  	};  } | 
 Swift
 Swift