fix: use atomic type for confirmation type
This commit is contained in:
parent
827f638be6
commit
9fb3ef5341
2 changed files with 28 additions and 24 deletions
|
|
@ -175,7 +175,7 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
|
||||||
|
|
||||||
// Try to detect the laptop lid state and stop if it's closed
|
// Try to detect the laptop lid state and stop if it's closed
|
||||||
if (reader.GetBoolean("core", "ignore_closed_lid", true)) {
|
if (reader.GetBoolean("core", "ignore_closed_lid", true)) {
|
||||||
glob_t glob_result{};
|
glob_t glob_result;
|
||||||
|
|
||||||
// Get any files containing lid state
|
// Get any files containing lid state
|
||||||
int return_value =
|
int return_value =
|
||||||
|
|
@ -238,22 +238,27 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
|
||||||
return PAM_SYSTEM_ERR;
|
return PAM_SYSTEM_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: We could replace mutex and condition_variable by atomic wait, but
|
||||||
|
// it's too recent (C++20)
|
||||||
mutex m;
|
mutex m;
|
||||||
condition_variable cv;
|
condition_variable cv;
|
||||||
Type confirmation_type;
|
atomic<Type> confirmation_type(Type::Unset);
|
||||||
// TODO: Find a clean way to do this
|
|
||||||
Type final_type;
|
|
||||||
|
|
||||||
// This task wait for the status of the python subprocess (we don't want a
|
// This task wait for the status of the python subprocess (we don't want a
|
||||||
// zombie process)
|
// zombie process)
|
||||||
optional_task<int> child_task(packaged_task<int()>([&] {
|
optional_task<int> child_task(packaged_task<int()>([&] {
|
||||||
int status;
|
int status;
|
||||||
wait(&status);
|
wait(&status);
|
||||||
|
|
||||||
{
|
{
|
||||||
unique_lock<mutex> lk(m);
|
unique_lock<mutex> lk(m);
|
||||||
confirmation_type = Type::Howdy;
|
Type type = confirmation_type.load(memory_order_acquire);
|
||||||
|
if (type == Type::Unset) {
|
||||||
|
confirmation_type.store(Type::Howdy, memory_order_release);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cv.notify_all();
|
cv.notify_one();
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}));
|
}));
|
||||||
child_task.activate();
|
child_task.activate();
|
||||||
|
|
@ -266,9 +271,13 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
|
||||||
(const char **)&auth_tok_ptr, nullptr);
|
(const char **)&auth_tok_ptr, nullptr);
|
||||||
{
|
{
|
||||||
unique_lock<mutex> lk(m);
|
unique_lock<mutex> lk(m);
|
||||||
confirmation_type = Type::Pam;
|
Type type = confirmation_type.load(memory_order_acquire);
|
||||||
|
if (type == Type::Unset) {
|
||||||
|
confirmation_type.store(Type::Pam, memory_order_release);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cv.notify_all();
|
cv.notify_one();
|
||||||
|
|
||||||
return tuple<int, char *>(pam_res, auth_tok_ptr);
|
return tuple<int, char *>(pam_res, auth_tok_ptr);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -279,16 +288,10 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
|
||||||
// Wait for the end either of the child or the password input
|
// Wait for the end either of the child or the password input
|
||||||
{
|
{
|
||||||
unique_lock<mutex> lk(m);
|
unique_lock<mutex> lk(m);
|
||||||
cv.wait(lk);
|
cv.wait(lk, [&] { return confirmation_type != Type::Unset; });
|
||||||
final_type = confirmation_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (final_type == Type::Howdy) {
|
if (confirmation_type == Type::Howdy) {
|
||||||
// We need to be sure that we're not going to block forever if the
|
|
||||||
// child has a problem
|
|
||||||
if (child_task.wait(3s) == future_status::timeout) {
|
|
||||||
kill(child_pid, SIGTERM);
|
|
||||||
}
|
|
||||||
child_task.stop(false);
|
child_task.stop(false);
|
||||||
|
|
||||||
// If the workaround is native
|
// If the workaround is native
|
||||||
|
|
@ -313,13 +316,13 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
|
||||||
}
|
}
|
||||||
syslog(LOG_INFO, "Login approved");
|
syslog(LOG_INFO, "Login approved");
|
||||||
return PAM_SUCCESS;
|
return PAM_SUCCESS;
|
||||||
} else {
|
|
||||||
return on_howdy_auth(howdy_status, conv_function);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We got an error
|
||||||
|
return on_howdy_auth(howdy_status, conv_function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The branch with Howdy confirmation type returns early, so we don't need an
|
// The password has been entered
|
||||||
// else statement
|
|
||||||
|
|
||||||
// Again, we need to be sure that we're not going to block forever if the
|
// Again, we need to be sure that we're not going to block forever if the
|
||||||
// child has a problem
|
// child has a problem
|
||||||
|
|
@ -334,14 +337,15 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
|
||||||
pass_task.stop(false);
|
pass_task.stop(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *token = nullptr;
|
char *password = nullptr;
|
||||||
tie(pam_res, token) = pass_task.get();
|
tie(pam_res, password) = pass_task.get();
|
||||||
|
|
||||||
if (pam_res != PAM_SUCCESS)
|
if (pam_res != PAM_SUCCESS)
|
||||||
return pam_res;
|
return pam_res;
|
||||||
|
|
||||||
int howdy_status = child_task.get();
|
int howdy_status = child_task.get();
|
||||||
if (strlen(token) == 0) {
|
// If python process sent Enter key
|
||||||
|
if (strlen(password) == 0) {
|
||||||
if (howdy_status == 0) {
|
if (howdy_status == 0) {
|
||||||
if (!reader.GetBoolean("core", "no_confirmation", true)) {
|
if (!reader.GetBoolean("core", "no_confirmation", true)) {
|
||||||
// Construct confirmation text from i18n string
|
// Construct confirmation text from i18n string
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
enum class Type { Howdy, Pam };
|
enum class Type { Unset, Howdy, Pam };
|
||||||
|
|
||||||
enum class Workaround { Off, Input, Native };
|
enum class Workaround { Off, Input, Native };
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue