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); } } |