[plasma/kscreenlocker] greeter: get rid of pam worker
Harald Sitter <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 02c33426d884323e2baf63f203f5e4d8e79bf6e6 by Harald Sitter, on behalf of David Edmundson.
Committed on 18/08/2026 at 11:15.
Pushed by sitter into branch 'master'.
get rid of pam worker
M +1 -2 greeter/CMakeLists.txt
M +197 -84 greeter/pamauthenticator.cpp
M +23 -19 greeter/pamauthenticator.h
D +0 -214 greeter/pamworker.cpp
D +0 -65 greeter/pamworker.h
https://invent.kde.org/plasma/kscreenlocker/-/commit/02c33426d884323e2baf63f203f5e4d8e79bf6e6
diff --git a/greeter/CMakeLists.txt b/greeter/CMakeLists.txt
index 64726387..c29f786a 100644
--- a/greeter/CMakeLists.txt
+++ b/greeter/CMakeLists.txt
@@ -14,7 +14,6 @@ set(kscreenlocker_authenticator_SRCS
pamauthenticator.cpp
pamauthenticator.h
pamauthenticatormodel.cpp
- pamworker.cpp
pamauthenticatordescriptor.cpp
)
@@ -46,7 +45,7 @@ ecm_qt_declare_logging_category(kscreenlocker_greet_SRCS
set_source_files_properties(worker/org.kde.plasma.screenlocker.worker.xml PROPERTIES INCLUDE "result.h")
qt_add_dbus_interface(kscreenlocker_authenticator_SRCS worker/org.kde.plasma.screenlocker.worker.xml org.kde.plasma.screenlocker.worker)
-qt_add_dbus_adaptor(kscreenlocker_authenticator_SRCS worker/org.kde.plasma.screenlocker.xml pamworker.h PamWorker)
+qt_add_dbus_adaptor(kscreenlocker_authenticator_SRCS worker/org.kde.plasma.screenlocker.xml pamauthenticator.h PamAuthenticator)
add_library(kscreenlocker_authenticator OBJECT ${kscreenlocker_authenticator_SRCS})
target_link_libraries(kscreenlocker_authenticator
diff --git a/greeter/pamauthenticator.cpp b/greeter/pamauthenticator.cpp
index 833405da..b343b87a 100644
--- a/greeter/pamauthenticator.cpp
+++ b/greeter/pamauthenticator.cpp
@@ -7,11 +7,19 @@
#include "pamauthenticator.h"
-#include <QElapsedTimer>
+#include <QDBusConnection>
+#include <QDBusPendingCallWatcher>
+#include <QDBusServer>
#include <QMetaMethod>
-#include <QThread>
+#include <QProcess>
+#include <QTimer>
-#include "pamworker.h"
+#include <KLibexec>
+
+#include "kscreenlocker_greet_logging.h"
+#include "org.kde.plasma.screenlocker.worker.h"
+#include "result.h"
+#include "screenlockeradaptor.h"
using namespace std::chrono_literals;
using namespace Qt::StringLiterals;
@@ -26,75 +34,15 @@ PamAuthenticator::PamAuthenticator(const QString &service, const QString &user,
})
, m_service(service)
, m_authenticatorType(types)
- , m_thread(std::make_unique<PamWorker>(service, user))
- , d(m_thread.worker())
+ , m_user(user)
{
- connect(d, &PamWorker::busyChanged, this, &PamAuthenticator::setBusy);
- connect(d, &PamWorker::inPasswordDelayChanged, this, &PamAuthenticator::setInPasswordDelay);
- connect(d, &PamWorker::prompt, this, [this](const QString &msg) {
- m_prompt = msg;
- Q_EMIT prompt(msg);
- });
- connect(d, &PamWorker::promptForSecret, this, [this](const QString &msg) {
- m_promptForSecret = msg;
- Q_EMIT promptForSecret(msg);
- });
- connect(d, &PamWorker::infoMessage, this, [this](const QString &msg) {
- m_infoMessage = msg;
- Q_EMIT infoMessage(msg);
- });
- connect(d, &PamWorker::errorMessage, this, [this](const QString &msg) {
- m_errorMessage = msg;
- Q_EMIT errorMessage(msg);
- });
-
- connect(d, &PamWorker::inAuthenticateChanged, this, [this] {
- Q_EMIT availableChanged();
- });
- connect(d, &PamWorker::unavailabilityChanged, this, [this](bool isUnavailable) {
- m_unavailable = isUnavailable;
- Q_EMIT availableChanged();
- });
-
- connect(d, &PamWorker::succeeded, this, [this]() {
- m_unlocked = true;
- Q_EMIT succeeded();
- });
- // Failed is not a persistent state. When a view provides authentication that will either result in failure or success,
- // failure simply means that the prompt is getting delayed.
- connect(d, &PamWorker::failed, this, [this] {
- // Guard against particularly broken PAM services. For example when pam-u2f doesn't find a token because it is
- // not plugged in it will fail the authentication, but it will do it so slowly that the timing checks in the
- // worker itself don't bite.
- // Here we can keep a higher level view of the failures and if need be break the loop by marking us unavailable.
- auto now = QDateTime::currentDateTimeUtc();
- if (now - m_lastFailed < 2s) {
- m_failedCount++;
- if (m_failedCount > 3) {
- m_unavailable = true;
- Q_EMIT availableChanged();
- }
- } else {
- m_failedCount = 0;
- }
- m_lastFailed = now;
-
- Q_EMIT failed();
- });
- connect(d, &PamWorker::loginFailedDelayStarted, this, &PamAuthenticator::loginFailedDelayStarted);
-
- m_thread.start();
-
- QMetaObject::invokeMethod(d, [this]() {
- d->start();
- });
+ new ScreenlockerAdaptor(this);
+ startWorker();
}
PamAuthenticator::~PamAuthenticator()
{
- // This is a special thread type that cleans up the worker before returning to us.
- m_thread.quit();
- m_thread.wait();
+ quitWorkerProcess();
}
bool PamAuthenticator::isBusy() const
@@ -128,17 +76,78 @@ bool PamAuthenticator::isUnlocked() const
void PamAuthenticator::tryUnlock()
{
m_unlocked = false;
- QMetaObject::invokeMethod(d, &PamWorker::authenticate);
+
+ if (m_busy) {
+ return;
+ }
+
+ if (!m_dbusWorker) {
+ qCWarning(KSCREENLOCKER_GREET) << "DBus worker not initialized, cannot authenticate yet.";
+ return;
+ }
+
+ if (m_unavailable) {
+ qCDebug(KSCREENLOCKER_GREET) << "PAM service is not available. Cannot authenticate.";
+ return;
+ }
+
+ setBusy(true);
+ auto watcher = new QDBusPendingCallWatcher(m_dbusWorker->Authenticate(), this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher]() {
+ watcher->deleteLater();
+ setBusy(false);
+
+ if (watcher->error().isValid()) {
+ qCWarning(KSCREENLOCKER_GREET) << "PAM worker failed to authenticate:" << watcher->error().message();
+ Q_EMIT failed();
+ return;
+ }
+
+ decltype(m_dbusWorker->Authenticate()) reply = watcher->reply();
+ switch (reply.value()) {
+ case WorkerResult::Type::Failure: {
+ // Guard against particularly broken PAM services. For example when pam-u2f doesn't find a token because it is
+ // not plugged in it will fail the authentication, but it will do it so slowly that the timing checks in the
+ // worker itself don't bite.
+ // Here we can keep a higher level view of the failures and if need be break the loop by marking us unavailable.
+ auto now = QDateTime::currentDateTimeUtc();
+ if (now - m_lastFailed < 2s) {
+ m_failedCount++;
+ if (m_failedCount > 3) {
+ m_unavailable = true;
+ Q_EMIT availableChanged();
+ }
+ } else {
+ m_failedCount = 0;
+ }
+ m_lastFailed = now;
+
+ Q_EMIT failed();
+ return;
+ }
+ case WorkerResult::Type::Success:
+ m_unlocked = true;
+ Q_EMIT succeeded();
+ return;
+ case WorkerResult::Type::Unavailable:
+ m_unavailable = true;
+ Q_EMIT availableChanged();
+ return;
+ };
+
+ qWarning() << "Unexpected authentication result" << reply.value();
+ });
}
void PamAuthenticator::respond(const QByteArray &response)
{
- QMetaObject::invokeMethod(
- d,
- [this, response]() {
- Q_EMIT d->promptResponseReceived(response);
- },
- Qt::QueuedConnection);
+ if (m_pendingPrompt.type() != QDBusMessage::InvalidMessage && m_dbusWorker) {
+ QDBusMessage reply = m_pendingPrompt.createReply(QString::fromUtf8(response));
+ m_dbusWorker->connection().send(reply);
+ m_pendingPrompt = {};
+ } else {
+ qCWarning(KSCREENLOCKER_GREET) << "Received prompt response, but no pending prompt was found!";
+ }
}
void PamAuthenticator::cancel()
@@ -147,7 +156,18 @@ void PamAuthenticator::cancel()
m_promptForSecret.clear();
m_infoMessage.clear();
m_errorMessage.clear();
- QMetaObject::invokeMethod(d, &PamWorker::cancelled);
+
+ if (!m_dbusWorker) {
+ return;
+ }
+
+ // Timings here are tight because we may need to cancel two workers, we don't want to get stuck on this for too long.
+ // Let it quit on its own. Mind that this usually will get stuck because the worker is itself waiting for a prompt response.
+ std::ignore = m_dbusWorker->Cancel();
+ if (m_workerProcess) {
+ m_workerProcess->waitForFinished((5ms).count());
+ }
+ quitWorkerProcess();
}
QString PamAuthenticator::getPrompt() const
@@ -186,20 +206,113 @@ void PamAuthenticator::setInPasswordDelay(bool timeout)
Q_EMIT inPasswordDelayChanged();
}
-PamAuthenticator::WorkerThread::WorkerThread(std::unique_ptr<PamWorker> &&worker, QObject *parent)
- : QThread(parent)
- , m_worker(std::move(worker))
+void PamAuthenticator::Ping(const QString &message)
+{
+ qCDebug(KSCREENLOCKER_GREET) << "Ping received" << message << calledFromDBus();
+ if (!m_dbusWorker) {
+ qCWarning(KSCREENLOCKER_GREET) << "Worker pinged before DBus worker interface was initialized.";
+ return;
+ }
+
+ auto watcher = new QDBusPendingCallWatcher(m_dbusWorker->Start(m_service, m_user), this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, [watcher]() {
+ watcher->deleteLater();
+ Q_ASSERT(watcher->isValid());
+ });
+}
+
+QString PamAuthenticator::Prompt(const QString &msg)
+{
+ return promptInternal(msg, false);
+}
+
+QString PamAuthenticator::MaskedPrompt(const QString &msg)
+{
+ return promptInternal(msg, true);
+}
+
+void PamAuthenticator::StartFailedDelay(uint useconds)
+{
+ setInPasswordDelay(true);
+ QTimer::singleShot(std::chrono::microseconds(useconds), this, [this]() {
+ setInPasswordDelay(false);
+ });
+ Q_EMIT loginFailedDelayStarted(useconds);
+}
+
+void PamAuthenticator::InfoMessage(const QString &msg)
+{
+ m_infoMessage = msg;
+ Q_EMIT infoMessage(msg);
+}
+
+void PamAuthenticator::ErrorMessage(const QString &msg)
{
- m_worker->moveToThread(this);
+ m_errorMessage = msg;
+ Q_EMIT errorMessage(msg);
}
-[[nodiscard]] PamWorker *PamAuthenticator::WorkerThread::worker() const
+QString PamAuthenticator::promptInternal(const QString &msg, bool isSecret)
{
- return m_worker.get();
+ setBusy(false);
+
+ if (isSecret) {
+ m_promptForSecret = msg;
+ Q_EMIT promptForSecret(msg);
+ } else {
+ m_prompt = msg;
+ Q_EMIT prompt(msg);
+ }
+
+ qCDebug(KSCREENLOCKER_GREET,
+ "[PAM worker %s] Message: %s: %s",
+ qUtf8Printable(m_service),
+ (isSecret ? "Echo-off prompt" : "Echo-on prompt"),
+ qUtf8Printable(msg));
+
+ setDelayedReply(true);
+ m_pendingPrompt = message();
+
+ return {};
+}
+
+void PamAuthenticator::quitWorkerProcess()
+{
+ if (m_workerProcess) {
+ m_workerProcess->terminate();
+ if (!m_workerProcess->waitForFinished((25ms).count())) {
+ qWarning() << "Worker did not terminate in time, killing it.";
+ m_workerProcess->kill();
+ }
+ }
+ m_dbusWorker.reset();
+ m_workerProcess = nullptr;
+}
+
+void PamAuthenticator::startWorker()
+{
+ Q_ASSERT(!m_workerProcess);
+
+ qCDebug(KSCREENLOCKER_GREET) << "Starting PAM worker for service" << m_service << "and user" << m_user;
+
+ m_server = new QDBusServer(this);
+ connect(m_server, &QDBusServer::newConnection, this, &PamAuthenticator::connectWorker);
+
+ m_workerProcess = new QProcess(this);
+ m_workerProcess->setProcessChannelMode(QProcess::ForwardedChannels);
+ m_workerProcess->setProgram(KLibexec::path(u"kscreenlocker_worker"_s));
+ m_workerProcess->setArguments({m_service});
+ m_workerProcess->start();
+ m_workerProcess->write(m_server->address().toUtf8());
+ m_workerProcess->closeWriteChannel();
}
-void PamAuthenticator::WorkerThread::run()
+void PamAuthenticator::connectWorker(const QDBusConnection &connection)
{
- QThread::run();
- m_worker.reset();
+ Q_ASSERT(!m_dbusWorker); // only accept a connection once to mitigate the risk of a malicious actor connecting to us
+ qCDebug(KSCREENLOCKER_GREET) << "New D-Bus connection established" << connection.name();
+ auto c = connection; // make a non-const copy
+ c.registerObject(u"/org/kde/plasma/screenlocker"_s, this, QDBusConnection::ExportAdaptors);
+ m_dbusWorker = std::make_unique<OrgKdePlasmaScreenlockerWorkerInterface>(QString(), u"/org/kde/plasma/screenlocker/worker"_s, c);
+ m_dbusWorker->setTimeout(std::numeric_limits<int>::max()); // disable timeout, we expect blocking calls to arrive eventually
}
diff --git a/greeter/pamauthenticator.h b/greeter/pamauthenticator.h
index aa562f60..a9c0de5e 100644
--- a/greeter/pamauthenticator.h
+++ b/greeter/pamauthenticator.h
@@ -7,14 +7,19 @@
#pragma once
+#include <QDBusConnection>
+#include <QDBusContext>
+#include <QDBusMessage>
#include <QDateTime>
#include <QObject>
-#include <QThread>
+#include <memory>
#include <qqmlregistration.h>
-class PamWorker;
+class QDBusServer;
+class QProcess;
+class OrgKdePlasmaScreenlockerWorkerInterface;
-class PamAuthenticator : public QObject
+class PamAuthenticator : public QObject, protected QDBusContext
{
Q_OBJECT
QML_NAMED_ELEMENT(Authenticator)
@@ -102,9 +107,19 @@ public Q_SLOTS:
void tryUnlock();
void respond(const QByteArray &response);
void cancel();
+ void Ping(const QString &message);
+ [[nodiscard]] QString Prompt(const QString &msg);
+ [[nodiscard]] QString MaskedPrompt(const QString &msg);
+ void StartFailedDelay(uint useconds);
+ void InfoMessage(const QString &msg);
+ void ErrorMessage(const QString &msg);
private:
void setBusy(bool busy);
+ [[nodiscard]] QString promptInternal(const QString &msg, bool isSecret);
+ void quitWorkerProcess();
+ void startWorker();
+ void connectWorker(const QDBusConnection &connection);
const std::vector<std::pair<QMetaMethod, const QString &>> m_signalsToMembers;
// NOTE Don't forget to reset in cancel as necessary
@@ -120,22 +135,11 @@ private:
uint m_failedCount = 0;
QDateTime m_lastFailed = QDateTime::currentDateTimeUtc();
NoninteractiveAuthenticatorTypes m_authenticatorType;
- // Tiny problem with bare bones QThread: when we shut down we want to clean up
- // our subprocess correctly, but doing that means running a function on the thread
- // before terminating it. This doesn't work out of the box because ther are
- // no facilities to effectively invokeMethod while the QApplication is already
- // mid shutdown. Instead we have a custom thread type that calls cleanup on the worker.
- class WorkerThread : public QThread
- {
- public:
- WorkerThread(std::unique_ptr<PamWorker> &&worker, QObject *parent = nullptr);
- [[nodiscard]] PamWorker *worker() const;
- void run() override;
-
- private:
- std::unique_ptr<PamWorker> m_worker;
- } m_thread;
- PamWorker *d;
+ QDBusMessage m_pendingPrompt;
+ QDBusServer *m_server = nullptr;
+ std::unique_ptr<OrgKdePlasmaScreenlockerWorkerInterface> m_dbusWorker;
+ QProcess *m_workerProcess = nullptr;
+ QString m_user;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(PamAuthenticator::NoninteractiveAuthenticatorTypes)
diff --git a/greeter/pamworker.cpp b/greeter/pamworker.cpp
deleted file mode 100644
index 012e123a..00000000
--- a/greeter/pamworker.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
-// SPDX-FileCopyrightText: 2020 David Edmundson <[email protected]>
-// SPDX-FileCopyrightText: 2026 Harald Sitter <[email protected]>
-
-#include "pamworker.h"
-
-#include <QDBusConnection>
-#include <QDBusMessage>
-#include <QDBusPendingCall>
-#include <QDBusServer>
-#include <QProcess>
-#include <QTimer>
-
-#include <KLibexec>
-
-#include "kscreenlocker_greet_logging.h"
-#include "result.h"
-#include "screenlockeradaptor.h"
-
-using namespace std::chrono_literals;
-using namespace Qt::StringLiterals;
-
-PamWorker::PamWorker(const QString &service, const QString &user)
- : QObject(nullptr)
- , m_nextAttemptAllowedTime(std::chrono::steady_clock::now())
- , m_service(service)
- , m_username(user)
-{
- connect(this, &PamWorker::promptResponseReceived, this, [this](const QByteArray &response) {
- if (m_pendingPrompt.type() != QDBusMessage::InvalidMessage) {
- QDBusMessage reply = m_pendingPrompt.createReply(QString::fromUtf8(response));
- m_dbusWorker->connection().send(reply);
- m_pendingPrompt = {};
- } else {
- qCWarning(KSCREENLOCKER_GREET) << "Received prompt response, but no pending prompt was found!";
- }
- });
-
- connect(this, &PamWorker::cancelled, this, [this] {
- if (!m_dbusWorker) {
- return;
- }
- // Timings here are tight because we may need to cancel two workers, we don't want to get stuck on this for too long.
- // Let it quit on its own. Mind that this usually will get stuck because the worker is itself waiting for a prompt response.
- std::ignore = m_dbusWorker->Cancel();
- if (m_workerProcess) {
- m_workerProcess->waitForFinished((5ms).count());
- }
- // Make sure everything is cleaned up properly
- quitWorkerProcess();
- });
-}
-
-PamWorker::~PamWorker()
-{
- quitWorkerProcess();
-}
-
-void PamWorker::authenticate()
-{
- if (m_inAuthenticate) {
- // No need to log in this case. We call authenticate multiple times to keep the auth session running even
- // when the backend (e.g. fprint) aborts things.
- return;
- }
-
- if (!m_dbusWorker) {
- qCWarning(KSCREENLOCKER_GREET) << "DBus worker not initialized, cannot authenticate yet. Retry in a bit.";
- return;
- }
-
- if (m_unavailable) {
- qCDebug(KSCREENLOCKER_GREET) << "PAM service is not available. Cannot authenticate.";
- return;
- }
-
- m_inAuthenticate = true;
- Q_EMIT inAuthenticateChanged(m_inAuthenticate);
- Q_EMIT busyChanged(true);
- auto scopedAuthenticate = qScopeGuard([this] {
- m_inAuthenticate = false;
- Q_EMIT inAuthenticateChanged(m_inAuthenticate);
- Q_EMIT busyChanged(false);
- });
-
- auto watcher = new QDBusPendingCallWatcher(m_dbusWorker->Authenticate(), this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [scopedAuthenticate = std::move(scopedAuthenticate), watcher, this]() {
- watcher->deleteLater();
- if (watcher->error().isValid()) {
- qCWarning(KSCREENLOCKER_GREET) << "PAM worker failed to authenticate:" << watcher->error().message();
- Q_EMIT failed();
- return;
- }
-
- decltype(m_dbusWorker->Authenticate()) reply = watcher->reply();
- switch (reply.value()) {
- case WorkerResult::Type::Failure:
- Q_EMIT failed();
- return;
- case WorkerResult::Type::Success:
- Q_EMIT succeeded();
- return;
- case WorkerResult::Type::Unavailable:
- m_unavailable = true;
- Q_EMIT unavailabilityChanged(m_unavailable);
- return;
- };
-
- qWarning() << "Unexpected authentication result" << reply.value();
- });
-}
-
-void PamWorker::StartFailedDelay(uint useconds)
-{
- m_nextAttemptAllowedTime = std::chrono::steady_clock::now() + std::chrono::microseconds(useconds);
- Q_EMIT inPasswordDelayChanged(true);
- QTimer::singleShot(std::chrono::microseconds(useconds), this, [this]() {
- Q_EMIT inPasswordDelayChanged(false);
- });
- Q_EMIT loginFailedDelayStarted(useconds);
-}
-
-void PamWorker::InfoMessage(const QString &msg)
-{
- Q_EMIT infoMessage(msg);
-}
-
-void PamWorker::ErrorMessage(const QString &msg)
-{
- Q_EMIT errorMessage(msg);
-}
-
-void PamWorker::start()
-{
- Q_ASSERT(!m_workerProcess);
-
- qCDebug(KSCREENLOCKER_GREET) << "Starting PAM worker for service" << m_service << "and user" << m_username;
- new ScreenlockerAdaptor(this);
-
- auto server = new QDBusServer(this);
- QObject::connect(server, &QDBusServer::newConnection, this, [this](const QDBusConnection &connection) {
- Q_ASSERT(!m_dbusWorker); // only accept a connection once to mitigate the risk of a malicious actor connecting to us
- qCDebug(KSCREENLOCKER_GREET) << "New D-Bus connection established" << connection.name();
- auto c = connection; // make a non-const copy
- c.registerObject(u"/org/kde/plasma/screenlocker"_s, this, QDBusConnection::ExportAdaptors);
- m_dbusWorker = std::make_unique<org::kde::plasma::screenlocker::worker>(QString(), u"/org/kde/plasma/screenlocker/worker"_s, c);
- m_dbusWorker->setTimeout(std::numeric_limits<int>::max()); // disable timeout, we expect blocking calls to arrive eventually
- });
-
- m_workerProcess = new QProcess(this);
- m_workerProcess->setProcessChannelMode(QProcess::ForwardedChannels);
- m_workerProcess->setProgram(KLibexec::path(u"kscreenlocker_worker"_s));
- m_workerProcess->setArguments({m_service});
- m_workerProcess->start();
- m_workerProcess->write(server->address().toUtf8());
- m_workerProcess->closeWriteChannel();
-}
-
-void PamWorker::Ping(const QString &message)
-{
- qCDebug(KSCREENLOCKER_GREET) << "Ping received" << message << calledFromDBus();
- org::kde::plasma::screenlocker::worker worker(QString(), u"/org/kde/plasma/screenlocker/worker"_s, connection());
- auto watcher = new QDBusPendingCallWatcher(worker.Start(m_service, m_username), this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [watcher]() {
- watcher->deleteLater();
- Q_ASSERT(watcher->isValid());
- });
-}
-
-QString PamWorker::Prompt(const QString &msg)
-{
- return promptInternal(msg, false);
-}
-
-QString PamWorker::MaskedPrompt(const QString &msg)
-{
- return promptInternal(msg, true);
-}
-
-QString PamWorker::promptInternal(const QString &msg, bool isSecret)
-{
- Q_EMIT busyChanged(false);
-
- if (isSecret) {
- Q_EMIT promptForSecret(msg);
- } else {
- Q_EMIT prompt(msg);
- }
-
- qCDebug(KSCREENLOCKER_GREET,
- "[PAM worker %s] Message: %s: %s",
- qUtf8Printable(m_service),
- (isSecret ? "Echo-off prompt" : "Echo-on prompt"),
- qUtf8Printable(msg));
-
- setDelayedReply(true);
-
- m_pendingPrompt = message();
-
- return {};
-}
-
-void PamWorker::quitWorkerProcess()
-{
- if (m_workerProcess) {
- m_workerProcess->terminate();
- if (!m_workerProcess->waitForFinished((25ms).count())) {
- qWarning() << "Worker did not terminate in time, killing it.";
- m_workerProcess->kill();
- }
- }
- m_dbusWorker.reset();
- m_workerProcess = nullptr;
-}
diff --git a/greeter/pamworker.h b/greeter/pamworker.h
deleted file mode 100644
index ed2a9e71..00000000
--- a/greeter/pamworker.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
-// SPDX-FileCopyrightText: 2020 David Edmundson <[email protected]>
-// SPDX-FileCopyrightText: 2026 Harald Sitter <[email protected]>
-
-#pragma once
-
-#include <memory>
-
-#include <QDBusContext>
-#include <QDBusMessage>
-#include <QObject>
-
-#include "org.kde.plasma.screenlocker.worker.h"
-
-class QProcess;
-
-class PamWorker : public QObject, QDBusContext
-{
- Q_OBJECT
-public:
- PamWorker(const QString &service, const QString &user);
- ~PamWorker() override;
- Q_DISABLE_COPY_MOVE(PamWorker)
- void start();
- void authenticate();
- void StartFailedDelay(uint useconds);
- void InfoMessage(const QString &msg);
- void ErrorMessage(const QString &msg);
-
-public Q_SLOTS:
- void Ping(const QString &message);
- [[nodiscard]] QString Prompt(const QString &msg);
- [[nodiscard]] QString MaskedPrompt(const QString &msg);
-
-Q_SIGNALS:
- void busyChanged(bool busy);
- void promptForSecret(const QString &msg);
- void prompt(const QString &msg);
- void infoMessage(const QString &msg);
- void errorMessage(const QString &msg);
- void failed();
- void loginFailedDelayStarted(const uint uSecDelay);
- void succeeded();
- void unavailabilityChanged(bool unavailable);
- void inAuthenticateChanged(bool inAuthenticate);
- void inPasswordDelayChanged(bool timeout);
-
- // internal
- void promptResponseReceived(const QByteArray &prompt);
- void cancelled();
-
-private:
- [[nodiscard]] QString promptInternal(const QString &msg, bool isSecret);
- void quitWorkerProcess();
-
- bool m_unavailable = false;
- bool m_inAuthenticate = false;
- std::chrono::steady_clock::time_point m_nextAttemptAllowedTime;
- int m_result = -1;
- QString m_service;
- QString m_username;
- QDBusMessage m_pendingPrompt;
- std::unique_ptr<org::kde::plasma::screenlocker::worker> m_dbusWorker;
- QProcess *m_workerProcess = nullptr;
-};