From 846c4b9d2e7ec3214a3b13bdbbce77f70fede515 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 23 Mar 2012 11:54:03 +0000
Subject: Allow TLS errors to bubble further up the stack


diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index e923cff..b0a1778 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -518,6 +518,7 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro
 	else if (error) {
 		std::string message;
 		std::string certificateErrorMessage;
+		bool forceSignout = false;
 		switch(error->getType()) {
 			case ClientError::UnknownError: message = QT_TRANSLATE_NOOP("", "Unknown Error"); break;
 			case ClientError::DomainNameResolveError: message = QT_TRANSLATE_NOOP("", "Unable to find server"); break;
@@ -536,6 +537,7 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro
 			case ClientError::TLSError: message = QT_TRANSLATE_NOOP("", "Encryption error"); break;
 			case ClientError::ClientCertificateLoadError: message = QT_TRANSLATE_NOOP("", "Error loading certificate (Invalid password?)"); break;
 			case ClientError::ClientCertificateError: message = QT_TRANSLATE_NOOP("", "Certificate not authorized"); break;
+			case ClientError::CertificateCardRemoved: message = QT_TRANSLATE_NOOP("", "Certificate card removed"); forceSignout = true; break;
 
 			case ClientError::UnknownCertificateError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Unknown certificate"); break;
 			case ClientError::CertificateExpiredError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate has expired"); break;
@@ -564,7 +566,7 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro
 		if (forceReconnectAfterCertificateTrust) {
 			performLoginFromCachedCredentials();
 		}
-		else if (!rosterController_) { //hasn't been logged in yet
+		else if (forceSignout || !rosterController_) { //hasn't been logged in yet or permanent error
 			signOut();
 			loginWindow_->setMessage(message);
 			loginWindow_->setIsLoggingIn(false);
diff --git a/Swiften/Client/ClientError.h b/Swiften/Client/ClientError.h
index 2f2d2af..a4dc040 100644
--- a/Swiften/Client/ClientError.h
+++ b/Swiften/Client/ClientError.h
@@ -28,6 +28,9 @@ namespace Swift {
 				ClientCertificateLoadError,
 				ClientCertificateError,
 
+				// Certifate on smartcard was removed
+				CertificateCardRemoved,
+
 				// Certificate verification errors
 				UnknownCertificateError,
 				CertificateExpiredError,
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 14481c6..45d80aa 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -15,6 +15,7 @@
 #include <Swiften/Base/Algorithm.h>
 #include <Swiften/Client/ClientSession.h>
 #include <Swiften/TLS/CertificateVerificationError.h>
+#include <Swiften/TLS/TLSError.h>
 #include <Swiften/Network/ChainedConnector.h>
 #include <Swiften/Network/NetworkFactories.h>
 #include <Swiften/Network/ProxyProvider.h>
@@ -217,21 +218,31 @@ void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {
 					break;
 			}
 		}
-		else if (boost::shared_ptr<SessionStream::Error> actualError = boost::dynamic_pointer_cast<SessionStream::Error>(error)) {
+		else if (boost::shared_ptr<TLSError> actualError = boost::dynamic_pointer_cast<TLSError>(error)) {
+			switch(actualError->getType()) {
+				case TLSError::CertificateCardRemoved:
+					clientError = ClientError(ClientError::CertificateCardRemoved);
+					break;
+				default:
+					clientError = ClientError(ClientError::TLSError);
+					break;
+			}
+		}
+		else if (boost::shared_ptr<SessionStream::SessionStreamError> actualError = boost::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) {
 			switch(actualError->type) {
-				case SessionStream::Error::ParseError:
+				case SessionStream::SessionStreamError::ParseError:
 					clientError = ClientError(ClientError::XMLError);
 					break;
-				case SessionStream::Error::TLSError:
+				case SessionStream::SessionStreamError::TLSError:
 					clientError = ClientError(ClientError::TLSError);
 					break;
-				case SessionStream::Error::InvalidTLSCertificateError:
+				case SessionStream::SessionStreamError::InvalidTLSCertificateError:
 					clientError = ClientError(ClientError::ClientCertificateLoadError);
 					break;
-				case SessionStream::Error::ConnectionReadError:
+				case SessionStream::SessionStreamError::ConnectionReadError:
 					clientError = ClientError(ClientError::ConnectionReadError);
 					break;
-				case SessionStream::Error::ConnectionWriteError:
+				case SessionStream::SessionStreamError::ConnectionWriteError:
 					clientError = ClientError(ClientError::ConnectionWriteError);
 					break;
 			}
diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp
index a6d5a3a..6793643 100644
--- a/Swiften/Client/UnitTest/ClientSessionTest.cpp
+++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp
@@ -420,11 +420,11 @@ class ClientSessionTest : public CppUnit::TestFixture {
 				}
 
 				void breakConnection() {
-					onClosed(boost::make_shared<SessionStream::Error>(SessionStream::Error::ConnectionReadError));
+					onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError));
 				}
 
 				void breakTLS() {
-					onClosed(boost::make_shared<SessionStream::Error>(SessionStream::Error::TLSError));
+					onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::TLSError));
 				}
 
 
diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp
index e630ddf..e11d2b0 100644
--- a/Swiften/Component/CoreComponent.cpp
+++ b/Swiften/Component/CoreComponent.cpp
@@ -114,23 +114,23 @@ void CoreComponent::handleSessionFinished(boost::shared_ptr<Error> error) {
 					break;
 			}
 		}
-		else if (boost::shared_ptr<SessionStream::Error> actualError = boost::dynamic_pointer_cast<SessionStream::Error>(error)) {
+		else if (boost::shared_ptr<SessionStream::SessionStreamError> actualError = boost::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) {
 			switch(actualError->type) {
-				case SessionStream::Error::ParseError:
+				case SessionStream::SessionStreamError::ParseError:
 					componentError = ComponentError(ComponentError::XMLError);
 					break;
-				case SessionStream::Error::TLSError:
+				case SessionStream::SessionStreamError::TLSError:
 					assert(false);
 					componentError = ComponentError(ComponentError::UnknownError);
 					break;
-				case SessionStream::Error::InvalidTLSCertificateError:
+				case SessionStream::SessionStreamError::InvalidTLSCertificateError:
 					assert(false);
 					componentError = ComponentError(ComponentError::UnknownError);
 					break;
-				case SessionStream::Error::ConnectionReadError:
+				case SessionStream::SessionStreamError::ConnectionReadError:
 					componentError = ComponentError(ComponentError::ConnectionReadError);
 					break;
-				case SessionStream::Error::ConnectionWriteError:
+				case SessionStream::SessionStreamError::ConnectionWriteError:
 					componentError = ComponentError(ComponentError::ConnectionWriteError);
 					break;
 			}
diff --git a/Swiften/Component/UnitTest/ComponentSessionTest.cpp b/Swiften/Component/UnitTest/ComponentSessionTest.cpp
index 9763c7f..da9ca7d 100644
--- a/Swiften/Component/UnitTest/ComponentSessionTest.cpp
+++ b/Swiften/Component/UnitTest/ComponentSessionTest.cpp
@@ -159,7 +159,7 @@ class ComponentSessionTest : public CppUnit::TestFixture {
 				}
 
 				void breakConnection() {
-					onClosed(boost::make_shared<SessionStream::Error>(SessionStream::Error::ConnectionReadError));
+					onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError));
 				}
 
 				void sendStreamStart() {
diff --git a/Swiften/Network/BOSHConnection.h b/Swiften/Network/BOSHConnection.h
index d9fa016..a2abfcd 100644
--- a/Swiften/Network/BOSHConnection.h
+++ b/Swiften/Network/BOSHConnection.h
@@ -36,13 +36,13 @@ namespace Swift {
 	class XMLParserFactory;
 	class TLSContextFactory;
 
-		class BOSHError : public SessionStream::Error {
+		class BOSHError : public SessionStream::SessionStreamError {
 				public:
 					enum Type {BadRequest, HostGone, HostUnknown, ImproperAddressing, 
 						  InternalServerError, ItemNotFound, OtherRequest, PolicyViolation, 
 						  RemoteConnectionFailed, RemoteStreamError, SeeOtherURI, SystemShutdown, UndefinedCondition,
 						  NoError};
-					BOSHError(Type type) : SessionStream::Error(SessionStream::Error::ConnectionReadError), type(type) {}
+					BOSHError(Type type) : SessionStream::SessionStreamError(SessionStream::SessionStreamError::ConnectionReadError), type(type) {}
 					Type getType() {return type;}
 					typedef boost::shared_ptr<BOSHError> ref;
 				private:
diff --git a/Swiften/Session/BOSHSessionStream.cpp b/Swiften/Session/BOSHSessionStream.cpp
index ce5df35..237a394 100644
--- a/Swiften/Session/BOSHSessionStream.cpp
+++ b/Swiften/Session/BOSHSessionStream.cpp
@@ -163,7 +163,7 @@ void BOSHSessionStream::handleElementReceived(boost::shared_ptr<Element> element
 
 void BOSHSessionStream::handleXMPPError() {
 	available = false;
-	onClosed(boost::make_shared<Error>(Error::ParseError));
+	onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::ParseError));
 }
 
 void BOSHSessionStream::handlePoolSessionStarted() {
diff --git a/Swiften/Session/BasicSessionStream.cpp b/Swiften/Session/BasicSessionStream.cpp
index f50c5d5..b49ffc9 100644
--- a/Swiften/Session/BasicSessionStream.cpp
+++ b/Swiften/Session/BasicSessionStream.cpp
@@ -111,11 +111,11 @@ void BasicSessionStream::addTLSEncryption() {
 	assert(available);
 	tlsLayer = new TLSLayer(tlsContextFactory);
 	if (hasTLSCertificate() && !tlsLayer->setClientCertificate(getTLSCertificate())) {
-		onClosed(boost::make_shared<Error>(Error::InvalidTLSCertificateError));
+		onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::InvalidTLSCertificateError));
 	}
 	else {
 		streamStack->addLayer(tlsLayer);
-		tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this));
+		tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this, _1));
 		tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, this));
 		tlsLayer->connect();
 	}
@@ -173,28 +173,28 @@ void BasicSessionStream::handleElementReceived(boost::shared_ptr<Element> elemen
 
 void BasicSessionStream::handleXMPPError() {
 	available = false;
-	onClosed(boost::make_shared<Error>(Error::ParseError));
+	onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::ParseError));
 }
 
 void BasicSessionStream::handleTLSConnected() {
 	onTLSEncrypted();
 }
 
-void BasicSessionStream::handleTLSError() {
+void BasicSessionStream::handleTLSError(boost::shared_ptr<TLSError> error) {
 	available = false;
-	onClosed(boost::make_shared<Error>(Error::TLSError));
+	onClosed(error);
 }
 
 void BasicSessionStream::handleConnectionFinished(const boost::optional<Connection::Error>& error) {
 	available = false;
 	if (error == Connection::ReadError) {
-		onClosed(boost::make_shared<Error>(Error::ConnectionReadError));
+		onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::ConnectionReadError));
 	}
 	else if (error) {
-		onClosed(boost::make_shared<Error>(Error::ConnectionWriteError));
+		onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::ConnectionWriteError));
 	}
 	else {
-		onClosed(boost::shared_ptr<Error>());
+		onClosed(boost::shared_ptr<SessionStreamError>());
 	}
 }
 
diff --git a/Swiften/Session/BasicSessionStream.h b/Swiften/Session/BasicSessionStream.h
index b0c4331..e1f32f4 100644
--- a/Swiften/Session/BasicSessionStream.h
+++ b/Swiften/Session/BasicSessionStream.h
@@ -12,6 +12,7 @@
 #include <Swiften/Network/Connection.h>
 #include <Swiften/Session/SessionStream.h>
 #include <Swiften/Elements/StreamType.h>
+#include <Swiften/TLS/TLSError.h>
 
 namespace Swift {
 	class TLSContextFactory;
@@ -65,7 +66,7 @@ namespace Swift {
 			void handleConnectionFinished(const boost::optional<Connection::Error>& error);
 			void handleXMPPError();
 			void handleTLSConnected();
-			void handleTLSError();
+			void handleTLSError(boost::shared_ptr<TLSError>);
 			void handleStreamStartReceived(const ProtocolHeader&);
 			void handleElementReceived(boost::shared_ptr<Element>);
 			void handleDataRead(const SafeByteArray& data);
diff --git a/Swiften/Session/SessionStream.h b/Swiften/Session/SessionStream.h
index 2ff2a56..32cb6b6 100644
--- a/Swiften/Session/SessionStream.h
+++ b/Swiften/Session/SessionStream.h
@@ -21,7 +21,7 @@
 namespace Swift {
 	class SessionStream {
 		public:
-			class Error : public Swift::Error {
+			class SessionStreamError : public Swift::Error {
 				public:
 					enum Type {
 						ParseError,
@@ -31,7 +31,7 @@ namespace Swift {
 						ConnectionWriteError
 					};
 
-					Error(Type type) : type(type) {}
+					SessionStreamError(Type type) : type(type) {}
 
 					Type type;
 			};
diff --git a/Swiften/StreamStack/TLSLayer.h b/Swiften/StreamStack/TLSLayer.h
index 5aab26a..ce0c89b 100644
--- a/Swiften/StreamStack/TLSLayer.h
+++ b/Swiften/StreamStack/TLSLayer.h
@@ -11,6 +11,7 @@
 #include <Swiften/TLS/Certificate.h>
 #include <Swiften/TLS/CertificateWithKey.h>
 #include <Swiften/TLS/CertificateVerificationError.h>
+#include <Swiften/TLS/TLSError.h>
 
 namespace Swift {
 	class TLSContext;
@@ -35,7 +36,7 @@ namespace Swift {
 			}
 
 		public:
-			boost::signal<void ()> onError;
+			boost::signal<void (boost::shared_ptr<TLSError>)> onError;
 			boost::signal<void ()> onConnected;
 
 		private:
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
index 54addef..8c03052 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
@@ -132,7 +132,7 @@ void OpenSSLContext::doConnect() {
 			break;
 		default:
 			state_ = Error;
-			onError();
+			onError(boost::make_shared<TLSError>());
 	}
 }
 
@@ -166,7 +166,7 @@ void OpenSSLContext::handleDataFromApplication(const SafeByteArray& data) {
 	}
 	else {
 		state_ = Error;
-		onError();
+		onError(boost::make_shared<TLSError>());
 	}
 }
 
@@ -182,7 +182,7 @@ void OpenSSLContext::sendPendingDataToApplication() {
 	}
 	if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) {
 		state_ = Error;
-		onError();
+		onError(boost::make_shared<TLSError>());
 	}
 }
 
diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp
index 9be1ded..4f8f36f 100644
--- a/Swiften/TLS/Schannel/SchannelContext.cpp
+++ b/Swiften/TLS/Schannel/SchannelContext.cpp
@@ -473,7 +473,7 @@ void SchannelContext::indicateError()
 {
 	m_state = Error;
 	m_receivedData.clear();
-	onError();
+	onError(boost::make_shared<TLSError>());
 }
 
 //------------------------------------------------------------------------
diff --git a/Swiften/TLS/TLSContext.h b/Swiften/TLS/TLSContext.h
index 9dee902..5640fe1 100644
--- a/Swiften/TLS/TLSContext.h
+++ b/Swiften/TLS/TLSContext.h
@@ -13,6 +13,7 @@
 #include <Swiften/TLS/Certificate.h>
 #include <Swiften/TLS/CertificateWithKey.h>
 #include <Swiften/TLS/CertificateVerificationError.h>
+#include <Swiften/TLS/TLSError.h>
 
 namespace Swift {
 
@@ -35,7 +36,7 @@ namespace Swift {
 		public:
 			boost::signal<void (const SafeByteArray&)> onDataForNetwork;
 			boost::signal<void (const SafeByteArray&)> onDataForApplication;
-			boost::signal<void ()> onError;
+			boost::signal<void (boost::shared_ptr<TLSError>)> onError;
 			boost::signal<void ()> onConnected;
 	};
 }
-- 
cgit v0.10.2-6-g49f6