From 3a4b4827fc812b6cca07f64866d9851eccb61de4 Mon Sep 17 00:00:00 2001 From: MusiKid Date: Sun, 25 Jul 2021 00:12:30 +0200 Subject: [PATCH] fix: fix native and input workarounds --- src/pam/main.cc | 65 ++++++++++++++++++++-------------------- src/pam/main.hh | 28 +++++++++++++++++ src/pam/optional_task.hh | 9 ++++-- 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/src/pam/main.cc b/src/pam/main.cc index 2af7270..8ef6c0f 100644 --- a/src/pam/main.cc +++ b/src/pam/main.cc @@ -104,12 +104,10 @@ int send_message(function conv, int type, const char *message) { - // Formet the message as PAM expects it // No need to free this, it's allocated on the stack const struct pam_message msg = {.msg_style = type, .msg = message}; const struct pam_message *msgp = &msg; - // Create a variable for the response to be stored in struct pam_response res_ = {}; struct pam_response *resp_ = &res_; @@ -117,17 +115,6 @@ int send_message(function child_task(packaged_task([&] { int status; wait(&status); { unique_lock lk(m); - t = Type::Howdy; + confirmation_type = Type::Howdy; } cv.notify_all(); return status; })); + child_task.activate(); + // This task waits for the password input (if the workaround wants it) optional_task> pass_task( packaged_task()>([&] { char *auth_tok_ptr = nullptr; @@ -275,35 +264,45 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, (const char **)&auth_tok_ptr, nullptr); { unique_lock lk(m); - t = Type::Pam; + confirmation_type = Type::Pam; } cv.notify_all(); return tuple(pam_res, auth_tok_ptr); })); + if (auth_tok) { pass_task.activate(); } - // Wait for the end - if (workaround == Workaround::Native) { + // Wait for the end either of the child or the password input + { unique_lock lk(m); cv.wait(lk); - } else if (auth_tok) { + } + + if (workaround != Workaround::Native && auth_tok) { pass_task.stop(false); } - if (t == Type::Howdy) { + if (confirmation_type == Type::Howdy) { + // This one is just 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); + + // If the workaround is native if (auth_tok) { // We cancel the thread using pthread, pam_get_authtok seems to be a // cancellation point - if (child_task.wait(1s) == future_status::timeout) { - kill(child_pid, SIGTERM); + if (pass_task.is_active()) { + pass_task.stop(true); } - child_task.stop(false); - pass_task.stop(false); } int howdy_status = child_task.get(); + // If exited succesfully if (howdy_status == 0) { if (!reader.GetBoolean("core", "no_confirmation", true)) { // Construct confirmation text from i18n string @@ -319,13 +318,12 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, return on_howdy_auth(howdy_status, conv_function); } } else { - if (!(workaround == Workaround::Native)) { + if (workaround != Workaround::Native) { if (child_task.wait(1s) == future_status::timeout) { kill(child_pid, SIGTERM); } child_task.stop(false); - } - if (auth_tok) { + } else { pass_task.stop(false); } @@ -353,6 +351,7 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv, } } + // The password has been entered, we are passing it to PAM stack return PAM_IGNORE; } } diff --git a/src/pam/main.hh b/src/pam/main.hh index e3d6b29..6b75580 100644 --- a/src/pam/main.hh +++ b/src/pam/main.hh @@ -1,8 +1,36 @@ #ifndef MAIN_H_ #define MAIN_H_ +#include +#include + enum class Type { Howdy, Pam }; enum class Workaround { Off, Input, Native }; +inline bool operator==(const std::string &l, const Workaround &r) { + switch (r) { + case Workaround::Off: + return (l == "off"); + case Workaround::Input: + return (l == "input"); + case Workaround::Native: + return (l == "native"); + default: + return false; + } +} + +inline bool operator==(const Workaround &l, const std::string &r) { + return operator==(r, l); +} + +inline bool operator!=(const std::string &l, const Workaround &r) { + return !operator==(l, r); +} + +inline bool operator!=(const Workaround &l, const std::string &r) { + return operator!=(r, l); +} + #endif // MAIN_H_ diff --git a/src/pam/optional_task.hh b/src/pam/optional_task.hh index 5048395..827c535 100644 --- a/src/pam/optional_task.hh +++ b/src/pam/optional_task.hh @@ -16,8 +16,9 @@ template class optional_task { public: optional_task(std::packaged_task); void activate(); - std::future_status wait(std::chrono::duration); + template std::future_status wait(std::chrono::duration); T get(); + bool is_active(); void stop(bool); ~optional_task(); }; @@ -31,8 +32,10 @@ template void optional_task::activate() { _spawned = true; _is_active = true; } + template -std::future_status optional_task::wait(std::chrono::duration dur) { +template +std::future_status optional_task::wait(std::chrono::duration dur) { return _future.wait_for(dur); } @@ -41,6 +44,8 @@ template T optional_task::get() { return _future.get(); } +template bool optional_task::is_active() { return _is_active; } + template void optional_task::stop(bool force) { if (!(_is_active && _thread.joinable()) && _spawned) { _is_active = false;