1 /* firewall_rules_dlg.c
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * Generate firewall ACL rules based on packet addresses and ports.
22 * For directional rules, an outside interface is assumed.
24 * There may be better ways to present the information, e.g. all rules
25 * in one huge text window, or some sort of tree view.
29 * To add a new product, add syntax functions modify the products[] array.
31 * To add a new syntax function, add its prototype above the products[]
32 * array, and add the function below with all the others.
35 /* Copied from ssl-dlg.c */
54 #include <epan/packet.h>
55 #include <epan/addr_resolv.h>
56 #include <epan/epan_dissect.h>
57 #include <epan/filesystem.h>
58 #include <epan/dissectors/packet-ipv6.h>
60 #include <../alert_box.h>
61 #include <../simple_dialog.h>
62 #include <wsutil/file_util.h>
65 #include <gtk/dlg_utils.h>
66 #include <gtk/file_dlg.h>
67 #include <gtk/help_dlg.h>
68 #include <gtk/gui_utils.h>
69 #include "gtk/old-gtk-compat.h"
70 #include "gtk/firewall_dlg.h"
72 #define MAX_RULE_LEN 200
89 /* Copied from packet_info struct */
90 typedef struct _rule_info_t {
100 GtkWidget *filter_combo_box;
102 GtkWidget *inbound_cb;
103 GtkWidget *firewall_save_as_w;
106 rule_type_t rule_type;
109 /* Syntax function prototypes */
110 typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
112 static void sf_dummy(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
114 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
115 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
117 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
118 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
119 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
120 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
121 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
122 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
123 /* XXX - Can you addresses-only filters using WFW/netsh? */
125 static void sf_ios_ext_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
126 static void sf_ipfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
127 static void sf_ipfw_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
128 static void sf_netfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
129 static void sf_pf_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
130 static void sf_netsh_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
132 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
133 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
134 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
135 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
136 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
137 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
139 typedef struct _fw_product_t {
142 syntax_func mac_func;
143 syntax_func ipv4_func;
144 syntax_func port_func;
145 syntax_func ipv4_port_func;
146 gboolean does_inbound;
149 static fw_product products[] = {
150 { "Cisco IOS (standard)", "!", NULL, sf_ios_std_ipv4, NULL, NULL, FALSE },
151 { "Cisco IOS (extended)", "!",
152 NULL, sf_ios_ext_ipv4, sf_ios_ext_port, sf_ios_ext_ipv4_port, TRUE },
153 { "IP Filter (ipfilter)", "#",
154 NULL, sf_ipfilter_ipv4, sf_ipfilter_port, sf_ipfilter_ipv4_port, TRUE },
155 { "IPFirewall (ipfw)", "#",
156 sf_ipfw_mac, sf_ipfw_ipv4, sf_ipfw_port, sf_ipfw_ipv4_port, TRUE },
157 { "Netfilter (iptables)", "#",
158 sf_netfilter_mac, sf_netfilter_ipv4, sf_netfilter_port,
159 sf_netfilter_ipv4_port, TRUE },
160 { "Packet Filter (pf)", "#",
161 NULL, sf_pf_ipv4, sf_pf_port, sf_pf_ipv4_port, TRUE },
162 { "Windows Firewall (netsh)", "#",
163 NULL, NULL, sf_netsh_port, sf_netsh_ipv4_port, FALSE }
165 #define NUM_PRODS (sizeof(products) / sizeof(fw_product))
168 static void select_product(GtkWidget * win, gpointer data);
169 static void select_filter(GtkWidget * win, gpointer data);
170 static void toggle_inbound(GtkToggleButton *t, gpointer data);
171 static void toggle_deny(GtkToggleButton *t, gpointer data);
172 static void set_rule_text(rule_info_t *rule_info);
173 static void firewall_destroy_cb(GtkWidget * win, gpointer data);
174 static void firewall_copy_cmd_cb(GtkWidget * w, gpointer data);
175 static void firewall_save_as_cmd_cb(GtkWidget * w, gpointer data);
176 static gboolean firewall_save_as_ok_cb(GtkWidget * w, gpointer fs);
177 static void firewall_save_as_destroy_cb(GtkWidget * win, gpointer user_data);
179 #define WS_RULE_INFO_KEY "rule_info_key"
182 /* List of "rule_info_t" structures for all rule windows. */
183 static GList *rule_infos;
185 /* Remove a "rule_info_t" structure from the list. */
187 forget_rule_info(rule_info_t *rule_info)
189 rule_infos = g_list_remove(rule_infos, rule_info);
194 firewall_rule_cb(GtkWidget *w _U_, gpointer data _U_)
196 GtkWidget *rule_w, *vbox, *txt_scrollw, *text;
197 GtkWidget *label, *product_combo_box;
198 GtkWidget *hbox, *button_hbox, *button;
199 rule_info_t *rule_info;
200 packet_info *pinfo = &cfile.edt->pi;
203 rule_info = g_new0(rule_info_t, 1);
204 COPY_ADDRESS(&(rule_info->dl_src), &(pinfo->dl_src));
205 COPY_ADDRESS(&(rule_info->dl_dst), &(pinfo->dl_dst));
206 COPY_ADDRESS(&(rule_info->net_src), &(pinfo->net_src));
207 COPY_ADDRESS(&(rule_info->net_dst), &(pinfo->net_dst));
208 rule_info->ptype = pinfo->ptype;
209 rule_info->srcport = pinfo->srcport;
210 rule_info->destport = pinfo->destport;
211 rule_info->inbound = TRUE;
212 rule_info->deny = TRUE;
213 rule_info->product = 0;
215 rule_w = dlg_window_new("Firewall ACL Rules");
217 gtk_widget_set_name(rule_w, "Firewall ACL rule window");
218 gtk_container_set_border_width(GTK_CONTAINER(rule_w), 6);
220 /* setup the container */
221 vbox = gtk_vbox_new(FALSE, 6);
222 gtk_container_add(GTK_CONTAINER(rule_w), vbox);
224 /* rule type selectors hbox */
225 hbox = gtk_hbox_new(FALSE, 1);
226 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
228 /* product selector */
229 label = gtk_label_new("Product");
230 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
232 product_combo_box = gtk_combo_box_text_new();
233 for (i = 0; i < NUM_PRODS; i++) {
234 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(product_combo_box), products[i].name);
236 g_object_set_data(G_OBJECT(product_combo_box), WS_RULE_INFO_KEY, rule_info);
237 g_signal_connect(product_combo_box, "changed", G_CALLBACK(select_product), NULL);
238 gtk_box_pack_start(GTK_BOX(hbox), product_combo_box, FALSE, FALSE, 5);
241 label = gtk_label_new("Filter");
242 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
244 rule_info->filter_combo_box = ws_combo_box_new_text_and_pointer();
245 g_object_set_data(G_OBJECT(rule_info->filter_combo_box), WS_RULE_INFO_KEY, rule_info); \
246 g_signal_connect(rule_info->filter_combo_box, "changed", G_CALLBACK(select_filter), NULL);
247 gtk_box_pack_start(GTK_BOX(hbox), rule_info->filter_combo_box, FALSE, FALSE, 5);
249 /* inbound selector */
250 rule_info->inbound_cb = gtk_check_button_new_with_label("Inbound");
251 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->inbound_cb),
253 gtk_box_pack_start(GTK_BOX(hbox), rule_info->inbound_cb, FALSE, FALSE, 10);
254 g_signal_connect(rule_info->inbound_cb, "toggled", G_CALLBACK(toggle_inbound), rule_info);
257 rule_info->deny_cb = gtk_check_button_new_with_label("Deny");
258 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->deny_cb),
260 gtk_box_pack_start(GTK_BOX(hbox), rule_info->deny_cb, FALSE, FALSE, 10);
261 g_signal_connect(rule_info->deny_cb, "toggled", G_CALLBACK(toggle_deny), rule_info);
263 /* create a scrolled window for the text */
264 txt_scrollw = scrolled_window_new(NULL, NULL);
265 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scrollw),
267 gtk_box_pack_start(GTK_BOX(vbox), txt_scrollw, TRUE, TRUE, 0);
269 /* create a text box */
270 text = gtk_text_view_new();
271 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
272 gtk_container_add(GTK_CONTAINER(txt_scrollw), text);
273 rule_info->text = text;
276 button_hbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_COPY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
277 gtk_box_pack_start(GTK_BOX(vbox), button_hbox, FALSE, FALSE, 0);
279 /* Create Copy Button */
280 button = g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_COPY);
281 g_signal_connect(button, "clicked", G_CALLBACK(firewall_copy_cmd_cb), rule_info);
282 gtk_widget_set_tooltip_text(button, "Copy rule to clipboard");
284 /* Create Save Button */
285 button = g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_SAVE);
286 g_signal_connect(button, "clicked", G_CALLBACK(firewall_save_as_cmd_cb), rule_info);
287 gtk_widget_set_tooltip_text(button, "Save the rule as currently displayed");
289 button = g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_CANCEL);
290 gtk_widget_set_tooltip_text(button, "Cancel the dialog");
291 window_set_cancel_button(rule_w, button, window_cancel_button_cb);
293 button = g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_HELP);
294 g_signal_connect(button, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_FIREWALL_DIALOG);
296 /* Tuck away the rule_info object into the window */
297 g_object_set_data(G_OBJECT(rule_w), WS_RULE_INFO_KEY, rule_info);
299 g_signal_connect(rule_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
300 g_signal_connect(rule_w, "destroy", G_CALLBACK(firewall_destroy_cb), NULL);
302 /* Make sure this widget gets destroyed if we quit the main loop,
303 so that if we exit, we clean up any temporary files we have
304 for "Follow SSL Stream" windows.
305 gtk_quit_add_destroy is deprecated and should not be used in newly-written code. This function is going to be removed in GTK+ 3.0
307 gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(rule_w));
311 gtk_combo_box_set_active(GTK_COMBO_BOX(product_combo_box), 0); /* invokes select_product callback */
312 gtk_widget_show_all(rule_w);
313 window_present(rule_w);
316 /* Set the current product. */
317 #define ADD_TO_FILTER_MENU(rt) \
318 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box), name, GUINT_TO_POINTER(rt)); \
319 if (rule_type == RT_NONE) { \
323 #define NAME_TCP_UDP (rule_info->ptype == PT_TCP ? "TCP" : "UDP")
326 select_product(GtkWidget *w, gpointer data _U_)
328 guint prod = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
329 rule_info_t *rule_info;
330 gchar name[MAX_RULE_LEN], addr_str[MAX_RULE_LEN];
332 rule_type_t rule_type = RT_NONE;
333 gboolean sensitive = FALSE;
335 rule_info = g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
337 if (prod >= NUM_PRODS || !rule_info)
340 rule_info->product = prod;
342 /* Clear the list store (ie: the como_box list items) */
343 ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box));
345 /* Fill in valid combo_box list items (in the list store). */
346 if (products[prod].mac_func && rule_info->dl_src.type == AT_ETHER) {
347 addr = &(rule_info->dl_src);
348 address_to_str_buf(addr, name, MAX_RULE_LEN);
349 ADD_TO_FILTER_MENU(RT_MAC_SRC);
351 addr = &(rule_info->dl_dst);
352 address_to_str_buf(addr, name, MAX_RULE_LEN);
353 ADD_TO_FILTER_MENU(RT_MAC_DST);
356 if (products[prod].ipv4_func && rule_info->net_src.type == AT_IPv4) {
357 addr = &(rule_info->net_src);
358 address_to_str_buf(addr, name, MAX_RULE_LEN);
359 ADD_TO_FILTER_MENU(RT_IPv4_SRC);
361 addr = &(rule_info->net_dst);
362 address_to_str_buf(addr, name, MAX_RULE_LEN);
363 ADD_TO_FILTER_MENU(RT_IPv4_DST);
366 if (products[prod].port_func && (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
367 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
369 ADD_TO_FILTER_MENU(RT_PORT_SRC);
370 if (rule_info->srcport != rule_info->destport) {
371 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
372 rule_info->destport);
373 ADD_TO_FILTER_MENU(RT_PORT_DST);
377 if (products[prod].ipv4_port_func && rule_info->net_src.type == AT_IPv4 &&
378 (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
379 addr = &(rule_info->net_src);
380 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
381 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
382 NAME_TCP_UDP, rule_info->srcport);
383 ADD_TO_FILTER_MENU(RT_IPv4_PORT_SRC);
385 addr = &(rule_info->net_dst);
386 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
387 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
388 NAME_TCP_UDP, rule_info->destport);
389 ADD_TO_FILTER_MENU(RT_IPv4_PORT_DST);
392 if (rule_type != RT_NONE) {
393 gtk_combo_box_set_active(GTK_COMBO_BOX(rule_info->filter_combo_box), 0); /* invokes select_filter callback */
396 select_filter(rule_info->filter_combo_box, NULL); /* Call if RT_NONE [with nothing selected] */
399 gtk_widget_set_sensitive(rule_info->filter_combo_box, sensitive);
400 gtk_widget_set_sensitive(rule_info->inbound_cb, products[prod].does_inbound && sensitive);
401 gtk_widget_set_sensitive(rule_info->deny_cb, sensitive);
404 /* Set the rule text based upon the current product and current filter. */
406 select_filter(GtkWidget *w, gpointer data _U_)
408 rule_type_t cur_type;
409 rule_info_t *rule_info;
412 rule_info = g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
417 if (ws_combo_box_get_active_pointer(GTK_COMBO_BOX(w), &ptr))
418 cur_type = GPOINTER_TO_UINT(ptr);
420 cur_type = RT_NONE; /* If nothing selected (eg: nothing in filter list) */
422 if (cur_type >= NUM_RULE_TYPES)
425 rule_info->rule_type = cur_type;
427 set_rule_text(rule_info);
430 /* Set inbound/outbound */
432 toggle_inbound(GtkToggleButton *t, gpointer data)
434 rule_info_t *rule_info = (rule_info_t *) data;
436 rule_info->inbound = gtk_toggle_button_get_active(t);
438 set_rule_text(rule_info);
441 /* Set deny/allow. */
443 toggle_deny(GtkToggleButton *t, gpointer data)
445 rule_info_t *rule_info = (rule_info_t *) data;
447 rule_info->deny = gtk_toggle_button_get_active(t);
449 set_rule_text(rule_info);
452 /* Set the rule text */
453 #define DL_ADDR (rt == RT_MAC_SRC ? &(rule_info->dl_src) : &(rule_info->dl_dst))
454 #define NET_ADDR (rt == RT_IPv4_SRC ? &(rule_info->net_src) : &(rule_info->net_dst))
455 #define NET_PORT (rt == RT_PORT_SRC ? rule_info->srcport : rule_info->destport)
457 set_rule_text(rule_info_t *rule_info) {
458 GString *rtxt = g_string_new("");
459 gchar addr_str[MAX_RULE_LEN];
460 rule_type_t rt = rule_info->rule_type;
461 guint prod = rule_info->product;
462 address *addr = NULL;
464 syntax_func rt_func = NULL;
466 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
468 if (prod < NUM_PRODS) {
469 g_string_printf(rtxt, "%s %s\n", products[prod].comment_pfx, products[prod].name);
472 g_string_append_printf(rtxt, "%s Not supported", products[prod].comment_pfx);
478 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
479 rt_func = products[prod].mac_func;
484 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
485 rt_func = products[prod].ipv4_func;
490 rt_func = products[prod].port_func;
492 case RT_IPv4_PORT_SRC:
493 case RT_IPv4_PORT_DST:
495 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
497 rt_func = products[prod].ipv4_port_func;
505 rt_func(rtxt, addr_str, port, rule_info->ptype, rule_info->inbound, rule_info->deny);
507 g_string_append_printf(rtxt, "ERROR: Unable to create rule");
510 gtk_text_buffer_set_text(buf, rtxt->str, (gint) rtxt->len);
512 g_string_free(rtxt, TRUE);
516 /* Rule text functions */
518 static void sf_dummy(GString *rtxt _U_, gchar *addr _U_, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny _U_) {
522 #define IPFW_DENY (deny ? "deny" : "allow")
523 #define IPFW_IN (inbound ? "in" : "out")
524 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
525 g_string_append_printf(rtxt, "add %s MAC %s any %s",
526 IPFW_DENY, addr, IPFW_IN);
529 #define NF_DROP (deny ? "DROP" : "ACCEPT")
530 #define NF_INPUT (inbound ? "INPUT" : "OUTPUT")
531 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
532 g_string_append_printf(rtxt, "iptables -A %s --mac-source %s -j %s",
533 NF_INPUT, addr, NF_DROP);
537 #define IOS_DENY (deny ? "deny" : "permit")
538 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny) {
539 g_string_append_printf(rtxt, "access-list NUMBER %s host %s", IOS_DENY, addr);
542 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
544 g_string_append_printf(rtxt, "access-list NUMBER %s ip host %s any", IOS_DENY, addr);
546 g_string_append_printf(rtxt, "access-list NUMBER %s ip any host %s", IOS_DENY, addr);
549 #define IPFILTER_DENY (deny ? "block" : "pass")
550 #define IPFILTER_IN (inbound ? "in" : "out")
551 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
552 g_string_append_printf(rtxt, "%s %s on le0 from %s to any",
553 IPFILTER_DENY, IPFILTER_IN, addr);
556 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
557 g_string_append_printf(rtxt, "add %s ip from %s to any %s",
558 IPFW_DENY, addr, IPFW_IN);
561 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
562 g_string_append_printf(rtxt, "iptables -A %s -i eth0 -d %s/32 -j %s",
563 NF_INPUT, addr, NF_DROP);
566 #define PF_DENY (deny ? "block" : "pass")
567 #define PF_IN (inbound ? "in" : "out")
568 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
569 g_string_append_printf(rtxt, "%s %s quick on $ext_if from %s to any",
570 PF_DENY, PF_IN, addr);
574 #define RT_TCP_UDP (ptype == PT_TCP ? "tcp" : "udp")
575 static void sf_ios_ext_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
576 g_string_append_printf(rtxt, "access-list NUMBER %s %s any any eq %u",
577 IOS_DENY, RT_TCP_UDP, port);
580 static void sf_ipfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype _U_, gboolean inbound, gboolean deny) {
581 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to any port = %u",
582 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, port);
585 static void sf_ipfw_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
586 g_string_append_printf(rtxt, "add %s %s from any to any %u %s",
587 IPFW_DENY, RT_TCP_UDP, port, IPFW_IN);
590 static void sf_netfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
591 g_string_append_printf(rtxt, "iptables -A %s -p %s --destination-port %u -j %s",
592 NF_INPUT, RT_TCP_UDP, port, NF_DROP);
595 static void sf_pf_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
596 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from any to any port %u",
597 PF_DENY, PF_IN, RT_TCP_UDP, port);
600 #define NETSH_DENY (deny ? "DISABLE" : "ENABLE")
601 static void sf_netsh_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
602 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s",
603 RT_TCP_UDP, port, NETSH_DENY);
607 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
609 g_string_append_printf(rtxt, "access-list NUMBER %s %s host %s any eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
611 g_string_append_printf(rtxt, "access-list NUMBER %s %s any host %s eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
614 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
616 g_string_append_printf(rtxt, "%s %s on le0 proto %s from %s to any port = %u",
617 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
619 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to %s port = %u",
620 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
623 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
624 g_string_append_printf(rtxt, "add %s %s from %s to any %u %s",
625 IPFW_DENY, RT_TCP_UDP, addr, port, IPFW_IN);
628 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
629 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from %s to any port %u",
630 PF_DENY, PF_IN, RT_TCP_UDP, addr, port);
633 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
634 g_string_append_printf(rtxt, "iptables -A %s -p %s -d %s/32 --destination-port %u -j %s",
635 NF_INPUT, RT_TCP_UDP, addr, port, NF_DROP);
638 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
639 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s %s",
640 RT_TCP_UDP, port, NETSH_DENY, addr);
643 /* The destroy call back has the responsibility of
644 * unlinking the temporary file
645 * and freeing the filter_out_filter */
647 firewall_destroy_cb(GtkWidget *w, gpointer data _U_)
649 rule_info_t *rule_info;
651 rule_info = g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
653 forget_rule_info(rule_info);
656 gtk_widget_destroy(w);
660 firewall_copy_cmd_cb(GtkWidget *w _U_, gpointer data)
662 rule_info_t *rule_info = data;
664 GtkTextIter start, end;
667 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
668 gtk_text_buffer_get_start_iter(buf, &start);
669 gtk_text_buffer_get_end_iter(buf, &end);
670 gtk_text_buffer_select_range(buf, &start, &end);
671 gtk_text_buffer_copy_clipboard(buf, gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
675 * Keep a static pointer to the current "Save SSL Follow Stream As" window, if
676 * any, so that if somebody tries to do "Save"
677 * while there's already a "Save SSL Follow Stream" window up, we just pop
678 * up the existing one, rather than creating a new one.
681 firewall_save_as_cmd_cb(GtkWidget *w _U_, gpointer data)
684 rule_info_t *rule_info = data;
686 #if 0 /* XXX: GtkFileChooserDialog/gtk_dialog_run currently being used is effectively modal so this is not req'd */
687 if (rule_info->firewall_save_as_w != NULL) {
688 /* There's already a dialog box; reactivate it. */
689 reactivate_window(rule_info->firewall_save_as_w);
693 new_win = file_selection_new("Wireshark: Save Firewall ACL Rule",
694 FILE_SELECTION_SAVE);
695 rule_info->firewall_save_as_w = new_win;
696 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(new_win), TRUE);
698 /* Tuck away the rule_info object into the window */
699 g_object_set_data(G_OBJECT(new_win), WS_RULE_INFO_KEY, rule_info);
701 g_signal_connect(new_win, "destroy", G_CALLBACK(firewall_save_as_destroy_cb), rule_info);
704 if (gtk_dialog_run(GTK_DIALOG(new_win)) == GTK_RESPONSE_ACCEPT)
706 firewall_save_as_ok_cb(new_win, new_win);
708 window_destroy(new_win);
711 /* "Run" the GtkFileChooserDialog. */
712 /* Upon exit: If "Accept" run the OK callback. */
713 /* If the OK callback returns with a FALSE status, re-run the dialog.*/
714 /* If not accept (ie: cancel) destroy the window. */
715 /* XXX: If the OK callback pops up an alert box (eg: for an error) it *must* */
716 /* return with a TRUE status so that the dialog window will be destroyed. */
717 /* Trying to re-run the dialog after popping up an alert box will not work */
718 /* since the user will not be able to dismiss the alert box. */
719 /* The (somewhat unfriendly) effect: the user must re-invoke the */
720 /* GtkFileChooserDialog whenever the OK callback pops up an alert box. */
722 /* ToDo: use GtkFileChooserWidget in a dialog window instead of */
723 /* GtkFileChooserDialog. */
724 while (gtk_dialog_run(GTK_DIALOG(new_win)) == GTK_RESPONSE_ACCEPT) {
725 if (firewall_save_as_ok_cb(NULL, new_win)) {
726 break; /* we're done */
729 window_destroy(new_win);
735 firewall_save_as_ok_cb(GtkWidget * w _U_, gpointer fs)
737 gchar *to_name, *rule;
738 rule_info_t *rule_info;
742 GtkTextIter start, end;
745 to_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
747 /* Perhaps the user specified a directory instead of a file.
748 Check whether they did. */
749 if (test_for_directory(to_name) == EISDIR) {
750 /* It's a directory - set the file selection box to display that
751 directory, and leave the selection box displayed. */
752 set_last_open_dir(to_name);
754 file_selection_set_current_folder(fs, get_last_open_dir());
755 gtk_file_chooser_set_current_name(fs, "");
756 return FALSE; /* run the dialog again */
759 rule_info = g_object_get_data(G_OBJECT(fs), WS_RULE_INFO_KEY);
760 fh = ws_fopen(to_name, "w");
762 open_failure_alert_box(to_name, errno, TRUE);
767 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
768 gtk_text_buffer_get_start_iter(buf, &start);
769 gtk_text_buffer_get_end_iter(buf, &end);
770 rule = gtk_text_buffer_get_text(buf, &start, &end, FALSE);
775 #if 0 /* handled by caller (for now) */
776 gtk_widget_hide(GTK_WIDGET(fs));
777 window_destroy(GTK_WIDGET(fs));
779 /* Save the directory name for future file dialogs. */
780 dirname = get_dirname(to_name); /* Overwrites to_name */
781 set_last_open_dir(dirname);
788 firewall_save_as_destroy_cb(GtkWidget * win _U_, gpointer data)
790 rule_info_t *rule_info = data;
792 /* Note that we no longer have a dialog box. */
793 rule_info->firewall_save_as_w = NULL;