summaryrefslogtreecommitdiff
diff options
authorAndrea Azzarone <azzaronea@gmail.com>2019-02-13 02:38:58 -0800
committerAndrea Azzarone <andrea.azzarone@canonical.com>2019-02-13 11:21:40 +0000
commitb5582152d954cd795c49fbf515e221e50a935e52 (patch)
tree06198de5c38b57f2ce285bbb828c3d08a3e54717
parent7d40a5390817ffde73edb9314c338cedfe9db33c (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_;
};