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
This commit is contained in:
Maximilian Seidler 2024-07-17 15:22:42 +02:00 committed by GitHub
parent a3d8a2c128
commit 9514925a7c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 33 additions and 19 deletions

View file

@ -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<CTimer> 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;
}

View file

@ -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);
@ -45,6 +43,7 @@ class CAuth {
SPamConversationState m_sConversationState;
bool m_bBlockInput = true;
bool m_bAuthenticated = false;
std::string m_sPamModule;

View file

@ -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,6 +985,7 @@ void CHyprlock::onLockFinished() {
else
ext_session_lock_v1_destroy(m_sLockState.lock);
m_sLockState.lock = nullptr;
m_bTerminate = true;
}

View file

@ -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);