[plasma/kscreenlocker] /: repair pamtest
Harald Sitter <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit d3c857b5792ffea071720e164ea8c3d231b8a787 by Harald Sitter.
Committed on 18/08/2026 at 11:15.
Pushed by sitter into branch 'master'.
repair pamtest
bit of a mixed bag
- we now *require* pam_wrapper inside the test scope
- pam_wrapper 1.1.6 is now necessary so we can run it on CI as well and
don't need UID_WRAPPER_DISABLE_DEEPBIND
- environment variables on the test get no longer thrashed
- environment variables on the test are now managed as a list variable
for ease of reading and the ability to comment on stuff
- do not configure test_service in the wrong dir
- use different dirs for services and data so we can QFINDTESTDATA them
- wait for ready signal from authenticator (previously authenticators
were always ready. now they are not)
- disable the auth time checking to prevent pam_matrix from triggering
them by being too quick to authenticate
M +15 -16 autotests/CMakeLists.txt
M +7 -1 autotests/pamtest.cpp
M +4 -0 greeter/pamauthenticator.cpp
M +3 -0 greeter/pamauthenticator.h
M +3 -1 greeter/worker/main.cpp
https://invent.kde.org/plasma/kscreenlocker/-/commit/d3c857b5792ffea071720e164ea8c3d231b8a787
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index 8bde2c0e..d7138eef 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -19,19 +19,18 @@ ecm_mark_as_test(logindTest)
# PamTest
#######################################
-pkg_search_module(PamWrapper pam_wrapper)
-# We're turning it off on the CI until pam_wrapper 1.15 is available on our image (which adds sanitizer support.)
-# see https://invent.kde.org/plasma/kscreenlocker/-/issues/11 for more details
-if (PamWrapper_FOUND AND NOT "$ENV{KDECI_BUILD}" STREQUAL "TRUE")
- pkg_get_variable(PamWrapperModuleDir pam_wrapper "modules")
- configure_file(data/test_service.in ./test_service)
- add_executable(pamTest pamtest.cpp)
- target_link_libraries(pamTest Qt::Test kscreenlocker_authenticator)
- add_test(NAME ksmserver-pamTest COMMAND pamTest)
- # they made a mistake in the env name, so set both old and new
- set_tests_properties(ksmserver-pamTest PROPERTIES ENVIRONMENT "UID_WRAPPER_DISABLE_DEEPBIND=1;PAM_WRAPPER_DISABLE_DEEPBIND=1")
- ecm_mark_as_test(pamTest)
- set_property(TEST ksmserver-pamTest
- PROPERTY
- ENVIRONMENT "LD_PRELOAD=libpam_wrapper.so;ASAN_OPTIONS=verify_asan_link_order=0")
-endif()
+pkg_search_module(PamWrapper REQUIRED pam_wrapper>=1.1.6)
+pkg_get_variable(PamWrapperModuleDir pam_wrapper "modules")
+# We use a different target dir so we can QFINDTESTDATA the two dirs separately
+configure_file(data/test_service.in services/test_service)
+add_executable(pamTest pamtest.cpp)
+target_link_libraries(pamTest Qt::Test kscreenlocker_authenticator)
+add_test(NAME ksmserver-pamTest COMMAND pamTest)
+set(ksmserver-pamTest-environment
+ # We need to disable deepbind for pam_wrapper to work with ASAN
+ "PAM_WRAPPER_DISABLE_DEEPBIND=1"
+ "LD_PRELOAD=libpam_wrapper.so"
+ "ASAN_OPTIONS=verify_asan_link_order=0"
+)
+set_tests_properties(ksmserver-pamTest PROPERTIES ENVIRONMENT "${ksmserver-pamTest-environment}")
+ecm_mark_as_test(pamTest)
diff --git a/autotests/pamtest.cpp b/autotests/pamtest.cpp
index eb84df65..a3f7cc11 100644
--- a/autotests/pamtest.cpp
+++ b/autotests/pamtest.cpp
@@ -29,19 +29,25 @@ PamTest::PamTest()
qputenv("PAM_WRAPPER", "1");
qputenv("PAM_WRAPPER_DEBUGLEVEL", "2"); // DEBUG level
- qputenv("PAM_WRAPPER_SERVICE_DIR", QFINDTESTDATA("data").toUtf8());
+ qputenv("PAM_WRAPPER_SERVICE_DIR", QFINDTESTDATA("services").toUtf8());
qputenv("PAM_MATRIX_PASSWD", QFINDTESTDATA("data/test_db").toUtf8());
+
+ // Do not trigger the time checks. pam_matrix will respond way too quickly (expectedly)!
+ qputenv("KSCREENLOCKER_PAM_TIME_CHECK", "0");
}
void PamTest::testLogin()
{
PamAuthenticator auth(QStringLiteral("test_service"), QStringLiteral("test_user"));
+ QSignalSpy readySpy(&auth, &PamAuthenticator::readyChanged);
QSignalSpy promptSpy(&auth, &PamAuthenticator::prompt);
QSignalSpy promptForSecretSpy(&auth, &PamAuthenticator::promptForSecret);
QSignalSpy succeededSpy(&auth, &PamAuthenticator::succeeded);
QSignalSpy failedSpy(&auth, &PamAuthenticator::failed);
QSignalSpy busyChangedSpy(&auth, &PamAuthenticator::busyChanged);
+ QVERIFY(readySpy.wait());
+
// invalid password
auth.tryUnlock();
diff --git a/greeter/pamauthenticator.cpp b/greeter/pamauthenticator.cpp
index b343b87a..07ab8f88 100644
--- a/greeter/pamauthenticator.cpp
+++ b/greeter/pamauthenticator.cpp
@@ -219,6 +219,10 @@ void PamAuthenticator::Ping(const QString &message)
watcher->deleteLater();
Q_ASSERT(watcher->isValid());
});
+
+ Q_ASSERT(!m_ready); // only one ping ever. thank you!
+ m_ready = true;
+ Q_EMIT readyChanged();
}
QString PamAuthenticator::Prompt(const QString &msg)
diff --git a/greeter/pamauthenticator.h b/greeter/pamauthenticator.h
index a9c0de5e..d70064c4 100644
--- a/greeter/pamauthenticator.h
+++ b/greeter/pamauthenticator.h
@@ -25,6 +25,7 @@ class PamAuthenticator : public QObject, protected QDBusContext
QML_NAMED_ELEMENT(Authenticator)
QML_UNCREATABLE("Not exposed except for its enum")
+ Q_PROPERTY(bool ready MEMBER m_ready NOTIFY readyChanged)
Q_PROPERTY(bool busy READ isBusy NOTIFY busyChanged)
Q_PROPERTY(bool inPasswordDelay READ inPasswordDelay NOTIFY inPasswordDelayChanged)
Q_PROPERTY(bool available READ isAvailable NOTIFY availableChanged)
@@ -92,6 +93,7 @@ public:
void setInPasswordDelay(bool timeout);
Q_SIGNALS:
+ void readyChanged();
void busyChanged();
void promptForSecret(const QString &msg);
void prompt(const QString &msg);
@@ -128,6 +130,7 @@ private:
QString m_errorMessage;
QString m_infoMessage;
QString m_service;
+ bool m_ready = false;
bool m_busy = false;
bool m_unlocked = false;
bool m_unavailable = false;
diff --git a/greeter/worker/main.cpp b/greeter/worker/main.cpp
index b0685d94..0ccd0ace 100644
--- a/greeter/worker/main.cpp
+++ b/greeter/worker/main.cpp
@@ -246,8 +246,10 @@ WorkerResult::Type Worker::authenticate()
qCWarning(WORKER) << timer.elapsed() << "ms elapsed during pam_authenticate call for service" << qUtf8Printable(m_service) << "with result code" << rc;
+ constexpr auto checkTimesDefault = "1"_L1;
+ static const auto checkTimes = qEnvironmentVariable("KSCREENLOCKER_PAM_TIME_CHECK", checkTimesDefault) == checkTimesDefault;
constexpr auto tooQuick = 50ms;
- if (timer.durationElapsed() <= tooQuick) {
+ if (checkTimes && timer.durationElapsed() <= tooQuick) {
// This happened faster than is reasonable for any service -> let's mark as unavailable to avoid hammering a broken service with retries
// Has been observed with the vibe coded face authenticators on github. They will report success in 0ms when they are totally defunct.
qCWarning(WORKER) << "Unexpectedly short auth error on PAM service" << qUtf8Printable(m_service) << timer.durationElapsed();