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