File indexing completed on 2024-04-28 16:52:17

0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 // SPDX-FileCopyrightText: 2020 Lucas Biaggi <lbjanuario@gmail.com>
0003 /*
0004  * Firewalld backend for plasma firewall
0005  */
0006 
0007 #include <KLocalizedString>
0008 #include <QDBusConnection>
0009 #include <QDBusPendingCall>
0010 #include <QDBusPendingReply>
0011 #include <QDebug>
0012 #include <QTimer>
0013 
0014 #include "systemdjob.h"
0015 namespace SYSTEMD
0016 {
0017 const QString BUS = QStringLiteral("org.freedesktop.systemd1");
0018 const QString PATH = QStringLiteral("/org/freedesktop/systemd1");
0019 const QString INTERFACE = QStringLiteral("org.freedesktop.systemd1.Manager");
0020 }
0021 
0022 Q_LOGGING_CATEGORY(SystemDJobDebug, "systemd.job")
0023 
0024 enum {
0025     DBUSSYSTEMDERROR = KJob::UserDefinedError,
0026 };
0027 
0028 SystemdJob::SystemdJob(const SYSTEMD::actions &action, const QString &service, bool serviceOnly)
0029     : KJob()
0030     , m_action(action)
0031     , m_service(service)
0032     , m_serviceOnly(serviceOnly){};
0033 
0034 void SystemdJob::systemdAction(const SYSTEMD::actions value)
0035 {
0036     QDBusMessage call;
0037     QVariantList unitData;
0038     switch (value) {
0039     case SYSTEMD::START:
0040         call = QDBusMessage::createMethodCall(SYSTEMD::BUS, SYSTEMD::PATH, SYSTEMD::INTERFACE, QStringLiteral("StartUnit"));
0041         call.setArguments({m_service, "fail"});
0042         unitData << QStringList(m_service) << false << true;
0043         break;
0044     case SYSTEMD::STOP:
0045         call = QDBusMessage::createMethodCall(SYSTEMD::BUS, SYSTEMD::PATH, SYSTEMD::INTERFACE, QStringLiteral("StopUnit"));
0046         call.setArguments({m_service, "fail"});
0047         unitData << QStringList(m_service) << false;
0048         break;
0049 
0050     default:
0051         setErrorText(i18n("Invalid Call"));
0052         setError(DBUSSYSTEMDERROR);
0053         emitResult();
0054     }
0055 
0056     /* waiting for start/stop of firewalld */
0057     if (!m_serviceOnly) {
0058         QDBusPendingCall message = QDBusConnection::systemBus().asyncCall(call);
0059         QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(message, this);
0060         connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, unitData, value](QDBusPendingCallWatcher *watcher) {
0061             QDBusPendingReply<> reply = *watcher;
0062             watcher->deleteLater();
0063             if (reply.isError()) {
0064                 setErrorText(reply.reply().errorMessage());
0065                 setError(DBUSSYSTEMDERROR);
0066                 emitResult();
0067             }
0068 
0069             systemdUnit(unitData, value);
0070         });
0071         return;
0072     }
0073 
0074     systemdUnit(unitData, value);
0075 }
0076 
0077 void SystemdJob::systemdUnit(const QVariantList values, SYSTEMD::actions action)
0078 {
0079     QDBusMessage call;
0080     const QString actionType = action == SYSTEMD::START ? "EnableUnitFiles" : "DisableUnitFiles";
0081     call = QDBusMessage::createMethodCall(SYSTEMD::BUS, SYSTEMD::PATH, SYSTEMD::INTERFACE, actionType);
0082     call.setArguments(values);
0083     call.setInteractiveAuthorizationAllowed(true);
0084     QDBusPendingCall message = QDBusConnection::systemBus().asyncCall(call);
0085     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(message, this);
0086     connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
0087         QDBusPendingReply<> reply = *watcher;
0088         watcher->deleteLater();
0089         if (reply.isError()) {
0090             setErrorText(reply.reply().errorMessage());
0091             setError(DBUSSYSTEMDERROR);
0092             emitResult();
0093         }
0094         reloadSystemd();
0095     });
0096 }
0097 
0098 void SystemdJob::reloadSystemd()
0099 {
0100     QDBusMessage call;
0101     call = QDBusMessage::createMethodCall(SYSTEMD::BUS, SYSTEMD::PATH, SYSTEMD::INTERFACE, QStringLiteral("Reload"));
0102     QDBusPendingCall message = QDBusConnection::systemBus().asyncCall(call);
0103     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(message, this);
0104     connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
0105         QDBusPendingReply<> reply = *watcher;
0106         watcher->deleteLater();
0107         if (reply.isError()) {
0108             setErrorText(reply.reply().errorMessage());
0109             setError(DBUSSYSTEMDERROR);
0110         }
0111         emitResult();
0112     });
0113 }
0114 SystemdJob::~SystemdJob() = default;
0115 
0116 void SystemdJob::start()
0117 {
0118     systemdAction(m_action);
0119 };