From 9514925a7c4c11028b6e3aae548b9c6859849462 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:22:42 +0200 Subject: [PATCH] core: grace unlock improvements and auth fixes for grace/SIGUSR1 unlocks (#424) * core: check m_bTerminate for grace unlocks * core: remove reference to the lock object on finished * core: add isUnlocked true if m_bFadeStarted or m_bTerminate * auth: return early on grace or SIGUSR1 unlocks --- src/core/Auth.cpp | 24 ++++++++++++++++-------- src/core/Auth.hpp | 7 +++---- src/core/hyprlock.cpp | 20 +++++++++++++------- src/core/hyprlock.hpp | 1 + 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/core/Auth.cpp b/src/core/Auth.cpp index 90857c6..eb7dffa 100644 --- a/src/core/Auth.cpp +++ b/src/core/Auth.cpp @@ -38,7 +38,7 @@ int conv(int num_msg, const struct pam_message** msg, struct pam_response** resp } // Needed for unlocks via SIGUSR1 - if (g_pHyprlock->m_bTerminate) + if (g_pHyprlock->isUnlocked()) return PAM_CONV_ERR; pamReply[i].resp = strdup(CONVERSATIONSTATE->input.c_str()); @@ -70,9 +70,21 @@ static void passwordCheckTimerCallback(std::shared_ptr self, void* data) void CAuth::start() { std::thread([this]() { resetConversation(); + + // Initial input m_sConversationState.prompt = "Password: "; waitForInput(); - auth(); + + // For grace or SIGUSR1 unlocks + if (g_pHyprlock->isUnlocked()) + return; + + const auto AUTHENTICATED = auth(); + m_bAuthenticated = AUTHENTICATED; + + // For SIGUSR1 unlocks + if (g_pHyprlock->isUnlocked()) + return; g_pHyprlock->addTimer(std::chrono::milliseconds(1), passwordCheckTimerCallback, nullptr); }).detach(); @@ -86,7 +98,6 @@ bool CAuth::auth() { int ret = pam_start(m_sPamModule.c_str(), uidPassword->pw_name, &localConv, &handle); if (ret != PAM_SUCCESS) { - m_sConversationState.success = false; m_sConversationState.failText = "pam_start failed"; Debug::log(ERR, "auth: pam_start failed for {}", m_sPamModule); return false; @@ -99,21 +110,19 @@ bool CAuth::auth() { m_sConversationState.waitingForPamAuth = false; if (ret != PAM_SUCCESS) { - m_sConversationState.success = false; m_sConversationState.failText = ret == PAM_AUTH_ERR ? "Authentication failed" : "pam_authenticate failed"; Debug::log(ERR, "auth: {} for {}", m_sConversationState.failText, m_sPamModule); return false; } - m_sConversationState.success = true; m_sConversationState.failText = "Successfully authenticated"; Debug::log(LOG, "auth: authenticated for {}", m_sPamModule); return true; } -bool CAuth::didAuthSucceed() { - return m_sConversationState.success; +bool CAuth::isAuthenticated() { + return m_bAuthenticated; } // clearing the input must be done from the main thread @@ -164,5 +173,4 @@ void CAuth::resetConversation() { m_sConversationState.input = ""; m_sConversationState.waitingForPamAuth = false; m_sConversationState.inputRequested = false; - m_sConversationState.success = false; } diff --git a/src/core/Auth.hpp b/src/core/Auth.hpp index b0fea79..d480c71 100644 --- a/src/core/Auth.hpp +++ b/src/core/Auth.hpp @@ -18,15 +18,13 @@ class CAuth { bool waitingForPamAuth = false; bool inputRequested = false; - - bool success = false; }; CAuth(); void start(); bool auth(); - bool didAuthSucceed(); + bool isAuthenticated(); void waitForInput(); void submitInput(std::string input); @@ -44,7 +42,8 @@ class CAuth { private: SPamConversationState m_sConversationState; - bool m_bBlockInput = true; + bool m_bBlockInput = true; + bool m_bAuthenticated = false; std::string m_sPamModule; diff --git a/src/core/hyprlock.cpp b/src/core/hyprlock.cpp index 727d5c7..56a6248 100644 --- a/src/core/hyprlock.cpp +++ b/src/core/hyprlock.cpp @@ -585,6 +585,10 @@ void CHyprlock::unlock() { renderAllOutputs(); } +bool CHyprlock::isUnlocked() { + return m_bFadeStarted || m_bTerminate; +} + // wl_seat static void handlePointerEnter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { @@ -610,9 +614,10 @@ static void handlePointerAxis(void* data, wl_pointer* wl_pointer, uint32_t time, } static void handlePointerMotion(void* data, struct wl_pointer* wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - if (g_pHyprlock->m_vLastEnterCoords.distance({wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)}) > 5 && - std::chrono::system_clock::now() < g_pHyprlock->m_tGraceEnds && !g_pHyprlock->m_bFadeStarted) { + if (std::chrono::system_clock::now() > g_pHyprlock->m_tGraceEnds) + return; + if (!g_pHyprlock->isUnlocked() && g_pHyprlock->m_vLastEnterCoords.distance({wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)}) > 5) { Debug::log(LOG, "In grace and cursor moved more than 5px, unlocking!"); g_pHyprlock->unlock(); } @@ -767,13 +772,13 @@ static const ext_session_lock_v1_listener sessionLockListener = { void CHyprlock::onPasswordCheckTimer() { // check result - if (g_pAuth->didAuthSucceed()) { + if (g_pAuth->isAuthenticated()) { unlock(); } else { - Debug::log(LOG, "Failed attempts: {}", m_sPasswordState.failedAttempts); - m_sPasswordState.passBuffer = ""; m_sPasswordState.failedAttempts += 1; + Debug::log(LOG, "Failed attempts: {}", m_sPasswordState.failedAttempts); + g_pAuth->m_bDisplayFailText = true; forceUpdateTimers(); @@ -843,7 +848,7 @@ void CHyprlock::repeatKey(xkb_keysym_t sym) { } void CHyprlock::onKey(uint32_t key, bool down) { - if (m_bFadeStarted) + if (m_bFadeStarted || m_bTerminate) return; if (down && std::chrono::system_clock::now() < m_tGraceEnds) { @@ -980,7 +985,8 @@ void CHyprlock::onLockFinished() { else ext_session_lock_v1_destroy(m_sLockState.lock); - m_bTerminate = true; + m_sLockState.lock = nullptr; + m_bTerminate = true; } ext_session_lock_manager_v1* CHyprlock::getSessionLockMgr() { diff --git a/src/core/hyprlock.hpp b/src/core/hyprlock.hpp index 7d34c51..c66d61f 100644 --- a/src/core/hyprlock.hpp +++ b/src/core/hyprlock.hpp @@ -31,6 +31,7 @@ class CHyprlock { void run(); void unlock(); + bool isUnlocked(); void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version); void onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name);