From 8405fa16b738b6ef6a5920cd9d0f5735f8b62369 Mon Sep 17 00:00:00 2001
From: Gurmeen Bindra <gurmeen.bindra@isode.com>
Date: Wed, 9 Sep 2015 11:17:12 +0100
Subject: Fix swiften handling when client certificate is missing

This patch prevents SWIFTEN from logging in if provided with a missing PKCS12 file.
Before this patch, swiften would attempt a password based login using operator JID
and pwd of the P12 file when the P12 file was missing.
This patch fixes it by checking the certificate and not initialising session stream
and connection if the certificate is empty. It emits a disconnect with client
certificate load error. The string for certificate load error has been modified to
indicate a file or password invalid.

Test-information:
Tested by doing a certificate based bind to an XMPP server. Removed the PKCS#12
file and checked that swift gave a certificate error instead of doing pwd connect

Change-Id: I1869a13f1f7135b6606f7383cd4a0356ffd6931b

diff --git a/Sluift/Helpers.cpp b/Sluift/Helpers.cpp
index 9819f76..12d2f8f 100644
--- a/Sluift/Helpers.cpp
+++ b/Sluift/Helpers.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014 Isode Limited.
+ * Copyright (c) 2013-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
@@ -31,7 +31,7 @@ std::string Swift::getErrorString(const ClientError& error) {
 		case ClientError::SessionStartError: reason += "Error starting session"; break;
 		case ClientError::StreamError: reason += "Stream error"; break;
 		case ClientError::TLSError: reason += "Encryption error"; break;
-		case ClientError::ClientCertificateLoadError: reason += "Error loading certificate (Invalid password?)"; break;
+		case ClientError::ClientCertificateLoadError: reason += "Error loading certificate (Invalid file or password?)"; break;
 		case ClientError::ClientCertificateError: reason += "Certificate not authorized"; break;
 		case ClientError::UnknownCertificateError: reason += "Unknown certificate"; break;
 		case ClientError::CertificateCardRemoved: reason += "Certificate card removed"; break;
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index a0dde5b..dcdd22b 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -608,7 +608,7 @@ void MainController::performLoginFromCachedCredentials() {
 		presenceNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
 		eventNotifier_ = new EventNotifier(eventController_, notifier_, client_->getAvatarManager(), client_->getNickResolver());
 		eventNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
-		if (certificate_ && !certificate_->isNull()) {
+		if (certificate_) {
 			client_->setCertificate(certificate_);
 		}
 		boost::shared_ptr<Presence> presence(new Presence());
@@ -664,7 +664,7 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro
 			case ClientError::SessionStartError: message = QT_TRANSLATE_NOOP("", "Error starting session"); break;
 			case ClientError::StreamError: message = QT_TRANSLATE_NOOP("", "Stream error"); break;
 			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::ClientCertificateLoadError: message = QT_TRANSLATE_NOOP("", "Error loading certificate (Invalid file or 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;
 
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index fa9bd33..af64577 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -190,11 +190,18 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio
 	}
 	else {
 		assert(!connection_);
+		assert(!sessionStream_);
+
+		if (certificate_ && certificate_->isNull()) {
+			//certificate cannot be read so do not initailise session
+			onDisconnected(boost::optional<ClientError>(ClientError::ClientCertificateLoadError));
+			return;
+		}
+
 		connection_ = connection;
 
-		assert(!sessionStream_);
 		sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), options.tlsOptions);
-		if (certificate_ && !certificate_->isNull()) {
+		if (certificate_) {
 			sessionStream_->setTLSCertificate(certificate_);
 		}
 		sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1));
-- 
cgit v0.10.2-6-g49f6