From 23481aa1306b7d77b18be3b1c8764cccdc80e32d Mon Sep 17 00:00:00 2001
From: Mili Verma <mili.verma@isode.com>
Date: Thu, 9 Jul 2015 09:40:05 +0100
Subject: Enable SSO

Add a hidden option to enable single sign on. When that is enabled, ensure that
the user only enters the domain name and that the JID is constructed from the
Windows log-on credentials.

Test-information:
Tested on Windows.
Unit tests pass.

Change-Id: Ia5592a3893f0807a3801b515c8fcddb580c9ef8d

diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 95094f2..a65a18a 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -40,6 +40,10 @@
 #include <Swiften/Client/ClientBlockListManager.h>
 #include <Swiften/Crypto/CryptoProvider.h>
 
+#ifdef SWIFTEN_PLATFORM_WIN32
+#include <Swiften/SASL/WindowsAuthentication.h>
+#endif
+
 #include <SwifTools/Dock/Dock.h>
 #include <SwifTools/Notifier/TogglableNotifier.h>
 #include <SwifTools/Idle/IdleDetector.h>
@@ -181,6 +185,11 @@ MainController::MainController(
 			std::string certificate = profileSettings.getStringSetting("certificate");
 			std::string jid = profileSettings.getStringSetting("jid");
 			ClientOptions clientOptions = parseClientOptions(profileSettings.getStringSetting("options"));
+
+#ifdef SWIFTEN_PLATFORM_WIN32
+			clientOptions.singleSignOn = settings_->getSetting(SettingConstants::SINGLE_SIGN_ON);
+#endif
+
 			loginWindow_->addAvailableAccount(jid, password, certificate, clientOptions);
 			if (jid == selectedLoginJID) {
 				cachedPassword = password;
@@ -511,10 +520,32 @@ void MainController::handleShowCertificateRequest() {
 
 void MainController::handleLoginRequest(const std::string &username, const std::string &password, const std::string& certificatePath, CertificateWithKey::ref certificate, const ClientOptions& options, bool remember, bool loginAutomatically) {
 	jid_ = JID(username);
-	if (!jid_.isValid() || jid_.getNode().empty()) {
+	if (options.singleSignOn && (!jid_.isValid() || !jid_.getNode().empty())) {
+		loginWindow_->setMessage(QT_TRANSLATE_NOOP("", "User address invalid. User address should be of the form 'wonderland.lit'"));
+		loginWindow_->setIsLoggingIn(false);
+	} else if (!options.singleSignOn && (!jid_.isValid() || jid_.getNode().empty())) {
 		loginWindow_->setMessage(QT_TRANSLATE_NOOP("", "User address invalid. User address should be of the form 'alice@wonderland.lit'"));
 		loginWindow_->setIsLoggingIn(false);
 	} else {
+#ifdef SWIFTEN_PLATFORM_WIN32
+		if (options.singleSignOn) {
+			std::string userName;
+			std::string clientName;
+			std::string serverName;
+			boost::shared_ptr<boost::system::error_code> errorCode = getUserNameEx(userName, clientName, serverName);
+
+			if (!errorCode) {
+				/* Create JID using the Windows logon name and user provided domain name */
+				jid_ = JID(clientName, username);
+			}
+			else {
+				loginWindow_->setMessage(str(format(QT_TRANSLATE_NOOP("", "Error obtaining Windows user name (%1%)")) % errorCode->message()));
+				loginWindow_->setIsLoggingIn(false);
+				return;
+			}
+		}
+#endif
+
 		loginWindow_->setMessage("");
 		loginWindow_->setIsLoggingIn(true);
 		profileSettings_ = new ProfileSettingsProvider(username, settings_);
diff --git a/Swift/Controllers/SettingConstants.cpp b/Swift/Controllers/SettingConstants.cpp
index d740686..9807abc 100644
--- a/Swift/Controllers/SettingConstants.cpp
+++ b/Swift/Controllers/SettingConstants.cpp
@@ -28,4 +28,5 @@ const SettingsProvider::Setting<std::string> SettingConstants::INVITE_AUTO_ACCEP
 const SettingsProvider::Setting<std::string> SettingConstants::TRELLIS_GRID_SIZE("trellisGridSize", "");
 const SettingsProvider::Setting<std::string> SettingConstants::TRELLIS_GRID_POSITIONS("trellisGridPositions", "");
 const SettingsProvider::Setting<bool> SettingConstants::DISCONNECT_ON_CARD_REMOVAL("disconnectOnCardRemoval", true);
+const SettingsProvider::Setting<bool> SettingConstants::SINGLE_SIGN_ON("singleSignOn", false);
 }
diff --git a/Swift/Controllers/SettingConstants.h b/Swift/Controllers/SettingConstants.h
index eca3199..c4ac4ad 100644
--- a/Swift/Controllers/SettingConstants.h
+++ b/Swift/Controllers/SettingConstants.h
@@ -95,5 +95,14 @@ namespace Swift {
 			 * smart card is removed; else not.
 			 */
 			static const SettingsProvider::Setting<bool> DISCONNECT_ON_CARD_REMOVAL;
+			/**
+			 * The #SINGLE_SIGN_ON setting
+			 * specifies whether to log in using Single Sign On.
+			 * This is currently supported on Windows.
+			 *
+			 * If set true Swift will use GSSAPI authentication to
+			 * log in the user; else not.
+			 */
+			static const SettingsProvider::Setting<bool> SINGLE_SIGN_ON;
 	};
 }
-- 
cgit v0.10.2-6-g49f6