diff options
| -rw-r--r-- | Swift/Controllers/MainController.cpp | 94 | ||||
| -rw-r--r-- | Swift/Controllers/MainController.h | 5 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/LoginWindow.h | 2 | ||||
| -rw-r--r-- | Swift/QtUI/QtLoginWindow.cpp | 13 | ||||
| -rw-r--r-- | Swift/QtUI/QtLoginWindow.h | 1 | ||||
| -rw-r--r-- | Swift/QtUI/QtSwift.cpp | 7 | ||||
| -rw-r--r-- | Swiften/Base/Algorithm.h | 1 | ||||
| -rw-r--r-- | Swiften/Client/ClientOptions.h | 12 | ||||
| -rw-r--r-- | Swiften/Client/CoreClient.cpp | 24 | ||||
| -rw-r--r-- | Swiften/Client/CoreClient.h | 1 | ||||
| -rw-r--r-- | Swiften/SASL/ClientAuthenticator.cpp | 5 | 
11 files changed, 129 insertions, 36 deletions
| diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 6cc862e..1e388d5 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -14,6 +14,7 @@  #include <stdlib.h>  #include <Swiften/Base/format.h> +#include <Swiften/Base/Algorithm.h>  #include <Swift/Controllers/Intl.h>  #include <Swift/Controllers/UIInterfaces/UIFactory.h>  #include "Swiften/Network/TimerFactory.h" @@ -86,7 +87,8 @@ MainController::MainController(  		Dock* dock,  		Notifier* notifier,  		URIHandler* uriHandler, -		bool useDelayForLatency) : +		bool useDelayForLatency, +		bool eagleMode) :  			eventLoop_(eventLoop),  			networkFactories_(networkFactories),  			uiFactory_(uiFactories), @@ -96,7 +98,8 @@ MainController::MainController(  			settings_(settings),  			uriHandler_(uriHandler),  			loginWindow_(NULL) , -			useDelayForLatency_(useDelayForLatency) { +			useDelayForLatency_(useDelayForLatency), +			eagleMode_(eagleMode) {  	storages_ = NULL;  	certificateStorage_ = NULL;  	statusTracker_ = NULL; @@ -130,19 +133,25 @@ MainController::MainController(  	bool loginAutomatically = settings_->getBoolSetting("loginAutomatically", false);  	std::string cachedPassword;  	std::string cachedCertificate; -	foreach (std::string profile, settings->getAvailableProfiles()) { -		ProfileSettingsProvider profileSettings(profile, settings); -		std::string password = profileSettings.getStringSetting("pass"); -		std::string certificate = profileSettings.getStringSetting("certificate"); -		std::string jid = profileSettings.getStringSetting("jid"); -		loginWindow_->addAvailableAccount(jid, password, certificate); -		if (jid == selectedLoginJID) { -			cachedPassword = password; -			cachedCertificate = certificate; +	if (!eagleMode_) { +		foreach (std::string profile, settings->getAvailableProfiles()) { +			ProfileSettingsProvider profileSettings(profile, settings); +			std::string password = eagleMode ? "" : profileSettings.getStringSetting("pass"); +			std::string certificate = profileSettings.getStringSetting("certificate"); +			std::string jid = profileSettings.getStringSetting("jid"); +			loginWindow_->addAvailableAccount(jid, password, certificate); +			if (jid == selectedLoginJID) { +				cachedPassword = password; +				cachedCertificate = certificate; +			}  		} +		loginWindow_->selectUser(selectedLoginJID); +		loginWindow_->setLoginAutomatically(loginAutomatically); +	} else { +		loginWindow_->setRememberingAllowed(false);  	} -	loginWindow_->selectUser(selectedLoginJID); -	loginWindow_->setLoginAutomatically(loginAutomatically); + +  	loginWindow_->onLoginRequest.connect(boost::bind(&MainController::handleLoginRequest, this, _1, _2, _3, _4, _5));  	loginWindow_->onPurgeSavedLoginRequest.connect(boost::bind(&MainController::handlePurgeSavedLoginRequest, this, _1));  	loginWindow_->onCancelLoginRequest.connect(boost::bind(&MainController::handleCancelLoginRequest, this)); @@ -166,6 +175,7 @@ MainController::MainController(  }  MainController::~MainController() { +	purgeCachedCredentials();  	//setManagersOffline();  	eventController_->disconnectAll(); @@ -180,7 +190,12 @@ MainController::~MainController() {  	delete uiEventStream_;  } +void MainController::purgeCachedCredentials() { +	safeClear(password_); +} +  void MainController::resetClient() { +	purgeCachedCredentials();  	resetCurrentError();  	resetPendingReconnects();  	vCardPhotoHash_.clear(); @@ -243,6 +258,9 @@ void MainController::handleConnected() {  	loginWindow_->setIsLoggingIn(false);  	resetCurrentError();  	resetPendingReconnects(); +	if (eagleMode_) { +		purgeCachedCredentials(); +	}  	bool freshLogin = rosterController_ == NULL;  	myStatusLooksOnline_ = true;  	if (freshLogin) { @@ -370,12 +388,14 @@ void MainController::handleLoginRequest(const std::string &username, const std::  		loginWindow_->setMessage("");  		loginWindow_->setIsLoggingIn(true);  		profileSettings_ = new ProfileSettingsProvider(username, settings_); -		profileSettings_->storeString("jid", username); -		profileSettings_->storeString("certificate", certificateFile); -		profileSettings_->storeString("pass", (remember || loginAutomatically) ? password : ""); -		settings_->storeString("lastLoginJID", username); -		settings_->storeBool("loginAutomatically", loginAutomatically); -		loginWindow_->addAvailableAccount(profileSettings_->getStringSetting("jid"), profileSettings_->getStringSetting("pass"), profileSettings_->getStringSetting("certificate")); +		if (!eagleMode_) { +			profileSettings_->storeString("jid", username); +			profileSettings_->storeString("certificate", certificateFile); +			profileSettings_->storeString("pass", (remember || loginAutomatically) ? password : ""); +			settings_->storeString("lastLoginJID", username); +			settings_->storeBool("loginAutomatically", loginAutomatically); +			loginWindow_->addAvailableAccount(profileSettings_->getStringSetting("jid"), profileSettings_->getStringSetting("pass"), profileSettings_->getStringSetting("certificate")); +		}  		password_ = password;  		certificateFile_ = certificateFile; @@ -389,6 +409,10 @@ void MainController::handlePurgeSavedLoginRequest(const std::string& username) {  }  void MainController::performLoginFromCachedCredentials() { +	if (eagleMode_ && password_.empty()) { +		/* Then we can't try to login again. */ +		return; +	}  	/* If we logged in with a bare JID, and we have a full bound JID, re-login with the  	 * bound JID to try and keep dynamically assigned resources */  	JID clientJID = jid_; @@ -434,11 +458,15 @@ void MainController::performLoginFromCachedCredentials() {  	if (rosterController_) {  		rosterController_->getWindow()->setConnecting();  	} - -	client_->connect(); +	ClientOptions clientOptions; +	clientOptions.forgetPassword = eagleMode_; +	client_->connect(clientOptions);  }  void MainController::handleDisconnected(const boost::optional<ClientError>& error) { +	if (eagleMode_) { +		purgeCachedCredentials(); +	}  	if (quitRequested_) {  		resetClient();  		loginWindow_->quit(); @@ -498,15 +526,19 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro  			loginWindow_->setIsLoggingIn(false);  		} else {  			logout(); -			setReconnectTimer(); -			if (lastDisconnectError_) { -				message = str(format(QT_TRANSLATE_NOOP("", "Reconnect to %1% failed: %2%. Will retry in %3% seconds.")) % jid_.getDomain() % message % boost::lexical_cast<std::string>(timeBeforeNextReconnect_)); -				lastDisconnectError_->conclude(); +			if (eagleMode_) { +				message = str(format(QT_TRANSLATE_NOOP("", "Disconnected from %1%: %2%. To reconnect, Sign Out and provide your password again.")) % jid_.getDomain() % message);  			} else { -				message = str(format(QT_TRANSLATE_NOOP("", "Disconnected from %1%: %2%.")) % jid_.getDomain() % message); +				setReconnectTimer(); +				if (lastDisconnectError_) { +					message = str(format(QT_TRANSLATE_NOOP("", "Reconnect to %1% failed: %2%. Will retry in %3% seconds.")) % jid_.getDomain() % message % boost::lexical_cast<std::string>(timeBeforeNextReconnect_)); +					lastDisconnectError_->conclude(); +				} else { +					message = str(format(QT_TRANSLATE_NOOP("", "Disconnected from %1%: %2%.")) % jid_.getDomain() % message); +				} +				lastDisconnectError_ = boost::shared_ptr<ErrorEvent>(new ErrorEvent(JID(jid_.getDomain()), message)); +				eventController_->handleIncomingEvent(lastDisconnectError_);  			} -			lastDisconnectError_ = boost::shared_ptr<ErrorEvent>(new ErrorEvent(JID(jid_.getDomain()), message)); -			eventController_->handleIncomingEvent(lastDisconnectError_);  		}  	}  	else if (!rosterController_) { //hasn't been logged in yet @@ -533,6 +565,9 @@ void MainController::handleCancelLoginRequest() {  }  void MainController::signOut() { +	if (eagleMode_) { +		purgeCachedCredentials(); +	}  	eventController_->clear();  	logout();  	loginWindow_->loggedOut(); @@ -540,6 +575,9 @@ void MainController::signOut() {  }  void MainController::logout() { +	if (eagleMode_) { +		purgeCachedCredentials(); +	}  	systemTrayController_->setMyStatusType(StatusShow::None);  	if (clientInitialized_ /*&& client_->isAvailable()*/) {  		client_->disconnect(); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 757abb8..21460ec 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -81,7 +81,8 @@ namespace Swift {  					Dock* dock,  					Notifier* notifier,  					URIHandler* uriHandler, -					bool useDelayForLatency); +					bool useDelayForLatency, +					bool eagleMode);  			~MainController(); @@ -111,6 +112,7 @@ namespace Swift {  			void setManagersOffline();  			void handleNotificationClicked(const JID& jid);  			void handleForceQuit(); +			void purgeCachedCredentials();  		private:  			EventLoop* eventLoop_; @@ -160,5 +162,6 @@ namespace Swift {  			bool myStatusLooksOnline_;  			bool quitRequested_;  			static const int SecondsToWaitBeforeForceQuitting; +			bool eagleMode_;  	};  } diff --git a/Swift/Controllers/UIInterfaces/LoginWindow.h b/Swift/Controllers/UIInterfaces/LoginWindow.h index 61fcaa1..fcaeb42 100644 --- a/Swift/Controllers/UIInterfaces/LoginWindow.h +++ b/Swift/Controllers/UIInterfaces/LoginWindow.h @@ -27,6 +27,8 @@ namespace Swift {  			boost::signal<void (const std::string&, const std::string&, const std::string& /* certificateFile */, bool /* remember password*/, bool /* login automatically */)> onLoginRequest;  			virtual void setLoginAutomatically(bool loginAutomatically) = 0;  			virtual void quit() = 0; +			/** Disable any GUI elements that suggest saving of passwords. */ +			virtual void setRememberingAllowed(bool allowed) = 0;  			/** Blocking request whether a cert should be permanently trusted.*/  			virtual bool askUserToTrustCertificatePermanently(const std::string& message, Certificate::ref) = 0; diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp index 4302c10..45d7c7e 100644 --- a/Swift/QtUI/QtLoginWindow.cpp +++ b/Swift/QtUI/QtLoginWindow.cpp @@ -197,6 +197,15 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream) : QMainWindow() {  	this->show();  } +void QtLoginWindow::setRememberingAllowed(bool allowed) { +	remember_->setEnabled(allowed); +	loginAutomatically_->setEnabled(allowed); +	if (!allowed) { +		remember_->setChecked(false); +		loginAutomatically_->setChecked(false); +	} +} +  bool QtLoginWindow::eventFilter(QObject *obj, QEvent *event) {  	if (obj == username_->view() && event->type() == QEvent::KeyPress) {  		QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); @@ -304,6 +313,10 @@ void QtLoginWindow::setIsLoggingIn(bool loggingIn) {  void QtLoginWindow::loginClicked() {  	if (username_->isEnabled()) {  		onLoginRequest(Q2PSTRING(username_->currentText()), Q2PSTRING(password_->text()), Q2PSTRING(certificateFile_), remember_->isChecked(), loginAutomatically_->isChecked()); +		if (!remember_->isEnabled()) { /* Mustn't remember logins */ +			username_->clearEditText(); +			password_->setText(""); +		}  	} else {  		onCancelLoginRequest();  	} diff --git a/Swift/QtUI/QtLoginWindow.h b/Swift/QtUI/QtLoginWindow.h index b667a4b..410ed0a 100644 --- a/Swift/QtUI/QtLoginWindow.h +++ b/Swift/QtUI/QtLoginWindow.h @@ -36,6 +36,7 @@ namespace Swift {  			virtual void removeAvailableAccount(const std::string& jid);  			virtual void setLoginAutomatically(bool loginAutomatically);  			virtual void setIsLoggingIn(bool loggingIn); +			virtual void setRememberingAllowed(bool allowed);  			void selectUser(const std::string& user);  			bool askUserToTrustCertificatePermanently(const std::string& message, Certificate::ref certificate);  			void hide(); diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index d7a1f78..f0c876c 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2011 Kevin Smith   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */ @@ -73,6 +73,7 @@ po::options_description QtSwift::getOptionsDescription() {  		("latency-debug", "use latency debugging (unsupported)")  		("multi-account", po::value<int>()->default_value(1), "number of accounts to open windows for (unsupported)")  		("start-minimized", "don't show the login/roster window at startup") +		("eagle-mode", "Settings more suitable for military/secure deployments")  		;  	return result;  } @@ -103,6 +104,7 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa  	tabs_ = options.count("no-tabs") && !(splitter_ > 0) ? NULL : new QtChatTabs();  	bool startMinimized = options.count("start-minimized") > 0; +	bool eagleMode = options.count("eagle-mode") > 0;  	settings_ = new QtSettingsProvider();  	applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME);  	storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir()); @@ -162,7 +164,8 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa  				dock_,  				notifier_,  				uriHandler_, -				options.count("latency-debug") > 0); +				options.count("latency-debug") > 0, +				eagleMode);  		mainControllers_.push_back(mainController);  	} diff --git a/Swiften/Base/Algorithm.h b/Swiften/Base/Algorithm.h index cd6f9dc..b7459ed 100644 --- a/Swiften/Base/Algorithm.h +++ b/Swiften/Base/Algorithm.h @@ -12,6 +12,7 @@  #include <algorithm>  namespace Swift { +  	/*  	 * Generic erase()  	 */ diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h index 1155b46..cc80dc2 100644 --- a/Swiften/Client/ClientOptions.h +++ b/Swiften/Client/ClientOptions.h @@ -12,7 +12,7 @@ struct ClientOptions {  		UseTLSWhenAvailable  	}; -	ClientOptions() : useStreamCompression(true), useTLS(UseTLSWhenAvailable), useStreamResumption(false) { +	ClientOptions() : useStreamCompression(true), useTLS(UseTLSWhenAvailable), useStreamResumption(false), forgetPassword(false) {  	}  	/** @@ -35,5 +35,15 @@ struct ClientOptions {  	 * Default: false  	 */  	bool useStreamResumption; + +	/** +	 * Forget the password once it's used. +	 * This makes the Client useless after the first login attempt. +	 * +	 * FIXME: This is a temporary workaround. +	 * +	 * Default: false +	 */ +	bool forgetPassword;  }; diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index 9521bd9..8684de2 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp @@ -9,6 +9,10 @@  #include <boost/bind.hpp>  #include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Base/IDGenerator.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Base/Algorithm.h>  #include <Swiften/Client/ClientSession.h>  #include <Swiften/TLS/PlatformTLSFactories.h>  #include <Swiften/TLS/CertificateVerificationError.h> @@ -17,10 +21,7 @@  #include <Swiften/TLS/PKCS12Certificate.h>  #include <Swiften/Session/BasicSessionStream.h>  #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Base/IDGenerator.h>  #include <Swiften/Client/ClientSessionStanzaChannel.h> -#include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h>  #include <Swiften/Network/PlatformProxyProvider.h>  #include <Swiften/Network/SOCKS5ProxiedConnectionFactory.h>  #include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h> @@ -50,6 +51,7 @@ CoreClient::~CoreClient() {  	stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&CoreClient::handlePresenceReceived, this, _1));  	stanzaChannel_->onStanzaAcked.disconnect(boost::bind(&CoreClient::handleStanzaAcked, this, _1));  	delete stanzaChannel_; +	purgePassword();  }  void CoreClient::connect(const ClientOptions& o) { @@ -88,6 +90,9 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio  	}  	if (!connection) { +		if (options.forgetPassword) { +			purgePassword(); +		}  		onDisconnected(disconnectRequested_ ? boost::optional<ClientError>() : boost::optional<ClientError>(ClientError::ConnectionError));  	}  	else { @@ -121,6 +126,9 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio  }  void CoreClient::disconnect() { +	if (options.forgetPassword) { +			purgePassword(); +		}  	// FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between  	// connector finishing without a connection due to an error or because of a disconnect.  	disconnectRequested_ = true; @@ -137,6 +145,9 @@ void CoreClient::setCertificate(const std::string& certificate) {  }  void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) { +	if (options.forgetPassword) { +		purgePassword(); +	}  	session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1));  	session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this)); @@ -248,6 +259,9 @@ void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {  void CoreClient::handleNeedCredentials() {  	assert(session_);  	session_->sendCredentials(password_); +	if (options.forgetPassword) { +		purgePassword(); +	}  }  void CoreClient::handleDataRead(const std::string& data) { @@ -318,4 +332,8 @@ const JID& CoreClient::getJID() const {  	}  } +void CoreClient::purgePassword() { +	safeClear(password_); +} +  } diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h index 6dc8392..9806d35 100644 --- a/Swiften/Client/CoreClient.h +++ b/Swiften/Client/CoreClient.h @@ -199,6 +199,7 @@ namespace Swift {  			void handlePresenceReceived(boost::shared_ptr<Presence>);  			void handleMessageReceived(boost::shared_ptr<Message>);  			void handleStanzaAcked(boost::shared_ptr<Stanza>); +			void purgePassword();  		private:  			JID jid_; diff --git a/Swiften/SASL/ClientAuthenticator.cpp b/Swiften/SASL/ClientAuthenticator.cpp index b882d04..12636e2 100644 --- a/Swiften/SASL/ClientAuthenticator.cpp +++ b/Swiften/SASL/ClientAuthenticator.cpp @@ -1,17 +1,20 @@  /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2011 Remko Tronçon   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */  #include <Swiften/SASL/ClientAuthenticator.h> +#include <Swiften/Base/Algorithm.h> +  namespace Swift {  ClientAuthenticator::ClientAuthenticator(const std::string& name) : name(name) {  }  ClientAuthenticator::~ClientAuthenticator() { +	safeClear(password);  }  } | 
 Swift
 Swift