1 | /*
|
---|
2 | Unix SMB/CIFS implementation.
|
---|
3 | basic raw test suite for change notify
|
---|
4 | Copyright (C) Andrew Tridgell 2003
|
---|
5 |
|
---|
6 | This program is free software; you can redistribute it and/or modify
|
---|
7 | it under the terms of the GNU General Public License as published by
|
---|
8 | the Free Software Foundation; either version 3 of the License, or
|
---|
9 | (at your option) any later version.
|
---|
10 |
|
---|
11 | This program is distributed in the hope that it will be useful,
|
---|
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | GNU General Public License for more details.
|
---|
15 |
|
---|
16 | You should have received a copy of the GNU General Public License
|
---|
17 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
18 | */
|
---|
19 |
|
---|
20 | #include "includes.h"
|
---|
21 | #include "libcli/raw/libcliraw.h"
|
---|
22 | #include "libcli/raw/raw_proto.h"
|
---|
23 | #include "libcli/libcli.h"
|
---|
24 | #include "system/filesys.h"
|
---|
25 | #include "torture/util.h"
|
---|
26 |
|
---|
27 | #define BASEDIR "\\test_notify"
|
---|
28 |
|
---|
29 | #define CHECK_STATUS(status, correct) do { \
|
---|
30 | if (!NT_STATUS_EQUAL(status, correct)) { \
|
---|
31 | printf("(%d) Incorrect status %s - should be %s\n", \
|
---|
32 | __LINE__, nt_errstr(status), nt_errstr(correct)); \
|
---|
33 | ret = false; \
|
---|
34 | goto done; \
|
---|
35 | }} while (0)
|
---|
36 |
|
---|
37 |
|
---|
38 | #define CHECK_VAL(v, correct) do { \
|
---|
39 | if ((v) != (correct)) { \
|
---|
40 | printf("(%d) wrong value for %s 0x%x should be 0x%x\n", \
|
---|
41 | __LINE__, #v, (int)v, (int)correct); \
|
---|
42 | ret = false; \
|
---|
43 | goto done; \
|
---|
44 | }} while (0)
|
---|
45 |
|
---|
46 | #define CHECK_WSTR(field, value, flags) do { \
|
---|
47 | if (!field.s || strcmp(field.s, value) || wire_bad_flags(&field, flags, cli->transport)) { \
|
---|
48 | printf("(%d) %s [%s] != %s\n", __LINE__, #field, field.s, value); \
|
---|
49 | ret = false; \
|
---|
50 | goto done; \
|
---|
51 | }} while (0)
|
---|
52 |
|
---|
53 | #define CHECK_WSTR2(tctx, field, value, flags) \
|
---|
54 | do { \
|
---|
55 | if (!field.s || strcmp(field.s, value) || \
|
---|
56 | wire_bad_flags(&field, flags, cli->transport)) { \
|
---|
57 | torture_result(tctx, TORTURE_FAIL, \
|
---|
58 | "(%d) %s [%s] != %s\n", __LINE__, #field, field.s, value); \
|
---|
59 | } \
|
---|
60 | } while (0)
|
---|
61 |
|
---|
62 | /*
|
---|
63 | basic testing of change notify on directories
|
---|
64 | */
|
---|
65 | static bool test_notify_dir(struct smbcli_state *cli, struct smbcli_state *cli2,
|
---|
66 | TALLOC_CTX *mem_ctx)
|
---|
67 | {
|
---|
68 | bool ret = true;
|
---|
69 | NTSTATUS status;
|
---|
70 | union smb_notify notify;
|
---|
71 | union smb_open io;
|
---|
72 | union smb_close cl;
|
---|
73 | int i, count, fnum, fnum2;
|
---|
74 | struct smbcli_request *req, *req2;
|
---|
75 | extern int torture_numops;
|
---|
76 |
|
---|
77 | printf("TESTING CHANGE NOTIFY ON DIRECTORIES\n");
|
---|
78 |
|
---|
79 | /*
|
---|
80 | get a handle on the directory
|
---|
81 | */
|
---|
82 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
83 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
84 | io.ntcreatex.in.flags = 0;
|
---|
85 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
86 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
87 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
88 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
89 | io.ntcreatex.in.alloc_size = 0;
|
---|
90 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
91 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
92 | io.ntcreatex.in.security_flags = 0;
|
---|
93 | io.ntcreatex.in.fname = BASEDIR;
|
---|
94 |
|
---|
95 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
96 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
97 | fnum = io.ntcreatex.out.file.fnum;
|
---|
98 |
|
---|
99 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
100 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
101 | fnum2 = io.ntcreatex.out.file.fnum;
|
---|
102 |
|
---|
103 | /* ask for a change notify,
|
---|
104 | on file or directory name changes */
|
---|
105 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
106 | notify.nttrans.in.buffer_size = 1000;
|
---|
107 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
|
---|
108 | notify.nttrans.in.file.fnum = fnum;
|
---|
109 | notify.nttrans.in.recursive = true;
|
---|
110 |
|
---|
111 | printf("Testing notify cancel\n");
|
---|
112 |
|
---|
113 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
114 | smb_raw_ntcancel(req);
|
---|
115 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
116 | CHECK_STATUS(status, NT_STATUS_CANCELLED);
|
---|
117 |
|
---|
118 | printf("Testing notify mkdir\n");
|
---|
119 |
|
---|
120 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
121 | smbcli_mkdir(cli2->tree, BASEDIR "\\subdir-name");
|
---|
122 |
|
---|
123 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
124 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
125 |
|
---|
126 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
127 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
|
---|
128 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
129 |
|
---|
130 | printf("Testing notify rmdir\n");
|
---|
131 |
|
---|
132 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
133 | smbcli_rmdir(cli2->tree, BASEDIR "\\subdir-name");
|
---|
134 |
|
---|
135 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
136 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
137 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
138 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
|
---|
139 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
140 |
|
---|
141 | printf("Testing notify mkdir - rmdir - mkdir - rmdir\n");
|
---|
142 |
|
---|
143 | smbcli_mkdir(cli2->tree, BASEDIR "\\subdir-name");
|
---|
144 | smbcli_rmdir(cli2->tree, BASEDIR "\\subdir-name");
|
---|
145 | smbcli_mkdir(cli2->tree, BASEDIR "\\subdir-name");
|
---|
146 | smbcli_rmdir(cli2->tree, BASEDIR "\\subdir-name");
|
---|
147 | smb_msleep(200);
|
---|
148 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
149 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
150 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
151 | CHECK_VAL(notify.nttrans.out.num_changes, 4);
|
---|
152 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
|
---|
153 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
154 | CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_REMOVED);
|
---|
155 | CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name", STR_UNICODE);
|
---|
156 | CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_ADDED);
|
---|
157 | CHECK_WSTR(notify.nttrans.out.changes[2].name, "subdir-name", STR_UNICODE);
|
---|
158 | CHECK_VAL(notify.nttrans.out.changes[3].action, NOTIFY_ACTION_REMOVED);
|
---|
159 | CHECK_WSTR(notify.nttrans.out.changes[3].name, "subdir-name", STR_UNICODE);
|
---|
160 |
|
---|
161 | count = torture_numops;
|
---|
162 | printf("Testing buffered notify on create of %d files\n", count);
|
---|
163 | for (i=0;i<count;i++) {
|
---|
164 | char *fname = talloc_asprintf(cli, BASEDIR "\\test%d.txt", i);
|
---|
165 | int fnum3 = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
|
---|
166 | if (fnum3 == -1) {
|
---|
167 | printf("Failed to create %s - %s\n",
|
---|
168 | fname, smbcli_errstr(cli->tree));
|
---|
169 | ret = false;
|
---|
170 | goto done;
|
---|
171 | }
|
---|
172 | talloc_free(fname);
|
---|
173 | smbcli_close(cli->tree, fnum3);
|
---|
174 | }
|
---|
175 |
|
---|
176 | /* (1st notify) setup a new notify on a different directory handle.
|
---|
177 | This new notify won't see the events above. */
|
---|
178 | notify.nttrans.in.file.fnum = fnum2;
|
---|
179 | req2 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
180 |
|
---|
181 | /* (2nd notify) whereas this notify will see the above buffered events,
|
---|
182 | and it directly returns the buffered events */
|
---|
183 | notify.nttrans.in.file.fnum = fnum;
|
---|
184 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
185 |
|
---|
186 | status = smbcli_unlink(cli->tree, BASEDIR "\\nonexistant.txt");
|
---|
187 | CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
|
---|
188 |
|
---|
189 | /* (1st unlink) as the 2nd notify directly returns,
|
---|
190 | this unlink is only seen by the 1st notify and
|
---|
191 | the 3rd notify (later) */
|
---|
192 | printf("Testing notify on unlink for the first file\n");
|
---|
193 | status = smbcli_unlink(cli2->tree, BASEDIR "\\test0.txt");
|
---|
194 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
195 |
|
---|
196 | /* receive the reply from the 2nd notify */
|
---|
197 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
198 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
199 |
|
---|
200 | CHECK_VAL(notify.nttrans.out.num_changes, count);
|
---|
201 | for (i=1;i<count;i++) {
|
---|
202 | CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_ADDED);
|
---|
203 | }
|
---|
204 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);
|
---|
205 |
|
---|
206 | printf("and now from the 1st notify\n");
|
---|
207 | status = smb_raw_changenotify_recv(req2, mem_ctx, ¬ify);
|
---|
208 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
209 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
210 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
|
---|
211 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);
|
---|
212 |
|
---|
213 | printf("(3rd notify) this notify will only see the 1st unlink\n");
|
---|
214 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
215 |
|
---|
216 | status = smbcli_unlink(cli->tree, BASEDIR "\\nonexistant.txt");
|
---|
217 | CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
|
---|
218 |
|
---|
219 | printf("Testing notify on wildcard unlink for %d files\n", count-1);
|
---|
220 | /* (2nd unlink) do a wildcard unlink */
|
---|
221 | status = smbcli_unlink(cli2->tree, BASEDIR "\\test*.txt");
|
---|
222 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
223 |
|
---|
224 | /* receive the 3rd notify */
|
---|
225 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
226 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
227 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
228 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
|
---|
229 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);
|
---|
230 |
|
---|
231 | /* and we now see the rest of the unlink calls on both directory handles */
|
---|
232 | notify.nttrans.in.file.fnum = fnum;
|
---|
233 | sleep(3);
|
---|
234 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
235 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
236 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
237 | CHECK_VAL(notify.nttrans.out.num_changes, count-1);
|
---|
238 | for (i=0;i<notify.nttrans.out.num_changes;i++) {
|
---|
239 | CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_REMOVED);
|
---|
240 | }
|
---|
241 | notify.nttrans.in.file.fnum = fnum2;
|
---|
242 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
243 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
244 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
245 | CHECK_VAL(notify.nttrans.out.num_changes, count-1);
|
---|
246 | for (i=0;i<notify.nttrans.out.num_changes;i++) {
|
---|
247 | CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_REMOVED);
|
---|
248 | }
|
---|
249 |
|
---|
250 | printf("Testing if a close() on the dir handle triggers the notify reply\n");
|
---|
251 |
|
---|
252 | notify.nttrans.in.file.fnum = fnum;
|
---|
253 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
254 |
|
---|
255 | cl.close.level = RAW_CLOSE_CLOSE;
|
---|
256 | cl.close.in.file.fnum = fnum;
|
---|
257 | cl.close.in.write_time = 0;
|
---|
258 | status = smb_raw_close(cli->tree, &cl);
|
---|
259 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
260 |
|
---|
261 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
262 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
263 | CHECK_VAL(notify.nttrans.out.num_changes, 0);
|
---|
264 |
|
---|
265 | done:
|
---|
266 | smb_raw_exit(cli->session);
|
---|
267 | return ret;
|
---|
268 | }
|
---|
269 |
|
---|
270 | /*
|
---|
271 | * Check notify reply for a rename action. Not sure if this is a valid thing
|
---|
272 | * to do, but depending on timing between inotify and messaging we get the
|
---|
273 | * add/remove/modify in any order. This routines tries to find the action/name
|
---|
274 | * pair in any of the three following notify_changes.
|
---|
275 | */
|
---|
276 |
|
---|
277 | static bool check_rename_reply(struct smbcli_state *cli,
|
---|
278 | int line,
|
---|
279 | struct notify_changes *actions,
|
---|
280 | uint32_t action, const char *name)
|
---|
281 | {
|
---|
282 | int i;
|
---|
283 |
|
---|
284 | for (i=0; i<3; i++) {
|
---|
285 | if (actions[i].action == action) {
|
---|
286 | if ((actions[i].name.s == NULL)
|
---|
287 | || (strcmp(actions[i].name.s, name) != 0)
|
---|
288 | || (wire_bad_flags(&actions[i].name, STR_UNICODE,
|
---|
289 | cli->transport))) {
|
---|
290 | printf("(%d) name [%s] != %s\n", line,
|
---|
291 | actions[i].name.s, name);
|
---|
292 | return false;
|
---|
293 | }
|
---|
294 | return true;
|
---|
295 | }
|
---|
296 | }
|
---|
297 |
|
---|
298 | printf("(%d) expected action %d, not found\n", line, action);
|
---|
299 | return false;
|
---|
300 | }
|
---|
301 |
|
---|
302 | /*
|
---|
303 | testing of recursive change notify
|
---|
304 | */
|
---|
305 | static bool test_notify_recursive(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
---|
306 | {
|
---|
307 | bool ret = true;
|
---|
308 | NTSTATUS status;
|
---|
309 | union smb_notify notify;
|
---|
310 | union smb_open io;
|
---|
311 | int fnum;
|
---|
312 | struct smbcli_request *req1, *req2;
|
---|
313 |
|
---|
314 | printf("TESTING CHANGE NOTIFY WITH RECURSION\n");
|
---|
315 |
|
---|
316 | /*
|
---|
317 | get a handle on the directory
|
---|
318 | */
|
---|
319 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
320 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
321 | io.ntcreatex.in.flags = 0;
|
---|
322 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
323 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
324 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
325 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
326 | io.ntcreatex.in.alloc_size = 0;
|
---|
327 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
328 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
329 | io.ntcreatex.in.security_flags = 0;
|
---|
330 | io.ntcreatex.in.fname = BASEDIR;
|
---|
331 |
|
---|
332 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
333 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
334 | fnum = io.ntcreatex.out.file.fnum;
|
---|
335 |
|
---|
336 | /* ask for a change notify, on file or directory name
|
---|
337 | changes. Setup both with and without recursion */
|
---|
338 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
339 | notify.nttrans.in.buffer_size = 1000;
|
---|
340 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_CREATION;
|
---|
341 | notify.nttrans.in.file.fnum = fnum;
|
---|
342 |
|
---|
343 | notify.nttrans.in.recursive = true;
|
---|
344 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
345 |
|
---|
346 | notify.nttrans.in.recursive = false;
|
---|
347 | req2 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
348 |
|
---|
349 | /* cancel initial requests so the buffer is setup */
|
---|
350 | smb_raw_ntcancel(req1);
|
---|
351 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
352 | CHECK_STATUS(status, NT_STATUS_CANCELLED);
|
---|
353 |
|
---|
354 | smb_raw_ntcancel(req2);
|
---|
355 | status = smb_raw_changenotify_recv(req2, mem_ctx, ¬ify);
|
---|
356 | CHECK_STATUS(status, NT_STATUS_CANCELLED);
|
---|
357 |
|
---|
358 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
359 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name\\subname1");
|
---|
360 | smbcli_close(cli->tree,
|
---|
361 | smbcli_open(cli->tree, BASEDIR "\\subdir-name\\subname2", O_CREAT, 0));
|
---|
362 | smbcli_rename(cli->tree, BASEDIR "\\subdir-name\\subname1", BASEDIR "\\subdir-name\\subname1-r");
|
---|
363 | smbcli_rename(cli->tree, BASEDIR "\\subdir-name\\subname2", BASEDIR "\\subname2-r");
|
---|
364 | smbcli_rename(cli->tree, BASEDIR "\\subname2-r", BASEDIR "\\subname3-r");
|
---|
365 |
|
---|
366 | notify.nttrans.in.completion_filter = 0;
|
---|
367 | notify.nttrans.in.recursive = true;
|
---|
368 | smb_msleep(200);
|
---|
369 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
370 |
|
---|
371 | smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name\\subname1-r");
|
---|
372 | smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
373 | smbcli_unlink(cli->tree, BASEDIR "\\subname3-r");
|
---|
374 |
|
---|
375 | notify.nttrans.in.recursive = false;
|
---|
376 | req2 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
377 |
|
---|
378 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
379 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
380 |
|
---|
381 | CHECK_VAL(notify.nttrans.out.num_changes, 11);
|
---|
382 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
|
---|
383 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
384 | CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_ADDED);
|
---|
385 | CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name\\subname1", STR_UNICODE);
|
---|
386 | CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_ADDED);
|
---|
387 | CHECK_WSTR(notify.nttrans.out.changes[2].name, "subdir-name\\subname2", STR_UNICODE);
|
---|
388 | CHECK_VAL(notify.nttrans.out.changes[3].action, NOTIFY_ACTION_OLD_NAME);
|
---|
389 | CHECK_WSTR(notify.nttrans.out.changes[3].name, "subdir-name\\subname1", STR_UNICODE);
|
---|
390 | CHECK_VAL(notify.nttrans.out.changes[4].action, NOTIFY_ACTION_NEW_NAME);
|
---|
391 | CHECK_WSTR(notify.nttrans.out.changes[4].name, "subdir-name\\subname1-r", STR_UNICODE);
|
---|
392 |
|
---|
393 | ret &= check_rename_reply(
|
---|
394 | cli, __LINE__, ¬ify.nttrans.out.changes[5],
|
---|
395 | NOTIFY_ACTION_ADDED, "subname2-r");
|
---|
396 | ret &= check_rename_reply(
|
---|
397 | cli, __LINE__, ¬ify.nttrans.out.changes[5],
|
---|
398 | NOTIFY_ACTION_REMOVED, "subdir-name\\subname2");
|
---|
399 | ret &= check_rename_reply(
|
---|
400 | cli, __LINE__, ¬ify.nttrans.out.changes[5],
|
---|
401 | NOTIFY_ACTION_MODIFIED, "subname2-r");
|
---|
402 |
|
---|
403 | ret &= check_rename_reply(
|
---|
404 | cli, __LINE__, ¬ify.nttrans.out.changes[8],
|
---|
405 | NOTIFY_ACTION_OLD_NAME, "subname2-r");
|
---|
406 | ret &= check_rename_reply(
|
---|
407 | cli, __LINE__, ¬ify.nttrans.out.changes[8],
|
---|
408 | NOTIFY_ACTION_NEW_NAME, "subname3-r");
|
---|
409 | ret &= check_rename_reply(
|
---|
410 | cli, __LINE__, ¬ify.nttrans.out.changes[8],
|
---|
411 | NOTIFY_ACTION_MODIFIED, "subname3-r");
|
---|
412 |
|
---|
413 | if (!ret) {
|
---|
414 | goto done;
|
---|
415 | }
|
---|
416 |
|
---|
417 | status = smb_raw_changenotify_recv(req2, mem_ctx, ¬ify);
|
---|
418 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
419 |
|
---|
420 | CHECK_VAL(notify.nttrans.out.num_changes, 3);
|
---|
421 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
|
---|
422 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name\\subname1-r", STR_UNICODE);
|
---|
423 | CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_REMOVED);
|
---|
424 | CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name", STR_UNICODE);
|
---|
425 | CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_REMOVED);
|
---|
426 | CHECK_WSTR(notify.nttrans.out.changes[2].name, "subname3-r", STR_UNICODE);
|
---|
427 |
|
---|
428 | done:
|
---|
429 | smb_raw_exit(cli->session);
|
---|
430 | return ret;
|
---|
431 | }
|
---|
432 |
|
---|
433 | /*
|
---|
434 | testing of change notify mask change
|
---|
435 | */
|
---|
436 | static bool test_notify_mask_change(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
---|
437 | {
|
---|
438 | bool ret = true;
|
---|
439 | NTSTATUS status;
|
---|
440 | union smb_notify notify;
|
---|
441 | union smb_open io;
|
---|
442 | int fnum;
|
---|
443 | struct smbcli_request *req1, *req2;
|
---|
444 |
|
---|
445 | printf("TESTING CHANGE NOTIFY WITH MASK CHANGE\n");
|
---|
446 |
|
---|
447 | /*
|
---|
448 | get a handle on the directory
|
---|
449 | */
|
---|
450 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
451 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
452 | io.ntcreatex.in.flags = 0;
|
---|
453 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
454 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
455 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
456 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
457 | io.ntcreatex.in.alloc_size = 0;
|
---|
458 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
459 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
460 | io.ntcreatex.in.security_flags = 0;
|
---|
461 | io.ntcreatex.in.fname = BASEDIR;
|
---|
462 |
|
---|
463 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
464 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
465 | fnum = io.ntcreatex.out.file.fnum;
|
---|
466 |
|
---|
467 | /* ask for a change notify, on file or directory name
|
---|
468 | changes. Setup both with and without recursion */
|
---|
469 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
470 | notify.nttrans.in.buffer_size = 1000;
|
---|
471 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
---|
472 | notify.nttrans.in.file.fnum = fnum;
|
---|
473 |
|
---|
474 | notify.nttrans.in.recursive = true;
|
---|
475 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
476 |
|
---|
477 | notify.nttrans.in.recursive = false;
|
---|
478 | req2 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
479 |
|
---|
480 | /* cancel initial requests so the buffer is setup */
|
---|
481 | smb_raw_ntcancel(req1);
|
---|
482 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
483 | CHECK_STATUS(status, NT_STATUS_CANCELLED);
|
---|
484 |
|
---|
485 | smb_raw_ntcancel(req2);
|
---|
486 | status = smb_raw_changenotify_recv(req2, mem_ctx, ¬ify);
|
---|
487 | CHECK_STATUS(status, NT_STATUS_CANCELLED);
|
---|
488 |
|
---|
489 | notify.nttrans.in.recursive = true;
|
---|
490 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
491 |
|
---|
492 | /* Set to hidden then back again. */
|
---|
493 | smbcli_close(cli->tree, smbcli_open(cli->tree, BASEDIR "\\tname1", O_CREAT, 0));
|
---|
494 | smbcli_setatr(cli->tree, BASEDIR "\\tname1", FILE_ATTRIBUTE_HIDDEN, 0);
|
---|
495 | smbcli_unlink(cli->tree, BASEDIR "\\tname1");
|
---|
496 |
|
---|
497 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
498 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
499 |
|
---|
500 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
501 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
|
---|
502 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "tname1", STR_UNICODE);
|
---|
503 |
|
---|
504 | /* Now try and change the mask to include other events.
|
---|
505 | * This should not work - once the mask is set on a directory
|
---|
506 | * fnum it seems to be fixed until the fnum is closed. */
|
---|
507 |
|
---|
508 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_CREATION;
|
---|
509 | notify.nttrans.in.recursive = true;
|
---|
510 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
511 |
|
---|
512 | notify.nttrans.in.recursive = false;
|
---|
513 | req2 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
514 |
|
---|
515 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
516 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name\\subname1");
|
---|
517 | smbcli_close(cli->tree,
|
---|
518 | smbcli_open(cli->tree, BASEDIR "\\subdir-name\\subname2", O_CREAT, 0));
|
---|
519 | smbcli_rename(cli->tree, BASEDIR "\\subdir-name\\subname1", BASEDIR "\\subdir-name\\subname1-r");
|
---|
520 | smbcli_rename(cli->tree, BASEDIR "\\subdir-name\\subname2", BASEDIR "\\subname2-r");
|
---|
521 | smbcli_rename(cli->tree, BASEDIR "\\subname2-r", BASEDIR "\\subname3-r");
|
---|
522 |
|
---|
523 | smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name\\subname1-r");
|
---|
524 | smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
525 | smbcli_unlink(cli->tree, BASEDIR "\\subname3-r");
|
---|
526 |
|
---|
527 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
528 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
529 |
|
---|
530 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
531 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
|
---|
532 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subname2-r", STR_UNICODE);
|
---|
533 |
|
---|
534 | status = smb_raw_changenotify_recv(req2, mem_ctx, ¬ify);
|
---|
535 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
536 |
|
---|
537 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
538 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
|
---|
539 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subname3-r", STR_UNICODE);
|
---|
540 |
|
---|
541 | if (!ret) {
|
---|
542 | goto done;
|
---|
543 | }
|
---|
544 |
|
---|
545 | done:
|
---|
546 | smb_raw_exit(cli->session);
|
---|
547 | return ret;
|
---|
548 | }
|
---|
549 |
|
---|
550 |
|
---|
551 | /*
|
---|
552 | testing of mask bits for change notify
|
---|
553 | */
|
---|
554 | static bool test_notify_mask(struct smbcli_state *cli, struct torture_context *tctx)
|
---|
555 | {
|
---|
556 | bool ret = true;
|
---|
557 | NTSTATUS status;
|
---|
558 | union smb_notify notify;
|
---|
559 | union smb_open io;
|
---|
560 | int fnum, fnum2;
|
---|
561 | uint32_t mask;
|
---|
562 | int i;
|
---|
563 | char c = 1;
|
---|
564 | struct timeval tv;
|
---|
565 | NTTIME t;
|
---|
566 |
|
---|
567 | printf("TESTING CHANGE NOTIFY COMPLETION FILTERS\n");
|
---|
568 |
|
---|
569 | tv = timeval_current_ofs(1000, 0);
|
---|
570 | t = timeval_to_nttime(&tv);
|
---|
571 |
|
---|
572 | /*
|
---|
573 | get a handle on the directory
|
---|
574 | */
|
---|
575 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
576 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
577 | io.ntcreatex.in.flags = 0;
|
---|
578 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
579 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
580 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
581 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
582 | io.ntcreatex.in.alloc_size = 0;
|
---|
583 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
584 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
585 | io.ntcreatex.in.security_flags = 0;
|
---|
586 | io.ntcreatex.in.fname = BASEDIR;
|
---|
587 |
|
---|
588 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
589 | notify.nttrans.in.buffer_size = 1000;
|
---|
590 | notify.nttrans.in.recursive = true;
|
---|
591 |
|
---|
592 | #define NOTIFY_MASK_TEST(test_name, setup, op, cleanup, Action, expected, nchanges) \
|
---|
593 | do { \
|
---|
594 | smbcli_getatr(cli->tree, test_name, NULL, NULL, NULL); \
|
---|
595 | do { for (mask=i=0;i<32;i++) { \
|
---|
596 | struct smbcli_request *req; \
|
---|
597 | status = smb_raw_open(cli->tree, tctx, &io); \
|
---|
598 | CHECK_STATUS(status, NT_STATUS_OK); \
|
---|
599 | fnum = io.ntcreatex.out.file.fnum; \
|
---|
600 | setup \
|
---|
601 | notify.nttrans.in.file.fnum = fnum; \
|
---|
602 | notify.nttrans.in.completion_filter = (1<<i); \
|
---|
603 | req = smb_raw_changenotify_send(cli->tree, ¬ify); \
|
---|
604 | op \
|
---|
605 | smb_msleep(200); smb_raw_ntcancel(req); \
|
---|
606 | status = smb_raw_changenotify_recv(req, tctx, ¬ify); \
|
---|
607 | cleanup \
|
---|
608 | smbcli_close(cli->tree, fnum); \
|
---|
609 | if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \
|
---|
610 | CHECK_STATUS(status, NT_STATUS_OK); \
|
---|
611 | /* special case to cope with file rename behaviour */ \
|
---|
612 | if (nchanges == 2 && notify.nttrans.out.num_changes == 1 && \
|
---|
613 | notify.nttrans.out.changes[0].action == NOTIFY_ACTION_MODIFIED && \
|
---|
614 | ((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \
|
---|
615 | Action == NOTIFY_ACTION_OLD_NAME) { \
|
---|
616 | printf("(rename file special handling OK)\n"); \
|
---|
617 | } else if (nchanges != notify.nttrans.out.num_changes) { \
|
---|
618 | printf("ERROR: nchanges=%d expected=%d action=%d filter=0x%08x\n", \
|
---|
619 | notify.nttrans.out.num_changes, \
|
---|
620 | nchanges, \
|
---|
621 | notify.nttrans.out.changes[0].action, \
|
---|
622 | notify.nttrans.in.completion_filter); \
|
---|
623 | ret = false; \
|
---|
624 | } else if (notify.nttrans.out.changes[0].action != Action) { \
|
---|
625 | printf("ERROR: nchanges=%d action=%d expectedAction=%d filter=0x%08x\n", \
|
---|
626 | notify.nttrans.out.num_changes, \
|
---|
627 | notify.nttrans.out.changes[0].action, \
|
---|
628 | Action, \
|
---|
629 | notify.nttrans.in.completion_filter); \
|
---|
630 | ret = false; \
|
---|
631 | } else if (strcmp(notify.nttrans.out.changes[0].name.s, "tname1") != 0) { \
|
---|
632 | printf("ERROR: nchanges=%d action=%d filter=0x%08x name=%s\n", \
|
---|
633 | notify.nttrans.out.num_changes, \
|
---|
634 | notify.nttrans.out.changes[0].action, \
|
---|
635 | notify.nttrans.in.completion_filter, \
|
---|
636 | notify.nttrans.out.changes[0].name.s); \
|
---|
637 | ret = false; \
|
---|
638 | } \
|
---|
639 | mask |= (1<<i); \
|
---|
640 | } \
|
---|
641 | if ((expected) != mask) { \
|
---|
642 | if (((expected) & ~mask) != 0) { \
|
---|
643 | printf("ERROR: trigger on too few bits. mask=0x%08x expected=0x%08x\n", \
|
---|
644 | mask, expected); \
|
---|
645 | ret = false; \
|
---|
646 | } else { \
|
---|
647 | printf("WARNING: trigger on too many bits. mask=0x%08x expected=0x%08x\n", \
|
---|
648 | mask, expected); \
|
---|
649 | } \
|
---|
650 | } \
|
---|
651 | } while (0); \
|
---|
652 | } while (0);
|
---|
653 |
|
---|
654 | printf("Testing mkdir\n");
|
---|
655 | NOTIFY_MASK_TEST("Testing mkdir",;,
|
---|
656 | smbcli_mkdir(cli->tree, BASEDIR "\\tname1");,
|
---|
657 | smbcli_rmdir(cli->tree, BASEDIR "\\tname1");,
|
---|
658 | NOTIFY_ACTION_ADDED,
|
---|
659 | FILE_NOTIFY_CHANGE_DIR_NAME, 1);
|
---|
660 |
|
---|
661 | printf("Testing create file\n");
|
---|
662 | NOTIFY_MASK_TEST("Testing create file",;,
|
---|
663 | smbcli_close(cli->tree, smbcli_open(cli->tree, BASEDIR "\\tname1", O_CREAT, 0));,
|
---|
664 | smbcli_unlink(cli->tree, BASEDIR "\\tname1");,
|
---|
665 | NOTIFY_ACTION_ADDED,
|
---|
666 | FILE_NOTIFY_CHANGE_FILE_NAME, 1);
|
---|
667 |
|
---|
668 | printf("Testing unlink\n");
|
---|
669 | NOTIFY_MASK_TEST("Testing unlink",
|
---|
670 | smbcli_close(cli->tree, smbcli_open(cli->tree, BASEDIR "\\tname1", O_CREAT, 0));,
|
---|
671 | smbcli_unlink(cli->tree, BASEDIR "\\tname1");,
|
---|
672 | ;,
|
---|
673 | NOTIFY_ACTION_REMOVED,
|
---|
674 | FILE_NOTIFY_CHANGE_FILE_NAME, 1);
|
---|
675 |
|
---|
676 | printf("Testing rmdir\n");
|
---|
677 | NOTIFY_MASK_TEST("Testing rmdir",
|
---|
678 | smbcli_mkdir(cli->tree, BASEDIR "\\tname1");,
|
---|
679 | smbcli_rmdir(cli->tree, BASEDIR "\\tname1");,
|
---|
680 | ;,
|
---|
681 | NOTIFY_ACTION_REMOVED,
|
---|
682 | FILE_NOTIFY_CHANGE_DIR_NAME, 1);
|
---|
683 |
|
---|
684 | printf("Testing rename file\n");
|
---|
685 | NOTIFY_MASK_TEST("Testing rename file",
|
---|
686 | smbcli_close(cli->tree, smbcli_open(cli->tree, BASEDIR "\\tname1", O_CREAT, 0));,
|
---|
687 | smbcli_rename(cli->tree, BASEDIR "\\tname1", BASEDIR "\\tname2");,
|
---|
688 | smbcli_unlink(cli->tree, BASEDIR "\\tname2");,
|
---|
689 | NOTIFY_ACTION_OLD_NAME,
|
---|
690 | FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_CREATION, 2);
|
---|
691 |
|
---|
692 | printf("Testing rename dir\n");
|
---|
693 | NOTIFY_MASK_TEST("Testing rename dir",
|
---|
694 | smbcli_mkdir(cli->tree, BASEDIR "\\tname1");,
|
---|
695 | smbcli_rename(cli->tree, BASEDIR "\\tname1", BASEDIR "\\tname2");,
|
---|
696 | smbcli_rmdir(cli->tree, BASEDIR "\\tname2");,
|
---|
697 | NOTIFY_ACTION_OLD_NAME,
|
---|
698 | FILE_NOTIFY_CHANGE_DIR_NAME, 2);
|
---|
699 |
|
---|
700 | printf("Testing set path attribute\n");
|
---|
701 | NOTIFY_MASK_TEST("Testing set path attribute",
|
---|
702 | smbcli_close(cli->tree, smbcli_open(cli->tree, BASEDIR "\\tname1", O_CREAT, 0));,
|
---|
703 | smbcli_setatr(cli->tree, BASEDIR "\\tname1", FILE_ATTRIBUTE_HIDDEN, 0);,
|
---|
704 | smbcli_unlink(cli->tree, BASEDIR "\\tname1");,
|
---|
705 | NOTIFY_ACTION_MODIFIED,
|
---|
706 | FILE_NOTIFY_CHANGE_ATTRIBUTES, 1);
|
---|
707 |
|
---|
708 | printf("Testing set path write time\n");
|
---|
709 | NOTIFY_MASK_TEST("Testing set path write time",
|
---|
710 | smbcli_close(cli->tree, smbcli_open(cli->tree, BASEDIR "\\tname1", O_CREAT, 0));,
|
---|
711 | smbcli_setatr(cli->tree, BASEDIR "\\tname1", FILE_ATTRIBUTE_NORMAL, 1000);,
|
---|
712 | smbcli_unlink(cli->tree, BASEDIR "\\tname1");,
|
---|
713 | NOTIFY_ACTION_MODIFIED,
|
---|
714 | FILE_NOTIFY_CHANGE_LAST_WRITE, 1);
|
---|
715 |
|
---|
716 | printf("Testing set file attribute\n");
|
---|
717 | NOTIFY_MASK_TEST("Testing set file attribute",
|
---|
718 | fnum2 = create_complex_file(cli, tctx, BASEDIR "\\tname1");,
|
---|
719 | smbcli_fsetatr(cli->tree, fnum2, FILE_ATTRIBUTE_HIDDEN, 0, 0, 0, 0);,
|
---|
720 | (smbcli_close(cli->tree, fnum2), smbcli_unlink(cli->tree, BASEDIR "\\tname1"));,
|
---|
721 | NOTIFY_ACTION_MODIFIED,
|
---|
722 | FILE_NOTIFY_CHANGE_ATTRIBUTES, 1);
|
---|
723 |
|
---|
724 | if (torture_setting_bool(tctx, "samba3", false)) {
|
---|
725 | printf("Samba3 does not yet support create times "
|
---|
726 | "everywhere\n");
|
---|
727 | }
|
---|
728 | else {
|
---|
729 | printf("Testing set file create time\n");
|
---|
730 | NOTIFY_MASK_TEST("Testing set file create time",
|
---|
731 | fnum2 = create_complex_file(cli, tctx,
|
---|
732 | BASEDIR "\\tname1");,
|
---|
733 | smbcli_fsetatr(cli->tree, fnum2, 0, t, 0, 0, 0);,
|
---|
734 | (smbcli_close(cli->tree, fnum2),
|
---|
735 | smbcli_unlink(cli->tree, BASEDIR "\\tname1"));,
|
---|
736 | NOTIFY_ACTION_MODIFIED,
|
---|
737 | FILE_NOTIFY_CHANGE_CREATION, 1);
|
---|
738 | }
|
---|
739 |
|
---|
740 | printf("Testing set file access time\n");
|
---|
741 | NOTIFY_MASK_TEST("Testing set file access time",
|
---|
742 | fnum2 = create_complex_file(cli, tctx, BASEDIR "\\tname1");,
|
---|
743 | smbcli_fsetatr(cli->tree, fnum2, 0, 0, t, 0, 0);,
|
---|
744 | (smbcli_close(cli->tree, fnum2), smbcli_unlink(cli->tree, BASEDIR "\\tname1"));,
|
---|
745 | NOTIFY_ACTION_MODIFIED,
|
---|
746 | FILE_NOTIFY_CHANGE_LAST_ACCESS, 1);
|
---|
747 |
|
---|
748 | printf("Testing set file write time\n");
|
---|
749 | NOTIFY_MASK_TEST("Testing set file write time",
|
---|
750 | fnum2 = create_complex_file(cli, tctx, BASEDIR "\\tname1");,
|
---|
751 | smbcli_fsetatr(cli->tree, fnum2, 0, 0, 0, t, 0);,
|
---|
752 | (smbcli_close(cli->tree, fnum2), smbcli_unlink(cli->tree, BASEDIR "\\tname1"));,
|
---|
753 | NOTIFY_ACTION_MODIFIED,
|
---|
754 | FILE_NOTIFY_CHANGE_LAST_WRITE, 1);
|
---|
755 |
|
---|
756 | printf("Testing set file change time\n");
|
---|
757 | NOTIFY_MASK_TEST("Testing set file change time",
|
---|
758 | fnum2 = create_complex_file(cli, tctx, BASEDIR "\\tname1");,
|
---|
759 | smbcli_fsetatr(cli->tree, fnum2, 0, 0, 0, 0, t);,
|
---|
760 | (smbcli_close(cli->tree, fnum2), smbcli_unlink(cli->tree, BASEDIR "\\tname1"));,
|
---|
761 | NOTIFY_ACTION_MODIFIED,
|
---|
762 | 0, 1);
|
---|
763 |
|
---|
764 |
|
---|
765 | printf("Testing write\n");
|
---|
766 | NOTIFY_MASK_TEST("Testing write",
|
---|
767 | fnum2 = create_complex_file(cli, tctx, BASEDIR "\\tname1");,
|
---|
768 | smbcli_write(cli->tree, fnum2, 1, &c, 10000, 1);,
|
---|
769 | (smbcli_close(cli->tree, fnum2), smbcli_unlink(cli->tree, BASEDIR "\\tname1"));,
|
---|
770 | NOTIFY_ACTION_MODIFIED,
|
---|
771 | 0, 1);
|
---|
772 |
|
---|
773 | printf("Testing truncate\n");
|
---|
774 | NOTIFY_MASK_TEST("Testing truncate",
|
---|
775 | fnum2 = create_complex_file(cli, tctx, BASEDIR "\\tname1");,
|
---|
776 | smbcli_ftruncate(cli->tree, fnum2, 10000);,
|
---|
777 | (smbcli_close(cli->tree, fnum2), smbcli_unlink(cli->tree, BASEDIR "\\tname1"));,
|
---|
778 | NOTIFY_ACTION_MODIFIED,
|
---|
779 | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_ATTRIBUTES, 1);
|
---|
780 |
|
---|
781 | done:
|
---|
782 | smb_raw_exit(cli->session);
|
---|
783 | return ret;
|
---|
784 | }
|
---|
785 |
|
---|
786 | /*
|
---|
787 | basic testing of change notify on files
|
---|
788 | */
|
---|
789 | static bool test_notify_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
---|
790 | {
|
---|
791 | NTSTATUS status;
|
---|
792 | bool ret = true;
|
---|
793 | union smb_open io;
|
---|
794 | union smb_close cl;
|
---|
795 | union smb_notify notify;
|
---|
796 | struct smbcli_request *req;
|
---|
797 | int fnum;
|
---|
798 | const char *fname = BASEDIR "\\file.txt";
|
---|
799 |
|
---|
800 | printf("TESTING CHANGE NOTIFY ON FILES\n");
|
---|
801 |
|
---|
802 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
803 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
804 | io.ntcreatex.in.flags = 0;
|
---|
805 | io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
---|
806 | io.ntcreatex.in.create_options = 0;
|
---|
807 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
808 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
809 | io.ntcreatex.in.alloc_size = 0;
|
---|
810 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
|
---|
811 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
812 | io.ntcreatex.in.security_flags = 0;
|
---|
813 | io.ntcreatex.in.fname = fname;
|
---|
814 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
815 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
816 | fnum = io.ntcreatex.out.file.fnum;
|
---|
817 |
|
---|
818 | /* ask for a change notify,
|
---|
819 | on file or directory name changes */
|
---|
820 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
821 | notify.nttrans.in.file.fnum = fnum;
|
---|
822 | notify.nttrans.in.buffer_size = 1000;
|
---|
823 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_STREAM_NAME;
|
---|
824 | notify.nttrans.in.recursive = false;
|
---|
825 |
|
---|
826 | printf("Testing if notifies on file handles are invalid (should be)\n");
|
---|
827 |
|
---|
828 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
829 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
830 | CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
|
---|
831 |
|
---|
832 | cl.close.level = RAW_CLOSE_CLOSE;
|
---|
833 | cl.close.in.file.fnum = fnum;
|
---|
834 | cl.close.in.write_time = 0;
|
---|
835 | status = smb_raw_close(cli->tree, &cl);
|
---|
836 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
837 |
|
---|
838 | status = smbcli_unlink(cli->tree, fname);
|
---|
839 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
840 |
|
---|
841 | done:
|
---|
842 | smb_raw_exit(cli->session);
|
---|
843 | return ret;
|
---|
844 | }
|
---|
845 |
|
---|
846 | /*
|
---|
847 | basic testing of change notifies followed by a tdis
|
---|
848 | */
|
---|
849 | static bool test_notify_tdis(struct torture_context *tctx)
|
---|
850 | {
|
---|
851 | bool ret = true;
|
---|
852 | NTSTATUS status;
|
---|
853 | union smb_notify notify;
|
---|
854 | union smb_open io;
|
---|
855 | int fnum;
|
---|
856 | struct smbcli_request *req;
|
---|
857 | struct smbcli_state *cli = NULL;
|
---|
858 |
|
---|
859 | printf("TESTING CHANGE NOTIFY FOLLOWED BY TDIS\n");
|
---|
860 |
|
---|
861 | if (!torture_open_connection(&cli, tctx, 0)) {
|
---|
862 | return false;
|
---|
863 | }
|
---|
864 |
|
---|
865 | /*
|
---|
866 | get a handle on the directory
|
---|
867 | */
|
---|
868 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
869 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
870 | io.ntcreatex.in.flags = 0;
|
---|
871 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
872 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
873 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
874 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
875 | io.ntcreatex.in.alloc_size = 0;
|
---|
876 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
877 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
878 | io.ntcreatex.in.security_flags = 0;
|
---|
879 | io.ntcreatex.in.fname = BASEDIR;
|
---|
880 |
|
---|
881 | status = smb_raw_open(cli->tree, tctx, &io);
|
---|
882 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
883 | fnum = io.ntcreatex.out.file.fnum;
|
---|
884 |
|
---|
885 | /* ask for a change notify,
|
---|
886 | on file or directory name changes */
|
---|
887 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
888 | notify.nttrans.in.buffer_size = 1000;
|
---|
889 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
|
---|
890 | notify.nttrans.in.file.fnum = fnum;
|
---|
891 | notify.nttrans.in.recursive = true;
|
---|
892 |
|
---|
893 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
894 |
|
---|
895 | status = smbcli_tdis(cli);
|
---|
896 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
897 | cli->tree = NULL;
|
---|
898 |
|
---|
899 | status = smb_raw_changenotify_recv(req, tctx, ¬ify);
|
---|
900 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
901 | CHECK_VAL(notify.nttrans.out.num_changes, 0);
|
---|
902 |
|
---|
903 | done:
|
---|
904 | torture_close_connection(cli);
|
---|
905 | return ret;
|
---|
906 | }
|
---|
907 |
|
---|
908 | /*
|
---|
909 | basic testing of change notifies followed by a exit
|
---|
910 | */
|
---|
911 | static bool test_notify_exit(struct torture_context *tctx)
|
---|
912 | {
|
---|
913 | bool ret = true;
|
---|
914 | NTSTATUS status;
|
---|
915 | union smb_notify notify;
|
---|
916 | union smb_open io;
|
---|
917 | int fnum;
|
---|
918 | struct smbcli_request *req;
|
---|
919 | struct smbcli_state *cli = NULL;
|
---|
920 |
|
---|
921 | printf("TESTING CHANGE NOTIFY FOLLOWED BY EXIT\n");
|
---|
922 |
|
---|
923 | if (!torture_open_connection(&cli, tctx, 0)) {
|
---|
924 | return false;
|
---|
925 | }
|
---|
926 |
|
---|
927 | /*
|
---|
928 | get a handle on the directory
|
---|
929 | */
|
---|
930 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
931 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
932 | io.ntcreatex.in.flags = 0;
|
---|
933 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
934 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
935 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
936 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
937 | io.ntcreatex.in.alloc_size = 0;
|
---|
938 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
939 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
940 | io.ntcreatex.in.security_flags = 0;
|
---|
941 | io.ntcreatex.in.fname = BASEDIR;
|
---|
942 |
|
---|
943 | status = smb_raw_open(cli->tree, tctx, &io);
|
---|
944 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
945 | fnum = io.ntcreatex.out.file.fnum;
|
---|
946 |
|
---|
947 | /* ask for a change notify,
|
---|
948 | on file or directory name changes */
|
---|
949 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
950 | notify.nttrans.in.buffer_size = 1000;
|
---|
951 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
|
---|
952 | notify.nttrans.in.file.fnum = fnum;
|
---|
953 | notify.nttrans.in.recursive = true;
|
---|
954 |
|
---|
955 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
956 |
|
---|
957 | status = smb_raw_exit(cli->session);
|
---|
958 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
959 |
|
---|
960 | status = smb_raw_changenotify_recv(req, tctx, ¬ify);
|
---|
961 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
962 | CHECK_VAL(notify.nttrans.out.num_changes, 0);
|
---|
963 |
|
---|
964 | done:
|
---|
965 | torture_close_connection(cli);
|
---|
966 | return ret;
|
---|
967 | }
|
---|
968 |
|
---|
969 | /*
|
---|
970 | basic testing of change notifies followed by a ulogoff
|
---|
971 | */
|
---|
972 | static bool test_notify_ulogoff(struct torture_context *tctx)
|
---|
973 | {
|
---|
974 | bool ret = true;
|
---|
975 | NTSTATUS status;
|
---|
976 | union smb_notify notify;
|
---|
977 | union smb_open io;
|
---|
978 | int fnum;
|
---|
979 | struct smbcli_request *req;
|
---|
980 | struct smbcli_state *cli = NULL;
|
---|
981 |
|
---|
982 | printf("TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
|
---|
983 |
|
---|
984 | if (!torture_open_connection(&cli, tctx, 0)) {
|
---|
985 | return false;
|
---|
986 | }
|
---|
987 |
|
---|
988 | /*
|
---|
989 | get a handle on the directory
|
---|
990 | */
|
---|
991 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
992 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
993 | io.ntcreatex.in.flags = 0;
|
---|
994 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
995 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
996 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
997 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
998 | io.ntcreatex.in.alloc_size = 0;
|
---|
999 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
1000 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
1001 | io.ntcreatex.in.security_flags = 0;
|
---|
1002 | io.ntcreatex.in.fname = BASEDIR;
|
---|
1003 |
|
---|
1004 | status = smb_raw_open(cli->tree, tctx, &io);
|
---|
1005 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1006 | fnum = io.ntcreatex.out.file.fnum;
|
---|
1007 |
|
---|
1008 | /* ask for a change notify,
|
---|
1009 | on file or directory name changes */
|
---|
1010 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
1011 | notify.nttrans.in.buffer_size = 1000;
|
---|
1012 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
|
---|
1013 | notify.nttrans.in.file.fnum = fnum;
|
---|
1014 | notify.nttrans.in.recursive = true;
|
---|
1015 |
|
---|
1016 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1017 |
|
---|
1018 | status = smb_raw_ulogoff(cli->session);
|
---|
1019 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1020 |
|
---|
1021 | status = smb_raw_changenotify_recv(req, tctx, ¬ify);
|
---|
1022 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1023 | CHECK_VAL(notify.nttrans.out.num_changes, 0);
|
---|
1024 |
|
---|
1025 | done:
|
---|
1026 | torture_close_connection(cli);
|
---|
1027 | return ret;
|
---|
1028 | }
|
---|
1029 |
|
---|
1030 | static void tcp_dis_handler(struct smbcli_transport *t, void *p)
|
---|
1031 | {
|
---|
1032 | struct smbcli_state *cli = (struct smbcli_state *)p;
|
---|
1033 | smbcli_transport_dead(cli->transport, NT_STATUS_LOCAL_DISCONNECT);
|
---|
1034 | cli->transport = NULL;
|
---|
1035 | cli->tree = NULL;
|
---|
1036 | }
|
---|
1037 | /*
|
---|
1038 | basic testing of change notifies followed by tcp disconnect
|
---|
1039 | */
|
---|
1040 | static bool test_notify_tcp_dis(struct torture_context *tctx)
|
---|
1041 | {
|
---|
1042 | bool ret = true;
|
---|
1043 | NTSTATUS status;
|
---|
1044 | union smb_notify notify;
|
---|
1045 | union smb_open io;
|
---|
1046 | int fnum;
|
---|
1047 | struct smbcli_request *req;
|
---|
1048 | struct smbcli_state *cli = NULL;
|
---|
1049 |
|
---|
1050 | printf("TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
|
---|
1051 |
|
---|
1052 | if (!torture_open_connection(&cli, tctx, 0)) {
|
---|
1053 | return false;
|
---|
1054 | }
|
---|
1055 |
|
---|
1056 | /*
|
---|
1057 | get a handle on the directory
|
---|
1058 | */
|
---|
1059 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
1060 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
1061 | io.ntcreatex.in.flags = 0;
|
---|
1062 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
1063 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
1064 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
1065 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
1066 | io.ntcreatex.in.alloc_size = 0;
|
---|
1067 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
1068 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
1069 | io.ntcreatex.in.security_flags = 0;
|
---|
1070 | io.ntcreatex.in.fname = BASEDIR;
|
---|
1071 |
|
---|
1072 | status = smb_raw_open(cli->tree, tctx, &io);
|
---|
1073 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1074 | fnum = io.ntcreatex.out.file.fnum;
|
---|
1075 |
|
---|
1076 | /* ask for a change notify,
|
---|
1077 | on file or directory name changes */
|
---|
1078 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
1079 | notify.nttrans.in.buffer_size = 1000;
|
---|
1080 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
|
---|
1081 | notify.nttrans.in.file.fnum = fnum;
|
---|
1082 | notify.nttrans.in.recursive = true;
|
---|
1083 |
|
---|
1084 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1085 |
|
---|
1086 | smbcli_transport_idle_handler(cli->transport, tcp_dis_handler, 250, cli);
|
---|
1087 |
|
---|
1088 | status = smb_raw_changenotify_recv(req, tctx, ¬ify);
|
---|
1089 | CHECK_STATUS(status, NT_STATUS_LOCAL_DISCONNECT);
|
---|
1090 |
|
---|
1091 | done:
|
---|
1092 | torture_close_connection(cli);
|
---|
1093 | return ret;
|
---|
1094 | }
|
---|
1095 |
|
---|
1096 | /*
|
---|
1097 | test setting up two change notify requests on one handle
|
---|
1098 | */
|
---|
1099 | static bool test_notify_double(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
---|
1100 | {
|
---|
1101 | bool ret = true;
|
---|
1102 | NTSTATUS status;
|
---|
1103 | union smb_notify notify;
|
---|
1104 | union smb_open io;
|
---|
1105 | int fnum;
|
---|
1106 | struct smbcli_request *req1, *req2;
|
---|
1107 |
|
---|
1108 | printf("TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
|
---|
1109 |
|
---|
1110 | /*
|
---|
1111 | get a handle on the directory
|
---|
1112 | */
|
---|
1113 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
1114 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
1115 | io.ntcreatex.in.flags = 0;
|
---|
1116 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
1117 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
1118 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
1119 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
1120 | io.ntcreatex.in.alloc_size = 0;
|
---|
1121 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
1122 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
1123 | io.ntcreatex.in.security_flags = 0;
|
---|
1124 | io.ntcreatex.in.fname = BASEDIR;
|
---|
1125 |
|
---|
1126 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
1127 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1128 | fnum = io.ntcreatex.out.file.fnum;
|
---|
1129 |
|
---|
1130 | /* ask for a change notify,
|
---|
1131 | on file or directory name changes */
|
---|
1132 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
1133 | notify.nttrans.in.buffer_size = 1000;
|
---|
1134 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
|
---|
1135 | notify.nttrans.in.file.fnum = fnum;
|
---|
1136 | notify.nttrans.in.recursive = true;
|
---|
1137 |
|
---|
1138 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1139 | req2 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1140 |
|
---|
1141 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
1142 |
|
---|
1143 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
1144 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1145 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1146 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
1147 |
|
---|
1148 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name2");
|
---|
1149 |
|
---|
1150 | status = smb_raw_changenotify_recv(req2, mem_ctx, ¬ify);
|
---|
1151 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1152 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1153 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name2", STR_UNICODE);
|
---|
1154 |
|
---|
1155 | done:
|
---|
1156 | smb_raw_exit(cli->session);
|
---|
1157 | return ret;
|
---|
1158 | }
|
---|
1159 |
|
---|
1160 |
|
---|
1161 | /*
|
---|
1162 | test multiple change notifies at different depths and with/without recursion
|
---|
1163 | */
|
---|
1164 | static bool test_notify_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
---|
1165 | {
|
---|
1166 | bool ret = true;
|
---|
1167 | union smb_notify notify;
|
---|
1168 | union smb_open io;
|
---|
1169 | struct smbcli_request *req;
|
---|
1170 | struct timeval tv;
|
---|
1171 | struct {
|
---|
1172 | const char *path;
|
---|
1173 | bool recursive;
|
---|
1174 | uint32_t filter;
|
---|
1175 | int expected;
|
---|
1176 | int fnum;
|
---|
1177 | int counted;
|
---|
1178 | } dirs[] = {
|
---|
1179 | {BASEDIR "\\abc", true, FILE_NOTIFY_CHANGE_NAME, 30 },
|
---|
1180 | {BASEDIR "\\zqy", true, FILE_NOTIFY_CHANGE_NAME, 8 },
|
---|
1181 | {BASEDIR "\\atsy", true, FILE_NOTIFY_CHANGE_NAME, 4 },
|
---|
1182 | {BASEDIR "\\abc\\foo", true, FILE_NOTIFY_CHANGE_NAME, 2 },
|
---|
1183 | {BASEDIR "\\abc\\blah", true, FILE_NOTIFY_CHANGE_NAME, 13 },
|
---|
1184 | {BASEDIR "\\abc\\blah", false, FILE_NOTIFY_CHANGE_NAME, 7 },
|
---|
1185 | {BASEDIR "\\abc\\blah\\a", true, FILE_NOTIFY_CHANGE_NAME, 2 },
|
---|
1186 | {BASEDIR "\\abc\\blah\\b", true, FILE_NOTIFY_CHANGE_NAME, 2 },
|
---|
1187 | {BASEDIR "\\abc\\blah\\c", true, FILE_NOTIFY_CHANGE_NAME, 2 },
|
---|
1188 | {BASEDIR "\\abc\\fooblah", true, FILE_NOTIFY_CHANGE_NAME, 2 },
|
---|
1189 | {BASEDIR "\\zqy\\xx", true, FILE_NOTIFY_CHANGE_NAME, 2 },
|
---|
1190 | {BASEDIR "\\zqy\\yyy", true, FILE_NOTIFY_CHANGE_NAME, 2 },
|
---|
1191 | {BASEDIR "\\zqy\\..", true, FILE_NOTIFY_CHANGE_NAME, 40 },
|
---|
1192 | {BASEDIR, true, FILE_NOTIFY_CHANGE_NAME, 40 },
|
---|
1193 | {BASEDIR, false,FILE_NOTIFY_CHANGE_NAME, 6 },
|
---|
1194 | {BASEDIR "\\atsy", false,FILE_NOTIFY_CHANGE_NAME, 4 },
|
---|
1195 | {BASEDIR "\\abc", true, FILE_NOTIFY_CHANGE_NAME, 24 },
|
---|
1196 | {BASEDIR "\\abc", false,FILE_NOTIFY_CHANGE_FILE_NAME, 0 },
|
---|
1197 | {BASEDIR "\\abc", true, FILE_NOTIFY_CHANGE_FILE_NAME, 0 },
|
---|
1198 | {BASEDIR "\\abc", true, FILE_NOTIFY_CHANGE_NAME, 24 },
|
---|
1199 | };
|
---|
1200 | int i;
|
---|
1201 | NTSTATUS status;
|
---|
1202 | bool all_done = false;
|
---|
1203 |
|
---|
1204 | printf("TESTING CHANGE NOTIFY FOR DIFFERENT DEPTHS\n");
|
---|
1205 |
|
---|
1206 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
1207 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
1208 | io.ntcreatex.in.flags = 0;
|
---|
1209 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
1210 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
1211 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
1212 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
1213 | io.ntcreatex.in.alloc_size = 0;
|
---|
1214 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
|
---|
1215 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
1216 | io.ntcreatex.in.security_flags = 0;
|
---|
1217 |
|
---|
1218 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
1219 | notify.nttrans.in.buffer_size = 20000;
|
---|
1220 |
|
---|
1221 | /*
|
---|
1222 | setup the directory tree, and the notify buffer on each directory
|
---|
1223 | */
|
---|
1224 | for (i=0;i<ARRAY_SIZE(dirs);i++) {
|
---|
1225 | io.ntcreatex.in.fname = dirs[i].path;
|
---|
1226 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
1227 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1228 | dirs[i].fnum = io.ntcreatex.out.file.fnum;
|
---|
1229 |
|
---|
1230 | notify.nttrans.in.completion_filter = dirs[i].filter;
|
---|
1231 | notify.nttrans.in.file.fnum = dirs[i].fnum;
|
---|
1232 | notify.nttrans.in.recursive = dirs[i].recursive;
|
---|
1233 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1234 | smb_raw_ntcancel(req);
|
---|
1235 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
1236 | CHECK_STATUS(status, NT_STATUS_CANCELLED);
|
---|
1237 | }
|
---|
1238 |
|
---|
1239 | /* trigger 2 events in each dir */
|
---|
1240 | for (i=0;i<ARRAY_SIZE(dirs);i++) {
|
---|
1241 | char *path = talloc_asprintf(mem_ctx, "%s\\test.dir", dirs[i].path);
|
---|
1242 | smbcli_mkdir(cli->tree, path);
|
---|
1243 | smbcli_rmdir(cli->tree, path);
|
---|
1244 | talloc_free(path);
|
---|
1245 | }
|
---|
1246 |
|
---|
1247 | /* give a bit of time for the events to propogate */
|
---|
1248 | tv = timeval_current();
|
---|
1249 |
|
---|
1250 | do {
|
---|
1251 | /* count events that have happened in each dir */
|
---|
1252 | for (i=0;i<ARRAY_SIZE(dirs);i++) {
|
---|
1253 | notify.nttrans.in.file.fnum = dirs[i].fnum;
|
---|
1254 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1255 | smb_raw_ntcancel(req);
|
---|
1256 | notify.nttrans.out.num_changes = 0;
|
---|
1257 | status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify);
|
---|
1258 | dirs[i].counted += notify.nttrans.out.num_changes;
|
---|
1259 | }
|
---|
1260 |
|
---|
1261 | all_done = true;
|
---|
1262 |
|
---|
1263 | for (i=0;i<ARRAY_SIZE(dirs);i++) {
|
---|
1264 | if (dirs[i].counted != dirs[i].expected) {
|
---|
1265 | all_done = false;
|
---|
1266 | }
|
---|
1267 | }
|
---|
1268 | } while (!all_done && timeval_elapsed(&tv) < 20);
|
---|
1269 |
|
---|
1270 | printf("took %.4f seconds to propogate all events\n", timeval_elapsed(&tv));
|
---|
1271 |
|
---|
1272 | for (i=0;i<ARRAY_SIZE(dirs);i++) {
|
---|
1273 | if (dirs[i].counted != dirs[i].expected) {
|
---|
1274 | printf("ERROR: i=%d expected %d got %d for '%s'\n",
|
---|
1275 | i, dirs[i].expected, dirs[i].counted, dirs[i].path);
|
---|
1276 | ret = false;
|
---|
1277 | }
|
---|
1278 | }
|
---|
1279 |
|
---|
1280 | /*
|
---|
1281 | run from the back, closing and deleting
|
---|
1282 | */
|
---|
1283 | for (i=ARRAY_SIZE(dirs)-1;i>=0;i--) {
|
---|
1284 | smbcli_close(cli->tree, dirs[i].fnum);
|
---|
1285 | smbcli_rmdir(cli->tree, dirs[i].path);
|
---|
1286 | }
|
---|
1287 |
|
---|
1288 | done:
|
---|
1289 | smb_raw_exit(cli->session);
|
---|
1290 | return ret;
|
---|
1291 | }
|
---|
1292 |
|
---|
1293 | /*
|
---|
1294 | Test response when cached server events exceed single NT NOTFIY response
|
---|
1295 | packet size.
|
---|
1296 | */
|
---|
1297 | static bool test_notify_overflow(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
---|
1298 | {
|
---|
1299 | bool ret = true;
|
---|
1300 | NTSTATUS status;
|
---|
1301 | union smb_notify notify;
|
---|
1302 | union smb_open io;
|
---|
1303 | int fnum;
|
---|
1304 | int count = 100;
|
---|
1305 | struct smbcli_request *req1;
|
---|
1306 | int i;
|
---|
1307 |
|
---|
1308 | printf("TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
|
---|
1309 |
|
---|
1310 | /* get a handle on the directory */
|
---|
1311 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
1312 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
1313 | io.ntcreatex.in.flags = 0;
|
---|
1314 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
1315 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
1316 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
1317 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
|
---|
1318 | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
1319 | io.ntcreatex.in.alloc_size = 0;
|
---|
1320 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
1321 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
1322 | io.ntcreatex.in.security_flags = 0;
|
---|
1323 | io.ntcreatex.in.fname = BASEDIR;
|
---|
1324 |
|
---|
1325 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
1326 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1327 | fnum = io.ntcreatex.out.file.fnum;
|
---|
1328 |
|
---|
1329 | /* ask for a change notify, on name changes. */
|
---|
1330 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
1331 | notify.nttrans.in.buffer_size = 1000;
|
---|
1332 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
|
---|
1333 | notify.nttrans.in.file.fnum = fnum;
|
---|
1334 |
|
---|
1335 | notify.nttrans.in.recursive = true;
|
---|
1336 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1337 |
|
---|
1338 | /* cancel initial requests so the buffer is setup */
|
---|
1339 | smb_raw_ntcancel(req1);
|
---|
1340 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
1341 | CHECK_STATUS(status, NT_STATUS_CANCELLED);
|
---|
1342 |
|
---|
1343 | /* open a lot of files, filling up the server side notify buffer */
|
---|
1344 | printf("Testing overflowed buffer notify on create of %d files\n",
|
---|
1345 | count);
|
---|
1346 | for (i=0;i<count;i++) {
|
---|
1347 | char *fname = talloc_asprintf(cli, BASEDIR "\\test%d.txt", i);
|
---|
1348 | int fnum2 = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR,
|
---|
1349 | DENY_NONE);
|
---|
1350 | if (fnum2 == -1) {
|
---|
1351 | printf("Failed to create %s - %s\n",
|
---|
1352 | fname, smbcli_errstr(cli->tree));
|
---|
1353 | ret = false;
|
---|
1354 | goto done;
|
---|
1355 | }
|
---|
1356 | talloc_free(fname);
|
---|
1357 | smbcli_close(cli->tree, fnum2);
|
---|
1358 | }
|
---|
1359 |
|
---|
1360 | /* expect that 0 events will be returned with NT_STATUS_OK */
|
---|
1361 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1362 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
1363 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1364 | CHECK_VAL(notify.nttrans.out.num_changes, 0);
|
---|
1365 |
|
---|
1366 | done:
|
---|
1367 | smb_raw_exit(cli->session);
|
---|
1368 | return ret;
|
---|
1369 | }
|
---|
1370 |
|
---|
1371 | /*
|
---|
1372 | Test if notifications are returned for changes to the base directory.
|
---|
1373 | They shouldn't be.
|
---|
1374 | */
|
---|
1375 | static bool test_notify_basedir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
---|
1376 | {
|
---|
1377 | bool ret = true;
|
---|
1378 | NTSTATUS status;
|
---|
1379 | union smb_notify notify;
|
---|
1380 | union smb_open io;
|
---|
1381 | int fnum;
|
---|
1382 | struct smbcli_request *req1;
|
---|
1383 |
|
---|
1384 | printf("TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
|
---|
1385 |
|
---|
1386 | /* get a handle on the directory */
|
---|
1387 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
1388 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
1389 | io.ntcreatex.in.flags = 0;
|
---|
1390 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
1391 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
1392 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
1393 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
|
---|
1394 | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
1395 | io.ntcreatex.in.alloc_size = 0;
|
---|
1396 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
1397 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
1398 | io.ntcreatex.in.security_flags = 0;
|
---|
1399 | io.ntcreatex.in.fname = BASEDIR;
|
---|
1400 |
|
---|
1401 | status = smb_raw_open(cli->tree, mem_ctx, &io);
|
---|
1402 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1403 | fnum = io.ntcreatex.out.file.fnum;
|
---|
1404 |
|
---|
1405 | /* create a test file that will also be modified */
|
---|
1406 | smbcli_close(cli->tree, smbcli_open(cli->tree, BASEDIR "\\tname1",
|
---|
1407 | O_CREAT, 0));
|
---|
1408 |
|
---|
1409 | /* ask for a change notify, on attribute changes. */
|
---|
1410 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
1411 | notify.nttrans.in.buffer_size = 1000;
|
---|
1412 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
---|
1413 | notify.nttrans.in.file.fnum = fnum;
|
---|
1414 | notify.nttrans.in.recursive = true;
|
---|
1415 |
|
---|
1416 | req1 = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1417 |
|
---|
1418 | /* set attribute on the base dir */
|
---|
1419 | smbcli_setatr(cli->tree, BASEDIR, FILE_ATTRIBUTE_HIDDEN, 0);
|
---|
1420 |
|
---|
1421 | /* set attribute on a file to assure we receive a notification */
|
---|
1422 | smbcli_setatr(cli->tree, BASEDIR "\\tname1", FILE_ATTRIBUTE_HIDDEN, 0);
|
---|
1423 | smb_msleep(200);
|
---|
1424 |
|
---|
1425 | /* check how many responses were given, expect only 1 for the file */
|
---|
1426 | status = smb_raw_changenotify_recv(req1, mem_ctx, ¬ify);
|
---|
1427 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1428 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1429 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
|
---|
1430 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "tname1", STR_UNICODE);
|
---|
1431 |
|
---|
1432 | done:
|
---|
1433 | smb_raw_exit(cli->session);
|
---|
1434 | return ret;
|
---|
1435 | }
|
---|
1436 |
|
---|
1437 |
|
---|
1438 | /*
|
---|
1439 | create a secondary tree connect - used to test for a bug in Samba3 messaging
|
---|
1440 | with change notify
|
---|
1441 | */
|
---|
1442 | static struct smbcli_tree *secondary_tcon(struct smbcli_state *cli,
|
---|
1443 | struct torture_context *tctx)
|
---|
1444 | {
|
---|
1445 | NTSTATUS status;
|
---|
1446 | const char *share, *host;
|
---|
1447 | struct smbcli_tree *tree;
|
---|
1448 | union smb_tcon tcon;
|
---|
1449 |
|
---|
1450 | share = torture_setting_string(tctx, "share", NULL);
|
---|
1451 | host = torture_setting_string(tctx, "host", NULL);
|
---|
1452 |
|
---|
1453 | printf("create a second tree context on the same session\n");
|
---|
1454 | tree = smbcli_tree_init(cli->session, tctx, false);
|
---|
1455 |
|
---|
1456 | tcon.generic.level = RAW_TCON_TCONX;
|
---|
1457 | tcon.tconx.in.flags = 0;
|
---|
1458 | tcon.tconx.in.password = data_blob(NULL, 0);
|
---|
1459 | tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
|
---|
1460 | tcon.tconx.in.device = "A:";
|
---|
1461 | status = smb_raw_tcon(tree, tctx, &tcon);
|
---|
1462 | if (!NT_STATUS_IS_OK(status)) {
|
---|
1463 | talloc_free(tree);
|
---|
1464 | printf("Failed to create secondary tree\n");
|
---|
1465 | return NULL;
|
---|
1466 | }
|
---|
1467 |
|
---|
1468 | tree->tid = tcon.tconx.out.tid;
|
---|
1469 | printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
|
---|
1470 |
|
---|
1471 | return tree;
|
---|
1472 | }
|
---|
1473 |
|
---|
1474 |
|
---|
1475 | /*
|
---|
1476 | very simple change notify test
|
---|
1477 | */
|
---|
1478 | static bool test_notify_tcon(struct smbcli_state *cli, struct torture_context *torture)
|
---|
1479 | {
|
---|
1480 | bool ret = true;
|
---|
1481 | NTSTATUS status;
|
---|
1482 | union smb_notify notify;
|
---|
1483 | union smb_open io;
|
---|
1484 | int fnum, fnum2;
|
---|
1485 | struct smbcli_request *req;
|
---|
1486 | extern int torture_numops;
|
---|
1487 | struct smbcli_tree *tree = NULL;
|
---|
1488 |
|
---|
1489 | printf("TESTING SIMPLE CHANGE NOTIFY\n");
|
---|
1490 |
|
---|
1491 | /*
|
---|
1492 | get a handle on the directory
|
---|
1493 | */
|
---|
1494 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
1495 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
1496 | io.ntcreatex.in.flags = 0;
|
---|
1497 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
1498 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
1499 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
1500 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
1501 | io.ntcreatex.in.alloc_size = 0;
|
---|
1502 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
1503 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
1504 | io.ntcreatex.in.security_flags = 0;
|
---|
1505 | io.ntcreatex.in.fname = BASEDIR;
|
---|
1506 |
|
---|
1507 | status = smb_raw_open(cli->tree, torture, &io);
|
---|
1508 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1509 | fnum = io.ntcreatex.out.file.fnum;
|
---|
1510 |
|
---|
1511 | status = smb_raw_open(cli->tree, torture, &io);
|
---|
1512 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1513 | fnum2 = io.ntcreatex.out.file.fnum;
|
---|
1514 |
|
---|
1515 | /* ask for a change notify,
|
---|
1516 | on file or directory name changes */
|
---|
1517 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
1518 | notify.nttrans.in.buffer_size = 1000;
|
---|
1519 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
|
---|
1520 | notify.nttrans.in.file.fnum = fnum;
|
---|
1521 | notify.nttrans.in.recursive = true;
|
---|
1522 |
|
---|
1523 | printf("Testing notify mkdir\n");
|
---|
1524 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1525 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
1526 |
|
---|
1527 | status = smb_raw_changenotify_recv(req, torture, ¬ify);
|
---|
1528 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1529 |
|
---|
1530 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1531 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
|
---|
1532 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
1533 |
|
---|
1534 | printf("Testing notify rmdir\n");
|
---|
1535 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1536 | smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
1537 |
|
---|
1538 | status = smb_raw_changenotify_recv(req, torture, ¬ify);
|
---|
1539 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1540 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1541 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
|
---|
1542 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
1543 |
|
---|
1544 | printf("SIMPLE CHANGE NOTIFY OK\n");
|
---|
1545 |
|
---|
1546 | printf("TESTING WITH SECONDARY TCON\n");
|
---|
1547 | tree = secondary_tcon(cli, torture);
|
---|
1548 |
|
---|
1549 | printf("Testing notify mkdir\n");
|
---|
1550 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1551 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
1552 |
|
---|
1553 | status = smb_raw_changenotify_recv(req, torture, ¬ify);
|
---|
1554 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1555 |
|
---|
1556 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1557 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
|
---|
1558 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
1559 |
|
---|
1560 | printf("Testing notify rmdir\n");
|
---|
1561 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1562 | smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
1563 |
|
---|
1564 | status = smb_raw_changenotify_recv(req, torture, ¬ify);
|
---|
1565 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1566 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1567 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
|
---|
1568 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
1569 |
|
---|
1570 | printf("CHANGE NOTIFY WITH TCON OK\n");
|
---|
1571 |
|
---|
1572 | printf("Disconnecting secondary tree\n");
|
---|
1573 | status = smb_tree_disconnect(tree);
|
---|
1574 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1575 | talloc_free(tree);
|
---|
1576 |
|
---|
1577 | printf("Testing notify mkdir\n");
|
---|
1578 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1579 | smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
1580 |
|
---|
1581 | status = smb_raw_changenotify_recv(req, torture, ¬ify);
|
---|
1582 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1583 |
|
---|
1584 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1585 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
|
---|
1586 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
1587 |
|
---|
1588 | printf("Testing notify rmdir\n");
|
---|
1589 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1590 | smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name");
|
---|
1591 |
|
---|
1592 | status = smb_raw_changenotify_recv(req, torture, ¬ify);
|
---|
1593 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1594 | CHECK_VAL(notify.nttrans.out.num_changes, 1);
|
---|
1595 | CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
|
---|
1596 | CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
|
---|
1597 |
|
---|
1598 | printf("CHANGE NOTIFY WITH TDIS OK\n");
|
---|
1599 | done:
|
---|
1600 | smb_raw_exit(cli->session);
|
---|
1601 | return ret;
|
---|
1602 | }
|
---|
1603 |
|
---|
1604 |
|
---|
1605 | /*
|
---|
1606 | testing alignment of multiple change notify infos
|
---|
1607 | */
|
---|
1608 | static bool test_notify_alignment(struct smbcli_state *cli,
|
---|
1609 | struct torture_context *tctx)
|
---|
1610 | {
|
---|
1611 | NTSTATUS status;
|
---|
1612 | union smb_notify notify;
|
---|
1613 | union smb_open io;
|
---|
1614 | int i, fnum, fnum2;
|
---|
1615 | struct smbcli_request *req;
|
---|
1616 | const char *fname = BASEDIR "\\starter";
|
---|
1617 | const char *fnames[] = { "a",
|
---|
1618 | "ab",
|
---|
1619 | "abc",
|
---|
1620 | "abcd" };
|
---|
1621 | int num_names = ARRAY_SIZE(fnames);
|
---|
1622 | char *fpath = NULL;
|
---|
1623 |
|
---|
1624 | torture_comment(tctx, "TESTING CHANGE NOTIFY REPLY ALIGNMENT\n");
|
---|
1625 |
|
---|
1626 | /* get a handle on the directory */
|
---|
1627 | io.generic.level = RAW_OPEN_NTCREATEX;
|
---|
1628 | io.ntcreatex.in.root_fid.fnum = 0;
|
---|
1629 | io.ntcreatex.in.flags = 0;
|
---|
1630 | io.ntcreatex.in.access_mask = SEC_FILE_ALL;
|
---|
1631 | io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
---|
1632 | io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
---|
1633 | io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
|
---|
1634 | NTCREATEX_SHARE_ACCESS_WRITE;
|
---|
1635 | io.ntcreatex.in.alloc_size = 0;
|
---|
1636 | io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
---|
1637 | io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
|
---|
1638 | io.ntcreatex.in.security_flags = 0;
|
---|
1639 | io.ntcreatex.in.fname = BASEDIR;
|
---|
1640 |
|
---|
1641 | status = smb_raw_open(cli->tree, tctx, &io);
|
---|
1642 | torture_assert_ntstatus_ok(tctx, status, "");
|
---|
1643 | fnum = io.ntcreatex.out.file.fnum;
|
---|
1644 |
|
---|
1645 | /* ask for a change notify, on file creation */
|
---|
1646 | notify.nttrans.level = RAW_NOTIFY_NTTRANS;
|
---|
1647 | notify.nttrans.in.buffer_size = 1000;
|
---|
1648 | notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_FILE_NAME;
|
---|
1649 | notify.nttrans.in.file.fnum = fnum;
|
---|
1650 | notify.nttrans.in.recursive = false;
|
---|
1651 |
|
---|
1652 | /* start change tracking */
|
---|
1653 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1654 |
|
---|
1655 | fnum2 = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
|
---|
1656 | torture_assert(tctx, fnum2 != -1, smbcli_errstr(cli->tree));
|
---|
1657 | smbcli_close(cli->tree, fnum2);
|
---|
1658 |
|
---|
1659 | status = smb_raw_changenotify_recv(req, tctx, ¬ify);
|
---|
1660 | torture_assert_ntstatus_ok(tctx, status, "");
|
---|
1661 |
|
---|
1662 | /* create 4 files that will cause CHANGE_NOTIFY_INFO structures
|
---|
1663 | * to be returned in the same packet with all possible 4-byte padding
|
---|
1664 | * permutations. As per MS-CIFS 2.2.7.4.2 these structures should be
|
---|
1665 | * 4-byte aligned. */
|
---|
1666 |
|
---|
1667 | for (i = 0; i < num_names; i++) {
|
---|
1668 | fpath = talloc_asprintf(tctx, "%s\\%s", BASEDIR, fnames[i]);
|
---|
1669 | fnum2 = smbcli_open(cli->tree, fpath,
|
---|
1670 | O_CREAT|O_RDWR, DENY_NONE);
|
---|
1671 | torture_assert(tctx, fnum2 != -1, smbcli_errstr(cli->tree));
|
---|
1672 | smbcli_close(cli->tree, fnum2);
|
---|
1673 | talloc_free(fpath);
|
---|
1674 | }
|
---|
1675 |
|
---|
1676 | /* We send a notify packet, and let smb_raw_changenotify_recv() do
|
---|
1677 | * the alignment checking for us. */
|
---|
1678 | req = smb_raw_changenotify_send(cli->tree, ¬ify);
|
---|
1679 | status = smb_raw_changenotify_recv(req, tctx, ¬ify);
|
---|
1680 | torture_assert_ntstatus_ok(tctx, status, "");
|
---|
1681 |
|
---|
1682 | /* Do basic checking for correctness. */
|
---|
1683 | torture_assert(tctx, notify.nttrans.out.num_changes == num_names, "");
|
---|
1684 | for (i = 0; i < num_names; i++) {
|
---|
1685 | torture_assert(tctx, notify.nttrans.out.changes[i].action ==
|
---|
1686 | NOTIFY_ACTION_ADDED, "");
|
---|
1687 | CHECK_WSTR2(tctx, notify.nttrans.out.changes[i].name, fnames[i],
|
---|
1688 | STR_UNICODE);
|
---|
1689 | }
|
---|
1690 |
|
---|
1691 | return true;
|
---|
1692 | }
|
---|
1693 |
|
---|
1694 | /*
|
---|
1695 | basic testing of change notify
|
---|
1696 | */
|
---|
1697 | bool torture_raw_notify(struct torture_context *torture,
|
---|
1698 | struct smbcli_state *cli,
|
---|
1699 | struct smbcli_state *cli2)
|
---|
1700 | {
|
---|
1701 | bool ret = true;
|
---|
1702 |
|
---|
1703 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1704 | return false;
|
---|
1705 | }
|
---|
1706 |
|
---|
1707 | ret &= test_notify_tcon(cli, torture);
|
---|
1708 | ret &= test_notify_dir(cli, cli2, torture);
|
---|
1709 | ret &= test_notify_mask(cli, torture);
|
---|
1710 | ret &= test_notify_recursive(cli, torture);
|
---|
1711 | ret &= test_notify_mask_change(cli, torture);
|
---|
1712 | ret &= test_notify_file(cli, torture);
|
---|
1713 | ret &= test_notify_tdis(torture);
|
---|
1714 | ret &= test_notify_exit(torture);
|
---|
1715 | ret &= test_notify_ulogoff(torture);
|
---|
1716 | ret &= test_notify_tcp_dis(torture);
|
---|
1717 | ret &= test_notify_double(cli, torture);
|
---|
1718 | ret &= test_notify_tree(cli, torture);
|
---|
1719 | ret &= test_notify_overflow(cli, torture);
|
---|
1720 | ret &= test_notify_basedir(cli, torture);
|
---|
1721 | ret &= test_notify_alignment(cli, torture);
|
---|
1722 |
|
---|
1723 | smb_raw_exit(cli->session);
|
---|
1724 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1725 | return ret;
|
---|
1726 | }
|
---|