diff options
Diffstat (limited to 'ui/qt/firewall_rules_dialog.cpp')
-rw-r--r-- | ui/qt/firewall_rules_dialog.cpp | 206 |
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); +} |