Merge ~azzar1/unity:fix-1733557-xenial into unity:xenial

Proposed by Andrea Azzarone
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: 6d1b7a7d8ff8d57bf61188cf5cc54b19be058969
Merged at revision: db57d37211ae86b97208015d5f9b0352519aa7e0
Proposed branch: ~azzar1/unity:fix-1733557-xenial
Merge into: unity:xenial
Diff against target: 159 lines (+57/-6)
4 files modified
lockscreen/LockScreenController.cpp (+2/-0)
lockscreen/UserAuthenticator.h (+1/-0)
lockscreen/UserAuthenticatorPam.cpp (+52/-6)
lockscreen/UserAuthenticatorPam.h (+2/-0)
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Approve
Review via email: mp+363311@code.launchpad.net

Commit message

lockscreen: 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

To post a comment you must log in.
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lockscreen/LockScreenController.cpp b/lockscreen/LockScreenController.cpp
index 5f5d54c..f8ba8c4 100644
--- a/lockscreen/LockScreenController.cpp
+++ b/lockscreen/LockScreenController.cpp
@@ -531,6 +531,8 @@ void Controller::OnUnlockRequested()
531531
532 HideBlankWindow();532 HideBlankWindow();
533 HideShields();533 HideShields();
534
535 user_authenticator_->AuthenticateCancel();
534}536}
535537
536void Controller::HideShields()538void Controller::HideShields()
diff --git a/lockscreen/UserAuthenticator.h b/lockscreen/UserAuthenticator.h
index e30ce2f..60e8684 100644
--- a/lockscreen/UserAuthenticator.h
+++ b/lockscreen/UserAuthenticator.h
@@ -43,6 +43,7 @@ public:
4343
44 // Authenticate the user in a background thread.44 // Authenticate the user in a background thread.
45 virtual bool AuthenticateStart(std::string const& username, AuthenticateEndCallback const&) = 0;45 virtual bool AuthenticateStart(std::string const& username, AuthenticateEndCallback const&) = 0;
46 virtual void AuthenticateCancel() = 0;
4647
47 sigc::signal<void> start_failed;48 sigc::signal<void> start_failed;
48 sigc::signal<void, std::string, PromiseAuthCodePtr const&> echo_on_requested;49 sigc::signal<void, std::string, PromiseAuthCodePtr const&> echo_on_requested;
diff --git a/lockscreen/UserAuthenticatorPam.cpp b/lockscreen/UserAuthenticatorPam.cpp
index f4e1952..d1d6c27 100644
--- a/lockscreen/UserAuthenticatorPam.cpp
+++ b/lockscreen/UserAuthenticatorPam.cpp
@@ -25,6 +25,8 @@
25#include "unity-shared/UnitySettings.h"25#include "unity-shared/UnitySettings.h"
26#include "UnityCore/GLibWrapper.h"26#include "UnityCore/GLibWrapper.h"
2727
28#include <NuxCore/Logger.h>
29
28#include <cstring>30#include <cstring>
29#include <security/pam_appl.h>31#include <security/pam_appl.h>
30#include <vector>32#include <vector>
@@ -33,23 +35,48 @@ namespace unity
33{35{
34namespace lockscreen36namespace lockscreen
35{37{
38namespace
39{
40DECLARE_LOGGER(logger, "unity.lockscreen");
41}
3642
37bool UserAuthenticatorPam::AuthenticateStart(std::string const& username,43bool UserAuthenticatorPam::AuthenticateStart(std::string const& username,
38 AuthenticateEndCallback const& authenticate_cb)44 AuthenticateEndCallback const& authenticate_cb)
39{45{
40 if (pam_handle_)46 if (pam_handle_)
47 {
48 LOG_ERROR(logger) << "Unable to start authentication because another one has already been started";
41 return false;49 return false;
50 }
4251
43 first_prompt_ = true;52 first_prompt_ = true;
53 cancelled_ = false;
44 username_ = username;54 username_ = username;
45 authenticate_cb_ = authenticate_cb;55 authenticate_cb_ = authenticate_cb;
4656
47 glib::Error error;57 glib::Error error;
48 g_thread_try_new(nullptr, AuthenticationThreadFunc, this, &error);58 g_autoptr(GThread) thread = g_thread_try_new(nullptr, AuthenticationThreadFunc, this, &error);
59
60 if (!thread || error)
61 {
62 LOG_ERROR(logger) << "Unable to create a new thread for PAM authentication: " << error.Message();
63 }
4964
50 return !error;65 return !error;
51}66}
5267
68void UserAuthenticatorPam::AuthenticateCancel()
69{
70 if (!pam_handle_)
71 {
72 LOG_DEBUG(logger) << "Unable to cancel authentication because none has been started";
73 return;
74 }
75
76 LOG_DEBUG(logger) << "Cancelling the authentication";
77 cancelled_ = true;
78}
79
53gpointer UserAuthenticatorPam::AuthenticationThreadFunc(gpointer data)80gpointer UserAuthenticatorPam::AuthenticationThreadFunc(gpointer data)
54{81{
55 auto self = static_cast<UserAuthenticatorPam*>(data);82 auto self = static_cast<UserAuthenticatorPam*>(data);
@@ -78,7 +105,10 @@ gpointer UserAuthenticatorPam::AuthenticationThreadFunc(gpointer data)
78105
79 pam_end(self->pam_handle_, self->status_);106 pam_end(self->pam_handle_, self->status_);
80 self->pam_handle_ = nullptr;107 self->pam_handle_ = nullptr;
81 self->source_manager_.AddTimeout(0, [self] { self->authenticate_cb_(self->status_ == PAM_SUCCESS); return false; });108
109 if (!self->cancelled_)
110 self->source_manager_.AddTimeout(0, [self] { self->authenticate_cb_(self->status_ == PAM_SUCCESS); return false; });
111
82 return nullptr;112 return nullptr;
83}113}
84114
@@ -88,8 +118,16 @@ bool UserAuthenticatorPam::InitPam()
88 conversation.conv = ConversationFunction;118 conversation.conv = ConversationFunction;
89 conversation.appdata_ptr = static_cast<void*>(this);119 conversation.appdata_ptr = static_cast<void*>(this);
90120
91 return pam_start("unity", username_.c_str(),121 int ret = pam_start("unity", username_.c_str(),
92 &conversation, &pam_handle_) == PAM_SUCCESS;122 &conversation, &pam_handle_);
123
124 if (ret != PAM_SUCCESS)
125 {
126 LOG_ERROR(logger) << "Unable to start pam: " << pam_strerror(pam_handle_, ret);
127 return false;
128 }
129
130 return true;
93}131}
94132
95int UserAuthenticatorPam::ConversationFunction(int num_msg,133int UserAuthenticatorPam::ConversationFunction(int num_msg,
@@ -166,9 +204,17 @@ int UserAuthenticatorPam::ConversationFunction(int num_msg,
166 auto future = promise->get_future();204 auto future = promise->get_future();
167 pam_response* resp_item = &tmp_response[i++];205 pam_response* resp_item = &tmp_response[i++];
168 resp_item->resp_retcode = 0;206 resp_item->resp_retcode = 0;
169 resp_item->resp = strdup(future.get().c_str());207 resp_item->resp = nullptr;
208
209 std::future_status status;
210 do
211 {
212 status = future.wait_for(std::chrono::seconds(1));
213 if (status == std::future_status::ready)
214 resp_item->resp = strdup(future.get().c_str());
215 } while (status != std::future_status::ready && !user_auth->cancelled_);
170216
171 if (!resp_item->resp)217 if (!resp_item->resp || user_auth->cancelled_)
172 {218 {
173 raise_error = true;219 raise_error = true;
174 break;220 break;
diff --git a/lockscreen/UserAuthenticatorPam.h b/lockscreen/UserAuthenticatorPam.h
index 82273cd..4043cd4 100644
--- a/lockscreen/UserAuthenticatorPam.h
+++ b/lockscreen/UserAuthenticatorPam.h
@@ -39,6 +39,7 @@ class UserAuthenticatorPam : public UserAuthenticator
39public:39public:
40 UserAuthenticatorPam() = default;40 UserAuthenticatorPam() = default;
41 bool AuthenticateStart(std::string const& username, AuthenticateEndCallback const&) override;41 bool AuthenticateStart(std::string const& username, AuthenticateEndCallback const&) override;
42 void AuthenticateCancel() override;
4243
43private:44private:
44 UserAuthenticatorPam(UserAuthenticatorPam const&) = delete;45 UserAuthenticatorPam(UserAuthenticatorPam const&) = delete;
@@ -57,6 +58,7 @@ private:
5758
58 int status_ = 0;59 int status_ = 0;
59 bool first_prompt_ = true;60 bool first_prompt_ = true;
61 bool cancelled_ = false;
60 pam_handle* pam_handle_ = nullptr;62 pam_handle* pam_handle_ = nullptr;
61 glib::SourceManager source_manager_;63 glib::SourceManager source_manager_;
62};64};

Subscribers

People subscribed via source and target branches