kcms/dateandtime: Auth manually before issuing calls to timedate1

Authorization for set-time implies set-ntp and set-timezone, if acquired first
then the user will only see one polkit dialog. However ntp needs to be disabled
first before the time can be changed. Unfortunately due to deficiencies inside
KAuth with the Polkit backend it's not possible to  authorize an arbitrary action,
so Polkit-qt is used for this. The code "executes" still a KAuth action to make
use of the  side channel for parent window and activation token to our agent,
but since the action doesn't have a helper will actually not execute anything.
This commit is contained in:
David Redondo 2026-09-30 16:18:55 +02:00
parent e4805a6d4a
commit 8af82f5f6a
3 changed files with 22 additions and 0 deletions

View file

@ -88,6 +88,7 @@ find_package(Plasma ${PROJECT_DEP_VERSION} REQUIRED)
find_package(PlasmaQuick ${PROJECT_DEP_VERSION} REQUIRED)
find_package(PlasmaActivities ${PROJECT_DEP_VERSION} REQUIRED)
find_package(PlasmaActivitiesStats ${PROJECT_DEP_VERSION} REQUIRED)
find_package(PolkitQt6-1 REQUIRED)
if(BUILD_TESTING)
find_package(Qt6Test ${QT_MIN_VERSION} CONFIG REQUIRED)

View file

@ -25,5 +25,7 @@ target_link_libraries(kcm_clock
KF6::KIOCore
KF6::KIOWidgets
KF6::Svg
KF6::AuthCore
PolkitQt6-1::Core
)
install(TARGETS kcm_clock DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/kcms/systemsettings_qwidgets )

View file

@ -13,8 +13,12 @@
#include <QVBoxLayout>
#include <KAboutData>
#include <KAuth/Action>
#include <KAuth/ExecuteJob>
#include <KMessageBox>
#include <KPluginFactory>
#include <PolkitQt1/Authority>
#include <PolkitQt1/Subject>
#include <QDBusConnection>
#include "dtime.h"
@ -47,6 +51,21 @@ bool KclockModule::timedatedSave()
QStringLiteral("/org/freedesktop/timedate1"),
QDBusConnection::systemBus());
// Auth manually for "set-time", this implies authroization for all the other actions => the user only sees one popup
// HACK First We use KAuth here just so it sidechannels parent window and activation token for us, everything else is noop because no helper
KAuth::Action action(authActionName());
action.setParentWindow(widget()->window()->windowHandle());
auto job = action.execute();
job->exec();
// Second do the actual authorization manually
auto authority = PolkitQt1::Authority::instance();
auto authorized = authority->checkAuthorizationSync(authActionName(),
PolkitQt1::SystemBusNameSubject(QDBusConnection::systemBus().baseService()),
PolkitQt1::Authority::AllowUserInteraction);
if (authorized != PolkitQt1::Authority::Yes) {
return false;
}
// final arg in each method is "user-interaction" i.e whether it's OK for polkit to ask for auth
// we cannot send requests up front then block for all replies as we need NTP to be disabled before we can make a call to SetTime