In some dialogs, have *no* auto-default buttons on macOS.
[metze/wireshark/wip.git] / ui / firewall_rules.c
1 /* firewall_rules_dlg.c
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later*/
4
5 /*
6  * Generate firewall ACL rules based on packet addresses and ports.
7  * For directional rules, an outside interface is assumed.
8  *
9  * There may be better ways to present the information, e.g. all rules
10  * in one huge text window, or some sort of tree view.
11  */
12
13 /*
14  * To add a new product, add syntax functions modify the products[] array.
15  *
16  * To add a new syntax function, add its prototype above the products[]
17  * array, and add the function below with all the others.
18  */
19
20  /* Copied from gtk/firewall_rules.c */
21
22 #include "config.h"
23
24 #include <glib.h>
25
26 #include "epan/address.h"
27
28 #include "firewall_rules.h"
29
30 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
31 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
32
33 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
34 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
35 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
36 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
37 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
38 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
39 /* XXX - Can you addresses-only filters using WFW/netsh? */
40
41 static void sf_ios_ext_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
42 static void sf_ipfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
43 static void sf_ipfw_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
44 static void sf_netfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
45 static void sf_pf_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
46 static void sf_netsh_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
47
48 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
49 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
50 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
51 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
52 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
53 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
54
55 typedef struct _fw_product_t {
56     const char *name;
57     const char *rule_hint;
58     const char *comment_pfx;
59     syntax_func mac_func;
60     syntax_func ipv4_func;
61     syntax_func port_func;
62     syntax_func ipv4_port_func;
63     gboolean does_inbound;
64 } fw_product;
65
66 static fw_product products[] = {
67     { "Cisco IOS (standard)", "Change NUMBER to a valid ACL number.", "!",
68       NULL, sf_ios_std_ipv4, NULL, NULL, FALSE },
69     { "Cisco IOS (extended)", "Change NUMBER to a valid ACL number.", "!",
70         NULL, sf_ios_ext_ipv4, sf_ios_ext_port, sf_ios_ext_ipv4_port, TRUE },
71     { "IP Filter (ipfilter)", "Change le0 to a valid interface if needed.", "#",
72         NULL, sf_ipfilter_ipv4, sf_ipfilter_port, sf_ipfilter_ipv4_port, TRUE },
73     { "IPFirewall (ipfw)", "", "#",
74         sf_ipfw_mac, sf_ipfw_ipv4, sf_ipfw_port, sf_ipfw_ipv4_port, TRUE },
75     { "Netfilter (iptables)", "Change eth0 to a valid interface if needed.", "#",
76         sf_netfilter_mac, sf_netfilter_ipv4, sf_netfilter_port,
77         sf_netfilter_ipv4_port, TRUE },
78     { "Packet Filter (pf)", "$ext_if should be set to a valid interface.", "#",
79         NULL, sf_pf_ipv4, sf_pf_port, sf_pf_ipv4_port, TRUE },
80     { "Windows Firewall (netsh)", "", "#",
81         NULL, NULL, sf_netsh_port, sf_netsh_ipv4_port, FALSE }
82 };
83 #define NUM_PRODS (sizeof(products) / sizeof(fw_product))
84
85
86 size_t firewall_product_count(void)
87 {
88     return NUM_PRODS;
89 }
90
91 const char *firewall_product_name(size_t product_idx)
92 {
93     if (product_idx >= NUM_PRODS) return "Unknown";
94     return products[product_idx].name;
95 }
96
97 const char *firewall_product_rule_hint(size_t product_idx)
98 {
99     if (product_idx >= NUM_PRODS) return "";
100     return products[product_idx].rule_hint;
101 }
102
103 const char *firewall_product_comment_prefix(size_t product_idx)
104 {
105     if (product_idx >= NUM_PRODS) return "";
106     return products[product_idx].comment_pfx;
107 }
108
109 syntax_func firewall_product_mac_func(size_t product_idx)
110 {
111     if (product_idx >= NUM_PRODS) return NULL;
112     return products[product_idx].mac_func;
113 }
114
115
116 syntax_func firewall_product_ipv4_func(size_t product_idx)
117 {
118     if (product_idx >= NUM_PRODS) return NULL;
119     return products[product_idx].ipv4_func;
120 }
121
122
123 syntax_func firewall_product_port_func(size_t product_idx)
124 {
125     if (product_idx >= NUM_PRODS) return NULL;
126     return products[product_idx].port_func;
127 }
128
129
130 syntax_func firewall_product_ipv4_port_func(size_t product_idx)
131 {
132     if (product_idx >= NUM_PRODS) return NULL;
133     return products[product_idx].ipv4_port_func;
134 }
135
136 gboolean firewall_product_does_inbound(size_t product_idx)
137 {
138     if (product_idx >= NUM_PRODS) return FALSE;
139     return products[product_idx].does_inbound;
140 }
141
142
143 /* MAC */
144 #define IPFW_RULE(deny) ((deny) ? "deny" : "allow")
145 #define IPFW_DIR(inbound) ((inbound) ? "in" : "out")
146 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
147     g_string_append_printf(rtxt, "add %s MAC %s any %s",
148         IPFW_RULE(deny), addr, IPFW_DIR(inbound));
149 }
150
151 #define NF_RULE(deny) ((deny) ? "DROP" : "ACCEPT")
152 #define NF_DIR(inbound) ((inbound) ? "INPUT" : "OUTPUT")
153 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
154     g_string_append_printf(rtxt, "iptables --append %s --in-interface eth0 --mac-source %s --jump %s",
155         NF_DIR(inbound), addr, NF_RULE(deny));
156 }
157
158 /* IPv4 */
159 #define IOS_RULE(deny) ((deny) ? "deny" : "permit")
160 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny) {
161     g_string_append_printf(rtxt, "access-list NUMBER %s host %s", IOS_RULE(deny), addr);
162 }
163
164 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
165     if (inbound)
166         g_string_append_printf(rtxt, "access-list NUMBER %s ip host %s any", IOS_RULE(deny), addr);
167     else
168         g_string_append_printf(rtxt, "access-list NUMBER %s ip any host %s", IOS_RULE(deny), addr);
169 }
170
171 #define IPFILTER_RULE(deny) ((deny) ? "block" : "pass")
172 #define IPFILTER_DIR(inbound) ((inbound) ? "in" : "out")
173
174 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
175     g_string_append_printf(rtxt, "%s %s on le0 from %s to any",
176         IPFILTER_RULE(deny), IPFILTER_DIR(inbound), addr);
177 }
178
179 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
180     g_string_append_printf(rtxt, "add %s ip from %s to any %s",
181         IPFW_RULE(deny), addr, IPFW_DIR(inbound));
182 }
183
184 #define NF_ADDR_DIR(inbound) ((inbound) ? "--source" : "--destination")
185 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
186     g_string_append_printf(rtxt, "iptables --append %s --in-interface eth0 %s %s/32 --jump %s",
187         NF_DIR(inbound), NF_ADDR_DIR(inbound), addr, NF_RULE(deny));
188 }
189
190 #define PF_RULE(deny) ((deny) ? "block" : "pass")
191 #define PF_DIR(inbound) ((inbound) ? "in" : "out")
192 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
193     g_string_append_printf(rtxt, "%s %s quick on $ext_if from %s to any",
194         PF_RULE(deny), PF_DIR(inbound), addr);
195 }
196
197 /* Port */
198 #define RT_TCP_UDP(ptype) ((ptype) == PT_TCP ? "tcp" : "udp")
199 static void sf_ios_ext_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
200     g_string_append_printf(rtxt, "access-list NUMBER %s %s any any eq %u",
201         IOS_RULE(deny), RT_TCP_UDP(ptype), port);
202 }
203
204 static void sf_ipfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
205     g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to any port = %u",
206         IPFILTER_RULE(deny), IPFILTER_DIR(inbound), RT_TCP_UDP(ptype), port);
207 }
208
209 static void sf_ipfw_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
210     g_string_append_printf(rtxt, "add %s %s from any to any %u %s",
211         IPFW_RULE(deny), RT_TCP_UDP(ptype), port, IPFW_DIR(inbound));
212 }
213
214 #define NF_PORT_DIR(inbound) ((inbound) ? "--source-port" : "--destination-port")
215 static void sf_netfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
216     g_string_append_printf(rtxt, "iptables --append %s --in-interface eth0 --protocol %s %s %u --jump %s",
217             NF_DIR(inbound), RT_TCP_UDP(ptype), NF_PORT_DIR(inbound), port, NF_RULE(deny));
218 }
219
220 static void sf_pf_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
221     g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from any to any port %u",
222         PF_RULE(deny), PF_DIR(inbound), RT_TCP_UDP(ptype), port);
223 }
224
225 #define NETSH_RULE(deny) ((deny) ? "DISABLE" : "ENABLE")
226 static void sf_netsh_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
227     g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s",
228         RT_TCP_UDP(ptype), port, NETSH_RULE(deny));
229 }
230
231 /* IPv4 + port */
232 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype, gboolean inbound, gboolean deny) {
233     if (inbound)
234         g_string_append_printf(rtxt, "access-list NUMBER %s %s host %s any eq %u", IOS_RULE(deny), RT_TCP_UDP(ptype), addr, port);
235     else
236         g_string_append_printf(rtxt, "access-list NUMBER %s %s any host %s eq %u", IOS_RULE(deny), RT_TCP_UDP(ptype), addr, port);
237 }
238
239 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
240     if (inbound)
241         g_string_append_printf(rtxt, "%s %s on le0 proto %s from %s to any port = %u",
242             IPFILTER_RULE(deny), IPFILTER_DIR(inbound), RT_TCP_UDP(ptype), addr, port);
243     else
244         g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to %s port = %u",
245             IPFILTER_RULE(deny), IPFILTER_DIR(inbound), RT_TCP_UDP(ptype), addr, port);
246 }
247
248 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
249     g_string_append_printf(rtxt, "add %s %s from %s to any %u %s",
250         IPFW_RULE(deny), RT_TCP_UDP(ptype), addr, port, IPFW_DIR(inbound));
251 }
252
253 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
254     g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from %s to any port %u",
255         PF_RULE(deny), PF_DIR(inbound), RT_TCP_UDP(ptype), addr, port);
256 }
257
258 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
259     g_string_append_printf(rtxt, "iptables --append %s --in-interface eth0 --protocol %s %s %s/32 %s %u --jump %s",
260         NF_DIR(inbound), RT_TCP_UDP(ptype), NF_ADDR_DIR(inbound), addr, NF_PORT_DIR(inbound), port, NF_RULE(deny));
261 }
262
263 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
264     g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s %s",
265         RT_TCP_UDP(ptype), port, NETSH_RULE(deny), addr);
266 }
267
268
269 /*
270  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
271  *
272  * Local variables:
273  * c-basic-offset: 4
274  * tab-width: 8
275  * indent-tabs-mode: nil
276  * End:
277  *
278  * vi: set shiftwidth=4 tabstop=8 expandtab:
279  * :indentSize=4:tabSize=8:noTabs=true:
280  */