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.

Reply via email to