From 987ff3ee1bed5fe17d3889411687283818cee29f Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Tue, 31 May 2016 18:29:39 -0700 Subject: [PATCH] Qt: Firewall Rules dialog. Add the Firewall ACL Rules dialog. Try showing all valid rules for a given product instead of making the user select from a combobox. We can add the combo back easily enough if that's desired. Add a rule hint field and use it in the Qt and GTK+ UIs. Bug: 12469 Change-Id: I39dd840e9838f96d7c5e2b4c34662811c21d0386 Reviewed-on: https://code.wireshark.org/review/15689 Petri-Dish: Gerald Combs Tested-by: Petri Dish Buildbot Reviewed-by: Gerald Combs --- ui/CMakeLists.txt | 1 + ui/Makefile.common | 2 + ui/firewall_rules.c | 290 ++++++++++++++++++++++++++++++++ ui/firewall_rules.h | 108 ++++++++++++ ui/gtk/firewall_dlg.c | 252 +++------------------------ ui/qt/CMakeLists.txt | 3 + ui/qt/Makefile.am | 2 + ui/qt/Makefile.common | 4 + ui/qt/Wireshark.pro | 3 + ui/qt/firewall_rules_dialog.cpp | 225 +++++++++++++++++++++++++ ui/qt/firewall_rules_dialog.h | 85 ++++++++++ ui/qt/firewall_rules_dialog.ui | 124 ++++++++++++++ ui/qt/main_window.cpp | 7 +- ui/qt/main_window.h | 2 + ui/qt/main_window.ui | 42 ++--- ui/qt/main_window_slots.cpp | 16 +- 16 files changed, 910 insertions(+), 256 deletions(-) create mode 100644 ui/firewall_rules.c create mode 100644 ui/firewall_rules.h create mode 100644 ui/qt/firewall_rules_dialog.cpp create mode 100644 ui/qt/firewall_rules_dialog.h create mode 100644 ui/qt/firewall_rules_dialog.ui diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 28d1ab00cf..8145dd1dee 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -33,6 +33,7 @@ set(COMMON_UI_SRC export_object_tftp.c export_pdu_ui_utils.c help_url.c + firewall_rules.c iface_lists.c io_graph_item.c language.c diff --git a/ui/Makefile.common b/ui/Makefile.common index 0cd6da548b..f0db822792 100644 --- a/ui/Makefile.common +++ b/ui/Makefile.common @@ -53,6 +53,7 @@ WIRESHARK_UI_SRC = \ export_object_smb.c \ export_object_tftp.c \ export_pdu_ui_utils.c \ + firewall_rules.c \ iface_lists.c \ io_graph_item.c \ language.c \ @@ -96,6 +97,7 @@ noinst_HEADERS = \ file_dialog.h \ help_url.h \ packet_list_utils.h \ + firewall_rules.h \ iface_lists.h \ io_graph_item.h \ language.h \ diff --git a/ui/firewall_rules.c b/ui/firewall_rules.c new file mode 100644 index 0000000000..ae7db51848 --- /dev/null +++ b/ui/firewall_rules.c @@ -0,0 +1,290 @@ +/* firewall_rules_dlg.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Generate firewall ACL rules based on packet addresses and ports. + * For directional rules, an outside interface is assumed. + * + * There may be better ways to present the information, e.g. all rules + * in one huge text window, or some sort of tree view. + */ + +/* + * To add a new product, add syntax functions modify the products[] array. + * + * To add a new syntax function, add its prototype above the products[] + * array, and add the function below with all the others. + */ + + /* Copied from gtk/firewall_rules.c */ + +#include "config.h" + +#include + +#include "epan/address.h" + +#include "firewall_rules.h" + +static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); + +static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +/* XXX - Can you addresses-only filters using WFW/netsh? */ + +static void sf_ios_ext_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_ipfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_ipfw_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_netfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_pf_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_netsh_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); + +static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); + +typedef struct _fw_product_t { + const char *name; + const char *rule_hint; + const char *comment_pfx; + syntax_func mac_func; + syntax_func ipv4_func; + syntax_func port_func; + syntax_func ipv4_port_func; + gboolean does_inbound; +} fw_product; + +static fw_product products[] = { + { "Cisco IOS (standard)", "Change NUMBER to a valid ACL number.", "!", + NULL, sf_ios_std_ipv4, NULL, NULL, FALSE }, + { "Cisco IOS (extended)", "Change NUMBER to a valid ACL number.", "!", + NULL, sf_ios_ext_ipv4, sf_ios_ext_port, sf_ios_ext_ipv4_port, TRUE }, + { "IP Filter (ipfilter)", "Change le0 to a valid interface.", "#", + NULL, sf_ipfilter_ipv4, sf_ipfilter_port, sf_ipfilter_ipv4_port, TRUE }, + { "IPFirewall (ipfw)", "", "#", + sf_ipfw_mac, sf_ipfw_ipv4, sf_ipfw_port, sf_ipfw_ipv4_port, TRUE }, + { "Netfilter (iptables)", "Change eth0 to a valid interface.", "#", + sf_netfilter_mac, sf_netfilter_ipv4, sf_netfilter_port, + sf_netfilter_ipv4_port, TRUE }, + { "Packet Filter (pf)", "$ext_if should be set to a valid interface.", "#", + NULL, sf_pf_ipv4, sf_pf_port, sf_pf_ipv4_port, TRUE }, + { "Windows Firewall (netsh)", "", "#", + NULL, NULL, sf_netsh_port, sf_netsh_ipv4_port, FALSE } +}; +#define NUM_PRODS (sizeof(products) / sizeof(fw_product)) + + +size_t firewall_product_count(void) +{ + return NUM_PRODS; +} + +const char *firewall_product_name(size_t product_idx) +{ + if (product_idx >= NUM_PRODS) return "Unknown"; + return products[product_idx].name; +} + +const char *firewall_product_rule_hint(size_t product_idx) +{ + if (product_idx >= NUM_PRODS) return ""; + return products[product_idx].rule_hint; +} + +const char *firewall_product_comment_prefix(size_t product_idx) +{ + if (product_idx >= NUM_PRODS) return ""; + return products[product_idx].comment_pfx; +} + +syntax_func firewall_product_mac_func(size_t product_idx) +{ + if (product_idx >= NUM_PRODS) return NULL; + return products[product_idx].mac_func; +} + + +syntax_func firewall_product_ipv4_func(size_t product_idx) +{ + if (product_idx >= NUM_PRODS) return NULL; + return products[product_idx].ipv4_func; +} + + +syntax_func firewall_product_port_func(size_t product_idx) +{ + if (product_idx >= NUM_PRODS) return NULL; + return products[product_idx].port_func; +} + + +syntax_func firewall_product_ipv4_port_func(size_t product_idx) +{ + if (product_idx >= NUM_PRODS) return NULL; + return products[product_idx].ipv4_port_func; +} + +gboolean firewall_product_does_inbound(size_t product_idx) +{ + if (product_idx >= NUM_PRODS) return FALSE; + return products[product_idx].does_inbound; +} + + +/* MAC */ +#define IPFW_DENY (deny ? "deny" : "allow") +#define IPFW_IN (inbound ? "in" : "out") +static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "add %s MAC %s any %s", + IPFW_DENY, addr, IPFW_IN); +} + +#define NF_DROP (deny ? "DROP" : "ACCEPT") +#define NF_INPUT (inbound ? "INPUT" : "OUTPUT") +static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "iptables -A %s -i eth0 --mac-source %s -j %s", + NF_INPUT, addr, NF_DROP); +} + +/* IPv4 */ +#define IOS_DENY (deny ? "deny" : "permit") +static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny) { + g_string_append_printf(rtxt, "access-list NUMBER %s host %s", IOS_DENY, addr); +} + +static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { + if (inbound) + g_string_append_printf(rtxt, "access-list NUMBER %s ip host %s any", IOS_DENY, addr); + else + g_string_append_printf(rtxt, "access-list NUMBER %s ip any host %s", IOS_DENY, addr); +} + +#define IPFILTER_DENY (deny ? "block" : "pass") +#define IPFILTER_IN (inbound ? "in" : "out") +static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "%s %s on le0 from %s to any", + IPFILTER_DENY, IPFILTER_IN, addr); +} + +static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "add %s ip from %s to any %s", + IPFW_DENY, addr, IPFW_IN); +} + +static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "iptables -A %s -i eth0 -d %s/32 -j %s", + NF_INPUT, addr, NF_DROP); +} + +#define PF_DENY (deny ? "block" : "pass") +#define PF_IN (inbound ? "in" : "out") +static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "%s %s quick on $ext_if from %s to any", + PF_DENY, PF_IN, addr); +} + +/* Port */ +#define RT_TCP_UDP (ptype == PT_TCP ? "tcp" : "udp") +static void sf_ios_ext_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) { + g_string_append_printf(rtxt, "access-list NUMBER %s %s any any eq %u", + IOS_DENY, RT_TCP_UDP, port); +} + +static void sf_ipfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype _U_, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to any port = %u", + IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, port); +} + +static void sf_ipfw_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "add %s %s from any to any %u %s", + IPFW_DENY, RT_TCP_UDP, port, IPFW_IN); +} + +static void sf_netfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "iptables -A %s -i eth0 -p %s --destination-port %u -j %s", + NF_INPUT, RT_TCP_UDP, port, NF_DROP); +} + +static void sf_pf_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from any to any port %u", + PF_DENY, PF_IN, RT_TCP_UDP, port); +} + +#define NETSH_DENY (deny ? "DISABLE" : "ENABLE") +static void sf_netsh_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) { + g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s", + RT_TCP_UDP, port, NETSH_DENY); +} + +/* IPv4 + port */ +static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { + if (inbound) + g_string_append_printf(rtxt, "access-list NUMBER %s %s host %s any eq %u", IOS_DENY, RT_TCP_UDP, addr, port); + else + g_string_append_printf(rtxt, "access-list NUMBER %s %s any host %s eq %u", IOS_DENY, RT_TCP_UDP, addr, port); +} + +static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { + if (inbound) + g_string_append_printf(rtxt, "%s %s on le0 proto %s from %s to any port = %u", + IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port); + else + g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to %s port = %u", + IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port); +} + +static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "add %s %s from %s to any %u %s", + IPFW_DENY, RT_TCP_UDP, addr, port, IPFW_IN); +} + +static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from %s to any port %u", + PF_DENY, PF_IN, RT_TCP_UDP, addr, port); +} + +static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { + g_string_append_printf(rtxt, "iptables -A %s -i eth0 -p %s -d %s/32 --destination-port %u -j %s", + NF_INPUT, RT_TCP_UDP, addr, port, NF_DROP); +} + +static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) { + g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s %s", + RT_TCP_UDP, port, NETSH_DENY, addr); +} + + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/firewall_rules.h b/ui/firewall_rules.h new file mode 100644 index 0000000000..690793c41b --- /dev/null +++ b/ui/firewall_rules.h @@ -0,0 +1,108 @@ +/* firewall_rules.h + * Produce ACL rules for various products from a packet. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 2006 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __UI_FIREWALL_RULES_H__ +#define __UI_FIREWALL_RULES_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Rule types */ +typedef enum { + RT_NONE, + RT_MAC_SRC, + RT_MAC_DST, + RT_IPv4_SRC, + RT_IPv4_DST, + RT_PORT_SRC, + RT_PORT_DST, + RT_IPv4_PORT_SRC, + RT_IPv4_PORT_DST, + NUM_RULE_TYPES +} rule_type_e; + +/** Fetch the number of firewall products. + * @return The number of firewall products. Should be used as the index for + * the rest of the functions below. + */ +size_t firewall_product_count(void); + +/** Product name + * Given an index, return the product name. + * @param product_idx Product index. + * @return Product name or "Unknown". + */ +const char *firewall_product_name(size_t product_idx); + +/** Product rule hint + * Given an index, return the product's rule hint. + * @param product_idx Product index. + * @return Product rule hint, e.g. "Change le0 to a valid interface." or "". + */ +const char *firewall_product_rule_hint(size_t product_idx); + +/** Comment prefix + * @param product_idx Product index. + * @return The comment prefix, e.g. "#" or an empty string. + */ +const char *firewall_product_comment_prefix(size_t product_idx); + +/* Syntax function prototypes */ +typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); + +/** MAC filter function + * @param product_idx Product index. + * @return A pointer to the MAC filter function or NULL. + */ +syntax_func firewall_product_mac_func(size_t product_idx); + +/** IPv4 filter function + * @param product_idx Product index. + * @return A pointer to the IPv4 filter function or NULL. + */ +syntax_func firewall_product_ipv4_func(size_t product_idx); + +/** Port filter function + * @param product_idx Product index. + * @return A pointer to the port filter function or NULL. + */ +syntax_func firewall_product_port_func(size_t product_idx); + +/** IPv4+port filter function + * @param product_idx Product index. + * @return A pointer to the IPv4+port filter function or NULL. + */ +syntax_func firewall_product_ipv4_port_func(size_t product_idx); + +/** Product inbound support + * Given an index, return the product's ability to support inbound rules. + * @param product_idx Product index. + * @return TRUE or FALSE. + */ +gboolean firewall_product_does_inbound(size_t product_idx); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __UI_FIREWALL_RULES_H__ */ diff --git a/ui/gtk/firewall_dlg.c b/ui/gtk/firewall_dlg.c index 155ba05669..1de148d7f6 100644 --- a/ui/gtk/firewall_dlg.c +++ b/ui/gtk/firewall_dlg.c @@ -23,13 +23,6 @@ * in one huge text window, or some sort of tree view. */ -/* - * To add a new product, add syntax functions modify the products[] array. - * - * To add a new syntax function, add its prototype above the products[] - * array, and add the function below with all the others. - */ - /* Copied from ssl-dlg.c */ #include "config.h" @@ -44,6 +37,7 @@ #include #include +#include #include #include @@ -58,24 +52,9 @@ #define MAX_RULE_LEN 200 -/* Rule types */ -typedef enum { - RT_NONE, - RT_MAC_SRC, - RT_MAC_DST, - RT_IPv4_SRC, - RT_IPv4_DST, - RT_PORT_SRC, - RT_PORT_DST, - RT_IPv4_PORT_SRC, - RT_IPv4_PORT_DST, - NUM_RULE_TYPES -} rule_type_t; - - /* Copied from packet_info struct */ typedef struct _rule_info_t { - gint product; + size_t product; address dl_src; address dl_dst; address net_src; @@ -89,68 +68,11 @@ typedef struct _rule_info_t { GtkWidget *inbound_cb; gboolean inbound; gboolean deny; - rule_type_t rule_type; + rule_type_e rule_type; } rule_info_t; -/* Syntax function prototypes */ -typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); - static void sf_dummy(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); - -static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -/* XXX - Can you addresses-only filters using WFW/netsh? */ - -static void sf_ios_ext_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_ipfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_ipfw_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_netfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_pf_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_netsh_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); - -static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); -static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); - -typedef struct _fw_product_t { - const gchar *name; - const gchar *comment_pfx; - syntax_func mac_func; - syntax_func ipv4_func; - syntax_func port_func; - syntax_func ipv4_port_func; - gboolean does_inbound; -} fw_product; - -static fw_product products[] = { - { "Cisco IOS (standard)", "!", NULL, sf_ios_std_ipv4, NULL, NULL, FALSE }, - { "Cisco IOS (extended)", "!", - NULL, sf_ios_ext_ipv4, sf_ios_ext_port, sf_ios_ext_ipv4_port, TRUE }, - { "IP Filter (ipfilter)", "#", - NULL, sf_ipfilter_ipv4, sf_ipfilter_port, sf_ipfilter_ipv4_port, TRUE }, - { "IPFirewall (ipfw)", "#", - sf_ipfw_mac, sf_ipfw_ipv4, sf_ipfw_port, sf_ipfw_ipv4_port, TRUE }, - { "Netfilter (iptables)", "#", - sf_netfilter_mac, sf_netfilter_ipv4, sf_netfilter_port, - sf_netfilter_ipv4_port, TRUE }, - { "Packet Filter (pf)", "#", - NULL, sf_pf_ipv4, sf_pf_port, sf_pf_ipv4_port, TRUE }, - { "Windows Firewall (netsh)", "#", - NULL, NULL, sf_netsh_port, sf_netsh_ipv4_port, FALSE } -}; -#define NUM_PRODS (sizeof(products) / sizeof(fw_product)) - - static void select_product(GtkWidget * win, gpointer data); static void select_filter(GtkWidget * win, gpointer data); static void toggle_inbound(GtkToggleButton *t, gpointer data); @@ -182,7 +104,7 @@ firewall_rule_cb(GtkWidget *w _U_, gpointer data _U_) GtkWidget *hbox, *button_hbox, *button; rule_info_t *rule_info; packet_info *pinfo = &cfile.edt->pi; - guint i; + size_t i; rule_info = g_new0(rule_info_t, 1); copy_address(&(rule_info->dl_src), &(pinfo->dl_src)); @@ -214,8 +136,8 @@ firewall_rule_cb(GtkWidget *w _U_, gpointer data _U_) gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); product_combo_box = gtk_combo_box_text_new(); - for (i = 0; i < NUM_PRODS; i++) { - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(product_combo_box), products[i].name); + for (i = 0; i < firewall_product_count(); i++) { + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(product_combo_box), firewall_product_name(i)); } g_object_set_data(G_OBJECT(product_combo_box), WS_RULE_INFO_KEY, rule_info); g_signal_connect(product_combo_box, "changed", G_CALLBACK(select_product), NULL); @@ -313,12 +235,12 @@ select_product(GtkWidget *w, gpointer data _U_) rule_info_t *rule_info; gchar name[MAX_RULE_LEN], addr_str[MAX_RULE_LEN]; address *addr; - rule_type_t rule_type = RT_NONE; + rule_type_e rule_type = RT_NONE; gboolean sensitive = FALSE; rule_info =(rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY); - if (prod >= NUM_PRODS || !rule_info) + if (prod >= firewall_product_count() || !rule_info) return; rule_info->product = prod; @@ -327,7 +249,7 @@ select_product(GtkWidget *w, gpointer data _U_) ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box)); /* Fill in valid combo_box list items (in the list store). */ - if (products[prod].mac_func && rule_info->dl_src.type == AT_ETHER) { + if (firewall_product_mac_func(prod) && rule_info->dl_src.type == AT_ETHER) { addr = &(rule_info->dl_src); address_to_str_buf(addr, name, MAX_RULE_LEN); ADD_TO_FILTER_MENU(RT_MAC_SRC); @@ -337,7 +259,7 @@ select_product(GtkWidget *w, gpointer data _U_) ADD_TO_FILTER_MENU(RT_MAC_DST); } - if (products[prod].ipv4_func && rule_info->net_src.type == AT_IPv4) { + if (firewall_product_ipv4_func(prod) && rule_info->net_src.type == AT_IPv4) { addr = &(rule_info->net_src); address_to_str_buf(addr, name, MAX_RULE_LEN); ADD_TO_FILTER_MENU(RT_IPv4_SRC); @@ -347,7 +269,7 @@ select_product(GtkWidget *w, gpointer data _U_) ADD_TO_FILTER_MENU(RT_IPv4_DST); } - if (products[prod].port_func && (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) { + if (firewall_product_port_func(prod) && (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) { g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP, rule_info->srcport); ADD_TO_FILTER_MENU(RT_PORT_SRC); @@ -358,7 +280,7 @@ select_product(GtkWidget *w, gpointer data _U_) } } - if (products[prod].ipv4_port_func && rule_info->net_src.type == AT_IPv4 && + if (firewall_product_ipv4_port_func(prod) && rule_info->net_src.type == AT_IPv4 && (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) { addr = &(rule_info->net_src); address_to_str_buf(addr, addr_str, MAX_RULE_LEN); @@ -381,7 +303,7 @@ select_product(GtkWidget *w, gpointer data _U_) } gtk_widget_set_sensitive(rule_info->filter_combo_box, sensitive); - gtk_widget_set_sensitive(rule_info->inbound_cb, products[prod].does_inbound && sensitive); + gtk_widget_set_sensitive(rule_info->inbound_cb, firewall_product_does_inbound(prod) && sensitive); gtk_widget_set_sensitive(rule_info->deny_cb, sensitive); } @@ -389,7 +311,7 @@ select_product(GtkWidget *w, gpointer data _U_) static void select_filter(GtkWidget *w, gpointer data _U_) { - rule_type_t cur_type; + rule_type_e cur_type; rule_info_t *rule_info; gpointer ptr; @@ -399,7 +321,7 @@ select_filter(GtkWidget *w, gpointer data _U_) if (ws_combo_box_get_active_pointer(GTK_COMBO_BOX(w), &ptr)) - cur_type = (rule_type_t)GPOINTER_TO_UINT(ptr); + cur_type = (rule_type_e)GPOINTER_TO_UINT(ptr); else cur_type = RT_NONE; /* If nothing selected (eg: nothing in filter list) */ @@ -441,44 +363,48 @@ static void set_rule_text(rule_info_t *rule_info) { GString *rtxt = g_string_new(""); gchar addr_str[MAX_RULE_LEN]; - rule_type_t rt = rule_info->rule_type; - guint prod = rule_info->product; + rule_type_e rt = rule_info->rule_type; + size_t prod = rule_info->product; address *addr = NULL; guint32 port = 0; syntax_func rt_func = NULL; GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text)); - if (prod < NUM_PRODS) { - g_string_printf(rtxt, "%s %s\n", products[prod].comment_pfx, products[prod].name); + if (prod < firewall_product_count()) { + const char *hint = firewall_product_rule_hint(prod); + g_string_printf(rtxt, "%s %s\n", firewall_product_comment_prefix(prod), firewall_product_name(prod)); + if (strlen(hint) > 0) { + g_string_append_printf(rtxt, " %s", hint); + } switch(rt) { case RT_NONE: - g_string_append_printf(rtxt, "%s Not supported", products[prod].comment_pfx); + g_string_append_printf(rtxt, "%s Not supported", firewall_product_comment_prefix(prod)); rt_func = sf_dummy; break; case RT_MAC_SRC: case RT_MAC_DST: addr = DL_ADDR; address_to_str_buf(addr, addr_str, MAX_RULE_LEN); - rt_func = products[prod].mac_func; + rt_func = firewall_product_mac_func(prod); break; case RT_IPv4_SRC: case RT_IPv4_DST: addr = NET_ADDR; address_to_str_buf(addr, addr_str, MAX_RULE_LEN); - rt_func = products[prod].ipv4_func; + rt_func = firewall_product_ipv4_func(prod); break; case RT_PORT_SRC: case RT_PORT_DST: port = NET_PORT; - rt_func = products[prod].port_func; + rt_func = firewall_product_port_func(prod); break; case RT_IPv4_PORT_SRC: case RT_IPv4_PORT_DST: addr = NET_ADDR; address_to_str_buf(addr, addr_str, MAX_RULE_LEN); port = NET_PORT; - rt_func = products[prod].ipv4_port_func; + rt_func = firewall_product_ipv4_port_func(prod); break; default: break; @@ -502,128 +428,6 @@ set_rule_text(rule_info_t *rule_info) { static void sf_dummy(GString *rtxt _U_, gchar *addr _U_, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny _U_) { } -/* MAC */ -#define IPFW_DENY (deny ? "deny" : "allow") -#define IPFW_IN (inbound ? "in" : "out") -static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "add %s MAC %s any %s", - IPFW_DENY, addr, IPFW_IN); -} - -#define NF_DROP (deny ? "DROP" : "ACCEPT") -#define NF_INPUT (inbound ? "INPUT" : "OUTPUT") -static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "iptables -A %s --mac-source %s -j %s", - NF_INPUT, addr, NF_DROP); -} - -/* IPv4 */ -#define IOS_DENY (deny ? "deny" : "permit") -static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny) { - g_string_append_printf(rtxt, "access-list NUMBER %s host %s", IOS_DENY, addr); -} - -static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { - if (inbound) - g_string_append_printf(rtxt, "access-list NUMBER %s ip host %s any", IOS_DENY, addr); - else - g_string_append_printf(rtxt, "access-list NUMBER %s ip any host %s", IOS_DENY, addr); -} - -#define IPFILTER_DENY (deny ? "block" : "pass") -#define IPFILTER_IN (inbound ? "in" : "out") -static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "%s %s on le0 from %s to any", - IPFILTER_DENY, IPFILTER_IN, addr); -} - -static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "add %s ip from %s to any %s", - IPFW_DENY, addr, IPFW_IN); -} - -static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "iptables -A %s -i eth0 -d %s/32 -j %s", - NF_INPUT, addr, NF_DROP); -} - -#define PF_DENY (deny ? "block" : "pass") -#define PF_IN (inbound ? "in" : "out") -static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "%s %s quick on $ext_if from %s to any", - PF_DENY, PF_IN, addr); -} - -/* Port */ -#define RT_TCP_UDP (ptype == PT_TCP ? "tcp" : "udp") -static void sf_ios_ext_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) { - g_string_append_printf(rtxt, "access-list NUMBER %s %s any any eq %u", - IOS_DENY, RT_TCP_UDP, port); -} - -static void sf_ipfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype _U_, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to any port = %u", - IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, port); -} - -static void sf_ipfw_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "add %s %s from any to any %u %s", - IPFW_DENY, RT_TCP_UDP, port, IPFW_IN); -} - -static void sf_netfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "iptables -A %s -p %s --destination-port %u -j %s", - NF_INPUT, RT_TCP_UDP, port, NF_DROP); -} - -static void sf_pf_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from any to any port %u", - PF_DENY, PF_IN, RT_TCP_UDP, port); -} - -#define NETSH_DENY (deny ? "DISABLE" : "ENABLE") -static void sf_netsh_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) { - g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s", - RT_TCP_UDP, port, NETSH_DENY); -} - -/* IPv4 + port */ -static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) { - if (inbound) - g_string_append_printf(rtxt, "access-list NUMBER %s %s host %s any eq %u", IOS_DENY, RT_TCP_UDP, addr, port); - else - g_string_append_printf(rtxt, "access-list NUMBER %s %s any host %s eq %u", IOS_DENY, RT_TCP_UDP, addr, port); -} - -static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { - if (inbound) - g_string_append_printf(rtxt, "%s %s on le0 proto %s from %s to any port = %u", - IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port); - else - g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to %s port = %u", - IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port); -} - -static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "add %s %s from %s to any %u %s", - IPFW_DENY, RT_TCP_UDP, addr, port, IPFW_IN); -} - -static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from %s to any port %u", - PF_DENY, PF_IN, RT_TCP_UDP, addr, port); -} - -static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) { - g_string_append_printf(rtxt, "iptables -A %s -p %s -d %s/32 --destination-port %u -j %s", - NF_INPUT, RT_TCP_UDP, addr, port, NF_DROP); -} - -static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) { - g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s %s", - RT_TCP_UDP, port, NETSH_DENY, addr); -} - /* The destroy call back has the responsibility of * unlinking the temporary file * and freeing the filter_out_filter */ diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 841c9d7f2d..9ea3c3593b 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -68,6 +68,7 @@ set(WIRESHARK_QT_HEADERS filter_expression_frame.h filter_expressions_preferences_frame.h find_line_edit.h + firewall_rules_dialog.h follow_stream_dialog.h follow_stream_text.h font_color_preferences_frame.h @@ -222,6 +223,7 @@ set(WIRESHARK_QT_SRC filter_expression_frame.cpp filter_expressions_preferences_frame.cpp find_line_edit.cpp + firewall_rules_dialog.cpp follow_stream_dialog.cpp follow_stream_text.cpp font_color_preferences_frame.cpp @@ -369,6 +371,7 @@ set(WIRESHARK_QT_UI filter_dialog.ui filter_expression_frame.ui filter_expressions_preferences_frame.ui + firewall_rules_dialog.ui follow_stream_dialog.ui font_color_preferences_frame.ui funnel_string_dialog.ui diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 134b8b167c..0d99addb52 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -205,6 +205,8 @@ filter_expression_frame.$(OBJEXT): ui_filter_expression_frame.h filter_expressions_preferences_frame.$(OBJEXT): ui_filter_expressions_preferences_frame.h +firewall_rules_dialog.$(OBJEXT): ui_firewall_rules_dialog.h + follow_stream_dialog.$(OBJEXT): ui_follow_stream_dialog.h font_color_preferences_frame.$(OBJEXT): ui_font_color_preferences_frame.h diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index 61d3270ae8..105f6621cc 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -53,6 +53,7 @@ NODIST_GENERATED_HEADER_FILES = \ ui_filter_dialog.h \ ui_filter_expression_frame.h \ ui_filter_expressions_preferences_frame.h \ + ui_firewall_rules_dialog.h \ ui_follow_stream_dialog.h \ ui_font_color_preferences_frame.h \ ui_funnel_string_dialog.h \ @@ -187,6 +188,7 @@ MOC_HDRS = \ filter_expression_frame.h \ filter_expressions_preferences_frame.h \ find_line_edit.h \ + firewall_rules_dialog.h \ follow_stream_dialog.h \ follow_stream_text.h \ font_color_preferences_frame.h \ @@ -303,6 +305,7 @@ UI_FILES = \ filter_dialog.ui \ filter_expression_frame.ui \ filter_expressions_preferences_frame.ui \ + firewall_rules_dialog.ui \ follow_stream_dialog.ui \ font_color_preferences_frame.ui \ funnel_string_dialog.ui \ @@ -455,6 +458,7 @@ WIRESHARK_QT_SRC = \ filter_expression_frame.cpp \ filter_expressions_preferences_frame.cpp \ find_line_edit.cpp \ + firewall_rules_dialog.cpp \ follow_stream_dialog.cpp \ follow_stream_text.cpp \ font_color_preferences_frame.cpp \ diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro index fd22a55929..c2ca0fbc4e 100644 --- a/ui/qt/Wireshark.pro +++ b/ui/qt/Wireshark.pro @@ -234,6 +234,7 @@ FORMS += \ filter_dialog.ui \ filter_expression_frame.ui \ filter_expressions_preferences_frame.ui \ + firewall_rules_dialog.ui \ follow_stream_dialog.ui \ font_color_preferences_frame.ui \ funnel_string_dialog.ui \ @@ -324,6 +325,7 @@ HEADERS += $$HEADERS_WS_C \ filter_expression_frame.h \ filter_expressions_preferences_frame.h \ find_line_edit.h \ + firewall_rules_dialog.h \ follow_stream_dialog.h \ follow_stream_text.h \ font_color_preferences_frame.h \ @@ -722,6 +724,7 @@ SOURCES += \ filter_expression_frame.cpp \ filter_expressions_preferences_frame.cpp \ find_line_edit.cpp \ + firewall_rules_dialog.cpp \ follow_stream_dialog.cpp \ follow_stream_text.cpp \ font_color_preferences_frame.cpp \ diff --git a/ui/qt/firewall_rules_dialog.cpp b/ui/qt/firewall_rules_dialog.cpp new file mode 100644 index 0000000000..417530d054 --- /dev/null +++ b/ui/qt/firewall_rules_dialog.cpp @@ -0,0 +1,225 @@ +/* firewall_rules_dialog.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#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 +#include +#include +#include +#include + +FirewallRulesDialog::FirewallRulesDialog(QWidget &parent, CaptureFile &cf) : + WiresharkDialog(parent, cf), + ui(new Ui::FirewallRulesDialog) +{ + 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 = QFileDialog::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->setLastOpenDir(file_name.constData()); + } + } 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); +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/firewall_rules_dialog.h b/ui/qt/firewall_rules_dialog.h new file mode 100644 index 0000000000..f9b9927fc7 --- /dev/null +++ b/ui/qt/firewall_rules_dialog.h @@ -0,0 +1,85 @@ +/* firewall_rules_dialog.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef FIREWALL_RULES_DIALOG_H +#define FIREWALL_RULES_DIALOG_H + +#include "epan/address.h" + +#include + +namespace Ui { +class FirewallRulesDialog; +} + +class QAbstractButton; + +typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); + +class FirewallRulesDialog : public WiresharkDialog +{ + Q_OBJECT + +public: + explicit FirewallRulesDialog(QWidget &parent, CaptureFile &cf); + ~FirewallRulesDialog(); + +private slots: + void on_productComboBox_currentIndexChanged(int new_idx); + void on_inboundCheckBox_toggled(bool); + void on_denyCheckBox_toggled(bool); + void on_buttonBox_helpRequested(); + + void on_buttonBox_clicked(QAbstractButton *button); + +private: + Ui::FirewallRulesDialog *ui; + + QString file_name_; + int packet_num_; + + size_t prod_; + address dl_src_; + address dl_dst_; + address net_src_; + address net_dst_; + port_type ptype_; + guint32 src_port_; + guint32 dst_port_; + + void updateWidgets(); + void addRule(QString description, syntax_func rule_func, address *addr, guint32 port); +}; + +#endif // FIREWALL_RULES_DIALOG_H + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/firewall_rules_dialog.ui b/ui/qt/firewall_rules_dialog.ui new file mode 100644 index 0000000000..6e9d4b5057 --- /dev/null +++ b/ui/qt/firewall_rules_dialog.ui @@ -0,0 +1,124 @@ + + + FirewallRulesDialog + + + + 0 + 0 + 650 + 450 + + + + + + + + + + + + Create rules for + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Inbound + + + true + + + + + + + Qt::Horizontal + + + + 20 + 5 + + + + + + + + Deny + + + true + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Save + + + + + + + + + buttonBox + accepted() + FirewallRulesDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + FirewallRulesDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 1fb7e436c8..1c06bf7508 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -2326,11 +2326,8 @@ void MainWindow::addDynamicMenus() } // Empty menus don't show up: https://bugreports.qt.io/browse/QTBUG-33728 - // We've added a placeholder in order to make sure the "Tools" menu is - // visible. Hide it as needed. - if (wsApp->dynamicMenuGroupItems(REGISTER_TOOLS_GROUP_UNSORTED).length() > 0) { - main_ui_->actionToolsPlaceholder->setVisible(false); - } + // We've added a placeholder in order to make sure some menus are visible. + // Hide them as needed. if (wsApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_ANSI).length() > 0) { main_ui_->actionTelephonyANSIPlaceholder->setVisible(false); } diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 913cad83f5..4bc4a96109 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -601,6 +601,8 @@ private slots: void on_actionBluetoothDevices_triggered(); void on_actionBluetoothHCI_Summary_triggered(); + void on_actionToolsFirewallAclRules_triggered(); + void externalMenuItem_triggered(); void on_actionContextCopyBytesHexTextDump_triggered(); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 4a8d3ca2ec..e4d23f9b83 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -80,31 +80,31 @@ + + + 16777215 + 27 + + Go to packet true - - - 16777215 - 27 - - - - Cancel - 16777215 27 + + Cancel + @@ -651,7 +651,7 @@ &Tools - + @@ -2650,20 +2650,6 @@ QAction::NoRole - - - false - - - No tools registered - - - No tools have been registered. - - - QAction::NoRole - - false @@ -2925,6 +2911,14 @@ Add a display filter button. + + + Firewall ACL Rules + + + Create firewall ACL rules + + diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 447ee6609f..d7e6130aa4 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -106,6 +106,7 @@ #include "file_set_dialog.h" #include "filter_action.h" #include "filter_dialog.h" +#include "firewall_rules_dialog.h" #include "funnel_statistics.h" #include "gsm_map_summary_dialog.h" #include "iax2_analysis_dialog.h" @@ -1217,8 +1218,8 @@ void MainWindow::setMenusForSelectedPacket() // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/NameResolution/ResolveName", // frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name || // gbl_resolv_flags.transport_name)); -// set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ToolsMenu/FirewallACLRules", -// frame_selected); + + main_ui_->actionToolsFirewallAclRules->setEnabled(frame_selected); main_ui_->actionStatisticsTcpStreamRoundTripTime->setEnabled(is_tcp); main_ui_->actionStatisticsTcpStreamStevens->setEnabled(is_tcp); @@ -3231,7 +3232,7 @@ void MainWindow::on_actionTelephonySipFlows_triggered() openVoipCallsDialog(true); } -// Bluetooth Menu +// Wireless Menu void MainWindow::on_actionBluetoothATT_Server_Attributes_triggered() { @@ -3263,6 +3264,15 @@ void MainWindow::on_actionBluetoothHCI_Summary_triggered() bluetooth_hci_summary_dialog->show(); } +// Tools Menu + +void MainWindow::on_actionToolsFirewallAclRules_triggered() +{ + FirewallRulesDialog *firewall_rules_dialog = new FirewallRulesDialog(*this, capture_file_); + firewall_rules_dialog->show(); +} + + // Help Menu void MainWindow::on_actionHelpContents_triggered() {