https://bugs.kde.org/show_bug.cgi?id=506567
Caballo Juan <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- Resolution|FIXED |--- Status|RESOLVED |REPORTED Ever confirmed|1 |0 --- Comment #25 from Caballo Juan <[email protected]> --- (In reply to David Edmundson from comment #24) > Git commit 51ae1c3d6e615891d03281935a93eed67130b720 by David Edmundson. > Committed on 02/02/2026 at 15:25. > Pushed by davidedmundson into branch 'Plasma/6.6'. > I tested the last stuff from kscreenlocker's master branch but the bug still seems to be there. Perhaps this commit addresses some other issue that appears to be unrelated to the fact that the fingerprint auth logic dies/gets corrupted after suspend or after the PAM timeout elapses. I am reopening this bug and attaching some logs. Unfortunately, I don't have the time to fix/rebase the PR I sent a few months ago (I worked on it for a few weeks, but got ignored lol). I'm also attaching my diff at the end of this post with what has, so far, worked for me. BTW, I noticed the following bugs in the latest and greatest in master, so this might help you come up with the right solution as my C++ is very bad: 1. pamauthenticator.cpp @ authenticate(): the current m_unavailable disable logic is extremely buggy as it permanently disables authenticators even if they experience transient errors, and doesn't allow any retry logic to kick in again 2. pamauthenticator.cpp @ `case PAM_TEXT_INFO`: we need to re-enable here the (fingerprint) authenticator, e.g `m_unavailable=false` again if we receive a timeout or a "valid" message from PAM. So far I've noticed PAM usually returns "place your XYZ finger on the fingerprint reader", and "timed out". If we get one of these messages, we need to make the device available again. 3. pamauthenticator.cpp @ authenticate() `if (rc == PAM_AUTHINFO_UNAVAIL || rc == PAM_MODULE_UNKNOWN`: this statement should further check if the FP device was disabled due to a timeout or if it was enabled back again (even if the returned pam_authenticate() returned an error) and if that's the case, reset the nextAttemptAllowed timer and invoke authenticate() again I also noticed that even without any of the above changes (latest master), the password entry field wobbles and indicates "Unlocking failed" shortly after pressing the suspend button. That might be a completely different issue. Logs (latest master) ``` kscreenlocker_greet: Greeter is starting up. kscreenlocker_greet: [PAM worker kde] start: successfully started kscreenlocker_greet: [PAM worker kde-smartcard] start: successfully started kscreenlocker_greet: [PAM worker kde-fingerprint] start: successfully started kscreenlocker_greet: Greeter is running in testing mode kscreenlocker_greet: Testing mode enabled: true Locked at 1770434097 kscreenlocker_greet: PamAuthenticators: starting authenticators kscreenlocker_greet: PamAuthenticators: state changing from PamAuthenticators::Idle to PamAuthenticators::Authenticating kscreenlocker_greet: [PAM worker kde-fingerprint] Authenticate: Starting authentication kscreenlocker_greet: [PAM worker kde] Authenticate: Starting authentication kscreenlocker_greet: [PAM worker kde-smartcard] Authenticate: Starting authentication kscreenlocker_greet: PamAuthenticators: Availability changed for non-interactive authenticator kde-fingerprint true kscreenlocker_greet: PamAuthenticators: Availability changed for non-interactive authenticator kde-smartcard true kscreenlocker_greet: [PAM worker kde-smartcard] Authenticate: Authentication done, result code: 28 (Module is unknown) kscreenlocker_greet: PamAuthenticators: Delay started on login failure for non-interactive authenticator kde-smartcard duration: 1934336 kscreenlocker_greet: PamAuthenticators: Availability changed for non-interactive authenticator kde-smartcard false kscreenlocker_greet: PamAuthenticators: Availability changed for non-interactive authenticator kde-smartcard false kscreenlocker_greet: [PAM worker kde] Message: Echo-off prompt: Password: kscreenlocker_greet: [PAM worker kde] Starting nested event loop to await response kscreenlocker_greet: PamAuthenticators: Secret prompt from interactive authenticator kde kscreenlocker_greet: [PAM worker kde-fingerprint] Message: Info message: Place your right index finger on the fingerprint reader kscreenlocker_greet: PamAuthenticators: Info message from non-interactive authenticator kde-fingerprint kscreenlocker_greet: PamAuthenticators: cancelling interactive authenticator kscreenlocker_greet: [PAM worker kde] Received cancellation, exiting with PAM_CONV_ERR kscreenlocker_greet: [PAM worker kde] Nested event loop's exit code was not zero, bailing kscreenlocker_greet: [PAM worker kde] Authenticate: Authentication done, result code: 20 (Authentication token manipulation error) kscreenlocker_greet: PamAuthenticators: Delay started on login failure for interactive authenticator kde duration: 1787620 kscreenlocker_greet: PamAuthenticators: Failure from interactive authenticator kde kscreenlocker_greet: PamAuthenticators: state changing from PamAuthenticators::Authenticating to PamAuthenticators::Idle kscreenlocker_greet: [PAM worker kde-fingerprint] Authenticate: Authentication done, result code: 9 (Authentication service cannot retrieve authentication info) kscreenlocker_greet: PamAuthenticators: Delay started on login failure for non-interactive authenticator kde-fingerprint duration: 2228651 kscreenlocker_greet: PamAuthenticators: Availability changed for non-interactive authenticator kde-fingerprint false kscreenlocker_greet: PamAuthenticators: Availability changed for non-interactive authenticator kde-fingerprint false kscreenlocker_greet: PamAuthenticators: starting authenticators kscreenlocker_greet: PamAuthenticators: state changing from PamAuthenticators::Idle to PamAuthenticators::Authenticating kscreenlocker_greet: [PAM worker kde] Authenticate: Starting authentication kscreenlocker_greet: [PAM worker kde] Message: Echo-off prompt: Password: kscreenlocker_greet: [PAM worker kde] Starting nested event loop to await response kscreenlocker_greet: PamAuthenticators: Secret prompt from interactive authenticator kde kscreenlocker_greet: PamAuthenticators: responding to interactive authenticator kscreenlocker_greet: [PAM worker kde] Received response, exiting nested event loop kscreenlocker_greet: PamAuthenticators: Interactive authenticator kde changed business kscreenlocker_greet: [PAM worker] Fail delay function was called, but authentication result was a success! kscreenlocker_greet: [PAM worker kde] Authenticate: Authentication done, result code: 0 (Success) kscreenlocker_greet: PamAuthenticators: Interactive authenticator kde changed business kscreenlocker_greet: PamAuthenticators: Success from interactive authenticator kde Unlocked ``` here's my very rough, 100% not prod-ready diff :P ``` diff --git a/CMakeLists.txt b/CMakeLists.txt index 01613b6a..c033d7ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_C_STANDARD 99) set(PROJECT_VERSION "6.6.80") set(PROJECT_VERSION_MAJOR 6) -set(PROJECT_DEP_VERSION "6.5.90") +set(PROJECT_DEP_VERSION "6.5.5") //test moment set(QT_MIN_VERSION "6.10.0") set(KF6_MIN_VERSION "6.22.0") diff --git a/greeter/pamauthenticator.cpp b/greeter/pamauthenticator.cpp index 9cbff076..6d002888 100644 --- a/greeter/pamauthenticator.cpp +++ b/greeter/pamauthenticator.cpp @@ -10,6 +10,7 @@ #include <QEventLoop> #include <QMetaMethod> #include <QThread> +#include <QTimer> #include <security/pam_appl.h> #include "kscreenlocker_greet_logging.h" @@ -18,7 +19,7 @@ class PamWorker : public QObject { Q_OBJECT public: - PamWorker(); + PamWorker(PamAuthenticator::NoninteractiveAuthenticatorTypes authenticatorType); ~PamWorker() override; Q_DISABLE_COPY_MOVE(PamWorker) void start(const QString &service, const QString &user); @@ -48,7 +49,9 @@ private: struct pam_conv m_conv; bool m_unavailable = false; + bool m_fingerprintRetry = false; bool m_inAuthenticate = false; + PamAuthenticator::NoninteractiveAuthenticatorTypes m_authenticatorType; std::chrono::steady_clock::time_point m_nextAttemptAllowedTime; int m_result = -1; QString m_service; @@ -134,6 +137,15 @@ int PamWorker::converse(int n, const struct pam_message **msg, struct pam_respon // if there's only the info message, let's predict the prompts too const QString info = QString::fromLocal8Bit(msg[i]->msg); qCDebug(KSCREENLOCKER_GREET, "[PAM worker %s] Message: Info message: %s", qUtf8Printable(c->m_service), qUtf8Printable(info)); + if (c->m_authenticatorType == PamAuthenticator::NoninteractiveAuthenticatorType::Fingerprint){ + if (info.contains(QStringLiteral("finger on the fingerprint reader")) || + info.contains(QStringLiteral("place your finger on the fingerprint reader")) + ){ + c->m_unavailable = false; + c->m_fingerprintRetry = true; + Q_EMIT c->unavailabilityChanged(c->m_unavailable); + } + } Q_EMIT c->infoMessage(info); break; } @@ -146,9 +158,10 @@ int PamWorker::converse(int n, const struct pam_message **msg, struct pam_respon return PAM_SUCCESS; } -PamWorker::PamWorker() +PamWorker::PamWorker(PamAuthenticator::NoninteractiveAuthenticatorTypes authenticatorType) : QObject(nullptr) , m_conv({&PamWorker::converse, this}) + , m_authenticatorType(authenticatorType) , m_nextAttemptAllowedTime(std::chrono::steady_clock::now()) { } @@ -162,7 +175,7 @@ PamWorker::~PamWorker() void PamWorker::authenticate() { - if (m_inAuthenticate || m_unavailable) { + if (!m_fingerprintRetry && (m_inAuthenticate || m_unavailable)) { return; } else if (std::chrono::steady_clock::now() < m_nextAttemptAllowedTime) { qCCritical(KSCREENLOCKER_GREET, "[PAM worker %s] Authentication attempt too soon. This shouldn't happen!", qUtf8Printable(m_service)); @@ -181,16 +194,28 @@ void PamWorker::authenticate() Q_EMIT busyChanged(false); if (rc == PAM_SUCCESS) { + m_unavailable = false; rc = pam_setcred(m_handle, PAM_REFRESH_CRED); /* ignore errors on refresh credentials. If this did not work we use the old ones. */ Q_EMIT succeeded(); } else if (rc == PAM_AUTHINFO_UNAVAIL || rc == PAM_MODULE_UNKNOWN) { + if (m_fingerprintRetry && m_authenticatorType == PamAuthenticator::NoninteractiveAuthenticatorType::Fingerprint) { + m_unavailable = false; + // reset timer to allow fp retry immediately + m_nextAttemptAllowedTime = std::chrono::steady_clock::now(); + QTimer::singleShot(1, this, &PamWorker::authenticate); + m_inAuthenticate = false; + Q_EMIT inAuthenticateChanged(m_inAuthenticate); + return; + } m_unavailable = true; Q_EMIT unavailabilityChanged(m_unavailable); } else { Q_EMIT failed(); } m_inAuthenticate = false; + m_fingerprintRetry = false; + Q_EMIT inAuthenticateChanged(m_inAuthenticate); } @@ -251,7 +276,7 @@ PamAuthenticator::PamAuthenticator(const QString &service, const QString &user, }) , m_service(service) , m_authenticatorType(types) - , d(new PamWorker) + , d(new PamWorker(types)) { d->moveToThread(&m_thread); ``` -- You are receiving this mail because: You are watching all bug changes.
