summaryrefslogtreecommitdiff
diff options
authorAndrea Azzarone <azzaronea@gmail.com>2019-02-13 02:38:58 -0800
committerAndrea Azzarone <andrea.azzarone@canonical.com>2019-02-18 09:56:38 +0100
commitb23c0a1083665f51b2a54a784acd711352365727 (patch)
treefea7ae8d8539acb7ce2c2b5ee5965d508fe72745
parentf21020e3b0e20a3557f4aaeea74aa957d7a4c427 (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.cpp2
-rw-r--r--lockscreen/UserAuthenticator.h1
-rw-r--r--lockscreen/UserAuthenticatorPam.cpp30
-rw-r--r--lockscreen/UserAuthenticatorPam.h2
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_;
};