summaryrefslogtreecommitdiffstats
path: root/ui/qt/firewall_rules_dialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt/firewall_rules_dialog.cpp')
-rw-r--r--ui/qt/firewall_rules_dialog.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/ui/qt/firewall_rules_dialog.cpp b/ui/qt/firewall_rules_dialog.cpp
new file mode 100644
index 00000000..a74355e1
--- /dev/null
+++ b/ui/qt/firewall_rules_dialog.cpp
@@ -0,0 +1,206 @@
+/* firewall_rules_dialog.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <config.h>
+
+#include "firewall_rules_dialog.h"
+#include <ui_firewall_rules_dialog.h>
+
+#include "epan/packet_info.h"
+#include "epan/to_str.h"
+
+#include "ui/all_files_wildcard.h"
+#include "ui/firewall_rules.h"
+#include "ui/help_url.h"
+
+#include "wsutil/file_util.h"
+#include "wsutil/utf8_entities.h"
+
+#include "main_application.h"
+#include "ui/qt/widgets/wireshark_file_dialog.h"
+
+#include <QClipboard>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QTextCursor>
+
+// XXX As described in bug 2482, some of the generated rules don't
+// make sense. We could generate rules for every conceivable use case,
+// but that would add complexity. We could also add controls to let
+// users fine-tune rule output, but that would also add complexity.
+
+FirewallRulesDialog::FirewallRulesDialog(QWidget &parent, CaptureFile &cf) :
+ WiresharkDialog(parent, cf),
+ ui(new Ui::FirewallRulesDialog),
+ prod_(0)
+{
+ ui->setupUi(this);
+
+ setWindowSubtitle(tr("Firewall ACL Rules"));
+
+ ui->buttonBox->button(QDialogButtonBox::Apply)->setText(tr("Copy"));
+
+ file_name_ = cf.fileName(); // XXX Add extension?
+ packet_num_ = cf.packetInfo()->num;
+
+ packet_info *pinfo = cf.packetInfo();
+ copy_address(&dl_src_, &(pinfo->dl_src));
+ copy_address(&dl_dst_, &(pinfo->dl_dst));
+ copy_address(&net_src_, &(pinfo->net_src));
+ copy_address(&net_dst_, &(pinfo->net_dst));
+ ptype_ = pinfo->ptype;
+ src_port_ = pinfo->srcport;
+ dst_port_ = pinfo->destport;
+ int nf_item = 0;
+
+ for (size_t prod = 0; prod < firewall_product_count(); prod++) {
+ QString prod_name = firewall_product_name(prod);
+
+ // Default to Netfilter since it's likely the most popular.
+ if (prod_name.contains("Netfilter")) nf_item = ui->productComboBox->count();
+ ui->productComboBox->addItem(prod_name);
+ }
+ ui->productComboBox->setCurrentIndex(nf_item);
+
+ ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
+}
+
+FirewallRulesDialog::~FirewallRulesDialog()
+{
+ delete ui;
+}
+
+void FirewallRulesDialog::updateWidgets()
+{
+ WiresharkDialog::updateWidgets();
+
+ QString comment_pfx = firewall_product_comment_prefix(prod_);
+ QString rule_hint = firewall_product_rule_hint(prod_);
+ QString rule_line;
+
+ rule_line = QString("%1 %2 rules for %3, packet %4.")
+ .arg(comment_pfx)
+ .arg(firewall_product_name(prod_))
+ .arg(file_name_)
+ .arg(packet_num_);
+
+ if (!rule_hint.isEmpty()) rule_line += " " + rule_hint;
+
+ ui->textBrowser->clear();
+ ui->textBrowser->append(rule_line);
+
+ syntax_func v4_func = firewall_product_ipv4_func(prod_);
+ syntax_func port_func = firewall_product_port_func(prod_);
+ syntax_func v4_port_func = firewall_product_ipv4_port_func(prod_);
+ syntax_func mac_func = firewall_product_mac_func(prod_);
+
+ if (v4_func && net_src_.type == AT_IPv4) {
+ addRule(tr("IPv4 source address."), v4_func, &net_src_, src_port_);
+ addRule(tr("IPv4 destination address."), v4_func, &net_dst_, dst_port_);
+ }
+
+ if (port_func && (ptype_ == PT_TCP || ptype_ == PT_UDP)) {
+ addRule(tr("Source port."), port_func, &net_src_, src_port_);
+ addRule(tr("Destination port."), port_func, &net_dst_, dst_port_);
+ }
+
+ if (v4_port_func && net_src_.type == AT_IPv4 &&
+ (ptype_ == PT_TCP || ptype_ == PT_UDP)) {
+ addRule(tr("IPv4 source address and port."), v4_port_func, &net_src_, src_port_);
+ addRule(tr("IPv4 destination address and port."), v4_port_func, &net_dst_, dst_port_);
+ }
+
+ if (mac_func && dl_src_.type == AT_ETHER) {
+ addRule(tr("MAC source address."), mac_func, &dl_src_, src_port_);
+ addRule(tr("MAC destination address."), mac_func, &dl_dst_, dst_port_);
+ }
+
+ ui->textBrowser->moveCursor(QTextCursor::Start);
+
+ ui->inboundCheckBox->setEnabled(firewall_product_does_inbound(prod_));
+}
+
+#define ADDR_BUF_LEN 200
+void FirewallRulesDialog::addRule(QString description, syntax_func rule_func, address *addr, guint32 port)
+{
+ if (!rule_func) return;
+
+ char addr_buf[ADDR_BUF_LEN];
+ QString comment_pfx = firewall_product_comment_prefix(prod_);
+ GString *rule_str = g_string_new("");
+ gboolean inbound = ui->inboundCheckBox->isChecked();
+ gboolean deny = ui->denyCheckBox->isChecked();
+
+ address_to_str_buf(addr, addr_buf, ADDR_BUF_LEN);
+ rule_func(rule_str, addr_buf, port, ptype_, inbound, deny);
+ ui->textBrowser->append(QString());
+
+ QString comment_line = comment_pfx + " " + description;
+ ui->textBrowser->append(comment_line);
+ ui->textBrowser->append(rule_str->str);
+
+ g_string_free(rule_str, TRUE);
+}
+
+
+void FirewallRulesDialog::on_productComboBox_currentIndexChanged(int new_idx)
+{
+ prod_ = (size_t) new_idx;
+ updateWidgets();
+}
+
+void FirewallRulesDialog::on_inboundCheckBox_toggled(bool)
+{
+ updateWidgets();
+}
+
+void FirewallRulesDialog::on_denyCheckBox_toggled(bool)
+{
+ updateWidgets();
+}
+
+void FirewallRulesDialog::on_buttonBox_clicked(QAbstractButton *button)
+{
+ if (button == ui->buttonBox->button(QDialogButtonBox::Save)) {
+ QString save_title = QString("Save %1 rules as" UTF8_HORIZONTAL_ELLIPSIS)
+ .arg(firewall_product_name(prod_));
+ QByteArray file_name = WiresharkFileDialog::getSaveFileName(this,
+ save_title,
+ mainApp->openDialogInitialDir().canonicalPath(),
+ tr("Text file (*.txt);;All Files (" ALL_FILES_WILDCARD ")")
+ ).toUtf8();
+ if (file_name.length() > 0) {
+ QFile save_file(file_name);
+ QByteArray rule_text = ui->textBrowser->toPlainText().toUtf8();
+
+ save_file.open(QIODevice::WriteOnly);
+ save_file.write(rule_text);
+ save_file.close();
+
+ if (save_file.error() != QFile::NoError) {
+ QMessageBox::warning(this, tr("Warning"), tr("Unable to save %1").arg(save_file.fileName()));
+ return;
+ }
+
+ /* Save the directory name for future file dialogs. */
+ mainApp->setLastOpenDirFromFilename(file_name);
+ }
+ } else if (button == ui->buttonBox->button(QDialogButtonBox::Apply)) {
+ if (ui->textBrowser->textCursor().hasSelection()) {
+ ui->textBrowser->copy();
+ } else {
+ mainApp->clipboard()->setText(ui->textBrowser->toPlainText());
+ }
+ }
+}
+
+void FirewallRulesDialog::on_buttonBox_helpRequested()
+{
+ mainApp->helpTopicAction(HELP_FIREWALL_DIALOG);
+}