kfirewall: move from kde-workspace

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-05-07 13:56:34 +03:00
parent 9b30ea4993
commit 015674649d
12 changed files with 1012 additions and 0 deletions

10
kfirewall/CMakeLists.txt Normal file
View file

@ -0,0 +1,10 @@
project(kfirewall)
find_program(IPTABLES_EXECUTABLE iptables-restore)
add_feature_info(iptables
IPTABLES_EXECUTABLE
"Firewall support"
)
add_subdirectory(kcm)
add_subdirectory(kded)

View file

@ -0,0 +1,37 @@
########### next target ###############
set(kfirewallconfig_SRCS
kfirewallconfig.cpp
kfirewallconfig.ui
)
kde4_add_plugin(kcm_kfirewallconfig ${kfirewallconfig_SRCS})
target_link_libraries(kcm_kfirewallconfig
${KDE4_KDEUI_LIBS}
${KDE4_KCMUTILS_LIBS}
)
install(
TARGETS kcm_kfirewallconfig
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}
)
install(
FILES kcm_kfirewallconfig.desktop
DESTINATION ${KDE4_SERVICES_INSTALL_DIR}
)
########### next target ###############
add_executable(kcmkfirewallhelper kfirewallhelper.cpp)
target_link_libraries(kcmkfirewallhelper
${KDE4_KDECORE_LIBS}
)
install(
TARGETS kcmkfirewallhelper
DESTINATION ${KDE4_LIBEXEC_INSTALL_DIR}
)
kde4_install_auth_helper_files(kcmkfirewallhelper org.kde.kcontrol.kcmkfirewall root)

View file

@ -0,0 +1,16 @@
[Desktop Entry]
Exec=kcmshell4 kfirewallconfig
Icon=security-high
Type=Service
X-KDE-ServiceTypes=KCModule
X-KDE-Library=kcm_kfirewallconfig
X-KDE-ParentApp=kcontrol
X-KDE-System-Settings-Parent-Category=network-settings
X-KDE-System-Settings-Parent-Category-V2=network-settings
X-DocPath=kcontrol/kfirewallconfig/index.html
Categories=Qt;KDE;X-KDE-settings-network-settings;
Name=Firewall
Comment=Change filrewall options
X-KDE-Keywords=Filrewall

View file

@ -0,0 +1,349 @@
/* This file is part of the KDE project
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kfirewallconfig.h"
#include <QJsonDocument>
#include <QFile>
#include <QComboBox>
#include <QSpinBox>
#include <kstandarddirs.h>
#include <kuser.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kauthaction.h>
#include <kaboutdata.h>
#include <kpluginfactory.h>
#include <kpluginloader.h>
#include <kdebug.h>
#include <limits.h>
K_PLUGIN_FACTORY(KCMFirewallFactory, registerPlugin<KCMFirewall>();)
K_EXPORT_PLUGIN(KCMFirewallFactory("kcmfirewallconfig", "kcm_firewallconfig"))
KCMFirewall::KCMFirewall(QWidget* parent, const QVariantList& args)
: KCModule(KCMFirewallFactory::componentData(), parent),
m_kfirewallconfigpath(KStandardDirs::locateLocal("data", "kfirewall.json"))
{
Q_UNUSED(args);
setQuickHelp(i18n("<h1>KFirewall</h1> This module allows you to change KDE firewall options."));
setupUi(this);
const QString iptablesexe = KStandardDirs::findRootExe("iptables-restore");
messagewidget->setMessageType(KMessageWidget::Error);
messagewidget->setCloseButtonVisible(false);
if (iptablesexe.isEmpty()) {
rulestable->setEnabled(false);
addbutton->setEnabled(false);
removebutton->setEnabled(false);
messagewidget->show();
messagewidget->setText(i18n("iptables is not available"));
} else {
messagewidget->hide();
}
KAboutData *about = new KAboutData(
I18N_NOOP("kcmkfirewall"), 0,
ki18n("KDE Firewall Module"),
0, KLocalizedString(), KAboutData::License_GPL,
ki18n("Copyright 2022, Ivailo Monev <email>xakepa10@gmail.com</email>")
);
about->addAuthor(ki18n("Ivailo Monev"), KLocalizedString(), "xakepa10@gmail.com");
setAboutData(about);
setNeedsAuthorization(true);
load();
connect(
rulestable, SIGNAL(itemChanged(QTableWidgetItem*)),
this, SLOT(slotItemChanged(QTableWidgetItem*))
);
connect(
rulestable->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection))
);
rulestable->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
connect(
addbutton, SIGNAL(pressed()),
this, SLOT(slotAddRule())
);
connect(
removebutton, SIGNAL(pressed()),
this, SLOT(slotRemoveRule())
);
}
KCMFirewall::~KCMFirewall()
{
}
void KCMFirewall::load()
{
rulestable->clearContents();
rulestable->setRowCount(0);
QFile kfirewallfile(m_kfirewallconfigpath);
if (!kfirewallfile.open(QFile::ReadOnly)) {
// may not exist yet
kDebug() << "Could not open config for reading" << kfirewallfile.errorString();
emit changed(false);
return;
}
const QByteArray kfirewalljsondata = kfirewallfile.readAll();
QJsonDocument kfirewalljsondocument = QJsonDocument::fromJson(kfirewalljsondata);
if (!kfirewalljsondata.isEmpty() && kfirewalljsondocument.isNull()) {
KMessageBox::error(this, i18n("Could create JSON document: %1", kfirewalljsondocument.errorString()));
return;
}
const QVariantMap kfirewallsettingsmap = kfirewalljsondocument.toVariant().toMap();
// qDebug() << Q_FUNC_INFO << kfirewallsettingsmap;
int counter = 0;
foreach(const QString &key, kfirewallsettingsmap.keys()) {
addRuleRow();
const QVariantMap rowsettingsmap = kfirewallsettingsmap.value(key).toMap();
const QString trafficvalue = rowsettingsmap.value(QString::fromLatin1("traffic")).toString();
const QString addressvalue = rowsettingsmap.value(QString::fromLatin1("address")).toString();
const uint portvalue = rowsettingsmap.value(QString::fromLatin1("port")).toUInt();
const QString actionvalue = rowsettingsmap.value(QString::fromLatin1("action")).toString();
int trafficindex = 0;
if (trafficvalue == QLatin1String("inbound")) {
trafficindex = 0;
} else if (trafficvalue == QLatin1String("outbound")) {
trafficindex = 1;
} else {
kWarning() << "Invalid traffic value";
}
QComboBox* tabletrafficwidget = qobject_cast<QComboBox*>(rulestable->cellWidget(counter, 0));
tabletrafficwidget->setCurrentIndex(trafficindex);
QTableWidgetItem* tableaddresswidget = rulestable->item(counter, 1);
tableaddresswidget->setText(addressvalue);
if (portvalue > INT_MAX) {
kWarning() << "Port value outside range" << portvalue;
}
QSpinBox* tableportwidget = qobject_cast<QSpinBox*>(rulestable->cellWidget(counter, 2));
tableportwidget->setValue(portvalue);
int actionindex = 0;
if (actionvalue == QLatin1String("accept")) {
actionindex = 0;
} else if (actionvalue == QLatin1String("reject")) {
actionindex = 1;
} else {
kWarning() << "Invalid action value" << actionvalue;
}
QComboBox* tableactionwidget = qobject_cast<QComboBox*>(rulestable->cellWidget(counter, 3));
tableactionwidget->setCurrentIndex(actionindex);
counter++;
}
emit changed(false);
}
void KCMFirewall::save()
{
QVariantMap kfirewallsettingsmap;
const QVariant uservalue = QVariant(KUser().loginName());
for (int i = 0; i < rulestable->rowCount(); i++) {
QVariant trafficvalue;
const QComboBox* tabletrafficwidget = qobject_cast<QComboBox*>(rulestable->cellWidget(i, 0));
switch (tabletrafficwidget->currentIndex()) {
case 0: {
trafficvalue = QVariant(QByteArray("inbound"));
break;
}
case 1: {
trafficvalue = QVariant(QByteArray("outbound"));
break;
}
default: {
Q_ASSERT(false);
break;
}
}
// qDebug() << Q_FUNC_INFO << trafficvalue;
const QTableWidgetItem* tableaddresswidget = rulestable->item(i, 1);
const QVariant addressvalue = QVariant(tableaddresswidget->text());
// qDebug() << Q_FUNC_INFO << addressvalue;
const QSpinBox* tableportwidget = qobject_cast<QSpinBox*>(rulestable->cellWidget(i, 2));
const QVariant portvalue = QVariant(tableportwidget->value());
// qDebug() << Q_FUNC_INFO << portvalue;
if (addressvalue.toString().isEmpty() && tableportwidget->value() <= 0) {
KMessageBox::error(this, i18n("Either address or port must be specified"));
return;
}
QVariant actionvalue;
const QComboBox* tableactionwidget = qobject_cast<QComboBox*>(rulestable->cellWidget(i, 3));
switch (tableactionwidget->currentIndex()) {
case 0: {
actionvalue = QVariant(QByteArray("accept"));
break;
}
case 1: {
actionvalue = QVariant(QByteArray("reject"));
break;
}
default: {
Q_ASSERT(false);
break;
}
}
// qDebug() << Q_FUNC_INFO << actionvalue;
QVariantMap rowsettingsmap;
rowsettingsmap.insert(QString::fromLatin1("user"), uservalue);
rowsettingsmap.insert(QString::fromLatin1("traffic"), trafficvalue);
rowsettingsmap.insert(QString::fromLatin1("address"), addressvalue);
rowsettingsmap.insert(QString::fromLatin1("port"), portvalue);
rowsettingsmap.insert(QString::fromLatin1("action"), actionvalue);
kfirewallsettingsmap.insert(QString::number(i), rowsettingsmap);
}
// qDebug() << Q_FUNC_INFO << kfirewallsettingsmap;
QJsonDocument kfirewalljsondocument = QJsonDocument::fromVariant(kfirewallsettingsmap);
if (!kfirewallsettingsmap.isEmpty() && kfirewalljsondocument.isNull()) {
KMessageBox::error(this, i18n("Could create JSON document: %1", kfirewalljsondocument.errorString()));
return;
}
const QByteArray kfirewalljsondata = kfirewalljsondocument.toJson();
QFile kfirewallfile(m_kfirewallconfigpath);
if (!kfirewallfile.open(QFile::WriteOnly)) {
KMessageBox::error(this, i18n("Could not open config for writing: %1", kfirewallfile.errorString()));
return;
}
if (kfirewallfile.write(kfirewalljsondata) != kfirewalljsondata.size()) {
KMessageBox::error(this, i18n("Could not write config: %1", kfirewallfile.errorString()));
return;
}
emit changed(false);
}
void KCMFirewall::defaults()
{
rulestable->clearContents();
rulestable->setRowCount(0);
emit changed(true);
}
void KCMFirewall::addRuleRow()
{
const int rulesrowcount = rulestable->rowCount();
rulestable->setRowCount(rulesrowcount + 1);
QComboBox* tabletrafficwidget = new QComboBox();
tabletrafficwidget->addItem(i18n("Inbound"));
tabletrafficwidget->addItem(i18n("Outbound"));
connect(
tabletrafficwidget, SIGNAL(currentIndexChanged(int)),
this, SLOT(slotTrafficChanged(int))
);
rulestable->setCellWidget(rulesrowcount, 0, tabletrafficwidget);
QTableWidgetItem* tableaddresswidget = new QTableWidgetItem();
tableaddresswidget->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
rulestable->setItem(rulesrowcount, 1, tableaddresswidget);
QSpinBox* tableportwidget = new QSpinBox();
tableportwidget->setRange(0, INT_MAX);
tableportwidget->setValue(0);
connect(
tableportwidget, SIGNAL(valueChanged(int)),
this, SLOT(slotPortChanged(int))
);
rulestable->setCellWidget(rulesrowcount, 2, tableportwidget);
QComboBox* tabletactionwidget = new QComboBox();
tabletactionwidget->addItem(i18n("Accept"));
tabletactionwidget->addItem(i18n("Reject"));
connect(
tabletactionwidget, SIGNAL(currentIndexChanged(int)),
this, SLOT(slotActionChanged(int))
);
rulestable->setCellWidget(rulesrowcount, 3, tabletactionwidget);
rulestable->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
}
void KCMFirewall::slotAddRule()
{
addRuleRow();
emit changed(true);
}
void KCMFirewall::slotRemoveRule()
{
QList<int> removedrows;
foreach (const QModelIndex &modelindex, rulestable->selectionModel()->selectedIndexes()) {
const int modelindexrow = modelindex.row();
// qDebug() << Q_FUNC_INFO << modelindexrow;
if (removedrows.contains(modelindexrow)) {
continue;
}
rulestable->removeRow(modelindexrow);
removedrows.append(modelindexrow);
}
emit changed(true);
}
void KCMFirewall::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
removebutton->setEnabled(!selected.isEmpty());
}
void KCMFirewall::slotItemChanged(QTableWidgetItem* tablewidget)
{
Q_UNUSED(tablewidget);
emit changed(true);
}
void KCMFirewall::slotTrafficChanged(const int value)
{
Q_UNUSED(value);
emit changed(true);
}
void KCMFirewall::slotPortChanged(const int value)
{
Q_UNUSED(value);
emit changed(true);
}
void KCMFirewall::slotActionChanged(const int value)
{
Q_UNUSED(value);
emit changed(true);
}
#include "moc_kfirewallconfig.cpp"

View file

@ -0,0 +1,61 @@
/* This file is part of the KDE project
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KFIREWALLCONFIG_H
#define KFIREWALLCONFIG_H
#include <kcmodule.h>
#include "ui_kfirewallconfig.h"
/**
* Control look of KDE firewall
*
* @author Ivailo Monev (xakepa10@gmail.com)
*/
class KCMFirewall : public KCModule, public Ui_KFirewallDialog
{
Q_OBJECT
public:
// KCModule reimplementations
KCMFirewall(QWidget* parent, const QVariantList&);
~KCMFirewall();
public Q_SLOTS:
void load() final;
void save() final;
void defaults() final;
private:
void addRuleRow();
private Q_SLOTS:
void slotAddRule();
void slotRemoveRule();
void slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void slotItemChanged(QTableWidgetItem* tablewidget);
void slotTrafficChanged(const int value);
void slotPortChanged(const int value);
void slotActionChanged(const int value);
private:
QString m_kfirewallconfigpath;
};
#endif // KFIREWALLCONFIG_H

View file

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="System"?>
<ui version="4.0">
<class>KFirewallDialog</class>
<widget class="QWidget" name="KFirewallDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>501</width>
<height>467</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Rules</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="4">
<widget class="QTableWidget" name="rulestable">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Traffic</string>
</property>
</column>
<column>
<property name="text">
<string>Address</string>
</property>
</column>
<column>
<property name="text">
<string>Port</string>
</property>
</column>
<column>
<property name="text">
<string>Action</string>
</property>
</column>
</widget>
</item>
<item row="1" column="3">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="addbutton">
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff/>
</iconset>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="removebutton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff/>
</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="KMessageWidget" name="messagewidget"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KMessageWidget</class>
<extends>QFrame</extends>
<header>kmessagewidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,180 @@
/* This file is part of the KDE project
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kfirewallhelper.h"
#include <QProcess>
#include <kstandarddirs.h>
#include <kauthhelpersupport.h>
#include <kdebug.h>
static QByteArray ruleForSettings(const QByteArray &uservalue, const QByteArray &trafficvalue,
const QByteArray &addressvalue, const uint portvalue,
const QByteArray &actionvalue, const bool appendrules, const bool tcprule)
{
if (!tcprule && portvalue <= 0) {
// no port specified
return QByteArray();
}
QByteArray iptablesruledata;
bool isinbound = false;
QByteArray iptablestraffic = trafficvalue.toUpper();
if (iptablestraffic == "INBOUND") {
iptablestraffic = "INPUT";
isinbound = true;
} else {
iptablestraffic = "OUTPUT";
}
if (appendrules) {
iptablesruledata.append("--append ");
} else {
iptablesruledata.append("--delete ");
}
iptablesruledata.append(iptablestraffic);
if (!addressvalue.isEmpty()) {
iptablesruledata.append(" --destination ");
iptablesruledata.append(addressvalue);
}
if (portvalue > 0) {
if (tcprule) {
iptablesruledata.append(" --proto tcp --dport ");
iptablesruledata.append(QByteArray::number(portvalue));
} else {
iptablesruledata.append(" --proto udp --dport ");
iptablesruledata.append(QByteArray::number(portvalue));
}
}
if (!isinbound) {
// NOTE: only output can be user-bound
iptablesruledata.append(" --match owner --uid-owner ");
iptablesruledata.append(uservalue);
}
iptablesruledata.append(" --jump ");
iptablesruledata.append(actionvalue.toUpper());
iptablesruledata.append("\n");
return iptablesruledata;
}
static QByteArray rulesForParameters(const QVariantMap &parameters, const bool appendrules)
{
QByteArray iptablesruledata("*filter\n");
foreach (const QString &key, parameters.keys()) {
const QVariantMap rulesettingsmap = parameters.value(key).toMap();
const QByteArray uservalue = rulesettingsmap.value(QString::fromLatin1("user")).toByteArray();
const QByteArray trafficvalue = rulesettingsmap.value(QString::fromLatin1("traffic")).toByteArray();
const QByteArray addressvalue = rulesettingsmap.value(QString::fromLatin1("address")).toByteArray();
const uint portvalue = rulesettingsmap.value(QString::fromLatin1("port")).toUInt();
const QByteArray actionvalue = rulesettingsmap.value(QString::fromLatin1("action")).toByteArray();
// qDebug() << Q_FUNC_INFO << trafficvalue << addressvalue << portvalue << actionvalue;
iptablesruledata.append(
ruleForSettings(
uservalue, trafficvalue, addressvalue, portvalue, actionvalue,
appendrules, true
)
);
iptablesruledata.append(
ruleForSettings(
uservalue, trafficvalue, addressvalue, portvalue, actionvalue,
appendrules, false
)
);
}
iptablesruledata.append("COMMIT\n");
// qDebug() << Q_FUNC_INFO << iptablesruledata;
return iptablesruledata;
}
static ActionReply applyRules(KFirewallHelper *helper, const QString &iptablesexe,
const QByteArray &iptablesruledata)
{
QProcess iptablesproc(helper);
iptablesproc.start(iptablesexe);
if (!iptablesproc.waitForStarted()) {
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription("Could not start iptables-restore");
errorreply.setErrorCode(3);
return errorreply;
}
if (iptablesproc.write(iptablesruledata) != iptablesruledata.size()) {
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription("Could not write rules");
errorreply.setErrorCode(4);
return errorreply;
}
iptablesproc.closeWriteChannel();
iptablesproc.waitForFinished();
if (iptablesproc.exitCode() != 0) {
QString errorstring = iptablesproc.readAllStandardError().trimmed();
if (errorstring.isEmpty()) {
errorstring = QString::fromLatin1("Could not apply rules");
}
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription(errorstring);
errorreply.setErrorCode(5);
return errorreply;
}
return KAuth::ActionReply::SuccessReply;
}
ActionReply KFirewallHelper::apply(const QVariantMap &parameters)
{
if (parameters.isEmpty()) {
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription("Empty rules");
errorreply.setErrorCode(1);
return errorreply;
}
const QString iptablesexe = KStandardDirs::findRootExe("iptables-restore");
if (iptablesexe.isEmpty()) {
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription("Could not find iptables-restore");
errorreply.setErrorCode(2);
return errorreply;
}
return applyRules(this, iptablesexe, rulesForParameters(parameters, true));
}
ActionReply KFirewallHelper::revert(const QVariantMap &parameters)
{
//qDebug() << Q_FUNC_INFO << parameters;
if (parameters.isEmpty()) {
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription("Empty rules");
errorreply.setErrorCode(1);
return errorreply;
}
const QString iptablesexe = KStandardDirs::findRootExe("iptables-restore");
if (iptablesexe.isEmpty()) {
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription("Could not find iptables-restore");
errorreply.setErrorCode(2);
return errorreply;
}
return applyRules(this, iptablesexe, rulesForParameters(parameters, false));
}
KDE4_AUTH_HELPER_MAIN("org.kde.kcontrol.kcmkfirewall", KFirewallHelper)

View file

@ -0,0 +1,35 @@
/* This file is part of the KDE project
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KFIREWALLHELPER_H
#define KFIREWALLHELPER_H
#include <kauthactionreply.h>
// methods return type must be ActionReply otherwise QMetaObject::invokeMethod() fails
using namespace KAuth;
class KFirewallHelper : public QObject
{
Q_OBJECT
public slots:
ActionReply apply(const QVariantMap &parameters);
ActionReply revert(const QVariantMap &parameters);
};
#endif // KFIREWALLHELPER_H

View file

@ -0,0 +1,30 @@
########### next target ###############
set(kded_kfirewall_SRCS
kded_kfirewall.cpp
${CMAKE_CURRENT_BINARY_DIR}/org.kde.kfirewall.xml
)
qt4_generate_dbus_interface(kded_kfirewall.h org.kde.kfirewall.xml )
kde4_add_plugin(kded_kfirewall ${kded_kfirewall_SRCS})
target_link_libraries(kded_kfirewall PRIVATE
${KDE4_KDECORE_LIBS}
)
install(
TARGETS kded_kfirewall
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}
)
install(
FILES kfirewall.desktop
DESTINATION ${KDE4_SERVICES_INSTALL_DIR}/kded
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kfirewall.xml
DESTINATION ${KDE4_DBUS_INTERFACES_INSTALL_DIR}
)

View file

@ -0,0 +1,115 @@
/* This file is part of the KDE project
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kded_kfirewall.h"
#include <QJsonDocument>
#include <QFile>
#include <kstandarddirs.h>
#include <kauthaction.h>
#include <kpluginfactory.h>
#include <kdebug.h>
K_PLUGIN_FACTORY(KFirewallModuleFactory, registerPlugin<KFirewallModule>();)
K_EXPORT_PLUGIN(KFirewallModuleFactory("kfirewall"))
KFirewallModule::KFirewallModule(QObject *parent, const QList<QVariant>&)
: KDEDModule(parent),
m_kfirewallconfigpath(KStandardDirs::locateLocal("data", "kfirewall.json")),
m_watcher(this)
{
enable();
connect(
&m_watcher, SIGNAL(fileChanged(QString)),
this, SLOT(slotFileChanged(QString))
);
m_watcher.addPath(m_kfirewallconfigpath);
}
KFirewallModule::~KFirewallModule()
{
disable();
}
bool KFirewallModule::enable()
{
m_kfirewallsettingsmap.clear();
QFile kfirewallfile(m_kfirewallconfigpath);
if (!kfirewallfile.open(QFile::ReadOnly)) {
// may not exist yet but if it is created eventually it will be applied
kDebug() << "Could not open config for reading" << kfirewallfile.errorString();
return true;
}
const QByteArray kfirewalljsondata = kfirewallfile.readAll();
QJsonDocument kfirewalljsondocument = QJsonDocument::fromJson(kfirewalljsondata);
if (!kfirewalljsondata.isEmpty() && kfirewalljsondocument.isNull()) {
kWarning() << "Could not create JSON document" << kfirewalljsondocument.errorString();
return false;
}
m_kfirewallsettingsmap = kfirewalljsondocument.toVariant().toMap();
if (m_kfirewallsettingsmap.isEmpty()) {
kDebug() << "No firewall rules";
return true;
}
KAuth::Action kfirewallaction("org.kde.kcontrol.kcmkfirewall.apply");
kfirewallaction.setHelperID("org.kde.kcontrol.kcmkfirewall");
kfirewallaction.setArguments(m_kfirewallsettingsmap);
KAuth::ActionReply kfirewallreply = kfirewallaction.execute();
// qDebug() << Q_FUNC_INFO << kfirewallreply.errorCode() << kfirewallreply.errorDescription();
if (kfirewallreply != KAuth::ActionReply::SuccessReply) {
kWarning() << kfirewallreply.errorCode() << kfirewallreply.errorDescription();
return false;
}
return true;
}
bool KFirewallModule::disable()
{
if (m_kfirewallsettingsmap.isEmpty()) {
kDebug() << "No firewall rules";
return true;
}
KAuth::Action kfirewallaction("org.kde.kcontrol.kcmkfirewall.revert");
kfirewallaction.setHelperID("org.kde.kcontrol.kcmkfirewall");
kfirewallaction.setArguments(m_kfirewallsettingsmap);
KAuth::ActionReply kfirewallreply = kfirewallaction.execute();
// qDebug() << Q_FUNC_INFO << kfirewallreply.errorCode() << kfirewallreply.errorDescription();
if (kfirewallreply != KAuth::ActionReply::SuccessReply) {
kWarning() << kfirewallreply.errorCode() << kfirewallreply.errorDescription();
return false;
}
m_kfirewallsettingsmap.clear();
return true;
}
void KFirewallModule::slotFileChanged(const QString &path)
{
Q_UNUSED(path);
disable();
enable();
}
#include "moc_kded_kfirewall.cpp"

View file

@ -0,0 +1,47 @@
/* This file is part of the KDE project
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KFIREWALL_KDED_H
#define KFIREWALL_KDED_H
#include <QFileSystemWatcher>
#include <kdedmodule.h>
class KFirewallModule: public KDEDModule
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kfirewall")
public:
KFirewallModule(QObject *parent, const QList<QVariant>&);
~KFirewallModule();
public Q_SLOTS:
Q_SCRIPTABLE bool enable();
Q_SCRIPTABLE bool disable();
private Q_SLOTS:
void slotFileChanged(const QString &path);
private:
QString m_kfirewallconfigpath;
QVariantMap m_kfirewallsettingsmap;
QFileSystemWatcher m_watcher;
};
#endif // KFIREWALL_KDED_H

View file

@ -0,0 +1,11 @@
[Desktop Entry]
Icon=security-high
Name=Firewall
Comment=Firewall service
Type=Service
X-KDE-ServiceTypes=KDEDModule
X-KDE-Library=kfirewall
X-KDE-DBus-ModuleName=kfirewall
X-KDE-Kded-autoload=true
X-KDE-Kded-load-on-demand=false
OnlyShowIn=KDE;