From 0863ece69f6490602e90b22c0dd17189bd8bf5a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 13 Dec 2010 21:08:40 +0100
Subject: Extend the certificate accept dialog & login after accept.


diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index f4fdff6..74e381a 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -409,6 +409,7 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro
 	}
 	else if (error) {
 		String message;
+		String certificateErrorMessage;
 		switch(error->getType()) {
 			case ClientError::UnknownError: message = "Unknown Error"; break;
 			case ClientError::DomainNameResolveError: message = "Unable to find server"; break;
@@ -428,26 +429,35 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro
 			case ClientError::ClientCertificateLoadError: message = "Error loading certificate (Invalid password?)"; break;
 			case ClientError::ClientCertificateError: message = "Certificate not authorized"; break;
 
-			case ClientError::UnknownCertificateError:
-			case ClientError::CertificateExpiredError:
-			case ClientError::CertificateNotYetValidError:
-			case ClientError::CertificateSelfSignedError:
-			case ClientError::CertificateRejectedError:
-			case ClientError::CertificateUntrustedError:
-			case ClientError::InvalidCertificatePurposeError:
-			case ClientError::CertificatePathLengthExceededError:
-			case ClientError::InvalidCertificateSignatureError:
-			case ClientError::InvalidCAError:
-			case ClientError::InvalidServerIdentityError:
-				// FIXME: Popup a dialog
-				message = "Certificate error (" + boost::lexical_cast<std::string>(error->getType()) + ")";
-				if (loginWindow_->askUserToTrustCertificatePermanently(message)) {
-					// FIXME: Only do this if the user accepts the certificate
-					certificateStorage_->addCertificate(certificateTrustChecker_->getLastCertificate());
-				}
-				break;
+			case ClientError::UnknownCertificateError: certificateErrorMessage = "Unknown certificate"; break;
+			case ClientError::CertificateExpiredError: certificateErrorMessage = "Certificate has expired"; break;
+			case ClientError::CertificateNotYetValidError: certificateErrorMessage = "Certificate is not yet valid"; break;
+			case ClientError::CertificateSelfSignedError: certificateErrorMessage = "Certificate is self-signed"; break;
+			case ClientError::CertificateRejectedError: certificateErrorMessage = "Certificate has been rejected"; break;
+			case ClientError::CertificateUntrustedError: certificateErrorMessage = "Certificate is not trusted"; break;
+			case ClientError::InvalidCertificatePurposeError: certificateErrorMessage = "Certificate cannot be used for encryptig your connection"; break;
+			case ClientError::CertificatePathLengthExceededError: certificateErrorMessage = "Certificate path length constraint exceeded"; break;
+			case ClientError::InvalidCertificateSignatureError: certificateErrorMessage = "Invalid certificate signature"; break;
+			case ClientError::InvalidCAError: certificateErrorMessage = "Invalid Certificate Authority"; break;
+			case ClientError::InvalidServerIdentityError: certificateErrorMessage = "Certificate does not match the host identity"; break;
+
+		}
+		bool forceReconnectAfterCertificateTrust = false;
+		if (!certificateErrorMessage.isEmpty()) {
+			Certificate::ref certificate = certificateTrustChecker_->getLastCertificate();
+			if (loginWindow_->askUserToTrustCertificatePermanently(certificateErrorMessage, certificate)) {
+				certificateStorage_->addCertificate(certificate);
+				forceReconnectAfterCertificateTrust = true;
+			}
+			else {
+				message = "Certificate error";
+			}
+		}
+
+		if (forceReconnectAfterCertificateTrust) {
+			performLoginFromCachedCredentials();
 		}
-		if (!rosterController_) { //hasn't been logged in yet
+		else if (!rosterController_) { //hasn't been logged in yet
 			signOut();
 			loginWindow_->setMessage(message);
 		} else {
diff --git a/Swift/Controllers/UIInterfaces/LoginWindow.h b/Swift/Controllers/UIInterfaces/LoginWindow.h
index e9ea92f..a25cdb9 100644
--- a/Swift/Controllers/UIInterfaces/LoginWindow.h
+++ b/Swift/Controllers/UIInterfaces/LoginWindow.h
@@ -4,14 +4,14 @@
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
-#ifndef SWIFTEN_LoginWindow_H
-#define SWIFTEN_LoginWindow_H
-
-#include "Swiften/Base/String.h"
+#pragma once
 
 #include "Swiften/Base/boost_bsignals.h"
 #include <boost/shared_ptr.hpp>
 
+#include <Swiften/Base/String.h>
+#include <Swiften/TLS/Certificate.h>
+
 namespace Swift {
 	class MainWindow;
 	class LoginWindow {
@@ -27,11 +27,9 @@ 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 String& message) = 0;
+			virtual bool askUserToTrustCertificatePermanently(const String& message, Certificate::ref) = 0;
 
 			boost::signal<void ()> onCancelLoginRequest;
 			boost::signal<void ()> onQuitRequest;
 	};
 }
-#endif
-
diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp
index 42641ba..c1f4f24 100644
--- a/Swift/QtUI/QtLoginWindow.cpp
+++ b/Swift/QtUI/QtLoginWindow.cpp
@@ -391,12 +391,18 @@ void QtLoginWindow::moveEvent(QMoveEvent*) {
 	emit geometryChanged();	
 }
 
-bool QtLoginWindow::askUserToTrustCertificatePermanently(const String& message) {
+bool QtLoginWindow::askUserToTrustCertificatePermanently(const String& message, Certificate::ref certificate) {
 	QMessageBox dialog(this);
-	dialog.setText("Invalid server certificate.");
-	dialog.setInformativeText("The certificate presented by the server is not valid. " + P2QSTRING(message) + " Would you like to permanently trust this certificate? This must only be done if you know it is correct.");
+
+	dialog.setText("The certificate presented by the server is not valid.");
+	dialog.setInformativeText(P2QSTRING(message) + "\n\nWould you like to permanently trust this certificate? This must only be done if you know it is correct.");
+
+	QString detailedText = "Subject: " + P2QSTRING(certificate->getSubjectName());
+	dialog.setDetailedText(detailedText);
+
 	dialog.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
 	dialog.setDefaultButton(QMessageBox::No);
+
 	return dialog.exec() == QMessageBox::Yes;
 }
 
diff --git a/Swift/QtUI/QtLoginWindow.h b/Swift/QtUI/QtLoginWindow.h
index 3978d73..0efd377 100644
--- a/Swift/QtUI/QtLoginWindow.h
+++ b/Swift/QtUI/QtLoginWindow.h
@@ -39,7 +39,7 @@ namespace Swift {
 			static QRect defaultPosition();
 			void setGentleGeometry(const QRect&);
 			void selectUser(const String& user);
-			bool askUserToTrustCertificatePermanently(const String& message);
+			bool askUserToTrustCertificatePermanently(const String& message, Certificate::ref certificate);
 
 			virtual void quit();
 
-- 
cgit v0.10.2-6-g49f6