File indexing completed on 2024-04-28 16:52:16
0001 // SPDX-License-Identifier: GPL-2.0-or-later 0002 // SPDX-FileCopyrightText: 2011 Craig Drummond <craig.p.drummond@gmail.com> 0003 // SPDX-FileCopyrightText: 2018 Alexis Lopes Zubeta <contact@azubieta.net> 0004 // SPDX-FileCopyrightText: 2020 Tomaz Canabrava <tcanabrava@kde.org> 0005 /* 0006 * UFW KControl Module 0007 */ 0008 0009 #include "firewallclient.h" 0010 0011 #include "loglistmodel.h" 0012 #include "rulelistmodel.h" 0013 0014 #include "ifirewallclientbackend.h" 0015 0016 #include <KLocalizedString> 0017 #include <KPluginFactory> 0018 #include <KPluginMetaData> 0019 0020 #include <QList> 0021 #include <QNetworkInterface> 0022 #include <QStringList> 0023 #include <QtGlobal> 0024 0025 Q_LOGGING_CATEGORY(FirewallClientDebug, "firewall.client") 0026 0027 IFirewallClientBackend *FirewallClient::m_currentBackend = nullptr; 0028 0029 FirewallClient::FirewallClient(QObject *parent) 0030 : QObject(parent) 0031 { 0032 } 0033 0034 FirewallClient::~FirewallClient() noexcept 0035 { 0036 m_currentBackend->deleteLater(); 0037 m_currentBackend = nullptr; 0038 } 0039 0040 QStringList FirewallClient::knownProtocols() 0041 { 0042 if (!m_currentBackend) { 0043 return {}; 0044 } 0045 return m_currentBackend->knownProtocols(); 0046 } 0047 0048 bool FirewallClient::isTcpAndUdp(int protocolIdx) 0049 { 0050 if (!m_currentBackend) { 0051 return false; 0052 } 0053 0054 return m_currentBackend->isTcpAndUdp(protocolIdx); 0055 } 0056 0057 int FirewallClient::indexOfProtocol(const QString &protocol) 0058 { 0059 if (!m_currentBackend) { 0060 return -1; 0061 } 0062 0063 const QStringList protocolList = m_currentBackend->knownProtocols(); 0064 for (int i = 0; i < m_currentBackend->knownProtocols().size(); i++) { 0065 if (protocolList[i].toLower() == protocol.toLower()) { 0066 return i; 0067 } 0068 } 0069 return -1; 0070 } 0071 0072 QStringList FirewallClient::knownInterfaces() 0073 { 0074 QStringList interface_names({i18n("Any")}); 0075 0076 for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) { 0077 interface_names << iface.name(); 0078 } 0079 0080 return interface_names; 0081 } 0082 0083 void FirewallClient::refresh() 0084 { 0085 if (!m_currentBackend) { 0086 return; 0087 } 0088 m_currentBackend->refresh(); 0089 } 0090 0091 RuleListModel *FirewallClient::rulesModel() const 0092 { 0093 if (!m_currentBackend) { 0094 return nullptr; 0095 } 0096 return m_currentBackend->rules(); 0097 } 0098 0099 Rule *FirewallClient::ruleAt(int index) 0100 { 0101 if (!m_currentBackend) { 0102 return nullptr; 0103 } 0104 return m_currentBackend->ruleAt(index); 0105 } 0106 0107 KJob *FirewallClient::addRule(Rule *rule) 0108 { 0109 if (!m_currentBackend) { 0110 return nullptr; 0111 } 0112 0113 if (!m_currentBackend->isCurrentlyLoaded()) { 0114 return nullptr; 0115 } 0116 0117 return m_currentBackend->addRule(rule); 0118 } 0119 0120 KJob *FirewallClient::removeRule(int index) 0121 { 0122 if (!m_currentBackend) { 0123 return nullptr; 0124 } 0125 if (!m_currentBackend->isCurrentlyLoaded()) { 0126 return nullptr; 0127 } 0128 return m_currentBackend->removeRule(index); 0129 } 0130 0131 KJob *FirewallClient::updateRule(Rule *rule) 0132 { 0133 if (!m_currentBackend) { 0134 return nullptr; 0135 } 0136 if (!m_currentBackend->isCurrentlyLoaded()) { 0137 return nullptr; 0138 } 0139 return m_currentBackend->updateRule(rule); 0140 } 0141 0142 KJob *FirewallClient::moveRule(int from, int to) 0143 { 0144 // TODO: Verify if this method is needed. 0145 if (!m_currentBackend) { 0146 return nullptr; 0147 } 0148 return m_currentBackend->moveRule(from, to); 0149 } 0150 0151 KJob *FirewallClient::save() 0152 { 0153 if (!m_currentBackend) { 0154 return nullptr; 0155 } 0156 return m_currentBackend->save(); 0157 } 0158 0159 QString FirewallClient::name() const 0160 { 0161 if (!m_currentBackend) { 0162 return {}; 0163 } 0164 return m_currentBackend->name(); 0165 } 0166 FirewallClient::Capabilities FirewallClient::capabilities() const 0167 { 0168 if (!m_currentBackend) { 0169 return FirewallClient::Capability::None; 0170 } 0171 return m_currentBackend->capabilities(); 0172 } 0173 0174 /* Creates a new Rule and returns it to the Qml side, passing arguments based 0175 * on the Connection Table. */ 0176 Rule *FirewallClient::createRuleFromConnection(const QString &protocol, const QString &localAddress, const QString &foreignAddres, const QString &status) 0177 { 0178 if (!m_currentBackend) { 0179 return nullptr; 0180 } 0181 return m_currentBackend->createRuleFromConnection(protocol, localAddress, foreignAddres, status); 0182 } 0183 0184 Rule *FirewallClient::createRuleFromLog(const QString &protocol, 0185 const QString &sourceAddress, 0186 const QString &sourcePort, 0187 const QString &destinationAddress, 0188 const QString &destinationPort, 0189 const QString &inn) 0190 { 0191 if (!m_currentBackend) { 0192 return nullptr; 0193 } 0194 return m_currentBackend->createRuleFromLog(protocol, sourceAddress, sourcePort, destinationAddress, destinationPort, inn); 0195 } 0196 0197 bool FirewallClient::enabled() const 0198 { 0199 if (!m_currentBackend) { 0200 return false; 0201 } 0202 return m_currentBackend->enabled(); 0203 } 0204 0205 QString FirewallClient::defaultIncomingPolicy() const 0206 { 0207 if (!m_currentBackend) { 0208 return {}; 0209 } 0210 return m_currentBackend->defaultIncomingPolicy(); 0211 } 0212 0213 QString FirewallClient::defaultOutgoingPolicy() const 0214 { 0215 if (!m_currentBackend) { 0216 return {}; 0217 } 0218 return m_currentBackend->defaultOutgoingPolicy(); 0219 } 0220 0221 LogListModel *FirewallClient::logsModel() const 0222 { 0223 // TODO: Perhaps this function is uneeded. 0224 if (!m_currentBackend) { 0225 return nullptr; 0226 } 0227 return m_currentBackend->logs(); 0228 } 0229 0230 bool FirewallClient::logsAutoRefresh() const 0231 { 0232 if (!m_currentBackend) { 0233 return false; 0234 } 0235 return m_currentBackend->logsAutoRefresh(); 0236 } 0237 0238 KJob *FirewallClient::setEnabled(bool enabled) 0239 { 0240 if (!m_currentBackend) { 0241 return nullptr; 0242 } 0243 return m_currentBackend->setEnabled(enabled); 0244 } 0245 0246 void FirewallClient::queryStatus(DefaultDataBehavior defaultsBehavior, ProfilesBehavior profilesBehavior) 0247 { 0248 if (!m_currentBackend) { 0249 return; 0250 } 0251 m_currentBackend->queryStatus(defaultsBehavior, profilesBehavior); 0252 } 0253 0254 KJob *FirewallClient::setDefaultIncomingPolicy(const QString &defaultIncomingPolicy) 0255 { 0256 if (!m_currentBackend) { 0257 return nullptr; 0258 } 0259 if (!m_currentBackend->isCurrentlyLoaded()) { 0260 return nullptr; 0261 } 0262 return m_currentBackend->setDefaultIncomingPolicy(defaultIncomingPolicy); 0263 } 0264 0265 KJob *FirewallClient::setDefaultOutgoingPolicy(const QString &defaultOutgoingPolicy) 0266 { 0267 if (!m_currentBackend) { 0268 return nullptr; 0269 } 0270 if (!m_currentBackend->isCurrentlyLoaded()) { 0271 return nullptr; 0272 } 0273 return m_currentBackend->setDefaultOutgoingPolicy(defaultOutgoingPolicy); 0274 } 0275 0276 void FirewallClient::setLogsAutoRefresh(bool logsAutoRefresh) 0277 { 0278 if (!m_currentBackend) { 0279 return; 0280 } 0281 m_currentBackend->setLogsAutoRefresh(logsAutoRefresh); 0282 } 0283 0284 bool FirewallClient::hasExecutable() const 0285 { 0286 if (!m_currentBackend) { 0287 return false; 0288 } 0289 return m_currentBackend->hasExecutable(); 0290 } 0291 0292 void FirewallClient::setBackend(const QStringList &backendList) 0293 { 0294 if (m_currentBackend) { 0295 Q_EMIT enabledChanged(false); 0296 delete m_currentBackend; 0297 m_currentBackend = nullptr; 0298 } 0299 // cppcheck-suppress unknownMacro 0300 const auto plugins = KPluginMetaData::findPlugins(QStringLiteral("kf" QT_STRINGIFY(QT_VERSION_MAJOR) "/plasma_firewall")); 0301 0302 QList<KPluginFactory *> factories; 0303 for (const KPluginMetaData &metadata : plugins) { 0304 QString pluginName = metadata.pluginId().remove(QStringLiteral("backend")); 0305 if (!backendList.contains(pluginName)) { 0306 continue; 0307 } 0308 KPluginFactory *factory = KPluginFactory::loadFactory(metadata).plugin; 0309 if (!factory) { 0310 continue; 0311 } 0312 factories.append(factory); 0313 } 0314 0315 // lambdas 0316 auto systemCheck = [this](const QList<KPluginFactory *> &factories) -> IFirewallClientBackend * { 0317 for (KPluginFactory *factory : factories) { 0318 auto perhaps = factory->create<IFirewallClientBackend>(this, QVariantList()); 0319 if (perhaps->isCurrentlyLoaded()) { 0320 return perhaps; 0321 } 0322 perhaps->deleteLater(); 0323 } 0324 return nullptr; 0325 }; 0326 0327 auto loadFromBinary = [this](const QList<KPluginFactory *> factories) -> IFirewallClientBackend * { 0328 for (KPluginFactory *factory : factories) { 0329 auto perhaps = factory->create<IFirewallClientBackend>(this, QVariantList()); 0330 if (perhaps->hasExecutable()) { 0331 return perhaps; 0332 } 0333 perhaps->deleteLater(); 0334 } 0335 return nullptr; 0336 }; 0337 0338 m_currentBackend = systemCheck(factories); 0339 if (!m_currentBackend) { 0340 m_currentBackend = loadFromBinary(factories); 0341 } 0342 0343 if (!m_currentBackend) { 0344 qCDebug(FirewallClientDebug) << "Could not find any of the specified backends" << backendList; 0345 return; 0346 } 0347 0348 connect(m_currentBackend, &IFirewallClientBackend::enabledChanged, this, &FirewallClient::enabledChanged); 0349 connect(m_currentBackend, &IFirewallClientBackend::defaultIncomingPolicyChanged, this, &FirewallClient::defaultIncomingPolicyChanged); 0350 connect(m_currentBackend, &IFirewallClientBackend::defaultOutgoingPolicyChanged, this, &FirewallClient::defaultOutgoingPolicyChanged); 0351 connect(m_currentBackend, &IFirewallClientBackend::logsAutoRefreshChanged, this, &FirewallClient::logsAutoRefreshChanged); 0352 connect(m_currentBackend, &IFirewallClientBackend::hasExecutableChanged, this, &FirewallClient::hasExecutableChanged); 0353 connect(m_currentBackend, &IFirewallClientBackend::showErrorMessage, this, &FirewallClient::showErrorMessage); 0354 } 0355 0356 QString FirewallClient::backend() const 0357 { 0358 if (!m_currentBackend) { 0359 return {}; 0360 } 0361 return m_currentBackend->name(); 0362 } 0363 0364 QString FirewallClient::version() const 0365 { 0366 if (!m_currentBackend) { 0367 return {}; 0368 } 0369 return m_currentBackend->version(); 0370 } 0371 0372 bool FirewallClient::supportsRuleUpdate() const 0373 { 0374 if (!m_currentBackend) { 0375 return false; 0376 } 0377 return m_currentBackend->supportsRuleUpdate(); 0378 } 0379 0380 QStringList FirewallClient::knownApplications() 0381 { 0382 if (!m_currentBackend) { 0383 return {}; 0384 } 0385 0386 return m_currentBackend->knownApplications(); 0387 } 0388 0389 #include "moc_firewallclient.cpp"