s3: smbd: dfs: Move lp_msdfs_shuffle_referrals() call out of parse_msdfs_symlink().
[Samba.git] / source4 / torture / smb2 / block.c
blobfa39ae1df9165494708c467b6399765d60b550e6
1 /*
2 * Unix SMB/CIFS implementation.
4 * block SMB2 transports using iptables
6 * Copyright (C) Guenther Deschner, 2017
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "torture/torture.h"
25 #include "torture/smb2/proto.h"
26 #include "system/network.h"
27 #include "lib/util/util_net.h"
28 #include "torture/smb2/block.h"
29 #include "libcli/smb/smbXcli_base.h"
32 * INPUT
33 * |
34 * -----> SAMBA_INPUT
35 * |
36 * -----> SAMBA_INPUT_transportname1
37 * -----> SAMBA_INPUT_transportname2
41 static bool run_cmd(const char *cmd)
43 int ret;
45 DEBUG(10, ("%s will call '%s'\n", __location__, cmd));
47 ret = system(cmd);
48 if (ret) {
49 DEBUG(1, ("%s failed to execute system call: %s: %d\n",
50 __location__, cmd, ret));
51 return false;
54 return true;
57 int smbrun(const char *cmd, int *outfd, char * const *env);
59 static bool run_cmd_return_buf(TALLOC_CTX *mem_ctx,
60 const char *cmd,
61 int *num_lines, char ***buf)
63 int ret;
64 int fd = -1;
66 DEBUG(10, ("%s will call '%s'\n", __location__, cmd));
68 ret = smbrun(cmd, &fd, NULL);
69 if (ret) {
70 DEBUG(1, ("%s failed to execute system call: %s: %d\n",
71 __location__, cmd, ret));
72 if (fd != -1) {
73 close(fd);
75 return false;
78 *buf = fd_lines_load(fd, num_lines, 0, mem_ctx);
79 if (fd != -1) {
80 close(fd);
82 if (*buf == NULL) {
83 return false;
86 return true;
89 static const char *iptables_command(struct torture_context *tctx)
91 return torture_setting_string(tctx, "iptables_command",
92 "/usr/sbin/iptables");
95 char *escape_shell_string(const char *src);
98 * iptables v1.6.1: chain name `SAMBA_INPUT_tree1->session->transport'
99 * too long (must be under 29 chars)
101 * maybe truncate chainname ?
103 static const char *samba_chain_name(struct torture_context *tctx,
104 const char *name,
105 const char *prefix)
107 const char *s;
108 char *sm;
110 s = talloc_asprintf(tctx, "%s_%s", prefix, name);
111 if (s == NULL) {
112 return NULL;
115 sm = escape_shell_string(s);
116 if (sm == NULL) {
117 return NULL;
120 s = talloc_strdup(tctx, sm);
121 free(sm);
123 return s;
126 static bool filter_tcp_setup(struct torture_context *tctx,
127 bool unblock)
129 const char *cmd_in, *cmd_out;
130 const char *ipt = iptables_command(tctx);
132 if (unblock) {
133 cmd_in = talloc_asprintf(tctx,
134 "%s -L SAMBA_INPUT > /dev/null 2>&1 && "
136 "%s -F SAMBA_INPUT; "
137 "%s -D INPUT -j SAMBA_INPUT; "
138 "%s -X SAMBA_INPUT;"
139 ")",
140 ipt, ipt, ipt, ipt);
141 cmd_out = talloc_asprintf(tctx,
142 "%s -L SAMBA_OUTPUT > /dev/null 2>&1 && "
144 "%s -F SAMBA_OUTPUT;"
145 "%s -D OUTPUT -j SAMBA_OUTPUT;"
146 "%s -X SAMBA_OUTPUT;"
147 ")",
148 ipt, ipt, ipt, ipt);
149 } else {
150 cmd_in = talloc_asprintf(tctx,
151 "%s -L SAMBA_INPUT > /dev/null 2>&1 || "
153 "%s -N SAMBA_INPUT && "
154 "%s -I INPUT -j SAMBA_INPUT "
155 ")",
156 ipt, ipt, ipt);
157 cmd_out = talloc_asprintf(tctx,
158 "%s -L SAMBA_OUTPUT > /dev/null 2>&1 || "
160 "%s -N SAMBA_OUTPUT && "
161 "%s -I OUTPUT -j SAMBA_OUTPUT;"
162 ")",
163 ipt, ipt, ipt);
166 if (cmd_in == NULL || cmd_out == NULL) {
167 return false;
170 if (!run_cmd(cmd_in)) {
171 return false;
173 /* if (!run_cmd(cmd_out)) { return false; } */
175 return true;
178 static bool filter_tcp_setup_name(struct torture_context *tctx,
179 const char *name, bool unblock)
181 const char *cmd_in, *cmd_out;
182 const char *chain_in, *chain_out;
183 const char *ipt = iptables_command(tctx);
185 chain_in = samba_chain_name(tctx, name, "SAMBA_INPUT");
186 chain_out = samba_chain_name(tctx, name, "SAMBA_OUTPUT");
187 if (chain_in == NULL || chain_out == NULL) {
188 return false;
191 if (unblock) {
192 cmd_in = talloc_asprintf(tctx, "%s -F %s; "
193 "%s -D SAMBA_INPUT -j %s; "
194 "%s -X %s",
195 ipt, chain_in,
196 ipt, chain_in,
197 ipt, chain_in);
198 cmd_out = talloc_asprintf(tctx, "%s -F %s; "
199 "%s -D SAMBA_OUTPUT -j %s; "
200 "%s -X %s",
201 ipt, chain_out,
202 ipt, chain_out,
203 ipt, chain_out);
204 } else {
205 cmd_in = talloc_asprintf(tctx, "%s -L %s > /dev/null 2>&1 || "
206 "%s -N %s && "
207 "%s -I SAMBA_INPUT -j %s",
208 ipt, chain_in,
209 ipt, chain_in,
210 ipt, chain_in);
211 cmd_out = talloc_asprintf(tctx, "%s -L %s > /dev/null 2>&1 || "
212 "%s -N %s && "
213 "%s -I SAMBA_OUTPUT -j %s",
214 ipt, chain_out,
215 ipt, chain_out,
216 ipt, chain_out);
219 if (cmd_in == NULL || cmd_out == NULL) {
220 return false;
223 if (!run_cmd(cmd_in)) {
224 return false;
226 /* if (!run_cmd(cmd_out)) return false; */
228 return true;
231 /* '11 452 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:43062' */
232 static bool get_packet_count(const char *s, uint32_t *count)
234 int i = 0;
235 char *p;
237 if (s == NULL) {
238 return false;
241 while (s[i] == ' ') {
242 s++;
245 p = strchr(s, ' ');
246 if (p == NULL) {
247 return false;
249 *p = '\0';
251 *count = atoi(s);
253 return true;
256 bool torture_list_tcp_transport_name(struct torture_context *tctx,
257 const char *name,
258 uint32_t *_packets)
260 const char *chain_in, *cmd;
261 int num_lines;
262 char **buf;
263 uint32_t packets = 0;
264 const char *ipt = iptables_command(tctx);
266 chain_in = samba_chain_name(tctx, name, "SAMBA_INPUT");
267 if (chain_in == NULL) {
268 return false;
271 cmd = talloc_asprintf(tctx, "%s -L %s -v -n", ipt, chain_in);
272 if (cmd == NULL) {
273 return false;
276 if (!run_cmd_return_buf(tctx, cmd, &num_lines, &buf)) {
277 return false;
279 SMB_ASSERT(num_lines >= 3);
281 if (!get_packet_count(buf[2], &packets)) {
282 return false;
285 torture_comment(tctx, "chain: '%s', packets: %d\n", name, (int)packets);
287 if (_packets != NULL) {
288 *_packets = packets;
291 return true;
294 uint16_t torture_get_local_port_from_transport(struct smb2_transport *t)
296 const struct sockaddr_storage *local_ss;
298 local_ss = smbXcli_conn_local_sockaddr(t->conn);
300 return get_sockaddr_port(local_ss);
303 static bool torture_block_tcp_transport_name_internal(
304 struct torture_context *tctx,
305 struct smb2_transport *t,
306 const char *name,
307 bool unblock)
309 char *cmd_in;
310 char *cmd_out;
311 const char *chain_in, *chain_out;
312 uint16_t port = torture_get_local_port_from_transport(t);
313 const char *ipt = iptables_command(tctx);
315 chain_in = samba_chain_name(tctx, name, "SAMBA_INPUT");
316 chain_out = samba_chain_name(tctx, name, "SAMBA_OUTPUT");
317 if (chain_in == NULL || chain_out == NULL) {
318 return false;
321 if (!unblock) {
322 filter_tcp_setup(tctx, false);
323 filter_tcp_setup_name(tctx, name, false);
326 torture_comment(tctx, "%sblocking %s dport %d\n",
327 unblock ? "un" : "", name, port);
329 cmd_in = talloc_asprintf(tctx,
330 "%s %s %s -p tcp --dport %d -j DROP",
331 ipt, unblock ? "-D" : "-I", chain_in, port);
332 cmd_out = talloc_asprintf(tctx,
333 "%s %s %s -p tcp --sport %d -j DROP",
334 ipt, unblock ? "-D" : "-I", chain_out, port);
335 if (cmd_in == NULL || cmd_out == NULL) {
336 return false;
339 if (!run_cmd(cmd_in)) {
340 return false;
342 /* if (!run_cmd(cmd_out)) return false; */
344 if (unblock) {
345 filter_tcp_setup_name(tctx, name, true);
346 /* better don't cleanup here */
347 /* filter_tcp_setup(tctx, true); */
350 return true;
353 bool torture_block_tcp_transport_name(struct torture_context *tctx,
354 struct smb2_transport *t,
355 const char *name)
357 return torture_block_tcp_transport_name_internal(tctx, t, name, false);
360 bool torture_unblock_tcp_transport_name(struct torture_context *tctx,
361 struct smb2_transport *t,
362 const char *name)
364 return torture_block_tcp_transport_name_internal(tctx, t, name, true);
367 void torture_unblock_cleanup(struct torture_context *tctx)
369 filter_tcp_setup(tctx, true);