diff options
| author | Andrea Azzarone <azzaronea@gmail.com> | 2019-02-13 02:38:58 -0800 |
|---|---|---|
| committer | Andrea Azzarone <andrea.azzarone@canonical.com> | 2019-02-13 11:21:40 +0000 |
| commit | b5582152d954cd795c49fbf515e221e50a935e52 (patch) | |
| tree | 06198de5c38b57f2ce285bbb828c3d08a3e54717 | |
| parent | 7d40a5390817ffde73edb9314c338cedfe9db33c (diff) | |
locksreen: cancel authentication if externally unlocked
The lockscreen can be externellay unlocked. This happens e.g. when you unlock the session from LightDM or from the CLI. We need to cancel the authentication in order to ensure that the next one does not fail. Fixes: https://bugs.launchpad.net/unity/+bug/1733557
| -rw-r--r-- | lockscreen/LockScreenController.cpp | 2 | ||||
| -rw-r--r-- | lockscreen/UserAuthenticator.h | 1 | ||||
| -rw-r--r-- | lockscreen/UserAuthenticatorPam.cpp | 30 | ||||
| -rw-r--r-- | lockscreen/UserAuthenticatorPam.h | 2 |
4 files changed, 32 insertions, 3 deletions
diff --git a/lockscreen/LockScreenController.cpp b/lockscreen/LockScreenController.cpp index 8f6e7bc9b..907a1308d 100644 --- a/lockscreen/LockScreenController.cpp +++ b/lockscreen/LockScreenController.cpp @@ -536,6 +536,8 @@ void Controller::OnUnlockRequested() HideBlankWindow(); HideShields(); + + user_authenticator_->AuthenticateCancel(); } void Controller::HideShields() diff --git a/lockscreen/UserAuthenticator.h b/lockscreen/UserAuthenticator.h index e30ce2fdb..60e868482 100644 --- a/lockscreen/UserAuthenticator.h +++ b/lockscreen/UserAuthenticator.h @@ -43,6 +43,7 @@ public: // Authenticate the user in a background thread. virtual bool AuthenticateStart(std::string const& username, AuthenticateEndCallback const&) = 0; + virtual void AuthenticateCancel() = 0; sigc::signal<void> start_failed; sigc::signal<void, std::string, PromiseAuthCodePtr const&> echo_on_requested; diff --git a/lockscreen/UserAuthenticatorPam.cpp b/lockscreen/UserAuthenticatorPam.cpp index 463d8f949..d1d6c271b 100644 --- a/lockscreen/UserAuthenticatorPam.cpp +++ b/lockscreen/UserAuthenticatorPam.cpp @@ -50,6 +50,7 @@ bool UserAuthenticatorPam::AuthenticateStart(std::string const& username, } first_prompt_ = true; + cancelled_ = false; username_ = username; authenticate_cb_ = authenticate_cb; @@ -64,6 +65,18 @@ bool UserAuthenticatorPam::AuthenticateStart(std::string const& username, return !error; } +void UserAuthenticatorPam::AuthenticateCancel() +{ + if (!pam_handle_) + { + LOG_DEBUG(logger) << "Unable to cancel authentication because none has been started"; + return; + } + + LOG_DEBUG(logger) << "Cancelling the authentication"; + cancelled_ = true; +} + gpointer UserAuthenticatorPam::AuthenticationThreadFunc(gpointer data) { auto self = static_cast<UserAuthenticatorPam*>(data); @@ -92,7 +105,10 @@ gpointer UserAuthenticatorPam::AuthenticationThreadFunc(gpointer data) pam_end(self->pam_handle_, self->status_); self->pam_handle_ = nullptr; - self->source_manager_.AddTimeout(0, [self] { self->authenticate_cb_(self->status_ == PAM_SUCCESS); return false; }); + + if (!self->cancelled_) + self->source_manager_.AddTimeout(0, [self] { self->authenticate_cb_(self->status_ == PAM_SUCCESS); return false; }); + return nullptr; } @@ -188,9 +204,17 @@ int UserAuthenticatorPam::ConversationFunction(int num_msg, auto future = promise->get_future(); pam_response* resp_item = &tmp_response[i++]; resp_item->resp_retcode = 0; - resp_item->resp = strdup(future.get().c_str()); + resp_item->resp = nullptr; + + std::future_status status; + do + { + status = future.wait_for(std::chrono::seconds(1)); + if (status == std::future_status::ready) + resp_item->resp = strdup(future.get().c_str()); + } while (status != std::future_status::ready && !user_auth->cancelled_); - if (!resp_item->resp) + if (!resp_item->resp || user_auth->cancelled_) { raise_error = true; break; diff --git a/lockscreen/UserAuthenticatorPam.h b/lockscreen/UserAuthenticatorPam.h index 82273cd49..4043cd429 100644 --- a/lockscreen/UserAuthenticatorPam.h +++ b/lockscreen/UserAuthenticatorPam.h @@ -39,6 +39,7 @@ class UserAuthenticatorPam : public UserAuthenticator public: UserAuthenticatorPam() = default; bool AuthenticateStart(std::string const& username, AuthenticateEndCallback const&) override; + void AuthenticateCancel() override; private: UserAuthenticatorPam(UserAuthenticatorPam const&) = delete; @@ -57,6 +58,7 @@ private: int status_ = 0; bool first_prompt_ = true; + bool cancelled_ = false; pam_handle* pam_handle_ = nullptr; glib::SourceManager source_manager_; }; |
