forked from osmocom/wireshark
44a615e854
Use wsApp->setLastOpenDirFromFilename() to convert a filename to a directory name before calling wsApp->setLastOpenDir(). This will ensure to always store a directory instead of a filename in the recent gui.fileopen_remembered_dir.
207 lines
6.7 KiB
C++
207 lines
6.7 KiB
C++
/* 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 "wireshark_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,
|
|
wsApp->lastOpenDir().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. */
|
|
wsApp->setLastOpenDirFromFilename(file_name);
|
|
}
|
|
} else if (button == ui->buttonBox->button(QDialogButtonBox::Apply)) {
|
|
if (ui->textBrowser->textCursor().hasSelection()) {
|
|
ui->textBrowser->copy();
|
|
} else {
|
|
wsApp->clipboard()->setText(ui->textBrowser->toPlainText());
|
|
}
|
|
}
|
|
}
|
|
|
|
void FirewallRulesDialog::on_buttonBox_helpRequested()
|
|
{
|
|
wsApp->helpTopicAction(HELP_FIREWALL_DIALOG);
|
|
}
|