Skip to content

Commit

Permalink
Poke systemctl to check if we have a firewall open and use it
Browse files Browse the repository at this point in the history
If we don't have one, rely on looking for the binary, as usual.
  • Loading branch information
tcanabrava committed Dec 10, 2020
1 parent 0f2b8c4 commit dac7ae2
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 18 deletions.
18 changes: 18 additions & 0 deletions kcm/backends/firewalld/firewalldclient.cpp
Expand Up @@ -13,6 +13,7 @@
#include <QTimer>
#include <QVariantList>
#include <QVariantMap>
#include <QProcess>

#include <loglistmodel.h>
#include <profile.h>
Expand Down Expand Up @@ -547,4 +548,21 @@ FirewallClient::Capabilities FirewalldClient::capabilities() const
QStringList FirewalldClient::knownProtocols() {
return {"TCP", "UDP"};
}

bool FirewalldClient::isCurrentlyLoaded() const
{
QProcess process;
const QString name = "systemctl";
const QStringList args = {"status", "firewalld"};

process.start(name, args);
process.waitForFinished();

// systemctl returns 0 for status if the app is loaded, and 3 otherwise.
// systemctl returns 0 for status if the app is loaded, and 3 otherwise.
qDebug() << "Firewalld is loaded?" << process.exitCode();

return process.exitCode() == EXIT_SUCCESS;
}

#include "firewalldclient.moc"
1 change: 1 addition & 0 deletions kcm/backends/firewalld/firewalldclient.h
Expand Up @@ -60,6 +60,7 @@ class Q_DECL_EXPORT FirewalldClient : public IFirewallClientBackend
void refreshProfiles() override;
bool hasDependencies() const override;
QStringList knownProtocols() override;
bool isCurrentlyLoaded() const override;

protected slots:
void refreshLogs();
Expand Down
17 changes: 17 additions & 0 deletions kcm/backends/ufw/ufwclient.cpp
Expand Up @@ -19,6 +19,7 @@
#include <QTimer>
#include <QVariantMap>
#include <QXmlStreamReader>
#include <QProcess>

#include <KConfig>
#include <KConfigGroup>
Expand Down Expand Up @@ -681,5 +682,21 @@ QString UfwClient::toXml(Rule *r) const

return xmlString;
}

bool UfwClient::isCurrentlyLoaded() const
{
QProcess process;
const QString name = "systemctl";
const QStringList args = {"status", "ufw"};

process.start(name, args);
process.waitForFinished();

// systemctl returns 0 for status if the app is loaded, and 3 otherwise.
qDebug() << "Ufw is loaded?" << process.exitCode();

return process.exitCode() == EXIT_SUCCESS;
}

#include "ufwclient.moc"

2 changes: 2 additions & 0 deletions kcm/backends/ufw/ufwclient.h
Expand Up @@ -68,6 +68,8 @@ class Q_DECL_EXPORT UfwClient : public IFirewallClientBackend
bool hasExecutable() const override;
void refreshProfiles() override;
bool hasDependencies() const override;
bool isCurrentlyLoaded() const override;

protected slots:
void refreshLogs();
QStringList knownProtocols() override;
Expand Down
51 changes: 35 additions & 16 deletions kcm/core/firewallclient.cpp
Expand Up @@ -30,12 +30,7 @@ IFirewallClientBackend *FirewallClient::m_currentBackend = nullptr;
FirewallClient::FirewallClient(QObject *parent)
: QObject(parent)
{
if (!m_currentBackend) {
setBackend("ufw");
}
if (!m_currentBackend) {
setBackend("firewalld");
}
setBackend({"ufw", "firewalld"});
}

QStringList FirewallClient::knownProtocols()
Expand Down Expand Up @@ -266,7 +261,7 @@ bool FirewallClient::hasExecutable() const
return m_currentBackend->hasExecutable();
}

void FirewallClient::setBackend(const QString &backend)
void FirewallClient::setBackend(const QStringList &backendList)
{
if (m_currentBackend) {
enabledChanged(false);
Expand All @@ -276,29 +271,53 @@ void FirewallClient::setBackend(const QString &backend)

const auto plugins = KPluginLoader::findPlugins(QStringLiteral("kf5/plasma_firewall"));

QList<KPluginFactory*> factories;
for (const KPluginMetaData &metadata : plugins) {
if (metadata.pluginId() != backend + QLatin1String("backend")) {
QString pluginName = metadata.pluginId().remove("backend");
if (!backendList.contains(pluginName)) {
continue;
}

KPluginFactory *factory = KPluginLoader(metadata.fileName()).factory();
if (!factory) {
continue;
}
factories.append(factory);
}

auto perhaps = factory->create<IFirewallClientBackend>(this, QVariantList() /*args*/);
if (perhaps->hasDependencies()) {
qCDebug(FirewallClientDebug) << "Backend " << backend << "Loaded";
m_currentBackend = perhaps;
break;
} else {
qCDebug(FirewallClientDebug) << "Backend " << backend << "Failed to meet dependencies";
// lambdas
auto systemCheck = [this] (const QList<KPluginFactory*> factories) -> IFirewallClientBackend* {
for (KPluginFactory *factory : factories) {
qDebug() << "Testing factory" << factory->objectName();
auto perhaps = factory->create<IFirewallClientBackend>(this, QVariantList());
if (perhaps->isCurrentlyLoaded()) {
qDebug() << "Is Loaded!";
return perhaps;
}
perhaps->deleteLater();
}
qDebug() << "Returning nullptr";
return nullptr;
};

auto loadFromBinary = [this] (const QList<KPluginFactory*> factories) -> IFirewallClientBackend* {
for (KPluginFactory *factory : factories) {
auto perhaps = factory->create<IFirewallClientBackend>(this, QVariantList() );
if (perhaps->hasDependencies()) {
return perhaps;
}
perhaps->deleteLater();
}
return nullptr;
};

m_currentBackend = systemCheck(factories);
if (!m_currentBackend) {
m_currentBackend = loadFromBinary(factories);
}

if (!m_currentBackend) {
qCDebug(FirewallClientDebug) << "Could not find backend" << backend;
qCDebug(FirewallClientDebug) << "Could not find any of the specified backends" << backendList;
return;
}

Expand Down
3 changes: 1 addition & 2 deletions kcm/core/firewallclient.h
Expand Up @@ -44,7 +44,6 @@ class KCM_FIREWALL_CORE_EXPORT FirewallClient : public QObject
Q_PROPERTY(RuleListModel *rulesModel READ rulesModel CONSTANT)
Q_PROPERTY(LogListModel *logsModel READ logsModel CONSTANT)
Q_PROPERTY(bool logsAutoRefresh READ logsAutoRefresh WRITE setLogsAutoRefresh NOTIFY logsAutoRefreshChanged)
Q_PROPERTY(QString backend READ backend WRITE setBackend NOTIFY backendChanged)
Q_PROPERTY(bool hasExecutable READ hasExecutable NOTIFY hasExecutableChanged)
Q_PROPERTY(Capabilities capabilities READ capabilities NOTIFY capabilitiesChanged)
Q_PROPERTY(QString name READ name)
Expand Down Expand Up @@ -125,7 +124,7 @@ class KCM_FIREWALL_CORE_EXPORT FirewallClient : public QObject
void showErrorMessage(const QString &message);

private:
void setBackend(const QString &backend);
void setBackend(const QStringList &backendList);
void setLogsAutoRefresh(bool logsAutoRefresh);
void queryStatus(DefaultDataBehavior defaultDataBehavior = ReadDefaults, ProfilesBehavior ProfilesBehavior = ListenProfiles);

Expand Down
8 changes: 8 additions & 0 deletions kcm/core/ifirewallclientbackend.h
Expand Up @@ -70,8 +70,16 @@ class Q_DECL_EXPORT IFirewallClientBackend : public QObject
virtual QString defaultOutgoingPolicy() const = 0;
virtual bool hasExecutable() const = 0;
virtual LogListModel *logs() = 0;

/* TODO: Move it away from here. This asks the
* Logs model to refresh after a few seconds
*/
virtual bool logsAutoRefresh() const = 0;

/* Returns true if the firewall represented
* by this backend is running right now */
virtual bool isCurrentlyLoaded() const = 0;

virtual void refreshProfiles() = 0;
virtual FirewallClient::Capabilities capabilities() const;
virtual QStringList knownProtocols() = 0;
Expand Down

0 comments on commit dac7ae2

Please sign in to comment.