1 | /*
|
---|
2 | Unix SMB/CIFS implementation.
|
---|
3 | test suite for various lock operations
|
---|
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 "torture/torture.h"
|
---|
22 | #include "libcli/raw/libcliraw.h"
|
---|
23 | #include "libcli/raw/raw_proto.h"
|
---|
24 | #include "system/time.h"
|
---|
25 | #include "system/filesys.h"
|
---|
26 | #include "libcli/libcli.h"
|
---|
27 | #include "torture/util.h"
|
---|
28 | #include "libcli/composite/composite.h"
|
---|
29 | #include "libcli/smb_composite/smb_composite.h"
|
---|
30 | #include "lib/cmdline/popt_common.h"
|
---|
31 | #include "param/param.h"
|
---|
32 |
|
---|
33 | #define CHECK_STATUS(status, correct) do { \
|
---|
34 | if (!NT_STATUS_EQUAL(status, correct)) { \
|
---|
35 | torture_result(tctx, TORTURE_FAIL, \
|
---|
36 | "(%s) Incorrect status %s - should be %s\n", \
|
---|
37 | __location__, nt_errstr(status), nt_errstr(correct)); \
|
---|
38 | ret = false; \
|
---|
39 | goto done; \
|
---|
40 | }} while (0)
|
---|
41 |
|
---|
42 | #define CHECK_STATUS_CONT(status, correct) do { \
|
---|
43 | if (!NT_STATUS_EQUAL(status, correct)) { \
|
---|
44 | torture_result(tctx, TORTURE_FAIL, \
|
---|
45 | "(%s) Incorrect status %s - should be %s\n", \
|
---|
46 | __location__, nt_errstr(status), nt_errstr(correct)); \
|
---|
47 | ret = false; \
|
---|
48 | }} while (0)
|
---|
49 |
|
---|
50 | #define CHECK_STATUS_OR(status, correct1, correct2) do { \
|
---|
51 | if ((!NT_STATUS_EQUAL(status, correct1)) && \
|
---|
52 | (!NT_STATUS_EQUAL(status, correct2))) { \
|
---|
53 | torture_result(tctx, TORTURE_FAIL, \
|
---|
54 | "(%s) Incorrect status %s - should be %s or %s\n", \
|
---|
55 | __location__, nt_errstr(status), nt_errstr(correct1), \
|
---|
56 | nt_errstr(correct2)); \
|
---|
57 | ret = false; \
|
---|
58 | goto done; \
|
---|
59 | }} while (0)
|
---|
60 |
|
---|
61 | #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
|
---|
62 | if ((!NT_STATUS_EQUAL(status, correct1)) && \
|
---|
63 | (!NT_STATUS_EQUAL(status, correct2))) { \
|
---|
64 | torture_result(tctx, TORTURE_FAIL, \
|
---|
65 | "(%s) Incorrect status %s - should be %s or %s\n", \
|
---|
66 | __location__, nt_errstr(status), nt_errstr(correct1), \
|
---|
67 | nt_errstr(correct2)); \
|
---|
68 | ret = false; \
|
---|
69 | }} while (0)
|
---|
70 | #define BASEDIR "\\testlock"
|
---|
71 |
|
---|
72 | #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
|
---|
73 | #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
|
---|
74 | #define TARGET_IS_WINDOWS(_tctx) \
|
---|
75 | ((torture_setting_bool(_tctx, "w2k3", false)) || \
|
---|
76 | (torture_setting_bool(_tctx, "w2k8", false)) || \
|
---|
77 | (torture_setting_bool(_tctx, "win7", false)))
|
---|
78 | #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
|
---|
79 | #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
|
---|
80 |
|
---|
81 | #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
|
---|
82 | (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
|
---|
83 | #define TARGET_SUPPORTS_SMBEXIT(_tctx) \
|
---|
84 | (torture_setting_bool(_tctx, "smbexit_pdu_support", true))
|
---|
85 | #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
|
---|
86 | (torture_setting_bool(_tctx, "smblock_pdu_support", true))
|
---|
87 | #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
|
---|
88 | (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
|
---|
89 | #define TARGET_RETURNS_RANGE_NOT_LOCKED(_tctx) \
|
---|
90 | (torture_setting_bool(_tctx, "range_not_locked_on_file_close", true))
|
---|
91 | /*
|
---|
92 | test SMBlock and SMBunlock ops
|
---|
93 | */
|
---|
94 | static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
|
---|
95 | {
|
---|
96 | union smb_lock io;
|
---|
97 | NTSTATUS status;
|
---|
98 | bool ret = true;
|
---|
99 | int fnum;
|
---|
100 | const char *fname = BASEDIR "\\test.txt";
|
---|
101 |
|
---|
102 | if (!TARGET_SUPPORTS_SMBLOCK(tctx))
|
---|
103 | torture_skip(tctx, "Target does not support the SMBlock PDU");
|
---|
104 |
|
---|
105 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
106 | return false;
|
---|
107 | }
|
---|
108 |
|
---|
109 | torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
|
---|
110 | io.generic.level = RAW_LOCK_LOCK;
|
---|
111 |
|
---|
112 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
113 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
114 | "Failed to create %s - %s\n",
|
---|
115 | fname, smbcli_errstr(cli->tree)));
|
---|
116 |
|
---|
117 | torture_comment(tctx, "Trying 0/0 lock\n");
|
---|
118 | io.lock.level = RAW_LOCK_LOCK;
|
---|
119 | io.lock.in.file.fnum = fnum;
|
---|
120 | io.lock.in.count = 0;
|
---|
121 | io.lock.in.offset = 0;
|
---|
122 | status = smb_raw_lock(cli->tree, &io);
|
---|
123 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
124 | cli->session->pid++;
|
---|
125 | status = smb_raw_lock(cli->tree, &io);
|
---|
126 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
127 | cli->session->pid--;
|
---|
128 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
129 | status = smb_raw_lock(cli->tree, &io);
|
---|
130 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
131 |
|
---|
132 | torture_comment(tctx, "Trying 0/1 lock\n");
|
---|
133 | io.lock.level = RAW_LOCK_LOCK;
|
---|
134 | io.lock.in.file.fnum = fnum;
|
---|
135 | io.lock.in.count = 1;
|
---|
136 | io.lock.in.offset = 0;
|
---|
137 | status = smb_raw_lock(cli->tree, &io);
|
---|
138 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
139 | cli->session->pid++;
|
---|
140 | status = smb_raw_lock(cli->tree, &io);
|
---|
141 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
142 | cli->session->pid--;
|
---|
143 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
144 | status = smb_raw_lock(cli->tree, &io);
|
---|
145 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
146 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
147 | status = smb_raw_lock(cli->tree, &io);
|
---|
148 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
149 |
|
---|
150 | torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
|
---|
151 | io.lock.level = RAW_LOCK_LOCK;
|
---|
152 | io.lock.in.file.fnum = fnum;
|
---|
153 | io.lock.in.count = 4000;
|
---|
154 | io.lock.in.offset = 0xEEFFFFFF;
|
---|
155 | status = smb_raw_lock(cli->tree, &io);
|
---|
156 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
157 | cli->session->pid++;
|
---|
158 | status = smb_raw_lock(cli->tree, &io);
|
---|
159 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
160 | cli->session->pid--;
|
---|
161 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
162 | status = smb_raw_lock(cli->tree, &io);
|
---|
163 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
164 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
165 | status = smb_raw_lock(cli->tree, &io);
|
---|
166 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
167 |
|
---|
168 | torture_comment(tctx, "Trying 0xEF000000 lock\n");
|
---|
169 | io.lock.level = RAW_LOCK_LOCK;
|
---|
170 | io.lock.in.file.fnum = fnum;
|
---|
171 | io.lock.in.count = 4000;
|
---|
172 | io.lock.in.offset = 0xEEFFFFFF;
|
---|
173 | status = smb_raw_lock(cli->tree, &io);
|
---|
174 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
175 | cli->session->pid++;
|
---|
176 | status = smb_raw_lock(cli->tree, &io);
|
---|
177 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
178 | cli->session->pid--;
|
---|
179 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
180 | status = smb_raw_lock(cli->tree, &io);
|
---|
181 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
182 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
183 | status = smb_raw_lock(cli->tree, &io);
|
---|
184 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
185 |
|
---|
186 | torture_comment(tctx, "Trying max lock\n");
|
---|
187 | io.lock.level = RAW_LOCK_LOCK;
|
---|
188 | io.lock.in.file.fnum = fnum;
|
---|
189 | io.lock.in.count = 4000;
|
---|
190 | io.lock.in.offset = 0xEF000000;
|
---|
191 | status = smb_raw_lock(cli->tree, &io);
|
---|
192 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
193 | cli->session->pid++;
|
---|
194 | status = smb_raw_lock(cli->tree, &io);
|
---|
195 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
196 | cli->session->pid--;
|
---|
197 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
198 | status = smb_raw_lock(cli->tree, &io);
|
---|
199 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
200 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
201 | status = smb_raw_lock(cli->tree, &io);
|
---|
202 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
203 |
|
---|
204 | torture_comment(tctx, "Trying wrong pid unlock\n");
|
---|
205 | io.lock.level = RAW_LOCK_LOCK;
|
---|
206 | io.lock.in.file.fnum = fnum;
|
---|
207 | io.lock.in.count = 4002;
|
---|
208 | io.lock.in.offset = 10001;
|
---|
209 | status = smb_raw_lock(cli->tree, &io);
|
---|
210 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
211 | cli->session->pid++;
|
---|
212 | io.lock.level = RAW_LOCK_UNLOCK;
|
---|
213 | status = smb_raw_lock(cli->tree, &io);
|
---|
214 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
215 | cli->session->pid--;
|
---|
216 | status = smb_raw_lock(cli->tree, &io);
|
---|
217 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
218 |
|
---|
219 | done:
|
---|
220 | smbcli_close(cli->tree, fnum);
|
---|
221 | smb_raw_exit(cli->session);
|
---|
222 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
223 | return ret;
|
---|
224 | }
|
---|
225 |
|
---|
226 |
|
---|
227 | /*
|
---|
228 | test locking&X ops
|
---|
229 | */
|
---|
230 | static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
|
---|
231 | {
|
---|
232 | union smb_lock io;
|
---|
233 | struct smb_lock_entry lock[1];
|
---|
234 | NTSTATUS status;
|
---|
235 | bool ret = true;
|
---|
236 | int fnum;
|
---|
237 | const char *fname = BASEDIR "\\test.txt";
|
---|
238 |
|
---|
239 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
240 | return false;
|
---|
241 | }
|
---|
242 |
|
---|
243 | torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
|
---|
244 | io.generic.level = RAW_LOCK_LOCKX;
|
---|
245 |
|
---|
246 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
247 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
248 | "Failed to create %s - %s\n",
|
---|
249 | fname, smbcli_errstr(cli->tree)));
|
---|
250 |
|
---|
251 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
252 | io.lockx.in.file.fnum = fnum;
|
---|
253 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
254 | io.lockx.in.timeout = 0;
|
---|
255 | io.lockx.in.ulock_cnt = 0;
|
---|
256 | io.lockx.in.lock_cnt = 1;
|
---|
257 | lock[0].pid = cli->session->pid;
|
---|
258 | lock[0].offset = 10;
|
---|
259 | lock[0].count = 1;
|
---|
260 | io.lockx.in.locks = &lock[0];
|
---|
261 | status = smb_raw_lock(cli->tree, &io);
|
---|
262 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
263 |
|
---|
264 |
|
---|
265 | torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
|
---|
266 | io.lockx.in.ulock_cnt = 0;
|
---|
267 | io.lockx.in.lock_cnt = 1;
|
---|
268 | lock[0].count = 4000;
|
---|
269 | lock[0].offset = 0xEEFFFFFF;
|
---|
270 | status = smb_raw_lock(cli->tree, &io);
|
---|
271 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
272 | lock[0].pid++;
|
---|
273 | status = smb_raw_lock(cli->tree, &io);
|
---|
274 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
275 | lock[0].pid--;
|
---|
276 | io.lockx.in.ulock_cnt = 1;
|
---|
277 | io.lockx.in.lock_cnt = 0;
|
---|
278 | status = smb_raw_lock(cli->tree, &io);
|
---|
279 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
280 | status = smb_raw_lock(cli->tree, &io);
|
---|
281 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
282 |
|
---|
283 | torture_comment(tctx, "Trying 0xEF000000 lock\n");
|
---|
284 | io.lockx.in.ulock_cnt = 0;
|
---|
285 | io.lockx.in.lock_cnt = 1;
|
---|
286 | lock[0].count = 4000;
|
---|
287 | lock[0].offset = 0xEF000000;
|
---|
288 | status = smb_raw_lock(cli->tree, &io);
|
---|
289 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
290 | lock[0].pid++;
|
---|
291 | status = smb_raw_lock(cli->tree, &io);
|
---|
292 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
293 | lock[0].pid--;
|
---|
294 | io.lockx.in.ulock_cnt = 1;
|
---|
295 | io.lockx.in.lock_cnt = 0;
|
---|
296 | status = smb_raw_lock(cli->tree, &io);
|
---|
297 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
298 | status = smb_raw_lock(cli->tree, &io);
|
---|
299 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
300 |
|
---|
301 | torture_comment(tctx, "Trying zero lock\n");
|
---|
302 | io.lockx.in.ulock_cnt = 0;
|
---|
303 | io.lockx.in.lock_cnt = 1;
|
---|
304 | lock[0].count = 0;
|
---|
305 | lock[0].offset = ~0;
|
---|
306 | status = smb_raw_lock(cli->tree, &io);
|
---|
307 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
308 | lock[0].pid++;
|
---|
309 | status = smb_raw_lock(cli->tree, &io);
|
---|
310 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
311 | lock[0].pid--;
|
---|
312 | io.lockx.in.ulock_cnt = 1;
|
---|
313 | io.lockx.in.lock_cnt = 0;
|
---|
314 | status = smb_raw_lock(cli->tree, &io);
|
---|
315 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
316 | status = smb_raw_lock(cli->tree, &io);
|
---|
317 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
318 |
|
---|
319 | torture_comment(tctx, "Trying max lock\n");
|
---|
320 | io.lockx.in.ulock_cnt = 0;
|
---|
321 | io.lockx.in.lock_cnt = 1;
|
---|
322 | lock[0].count = 0;
|
---|
323 | lock[0].offset = ~0;
|
---|
324 | status = smb_raw_lock(cli->tree, &io);
|
---|
325 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
326 | lock[0].pid++;
|
---|
327 | status = smb_raw_lock(cli->tree, &io);
|
---|
328 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
329 | lock[0].pid--;
|
---|
330 | io.lockx.in.ulock_cnt = 1;
|
---|
331 | io.lockx.in.lock_cnt = 0;
|
---|
332 | status = smb_raw_lock(cli->tree, &io);
|
---|
333 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
334 | status = smb_raw_lock(cli->tree, &io);
|
---|
335 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
336 |
|
---|
337 | torture_comment(tctx, "Trying 2^63\n");
|
---|
338 | io.lockx.in.ulock_cnt = 0;
|
---|
339 | io.lockx.in.lock_cnt = 1;
|
---|
340 | lock[0].count = 1;
|
---|
341 | lock[0].offset = 1;
|
---|
342 | lock[0].offset <<= 63;
|
---|
343 | status = smb_raw_lock(cli->tree, &io);
|
---|
344 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
345 | lock[0].pid++;
|
---|
346 | status = smb_raw_lock(cli->tree, &io);
|
---|
347 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
348 | lock[0].pid--;
|
---|
349 | io.lockx.in.ulock_cnt = 1;
|
---|
350 | io.lockx.in.lock_cnt = 0;
|
---|
351 | status = smb_raw_lock(cli->tree, &io);
|
---|
352 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
353 | status = smb_raw_lock(cli->tree, &io);
|
---|
354 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
355 |
|
---|
356 | torture_comment(tctx, "Trying 2^63 - 1\n");
|
---|
357 | io.lockx.in.ulock_cnt = 0;
|
---|
358 | io.lockx.in.lock_cnt = 1;
|
---|
359 | lock[0].count = 1;
|
---|
360 | lock[0].offset = 1;
|
---|
361 | lock[0].offset <<= 63;
|
---|
362 | lock[0].offset--;
|
---|
363 | status = smb_raw_lock(cli->tree, &io);
|
---|
364 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
365 | lock[0].pid++;
|
---|
366 | status = smb_raw_lock(cli->tree, &io);
|
---|
367 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
368 | lock[0].pid--;
|
---|
369 | io.lockx.in.ulock_cnt = 1;
|
---|
370 | io.lockx.in.lock_cnt = 0;
|
---|
371 | status = smb_raw_lock(cli->tree, &io);
|
---|
372 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
373 | status = smb_raw_lock(cli->tree, &io);
|
---|
374 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
375 |
|
---|
376 | torture_comment(tctx, "Trying max lock 2\n");
|
---|
377 | io.lockx.in.ulock_cnt = 0;
|
---|
378 | io.lockx.in.lock_cnt = 1;
|
---|
379 | lock[0].count = 1;
|
---|
380 | lock[0].offset = ~0;
|
---|
381 | status = smb_raw_lock(cli->tree, &io);
|
---|
382 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
383 | lock[0].pid++;
|
---|
384 | lock[0].count = 2;
|
---|
385 | status = smb_raw_lock(cli->tree, &io);
|
---|
386 | if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx))
|
---|
387 | CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
|
---|
388 | else
|
---|
389 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
390 | lock[0].pid--;
|
---|
391 | io.lockx.in.ulock_cnt = 1;
|
---|
392 | io.lockx.in.lock_cnt = 0;
|
---|
393 | lock[0].count = 1;
|
---|
394 | status = smb_raw_lock(cli->tree, &io);
|
---|
395 |
|
---|
396 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
397 | status = smb_raw_lock(cli->tree, &io);
|
---|
398 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
399 |
|
---|
400 | done:
|
---|
401 | smbcli_close(cli->tree, fnum);
|
---|
402 | smb_raw_exit(cli->session);
|
---|
403 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
404 | return ret;
|
---|
405 | }
|
---|
406 |
|
---|
407 | /*
|
---|
408 | test high pid
|
---|
409 | */
|
---|
410 | static bool test_pidhigh(struct torture_context *tctx,
|
---|
411 | struct smbcli_state *cli)
|
---|
412 | {
|
---|
413 | union smb_lock io;
|
---|
414 | struct smb_lock_entry lock[1];
|
---|
415 | NTSTATUS status;
|
---|
416 | bool ret = true;
|
---|
417 | int fnum;
|
---|
418 | const char *fname = BASEDIR "\\test.txt";
|
---|
419 | uint8_t c = 1;
|
---|
420 |
|
---|
421 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
422 | return false;
|
---|
423 | }
|
---|
424 |
|
---|
425 | torture_comment(tctx, "Testing high pid\n");
|
---|
426 | io.generic.level = RAW_LOCK_LOCKX;
|
---|
427 |
|
---|
428 | cli->session->pid = 1;
|
---|
429 |
|
---|
430 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
431 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
432 | "Failed to create %s - %s\n",
|
---|
433 | fname, smbcli_errstr(cli->tree)));
|
---|
434 |
|
---|
435 | if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
|
---|
436 | torture_result(tctx, TORTURE_FAIL,
|
---|
437 | "Failed to write 1 byte - %s\n",
|
---|
438 | smbcli_errstr(cli->tree));
|
---|
439 | ret = false;
|
---|
440 | goto done;
|
---|
441 | }
|
---|
442 |
|
---|
443 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
444 | io.lockx.in.file.fnum = fnum;
|
---|
445 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
446 | io.lockx.in.timeout = 0;
|
---|
447 | io.lockx.in.ulock_cnt = 0;
|
---|
448 | io.lockx.in.lock_cnt = 1;
|
---|
449 | lock[0].pid = cli->session->pid;
|
---|
450 | lock[0].offset = 0;
|
---|
451 | lock[0].count = 0xFFFFFFFF;
|
---|
452 | io.lockx.in.locks = &lock[0];
|
---|
453 | status = smb_raw_lock(cli->tree, &io);
|
---|
454 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
455 |
|
---|
456 | if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
|
---|
457 | torture_result(tctx, TORTURE_FAIL,
|
---|
458 | "Failed to read 1 byte - %s\n",
|
---|
459 | smbcli_errstr(cli->tree));
|
---|
460 | ret = false;
|
---|
461 | goto done;
|
---|
462 | }
|
---|
463 |
|
---|
464 | cli->session->pid = 2;
|
---|
465 |
|
---|
466 | if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
|
---|
467 | torture_result(tctx, TORTURE_FAIL,
|
---|
468 | "pid is incorrect handled for read with lock!\n");
|
---|
469 | ret = false;
|
---|
470 | goto done;
|
---|
471 | }
|
---|
472 |
|
---|
473 | cli->session->pid = 0x10001;
|
---|
474 |
|
---|
475 | if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
|
---|
476 | torture_result(tctx, TORTURE_FAIL,
|
---|
477 | "High pid is used on this server!\n");
|
---|
478 | ret = false;
|
---|
479 | } else {
|
---|
480 | torture_warning(tctx, "High pid is not used on this server (correct)\n");
|
---|
481 | }
|
---|
482 |
|
---|
483 | done:
|
---|
484 | smbcli_close(cli->tree, fnum);
|
---|
485 | smb_raw_exit(cli->session);
|
---|
486 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
487 | return ret;
|
---|
488 | }
|
---|
489 |
|
---|
490 |
|
---|
491 | /*
|
---|
492 | test locking&X async operation
|
---|
493 | */
|
---|
494 | static bool test_async(struct torture_context *tctx,
|
---|
495 | struct smbcli_state *cli)
|
---|
496 | {
|
---|
497 | struct smbcli_session *session;
|
---|
498 | struct smb_composite_sesssetup setup;
|
---|
499 | struct smbcli_tree *tree;
|
---|
500 | union smb_tcon tcon;
|
---|
501 | const char *host, *share;
|
---|
502 | union smb_lock io;
|
---|
503 | struct smb_lock_entry lock[2];
|
---|
504 | NTSTATUS status;
|
---|
505 | bool ret = true;
|
---|
506 | int fnum;
|
---|
507 | const char *fname = BASEDIR "\\test.txt";
|
---|
508 | time_t t;
|
---|
509 | struct smbcli_request *req, *req2;
|
---|
510 | struct smbcli_session_options options;
|
---|
511 |
|
---|
512 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
513 | return false;
|
---|
514 | }
|
---|
515 |
|
---|
516 | lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
|
---|
517 |
|
---|
518 | torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
|
---|
519 | io.generic.level = RAW_LOCK_LOCKX;
|
---|
520 |
|
---|
521 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
522 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
523 | "Failed to create %s - %s\n",
|
---|
524 | fname, smbcli_errstr(cli->tree)));
|
---|
525 |
|
---|
526 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
527 | io.lockx.in.file.fnum = fnum;
|
---|
528 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
529 | io.lockx.in.timeout = 0;
|
---|
530 | io.lockx.in.ulock_cnt = 0;
|
---|
531 | io.lockx.in.lock_cnt = 1;
|
---|
532 | lock[0].pid = cli->session->pid;
|
---|
533 | lock[0].offset = 100;
|
---|
534 | lock[0].count = 10;
|
---|
535 | lock[1].pid = cli->session->pid;
|
---|
536 | lock[1].offset = 110;
|
---|
537 | lock[1].count = 10;
|
---|
538 | io.lockx.in.locks = &lock[0];
|
---|
539 | status = smb_raw_lock(cli->tree, &io);
|
---|
540 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
541 |
|
---|
542 | t = time_mono(NULL);
|
---|
543 |
|
---|
544 | torture_comment(tctx, "Testing cancel by CANCEL_LOCK\n");
|
---|
545 |
|
---|
546 | /* setup a timed lock */
|
---|
547 | io.lockx.in.timeout = 10000;
|
---|
548 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
549 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
550 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
551 |
|
---|
552 | /* cancel the wrong range */
|
---|
553 | lock[0].offset = 0;
|
---|
554 | io.lockx.in.timeout = 0;
|
---|
555 | io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
|
---|
556 | status = smb_raw_lock(cli->tree, &io);
|
---|
557 | CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
|
---|
558 |
|
---|
559 | /* cancel with the wrong bits set */
|
---|
560 | lock[0].offset = 100;
|
---|
561 | io.lockx.in.timeout = 0;
|
---|
562 | io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
|
---|
563 | status = smb_raw_lock(cli->tree, &io);
|
---|
564 | CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
|
---|
565 |
|
---|
566 | /* cancel the right range */
|
---|
567 | lock[0].offset = 100;
|
---|
568 | io.lockx.in.timeout = 0;
|
---|
569 | io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
|
---|
570 | status = smb_raw_lock(cli->tree, &io);
|
---|
571 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
572 |
|
---|
573 | /* receive the failed lock request */
|
---|
574 | status = smbcli_request_simple_recv(req);
|
---|
575 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
576 |
|
---|
577 | torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
|
---|
578 | "lock cancel was not immediate (%s)\n", __location__));
|
---|
579 |
|
---|
580 | /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
|
---|
581 | * if the lock vector contains one entry. When given mutliple cancel
|
---|
582 | * requests in a single PDU we expect the server to return an
|
---|
583 | * error. Samba4 handles this correctly. Windows servers seem to
|
---|
584 | * accept the request but only cancel the first lock. Samba3
|
---|
585 | * now does what Windows does (JRA).
|
---|
586 | */
|
---|
587 | torture_comment(tctx, "Testing multiple cancel\n");
|
---|
588 |
|
---|
589 | /* acquire second lock */
|
---|
590 | io.lockx.in.timeout = 0;
|
---|
591 | io.lockx.in.ulock_cnt = 0;
|
---|
592 | io.lockx.in.lock_cnt = 1;
|
---|
593 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
594 | io.lockx.in.locks = &lock[1];
|
---|
595 | status = smb_raw_lock(cli->tree, &io);
|
---|
596 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
597 |
|
---|
598 | /* setup 2 timed locks */
|
---|
599 | t = time_mono(NULL);
|
---|
600 | io.lockx.in.timeout = 10000;
|
---|
601 | io.lockx.in.lock_cnt = 1;
|
---|
602 | io.lockx.in.locks = &lock[0];
|
---|
603 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
604 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
605 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
606 | io.lockx.in.locks = &lock[1];
|
---|
607 | req2 = smb_raw_lock_send(cli->tree, &io);
|
---|
608 | torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
|
---|
609 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
610 |
|
---|
611 | /* try to cancel both locks in the same packet */
|
---|
612 | io.lockx.in.timeout = 0;
|
---|
613 | io.lockx.in.lock_cnt = 2;
|
---|
614 | io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
|
---|
615 | io.lockx.in.locks = lock;
|
---|
616 | status = smb_raw_lock(cli->tree, &io);
|
---|
617 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
618 |
|
---|
619 | torture_warning(tctx, "Target server accepted a lock cancel "
|
---|
620 | "request with multiple locks. This violates "
|
---|
621 | "MS-CIFS 2.2.4.32.1.\n");
|
---|
622 |
|
---|
623 | /* receive the failed lock requests */
|
---|
624 | status = smbcli_request_simple_recv(req);
|
---|
625 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
626 |
|
---|
627 | torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
|
---|
628 | "first lock was not cancelled immediately (%s)\n",
|
---|
629 | __location__));
|
---|
630 |
|
---|
631 | /* send cancel to second lock */
|
---|
632 | io.lockx.in.timeout = 0;
|
---|
633 | io.lockx.in.lock_cnt = 1;
|
---|
634 | io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK |
|
---|
635 | LOCKING_ANDX_LARGE_FILES;
|
---|
636 | io.lockx.in.locks = &lock[1];
|
---|
637 | status = smb_raw_lock(cli->tree, &io);
|
---|
638 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
639 |
|
---|
640 | status = smbcli_request_simple_recv(req2);
|
---|
641 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
642 |
|
---|
643 | torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
|
---|
644 | "second lock was not cancelled immediately (%s)\n",
|
---|
645 | __location__));
|
---|
646 |
|
---|
647 | /* cleanup the second lock */
|
---|
648 | io.lockx.in.ulock_cnt = 1;
|
---|
649 | io.lockx.in.lock_cnt = 0;
|
---|
650 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
651 | io.lockx.in.locks = &lock[1];
|
---|
652 | status = smb_raw_lock(cli->tree, &io);
|
---|
653 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
654 |
|
---|
655 | /* If a lock request contained multiple ranges and we are cancelling
|
---|
656 | * one while it's still pending, what happens? */
|
---|
657 | torture_comment(tctx, "Testing cancel 1/2 lock request\n");
|
---|
658 |
|
---|
659 | /* Send request with two ranges */
|
---|
660 | io.lockx.in.timeout = -1;
|
---|
661 | io.lockx.in.ulock_cnt = 0;
|
---|
662 | io.lockx.in.lock_cnt = 2;
|
---|
663 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
664 | io.lockx.in.locks = lock;
|
---|
665 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
666 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
667 | "Failed to setup pending lock (%s)\n", __location__));
|
---|
668 |
|
---|
669 | /* Try to cancel the first lock range */
|
---|
670 | io.lockx.in.timeout = 0;
|
---|
671 | io.lockx.in.lock_cnt = 1;
|
---|
672 | io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
|
---|
673 | io.lockx.in.locks = &lock[0];
|
---|
674 | status = smb_raw_lock(cli->tree, &io);
|
---|
675 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
676 |
|
---|
677 | /* Locking request should've failed and second range should be
|
---|
678 | * unlocked */
|
---|
679 | status = smbcli_request_simple_recv(req);
|
---|
680 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
681 |
|
---|
682 | io.lockx.in.timeout = 0;
|
---|
683 | io.lockx.in.ulock_cnt = 0;
|
---|
684 | io.lockx.in.lock_cnt = 1;
|
---|
685 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
686 | io.lockx.in.locks = &lock[1];
|
---|
687 | status = smb_raw_lock(cli->tree, &io);
|
---|
688 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
689 |
|
---|
690 | /* Cleanup both locks */
|
---|
691 | io.lockx.in.ulock_cnt = 2;
|
---|
692 | io.lockx.in.lock_cnt = 0;
|
---|
693 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
694 | io.lockx.in.locks = lock;
|
---|
695 | status = smb_raw_lock(cli->tree, &io);
|
---|
696 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
697 |
|
---|
698 | torture_comment(tctx, "Testing cancel 2/2 lock request\n");
|
---|
699 |
|
---|
700 | /* Lock second range so it contends */
|
---|
701 | io.lockx.in.timeout = 0;
|
---|
702 | io.lockx.in.ulock_cnt = 0;
|
---|
703 | io.lockx.in.lock_cnt = 1;
|
---|
704 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
705 | io.lockx.in.locks = &lock[1];
|
---|
706 | status = smb_raw_lock(cli->tree, &io);
|
---|
707 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
708 |
|
---|
709 | /* Send request with two ranges */
|
---|
710 | io.lockx.in.timeout = -1;
|
---|
711 | io.lockx.in.ulock_cnt = 0;
|
---|
712 | io.lockx.in.lock_cnt = 2;
|
---|
713 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
714 | io.lockx.in.locks = lock;
|
---|
715 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
716 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
717 | "Failed to setup pending lock (%s)\n", __location__));
|
---|
718 |
|
---|
719 | /* Try to cancel the second lock range */
|
---|
720 | io.lockx.in.timeout = 0;
|
---|
721 | io.lockx.in.lock_cnt = 1;
|
---|
722 | io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
|
---|
723 | io.lockx.in.locks = &lock[1];
|
---|
724 | status = smb_raw_lock(cli->tree, &io);
|
---|
725 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
726 |
|
---|
727 | /* Locking request should've failed and first range should be
|
---|
728 | * unlocked */
|
---|
729 | status = smbcli_request_simple_recv(req);
|
---|
730 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
731 |
|
---|
732 | io.lockx.in.timeout = 0;
|
---|
733 | io.lockx.in.ulock_cnt = 0;
|
---|
734 | io.lockx.in.lock_cnt = 1;
|
---|
735 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
736 | io.lockx.in.locks = &lock[0];
|
---|
737 | status = smb_raw_lock(cli->tree, &io);
|
---|
738 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
739 |
|
---|
740 | /* Cleanup both locks */
|
---|
741 | io.lockx.in.ulock_cnt = 2;
|
---|
742 | io.lockx.in.lock_cnt = 0;
|
---|
743 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
744 | io.lockx.in.locks = lock;
|
---|
745 | status = smb_raw_lock(cli->tree, &io);
|
---|
746 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
747 |
|
---|
748 | torture_comment(tctx, "Testing cancel by unlock\n");
|
---|
749 | io.lockx.in.ulock_cnt = 0;
|
---|
750 | io.lockx.in.lock_cnt = 1;
|
---|
751 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
752 | io.lockx.in.timeout = 0;
|
---|
753 | io.lockx.in.locks = &lock[0];
|
---|
754 | status = smb_raw_lock(cli->tree, &io);
|
---|
755 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
756 |
|
---|
757 | io.lockx.in.timeout = 5000;
|
---|
758 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
759 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
760 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
761 |
|
---|
762 | io.lockx.in.ulock_cnt = 1;
|
---|
763 | io.lockx.in.lock_cnt = 0;
|
---|
764 | status = smb_raw_lock(cli->tree, &io);
|
---|
765 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
766 |
|
---|
767 | t = time_mono(NULL);
|
---|
768 | status = smbcli_request_simple_recv(req);
|
---|
769 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
770 |
|
---|
771 | torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
|
---|
772 | "lock cancel by unlock was not immediate (%s) - took %d secs\n",
|
---|
773 | __location__, (int)(time_mono(NULL)-t)));
|
---|
774 |
|
---|
775 | torture_comment(tctx, "Testing cancel by close\n");
|
---|
776 | io.lockx.in.ulock_cnt = 0;
|
---|
777 | io.lockx.in.lock_cnt = 1;
|
---|
778 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
779 | io.lockx.in.timeout = 0;
|
---|
780 | status = smb_raw_lock(cli->tree, &io);
|
---|
781 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
782 |
|
---|
783 | t = time_mono(NULL);
|
---|
784 | io.lockx.in.timeout = 10000;
|
---|
785 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
786 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
787 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
788 |
|
---|
789 | status = smbcli_close(cli->tree, fnum);
|
---|
790 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
791 |
|
---|
792 | status = smbcli_request_simple_recv(req);
|
---|
793 | if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
|
---|
794 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
795 | else
|
---|
796 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
797 |
|
---|
798 | torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
|
---|
799 | "lock cancel by close was not immediate (%s)\n", __location__));
|
---|
800 |
|
---|
801 | torture_comment(tctx, "create a new sessions\n");
|
---|
802 | session = smbcli_session_init(cli->transport, tctx, false, options);
|
---|
803 | setup.in.sesskey = cli->transport->negotiate.sesskey;
|
---|
804 | setup.in.capabilities = cli->transport->negotiate.capabilities;
|
---|
805 | setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
|
---|
806 | setup.in.credentials = cmdline_credentials;
|
---|
807 | setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
|
---|
808 | status = smb_composite_sesssetup(session, &setup);
|
---|
809 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
810 | session->vuid = setup.out.vuid;
|
---|
811 |
|
---|
812 | torture_comment(tctx, "create new tree context\n");
|
---|
813 | share = torture_setting_string(tctx, "share", NULL);
|
---|
814 | host = torture_setting_string(tctx, "host", NULL);
|
---|
815 | tree = smbcli_tree_init(session, tctx, false);
|
---|
816 | tcon.generic.level = RAW_TCON_TCONX;
|
---|
817 | tcon.tconx.in.flags = 0;
|
---|
818 | tcon.tconx.in.password = data_blob(NULL, 0);
|
---|
819 | tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
|
---|
820 | tcon.tconx.in.device = "A:";
|
---|
821 | status = smb_raw_tcon(tree, tctx, &tcon);
|
---|
822 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
823 | tree->tid = tcon.tconx.out.tid;
|
---|
824 |
|
---|
825 | torture_comment(tctx, "Testing cancel by exit\n");
|
---|
826 | if (TARGET_SUPPORTS_SMBEXIT(tctx)) {
|
---|
827 | fname = BASEDIR "\\test_exit.txt";
|
---|
828 | fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
829 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
830 | "Failed to reopen %s - %s\n",
|
---|
831 | fname, smbcli_errstr(tree)));
|
---|
832 |
|
---|
833 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
834 | io.lockx.in.file.fnum = fnum;
|
---|
835 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
836 | io.lockx.in.timeout = 0;
|
---|
837 | io.lockx.in.ulock_cnt = 0;
|
---|
838 | io.lockx.in.lock_cnt = 1;
|
---|
839 | lock[0].pid = session->pid;
|
---|
840 | lock[0].offset = 100;
|
---|
841 | lock[0].count = 10;
|
---|
842 | io.lockx.in.locks = &lock[0];
|
---|
843 | status = smb_raw_lock(tree, &io);
|
---|
844 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
845 |
|
---|
846 | io.lockx.in.ulock_cnt = 0;
|
---|
847 | io.lockx.in.lock_cnt = 1;
|
---|
848 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
849 | io.lockx.in.timeout = 0;
|
---|
850 | status = smb_raw_lock(tree, &io);
|
---|
851 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
852 |
|
---|
853 | io.lockx.in.timeout = 10000;
|
---|
854 | t = time_mono(NULL);
|
---|
855 | req = smb_raw_lock_send(tree, &io);
|
---|
856 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
857 | "Failed to setup timed lock (%s)\n",
|
---|
858 | __location__));
|
---|
859 |
|
---|
860 | status = smb_raw_exit(session);
|
---|
861 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
862 |
|
---|
863 | status = smbcli_request_simple_recv(req);
|
---|
864 | if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
|
---|
865 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
866 | else
|
---|
867 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
868 |
|
---|
869 | torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
|
---|
870 | "lock cancel by exit was not immediate (%s)\n",
|
---|
871 | __location__));
|
---|
872 | }
|
---|
873 | else {
|
---|
874 | torture_comment(tctx,
|
---|
875 | " skipping test, SMBExit not supported\n");
|
---|
876 | }
|
---|
877 |
|
---|
878 | torture_comment(tctx, "Testing cancel by ulogoff\n");
|
---|
879 | fname = BASEDIR "\\test_ulogoff.txt";
|
---|
880 | fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
881 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
882 | "Failed to reopen %s - %s\n",
|
---|
883 | fname, smbcli_errstr(tree)));
|
---|
884 |
|
---|
885 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
886 | io.lockx.in.file.fnum = fnum;
|
---|
887 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
888 | io.lockx.in.timeout = 0;
|
---|
889 | io.lockx.in.ulock_cnt = 0;
|
---|
890 | io.lockx.in.lock_cnt = 1;
|
---|
891 | lock[0].pid = session->pid;
|
---|
892 | lock[0].offset = 100;
|
---|
893 | lock[0].count = 10;
|
---|
894 | io.lockx.in.locks = &lock[0];
|
---|
895 | status = smb_raw_lock(tree, &io);
|
---|
896 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
897 |
|
---|
898 | io.lockx.in.ulock_cnt = 0;
|
---|
899 | io.lockx.in.lock_cnt = 1;
|
---|
900 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
901 | io.lockx.in.timeout = 0;
|
---|
902 | status = smb_raw_lock(tree, &io);
|
---|
903 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
904 |
|
---|
905 | io.lockx.in.timeout = 10000;
|
---|
906 | t = time_mono(NULL);
|
---|
907 | req = smb_raw_lock_send(tree, &io);
|
---|
908 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
909 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
910 |
|
---|
911 | status = smb_raw_ulogoff(session);
|
---|
912 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
913 |
|
---|
914 | status = smbcli_request_simple_recv(req);
|
---|
915 | if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) {
|
---|
916 | if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
|
---|
917 | torture_result(tctx, TORTURE_FAIL,
|
---|
918 | "lock not canceled by ulogoff - %s "
|
---|
919 | "(ignored because of vfs_vifs fails it)\n",
|
---|
920 | nt_errstr(status));
|
---|
921 | smb_tree_disconnect(tree);
|
---|
922 | smb_raw_exit(session);
|
---|
923 | goto done;
|
---|
924 | }
|
---|
925 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
926 | } else {
|
---|
927 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
928 | }
|
---|
929 |
|
---|
930 | torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
|
---|
931 | "lock cancel by ulogoff was not immediate (%s)\n", __location__));
|
---|
932 |
|
---|
933 | torture_comment(tctx, "Testing cancel by tdis\n");
|
---|
934 | tree->session = cli->session;
|
---|
935 |
|
---|
936 | fname = BASEDIR "\\test_tdis.txt";
|
---|
937 | fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
938 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
939 | "Failed to reopen %s - %s\n",
|
---|
940 | fname, smbcli_errstr(tree)));
|
---|
941 |
|
---|
942 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
943 | io.lockx.in.file.fnum = fnum;
|
---|
944 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
945 | io.lockx.in.timeout = 0;
|
---|
946 | io.lockx.in.ulock_cnt = 0;
|
---|
947 | io.lockx.in.lock_cnt = 1;
|
---|
948 | lock[0].pid = cli->session->pid;
|
---|
949 | lock[0].offset = 100;
|
---|
950 | lock[0].count = 10;
|
---|
951 | io.lockx.in.locks = &lock[0];
|
---|
952 | status = smb_raw_lock(tree, &io);
|
---|
953 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
954 |
|
---|
955 | status = smb_raw_lock(tree, &io);
|
---|
956 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
957 |
|
---|
958 | io.lockx.in.timeout = 10000;
|
---|
959 | t = time_mono(NULL);
|
---|
960 | req = smb_raw_lock_send(tree, &io);
|
---|
961 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
962 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
963 |
|
---|
964 | status = smb_tree_disconnect(tree);
|
---|
965 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
966 |
|
---|
967 | status = smbcli_request_simple_recv(req);
|
---|
968 | if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
|
---|
969 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
970 | else
|
---|
971 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
972 |
|
---|
973 | torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
|
---|
974 | "lock cancel by tdis was not immediate (%s)\n", __location__));
|
---|
975 |
|
---|
976 | done:
|
---|
977 | smb_raw_exit(cli->session);
|
---|
978 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
979 | return ret;
|
---|
980 | }
|
---|
981 |
|
---|
982 | /*
|
---|
983 | test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
|
---|
984 | */
|
---|
985 | static bool test_errorcode(struct torture_context *tctx,
|
---|
986 | struct smbcli_state *cli)
|
---|
987 | {
|
---|
988 | union smb_lock io;
|
---|
989 | union smb_open op;
|
---|
990 | struct smb_lock_entry lock[2];
|
---|
991 | NTSTATUS status;
|
---|
992 | bool ret = true;
|
---|
993 | int fnum, fnum2;
|
---|
994 | const char *fname;
|
---|
995 | struct smbcli_request *req;
|
---|
996 | time_t start;
|
---|
997 | int t;
|
---|
998 | int delay;
|
---|
999 | uint16_t deny_mode = 0;
|
---|
1000 |
|
---|
1001 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1002 | return false;
|
---|
1003 | }
|
---|
1004 |
|
---|
1005 | torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
|
---|
1006 |
|
---|
1007 | torture_comment(tctx, "Testing with timeout = 0\n");
|
---|
1008 | fname = BASEDIR "\\test0.txt";
|
---|
1009 | t = 0;
|
---|
1010 |
|
---|
1011 | /*
|
---|
1012 | * the first run is with t = 0,
|
---|
1013 | * the second with t > 0 (=1)
|
---|
1014 | */
|
---|
1015 | next_run:
|
---|
1016 | /*
|
---|
1017 | * use the DENY_DOS mode, that creates two fnum's of one low-level
|
---|
1018 | * file handle, this demonstrates that the cache is per fnum, not
|
---|
1019 | * per file handle
|
---|
1020 | */
|
---|
1021 | if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx))
|
---|
1022 | deny_mode = OPENX_MODE_DENY_DOS;
|
---|
1023 | else
|
---|
1024 | deny_mode = OPENX_MODE_DENY_NONE;
|
---|
1025 |
|
---|
1026 | op.openx.level = RAW_OPEN_OPENX;
|
---|
1027 | op.openx.in.fname = fname;
|
---|
1028 | op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
|
---|
1029 | op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | deny_mode;
|
---|
1030 | op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
|
---|
1031 | op.openx.in.search_attrs = 0;
|
---|
1032 | op.openx.in.file_attrs = 0;
|
---|
1033 | op.openx.in.write_time = 0;
|
---|
1034 | op.openx.in.size = 0;
|
---|
1035 | op.openx.in.timeout = 0;
|
---|
1036 |
|
---|
1037 | status = smb_raw_open(cli->tree, tctx, &op);
|
---|
1038 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1039 | fnum = op.openx.out.file.fnum;
|
---|
1040 |
|
---|
1041 | status = smb_raw_open(cli->tree, tctx, &op);
|
---|
1042 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1043 | fnum2 = op.openx.out.file.fnum;
|
---|
1044 |
|
---|
1045 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
1046 | io.lockx.in.file.fnum = fnum;
|
---|
1047 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
1048 | io.lockx.in.timeout = t;
|
---|
1049 | io.lockx.in.ulock_cnt = 0;
|
---|
1050 | io.lockx.in.lock_cnt = 1;
|
---|
1051 | lock[0].pid = cli->session->pid;
|
---|
1052 | lock[0].offset = 100;
|
---|
1053 | lock[0].count = 10;
|
---|
1054 | io.lockx.in.locks = &lock[0];
|
---|
1055 | status = smb_raw_lock(cli->tree, &io);
|
---|
1056 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1057 |
|
---|
1058 | /*
|
---|
1059 | * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
|
---|
1060 | * this also demonstrates that the error code cache is per file handle
|
---|
1061 | * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
|
---|
1062 | */
|
---|
1063 | io.lockx.in.file.fnum = fnum2;
|
---|
1064 | status = smb_raw_lock(cli->tree, &io);
|
---|
1065 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1066 |
|
---|
1067 | io.lockx.in.file.fnum = fnum;
|
---|
1068 | status = smb_raw_lock(cli->tree, &io);
|
---|
1069 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1070 |
|
---|
1071 | /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
|
---|
1072 | io.lockx.in.file.fnum = fnum;
|
---|
1073 | status = smb_raw_lock(cli->tree, &io);
|
---|
1074 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1075 |
|
---|
1076 | io.lockx.in.file.fnum = fnum2;
|
---|
1077 | status = smb_raw_lock(cli->tree, &io);
|
---|
1078 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1079 |
|
---|
1080 | io.lockx.in.file.fnum = fnum;
|
---|
1081 | status = smb_raw_lock(cli->tree, &io);
|
---|
1082 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1083 |
|
---|
1084 | io.lockx.in.file.fnum = fnum2;
|
---|
1085 | status = smb_raw_lock(cli->tree, &io);
|
---|
1086 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1087 |
|
---|
1088 | /* demonstrate that the smbpid doesn't matter */
|
---|
1089 | lock[0].pid++;
|
---|
1090 | io.lockx.in.file.fnum = fnum;
|
---|
1091 | status = smb_raw_lock(cli->tree, &io);
|
---|
1092 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1093 |
|
---|
1094 | io.lockx.in.file.fnum = fnum2;
|
---|
1095 | status = smb_raw_lock(cli->tree, &io);
|
---|
1096 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1097 | lock[0].pid--;
|
---|
1098 |
|
---|
1099 | /*
|
---|
1100 | * demonstrate the a successful lock with count = 0 and the same offset,
|
---|
1101 | * doesn't reset the error cache
|
---|
1102 | */
|
---|
1103 | lock[0].offset = 100;
|
---|
1104 | lock[0].count = 0;
|
---|
1105 | io.lockx.in.file.fnum = fnum;
|
---|
1106 | status = smb_raw_lock(cli->tree, &io);
|
---|
1107 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1108 |
|
---|
1109 | io.lockx.in.file.fnum = fnum2;
|
---|
1110 | status = smb_raw_lock(cli->tree, &io);
|
---|
1111 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1112 |
|
---|
1113 | lock[0].offset = 100;
|
---|
1114 | lock[0].count = 10;
|
---|
1115 | io.lockx.in.file.fnum = fnum;
|
---|
1116 | status = smb_raw_lock(cli->tree, &io);
|
---|
1117 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1118 |
|
---|
1119 | io.lockx.in.file.fnum = fnum2;
|
---|
1120 | status = smb_raw_lock(cli->tree, &io);
|
---|
1121 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1122 |
|
---|
1123 | /*
|
---|
1124 | * demonstrate the a successful lock with count = 0 and outside the locked range,
|
---|
1125 | * doesn't reset the error cache
|
---|
1126 | */
|
---|
1127 | lock[0].offset = 110;
|
---|
1128 | lock[0].count = 0;
|
---|
1129 | io.lockx.in.file.fnum = fnum;
|
---|
1130 | status = smb_raw_lock(cli->tree, &io);
|
---|
1131 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1132 |
|
---|
1133 | io.lockx.in.file.fnum = fnum2;
|
---|
1134 | status = smb_raw_lock(cli->tree, &io);
|
---|
1135 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1136 |
|
---|
1137 | lock[0].offset = 100;
|
---|
1138 | lock[0].count = 10;
|
---|
1139 | io.lockx.in.file.fnum = fnum;
|
---|
1140 | status = smb_raw_lock(cli->tree, &io);
|
---|
1141 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1142 |
|
---|
1143 | io.lockx.in.file.fnum = fnum2;
|
---|
1144 | status = smb_raw_lock(cli->tree, &io);
|
---|
1145 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1146 |
|
---|
1147 | lock[0].offset = 99;
|
---|
1148 | lock[0].count = 0;
|
---|
1149 | io.lockx.in.file.fnum = fnum;
|
---|
1150 | status = smb_raw_lock(cli->tree, &io);
|
---|
1151 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1152 |
|
---|
1153 | io.lockx.in.file.fnum = fnum2;
|
---|
1154 | status = smb_raw_lock(cli->tree, &io);
|
---|
1155 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1156 |
|
---|
1157 | lock[0].offset = 100;
|
---|
1158 | lock[0].count = 10;
|
---|
1159 | io.lockx.in.file.fnum = fnum;
|
---|
1160 | status = smb_raw_lock(cli->tree, &io);
|
---|
1161 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1162 |
|
---|
1163 | io.lockx.in.file.fnum = fnum2;
|
---|
1164 | status = smb_raw_lock(cli->tree, &io);
|
---|
1165 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1166 |
|
---|
1167 | /* demonstrate that a changing count doesn't reset the error cache */
|
---|
1168 | lock[0].offset = 100;
|
---|
1169 | lock[0].count = 5;
|
---|
1170 | io.lockx.in.file.fnum = fnum;
|
---|
1171 | status = smb_raw_lock(cli->tree, &io);
|
---|
1172 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1173 |
|
---|
1174 | io.lockx.in.file.fnum = fnum2;
|
---|
1175 | status = smb_raw_lock(cli->tree, &io);
|
---|
1176 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1177 |
|
---|
1178 | lock[0].offset = 100;
|
---|
1179 | lock[0].count = 15;
|
---|
1180 | io.lockx.in.file.fnum = fnum;
|
---|
1181 | status = smb_raw_lock(cli->tree, &io);
|
---|
1182 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1183 |
|
---|
1184 | io.lockx.in.file.fnum = fnum2;
|
---|
1185 | status = smb_raw_lock(cli->tree, &io);
|
---|
1186 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1187 |
|
---|
1188 | /*
|
---|
1189 | * demonstrate the a lock with count = 0 and inside the locked range,
|
---|
1190 | * fails and resets the error cache
|
---|
1191 | */
|
---|
1192 | lock[0].offset = 101;
|
---|
1193 | lock[0].count = 0;
|
---|
1194 | io.lockx.in.file.fnum = fnum;
|
---|
1195 | status = smb_raw_lock(cli->tree, &io);
|
---|
1196 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1197 | status = smb_raw_lock(cli->tree, &io);
|
---|
1198 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1199 |
|
---|
1200 | io.lockx.in.file.fnum = fnum2;
|
---|
1201 | status = smb_raw_lock(cli->tree, &io);
|
---|
1202 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1203 | status = smb_raw_lock(cli->tree, &io);
|
---|
1204 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1205 |
|
---|
1206 | lock[0].offset = 100;
|
---|
1207 | lock[0].count = 10;
|
---|
1208 | io.lockx.in.file.fnum = fnum;
|
---|
1209 | status = smb_raw_lock(cli->tree, &io);
|
---|
1210 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1211 | status = smb_raw_lock(cli->tree, &io);
|
---|
1212 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1213 |
|
---|
1214 | io.lockx.in.file.fnum = fnum2;
|
---|
1215 | status = smb_raw_lock(cli->tree, &io);
|
---|
1216 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1217 | status = smb_raw_lock(cli->tree, &io);
|
---|
1218 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1219 |
|
---|
1220 | /* demonstrate the a changing offset, resets the error cache */
|
---|
1221 | lock[0].offset = 105;
|
---|
1222 | lock[0].count = 10;
|
---|
1223 | io.lockx.in.file.fnum = fnum;
|
---|
1224 | status = smb_raw_lock(cli->tree, &io);
|
---|
1225 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1226 | status = smb_raw_lock(cli->tree, &io);
|
---|
1227 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1228 |
|
---|
1229 | io.lockx.in.file.fnum = fnum2;
|
---|
1230 | status = smb_raw_lock(cli->tree, &io);
|
---|
1231 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1232 | status = smb_raw_lock(cli->tree, &io);
|
---|
1233 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1234 |
|
---|
1235 | lock[0].offset = 100;
|
---|
1236 | lock[0].count = 10;
|
---|
1237 | io.lockx.in.file.fnum = fnum;
|
---|
1238 | status = smb_raw_lock(cli->tree, &io);
|
---|
1239 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1240 | status = smb_raw_lock(cli->tree, &io);
|
---|
1241 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1242 |
|
---|
1243 | io.lockx.in.file.fnum = fnum2;
|
---|
1244 | status = smb_raw_lock(cli->tree, &io);
|
---|
1245 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1246 | status = smb_raw_lock(cli->tree, &io);
|
---|
1247 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1248 |
|
---|
1249 | lock[0].offset = 95;
|
---|
1250 | lock[0].count = 9;
|
---|
1251 | io.lockx.in.file.fnum = fnum;
|
---|
1252 | status = smb_raw_lock(cli->tree, &io);
|
---|
1253 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1254 | status = smb_raw_lock(cli->tree, &io);
|
---|
1255 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1256 |
|
---|
1257 | io.lockx.in.file.fnum = fnum2;
|
---|
1258 | status = smb_raw_lock(cli->tree, &io);
|
---|
1259 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1260 | status = smb_raw_lock(cli->tree, &io);
|
---|
1261 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1262 |
|
---|
1263 | lock[0].offset = 100;
|
---|
1264 | lock[0].count = 10;
|
---|
1265 | io.lockx.in.file.fnum = fnum;
|
---|
1266 | status = smb_raw_lock(cli->tree, &io);
|
---|
1267 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1268 | status = smb_raw_lock(cli->tree, &io);
|
---|
1269 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1270 |
|
---|
1271 | io.lockx.in.file.fnum = fnum2;
|
---|
1272 | status = smb_raw_lock(cli->tree, &io);
|
---|
1273 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1274 | status = smb_raw_lock(cli->tree, &io);
|
---|
1275 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1276 |
|
---|
1277 | /*
|
---|
1278 | * demonstrate the a successful lock in a different range,
|
---|
1279 | * doesn't reset the cache, the failing lock on the 2nd handle
|
---|
1280 | * resets the cache
|
---|
1281 | */
|
---|
1282 | lock[0].offset = 120;
|
---|
1283 | lock[0].count = 15;
|
---|
1284 | io.lockx.in.file.fnum = fnum;
|
---|
1285 | status = smb_raw_lock(cli->tree, &io);
|
---|
1286 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1287 |
|
---|
1288 | io.lockx.in.file.fnum = fnum2;
|
---|
1289 | status = smb_raw_lock(cli->tree, &io);
|
---|
1290 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1291 |
|
---|
1292 | lock[0].offset = 100;
|
---|
1293 | lock[0].count = 10;
|
---|
1294 | io.lockx.in.file.fnum = fnum;
|
---|
1295 | status = smb_raw_lock(cli->tree, &io);
|
---|
1296 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1297 | status = smb_raw_lock(cli->tree, &io);
|
---|
1298 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1299 |
|
---|
1300 | io.lockx.in.file.fnum = fnum2;
|
---|
1301 | status = smb_raw_lock(cli->tree, &io);
|
---|
1302 | CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
|
---|
1303 | status = smb_raw_lock(cli->tree, &io);
|
---|
1304 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1305 |
|
---|
1306 | /* end of the loop */
|
---|
1307 | if (t == 0) {
|
---|
1308 | smb_raw_exit(cli->session);
|
---|
1309 | t = 1;
|
---|
1310 | torture_comment(tctx, "Testing with timeout > 0 (=%d)\n",
|
---|
1311 | t);
|
---|
1312 | fname = BASEDIR "\\test1.txt";
|
---|
1313 | goto next_run;
|
---|
1314 | }
|
---|
1315 |
|
---|
1316 | t = 4000;
|
---|
1317 | torture_comment(tctx, "Testing special cases with timeout > 0 (=%d)\n",
|
---|
1318 | t);
|
---|
1319 |
|
---|
1320 | /*
|
---|
1321 | * the following 3 test sections demonstrate that
|
---|
1322 | * the cache is only set when the error is reported
|
---|
1323 | * to the client (after the timeout went by)
|
---|
1324 | */
|
---|
1325 | smb_raw_exit(cli->session);
|
---|
1326 | torture_comment(tctx, "Testing a conflict while a lock is pending\n");
|
---|
1327 | fname = BASEDIR "\\test2.txt";
|
---|
1328 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
1329 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
1330 | "Failed to reopen %s - %s\n",
|
---|
1331 | fname, smbcli_errstr(cli->tree)));
|
---|
1332 |
|
---|
1333 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
1334 | io.lockx.in.file.fnum = fnum;
|
---|
1335 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
1336 | io.lockx.in.timeout = 0;
|
---|
1337 | io.lockx.in.ulock_cnt = 0;
|
---|
1338 | io.lockx.in.lock_cnt = 1;
|
---|
1339 | lock[0].pid = cli->session->pid;
|
---|
1340 | lock[0].offset = 100;
|
---|
1341 | lock[0].count = 10;
|
---|
1342 | io.lockx.in.locks = &lock[0];
|
---|
1343 | status = smb_raw_lock(cli->tree, &io);
|
---|
1344 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1345 |
|
---|
1346 | start = time_mono(NULL);
|
---|
1347 | io.lockx.in.timeout = t;
|
---|
1348 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
1349 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
1350 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
1351 |
|
---|
1352 | io.lockx.in.timeout = 0;
|
---|
1353 | lock[0].offset = 105;
|
---|
1354 | lock[0].count = 10;
|
---|
1355 | status = smb_raw_lock(cli->tree, &io);
|
---|
1356 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
1357 |
|
---|
1358 | status = smbcli_request_simple_recv(req);
|
---|
1359 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1360 |
|
---|
1361 | delay = t / 1000;
|
---|
1362 | if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
|
---|
1363 | delay /= 2;
|
---|
1364 | }
|
---|
1365 |
|
---|
1366 | torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
|
---|
1367 | "lock comes back to early timeout[%d] delay[%d]"
|
---|
1368 | "(%s)\n", t, delay, __location__));
|
---|
1369 |
|
---|
1370 | status = smb_raw_lock(cli->tree, &io);
|
---|
1371 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
1372 |
|
---|
1373 | smbcli_close(cli->tree, fnum);
|
---|
1374 | fname = BASEDIR "\\test3.txt";
|
---|
1375 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
1376 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
1377 | "Failed to reopen %s - %s\n",
|
---|
1378 | fname, smbcli_errstr(cli->tree)));
|
---|
1379 |
|
---|
1380 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
1381 | io.lockx.in.file.fnum = fnum;
|
---|
1382 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
1383 | io.lockx.in.timeout = 0;
|
---|
1384 | io.lockx.in.ulock_cnt = 0;
|
---|
1385 | io.lockx.in.lock_cnt = 1;
|
---|
1386 | lock[0].pid = cli->session->pid;
|
---|
1387 | lock[0].offset = 100;
|
---|
1388 | lock[0].count = 10;
|
---|
1389 | io.lockx.in.locks = &lock[0];
|
---|
1390 | status = smb_raw_lock(cli->tree, &io);
|
---|
1391 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1392 |
|
---|
1393 | start = time_mono(NULL);
|
---|
1394 | io.lockx.in.timeout = t;
|
---|
1395 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
1396 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
1397 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
1398 |
|
---|
1399 | io.lockx.in.timeout = 0;
|
---|
1400 | lock[0].offset = 105;
|
---|
1401 | lock[0].count = 10;
|
---|
1402 | status = smb_raw_lock(cli->tree, &io);
|
---|
1403 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
1404 |
|
---|
1405 | status = smbcli_request_simple_recv(req);
|
---|
1406 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1407 |
|
---|
1408 | delay = t / 1000;
|
---|
1409 | if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
|
---|
1410 | delay /= 2;
|
---|
1411 | }
|
---|
1412 |
|
---|
1413 | torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
|
---|
1414 | "lock comes back to early timeout[%d] delay[%d]"
|
---|
1415 | "(%s)\n", t, delay, __location__));
|
---|
1416 |
|
---|
1417 | lock[0].offset = 100;
|
---|
1418 | lock[0].count = 10;
|
---|
1419 | status = smb_raw_lock(cli->tree, &io);
|
---|
1420 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1421 |
|
---|
1422 | smbcli_close(cli->tree, fnum);
|
---|
1423 | fname = BASEDIR "\\test4.txt";
|
---|
1424 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
1425 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
1426 | "Failed to reopen %s - %s\n",
|
---|
1427 | fname, smbcli_errstr(cli->tree)));
|
---|
1428 |
|
---|
1429 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
1430 | io.lockx.in.file.fnum = fnum;
|
---|
1431 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
|
---|
1432 | io.lockx.in.timeout = 0;
|
---|
1433 | io.lockx.in.ulock_cnt = 0;
|
---|
1434 | io.lockx.in.lock_cnt = 1;
|
---|
1435 | lock[0].pid = cli->session->pid;
|
---|
1436 | lock[0].offset = 100;
|
---|
1437 | lock[0].count = 10;
|
---|
1438 | io.lockx.in.locks = &lock[0];
|
---|
1439 | status = smb_raw_lock(cli->tree, &io);
|
---|
1440 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1441 |
|
---|
1442 | start = time_mono(NULL);
|
---|
1443 | io.lockx.in.timeout = t;
|
---|
1444 | req = smb_raw_lock_send(cli->tree, &io);
|
---|
1445 | torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
|
---|
1446 | "Failed to setup timed lock (%s)\n", __location__));
|
---|
1447 |
|
---|
1448 | io.lockx.in.timeout = 0;
|
---|
1449 | status = smb_raw_lock(cli->tree, &io);
|
---|
1450 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
1451 |
|
---|
1452 | status = smbcli_request_simple_recv(req);
|
---|
1453 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1454 |
|
---|
1455 | delay = t / 1000;
|
---|
1456 | if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
|
---|
1457 | delay /= 2;
|
---|
1458 | }
|
---|
1459 |
|
---|
1460 | torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
|
---|
1461 | "lock comes back to early timeout[%d] delay[%d]"
|
---|
1462 | "(%s)\n", t, delay, __location__));
|
---|
1463 |
|
---|
1464 | status = smb_raw_lock(cli->tree, &io);
|
---|
1465 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1466 |
|
---|
1467 | done:
|
---|
1468 | smb_raw_exit(cli->session);
|
---|
1469 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1470 | return ret;
|
---|
1471 | }
|
---|
1472 |
|
---|
1473 |
|
---|
1474 | /*
|
---|
1475 | test LOCKING_ANDX_CHANGE_LOCKTYPE
|
---|
1476 | */
|
---|
1477 | static bool test_changetype(struct torture_context *tctx,
|
---|
1478 | struct smbcli_state *cli)
|
---|
1479 | {
|
---|
1480 | union smb_lock io;
|
---|
1481 | struct smb_lock_entry lock[2];
|
---|
1482 | NTSTATUS status;
|
---|
1483 | bool ret = true;
|
---|
1484 | int fnum;
|
---|
1485 | uint8_t c = 0;
|
---|
1486 | const char *fname = BASEDIR "\\test.txt";
|
---|
1487 |
|
---|
1488 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1489 | return false;
|
---|
1490 | }
|
---|
1491 |
|
---|
1492 | torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
|
---|
1493 | io.generic.level = RAW_LOCK_LOCKX;
|
---|
1494 |
|
---|
1495 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
1496 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
1497 | "Failed to create %s - %s\n",
|
---|
1498 | fname, smbcli_errstr(cli->tree)));
|
---|
1499 |
|
---|
1500 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
1501 | io.lockx.in.file.fnum = fnum;
|
---|
1502 | io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
|
---|
1503 | io.lockx.in.timeout = 0;
|
---|
1504 | io.lockx.in.ulock_cnt = 0;
|
---|
1505 | io.lockx.in.lock_cnt = 1;
|
---|
1506 | lock[0].pid = cli->session->pid;
|
---|
1507 | lock[0].offset = 100;
|
---|
1508 | lock[0].count = 10;
|
---|
1509 | io.lockx.in.locks = &lock[0];
|
---|
1510 | status = smb_raw_lock(cli->tree, &io);
|
---|
1511 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1512 |
|
---|
1513 | if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
|
---|
1514 | torture_result(tctx, TORTURE_FAIL,
|
---|
1515 | "allowed write on read locked region (%s)\n", __location__);
|
---|
1516 | ret = false;
|
---|
1517 | goto done;
|
---|
1518 | }
|
---|
1519 |
|
---|
1520 | /* windows server don't seem to support this */
|
---|
1521 | io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
|
---|
1522 | status = smb_raw_lock(cli->tree, &io);
|
---|
1523 | CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
|
---|
1524 |
|
---|
1525 | if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
|
---|
1526 | torture_result(tctx, TORTURE_FAIL,
|
---|
1527 | "allowed write after lock change (%s)\n", __location__);
|
---|
1528 | ret = false;
|
---|
1529 | goto done;
|
---|
1530 | }
|
---|
1531 |
|
---|
1532 | done:
|
---|
1533 | smbcli_close(cli->tree, fnum);
|
---|
1534 | smb_raw_exit(cli->session);
|
---|
1535 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1536 | return ret;
|
---|
1537 | }
|
---|
1538 |
|
---|
1539 | struct double_lock_test {
|
---|
1540 | struct smb_lock_entry lock1;
|
---|
1541 | struct smb_lock_entry lock2;
|
---|
1542 | NTSTATUS exp_status;
|
---|
1543 | };
|
---|
1544 |
|
---|
1545 | /**
|
---|
1546 | * Tests zero byte locks.
|
---|
1547 | */
|
---|
1548 | static struct double_lock_test zero_byte_tests[] = {
|
---|
1549 | /* {pid, offset, count}, {pid, offset, count}, status */
|
---|
1550 |
|
---|
1551 | /** First, takes a zero byte lock at offset 10. Then:
|
---|
1552 | * - Taking 0 byte lock at 10 should succeed.
|
---|
1553 | * - Taking 1 byte locks at 9,10,11 should succeed.
|
---|
1554 | * - Taking 2 byte lock at 9 should fail.
|
---|
1555 | * - Taking 2 byte lock at 10 should succeed.
|
---|
1556 | * - Taking 3 byte lock at 9 should fail.
|
---|
1557 | */
|
---|
1558 | {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
|
---|
1559 | {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
|
---|
1560 | {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
|
---|
1561 | {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
|
---|
1562 | {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
|
---|
1563 | {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
|
---|
1564 | {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
|
---|
1565 |
|
---|
1566 | /** Same, but opposite order. */
|
---|
1567 | {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
|
---|
1568 | {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
|
---|
1569 | {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
|
---|
1570 | {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
|
---|
1571 | {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
|
---|
1572 | {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
|
---|
1573 | {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
|
---|
1574 |
|
---|
1575 | /** Zero zero case. */
|
---|
1576 | {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
|
---|
1577 | };
|
---|
1578 |
|
---|
1579 | static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
|
---|
1580 | {
|
---|
1581 | union smb_lock io;
|
---|
1582 | NTSTATUS status;
|
---|
1583 | bool ret = true;
|
---|
1584 | int fnum, i;
|
---|
1585 | const char *fname = BASEDIR "\\zero.txt";
|
---|
1586 |
|
---|
1587 | torture_comment(tctx, "Testing zero length byte range locks:\n");
|
---|
1588 |
|
---|
1589 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1590 | return false;
|
---|
1591 | }
|
---|
1592 |
|
---|
1593 | io.generic.level = RAW_LOCK_LOCKX;
|
---|
1594 |
|
---|
1595 | fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
1596 | torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
|
---|
1597 | "Failed to create %s - %s\n",
|
---|
1598 | fname, smbcli_errstr(cli->tree)));
|
---|
1599 |
|
---|
1600 | /* Setup initial parameters */
|
---|
1601 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
1602 | io.lockx.in.file.fnum = fnum;
|
---|
1603 | io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
|
---|
1604 | io.lockx.in.timeout = 0;
|
---|
1605 |
|
---|
1606 | /* Try every combination of locks in zero_byte_tests. The first lock is
|
---|
1607 | * assumed to succeed. The second lock may contend, depending on the
|
---|
1608 | * expected status. */
|
---|
1609 | for (i = 0;
|
---|
1610 | i < ARRAY_SIZE(zero_byte_tests);
|
---|
1611 | i++) {
|
---|
1612 | torture_comment(tctx, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
|
---|
1613 | zero_byte_tests[i].lock1.pid,
|
---|
1614 | (unsigned long long) zero_byte_tests[i].lock1.offset,
|
---|
1615 | (unsigned long long) zero_byte_tests[i].lock1.count,
|
---|
1616 | zero_byte_tests[i].lock2.pid,
|
---|
1617 | (unsigned long long) zero_byte_tests[i].lock2.offset,
|
---|
1618 | (unsigned long long) zero_byte_tests[i].lock2.count,
|
---|
1619 | nt_errstr(zero_byte_tests[i].exp_status));
|
---|
1620 |
|
---|
1621 | /* Lock both locks. */
|
---|
1622 | io.lockx.in.ulock_cnt = 0;
|
---|
1623 | io.lockx.in.lock_cnt = 1;
|
---|
1624 |
|
---|
1625 | io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
|
---|
1626 | &zero_byte_tests[i].lock1);
|
---|
1627 | status = smb_raw_lock(cli->tree, &io);
|
---|
1628 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1629 |
|
---|
1630 | io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
|
---|
1631 | &zero_byte_tests[i].lock2);
|
---|
1632 | status = smb_raw_lock(cli->tree, &io);
|
---|
1633 |
|
---|
1634 | if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
|
---|
1635 | NT_STATUS_LOCK_NOT_GRANTED)) {
|
---|
1636 | /* Allow either of the failure messages and keep going
|
---|
1637 | * if we see the wrong status. */
|
---|
1638 | CHECK_STATUS_OR_CONT(status,
|
---|
1639 | NT_STATUS_LOCK_NOT_GRANTED,
|
---|
1640 | NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1641 |
|
---|
1642 | } else {
|
---|
1643 | CHECK_STATUS_CONT(status,
|
---|
1644 | zero_byte_tests[i].exp_status);
|
---|
1645 | }
|
---|
1646 |
|
---|
1647 | /* Unlock both locks. */
|
---|
1648 | io.lockx.in.ulock_cnt = 1;
|
---|
1649 | io.lockx.in.lock_cnt = 0;
|
---|
1650 |
|
---|
1651 | if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
|
---|
1652 | status = smb_raw_lock(cli->tree, &io);
|
---|
1653 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1654 | }
|
---|
1655 |
|
---|
1656 | io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
|
---|
1657 | &zero_byte_tests[i].lock1);
|
---|
1658 | status = smb_raw_lock(cli->tree, &io);
|
---|
1659 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1660 | }
|
---|
1661 |
|
---|
1662 | done:
|
---|
1663 | smbcli_close(cli->tree, fnum);
|
---|
1664 | smb_raw_exit(cli->session);
|
---|
1665 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1666 | return ret;
|
---|
1667 | }
|
---|
1668 |
|
---|
1669 | static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
|
---|
1670 | {
|
---|
1671 | union smb_lock io;
|
---|
1672 | NTSTATUS status;
|
---|
1673 | bool ret = true;
|
---|
1674 | int fnum1, fnum2;
|
---|
1675 | const char *fname = BASEDIR "\\unlock.txt";
|
---|
1676 | struct smb_lock_entry lock1;
|
---|
1677 | struct smb_lock_entry lock2;
|
---|
1678 |
|
---|
1679 | torture_comment(tctx, "Testing LOCKX unlock:\n");
|
---|
1680 |
|
---|
1681 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1682 | return false;
|
---|
1683 | }
|
---|
1684 |
|
---|
1685 | fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
1686 | torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
|
---|
1687 | "Failed to create %s - %s\n",
|
---|
1688 | fname, smbcli_errstr(cli->tree)));
|
---|
1689 |
|
---|
1690 | fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
1691 | torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
|
---|
1692 | "Failed to create %s - %s\n",
|
---|
1693 | fname, smbcli_errstr(cli->tree)));
|
---|
1694 |
|
---|
1695 | /* Setup initial parameters */
|
---|
1696 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
1697 | io.lockx.in.timeout = 0;
|
---|
1698 |
|
---|
1699 | lock1.pid = cli->session->pid;
|
---|
1700 | lock1.offset = 0;
|
---|
1701 | lock1.count = 10;
|
---|
1702 | lock2.pid = cli->session->pid - 1;
|
---|
1703 | lock2.offset = 0;
|
---|
1704 | lock2.count = 10;
|
---|
1705 |
|
---|
1706 | /**
|
---|
1707 | * Take exclusive lock, then unlock it with a shared-unlock call.
|
---|
1708 | */
|
---|
1709 | torture_comment(tctx, " taking exclusive lock.\n");
|
---|
1710 | io.lockx.in.ulock_cnt = 0;
|
---|
1711 | io.lockx.in.lock_cnt = 1;
|
---|
1712 | io.lockx.in.mode = 0;
|
---|
1713 | io.lockx.in.file.fnum = fnum1;
|
---|
1714 | io.lockx.in.locks = &lock1;
|
---|
1715 | status = smb_raw_lock(cli->tree, &io);
|
---|
1716 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1717 |
|
---|
1718 | torture_comment(tctx, " unlock the exclusive with a shared unlock call.\n");
|
---|
1719 | io.lockx.in.ulock_cnt = 1;
|
---|
1720 | io.lockx.in.lock_cnt = 0;
|
---|
1721 | io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
|
---|
1722 | io.lockx.in.file.fnum = fnum1;
|
---|
1723 | io.lockx.in.locks = &lock1;
|
---|
1724 | status = smb_raw_lock(cli->tree, &io);
|
---|
1725 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1726 |
|
---|
1727 | torture_comment(tctx, " try shared lock on pid2/fnum2, testing the unlock.\n");
|
---|
1728 | io.lockx.in.ulock_cnt = 0;
|
---|
1729 | io.lockx.in.lock_cnt = 1;
|
---|
1730 | io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
|
---|
1731 | io.lockx.in.file.fnum = fnum2;
|
---|
1732 | io.lockx.in.locks = &lock2;
|
---|
1733 | status = smb_raw_lock(cli->tree, &io);
|
---|
1734 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1735 |
|
---|
1736 | /**
|
---|
1737 | * Unlock a shared lock with an exclusive-unlock call.
|
---|
1738 | */
|
---|
1739 | torture_comment(tctx, " unlock new shared lock with exclusive unlock call.\n");
|
---|
1740 | io.lockx.in.ulock_cnt = 1;
|
---|
1741 | io.lockx.in.lock_cnt = 0;
|
---|
1742 | io.lockx.in.mode = 0;
|
---|
1743 | io.lockx.in.file.fnum = fnum2;
|
---|
1744 | io.lockx.in.locks = &lock2;
|
---|
1745 | status = smb_raw_lock(cli->tree, &io);
|
---|
1746 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1747 |
|
---|
1748 | torture_comment(tctx, " try exclusive lock on pid1, testing the unlock.\n");
|
---|
1749 | io.lockx.in.ulock_cnt = 0;
|
---|
1750 | io.lockx.in.lock_cnt = 1;
|
---|
1751 | io.lockx.in.mode = 0;
|
---|
1752 | io.lockx.in.file.fnum = fnum1;
|
---|
1753 | io.lockx.in.locks = &lock1;
|
---|
1754 | status = smb_raw_lock(cli->tree, &io);
|
---|
1755 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1756 |
|
---|
1757 | /* cleanup */
|
---|
1758 | io.lockx.in.ulock_cnt = 1;
|
---|
1759 | io.lockx.in.lock_cnt = 0;
|
---|
1760 | status = smb_raw_lock(cli->tree, &io);
|
---|
1761 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1762 |
|
---|
1763 | /**
|
---|
1764 | * Test unlocking of 0-byte locks.
|
---|
1765 | */
|
---|
1766 |
|
---|
1767 | torture_comment(tctx, " lock shared and exclusive 0-byte locks, testing that Windows "
|
---|
1768 | "always unlocks the exclusive first.\n");
|
---|
1769 | lock1.pid = cli->session->pid;
|
---|
1770 | lock1.offset = 10;
|
---|
1771 | lock1.count = 0;
|
---|
1772 | lock2.pid = cli->session->pid;
|
---|
1773 | lock2.offset = 5;
|
---|
1774 | lock2.count = 10;
|
---|
1775 | io.lockx.in.ulock_cnt = 0;
|
---|
1776 | io.lockx.in.lock_cnt = 1;
|
---|
1777 | io.lockx.in.file.fnum = fnum1;
|
---|
1778 | io.lockx.in.locks = &lock1;
|
---|
1779 |
|
---|
1780 | /* lock 0-byte shared
|
---|
1781 | * Note: Order of the shared/exclusive locks doesn't matter. */
|
---|
1782 | io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
|
---|
1783 | status = smb_raw_lock(cli->tree, &io);
|
---|
1784 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1785 |
|
---|
1786 | /* lock 0-byte exclusive */
|
---|
1787 | io.lockx.in.mode = 0;
|
---|
1788 | status = smb_raw_lock(cli->tree, &io);
|
---|
1789 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1790 |
|
---|
1791 | /* test contention */
|
---|
1792 | io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
|
---|
1793 | io.lockx.in.locks = &lock2;
|
---|
1794 | io.lockx.in.file.fnum = fnum2;
|
---|
1795 | status = smb_raw_lock(cli->tree, &io);
|
---|
1796 | CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
|
---|
1797 | NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1798 |
|
---|
1799 | /* unlock */
|
---|
1800 | io.lockx.in.ulock_cnt = 1;
|
---|
1801 | io.lockx.in.lock_cnt = 0;
|
---|
1802 | io.lockx.in.file.fnum = fnum1;
|
---|
1803 | io.lockx.in.locks = &lock1;
|
---|
1804 | status = smb_raw_lock(cli->tree, &io);
|
---|
1805 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1806 |
|
---|
1807 | /* test - can we take a shared lock? */
|
---|
1808 | io.lockx.in.ulock_cnt = 0;
|
---|
1809 | io.lockx.in.lock_cnt = 1;
|
---|
1810 | io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
|
---|
1811 | io.lockx.in.file.fnum = fnum2;
|
---|
1812 | io.lockx.in.locks = &lock2;
|
---|
1813 | status = smb_raw_lock(cli->tree, &io);
|
---|
1814 |
|
---|
1815 | /* XXX Samba 3 will fail this test. This is temporary(because this isn't
|
---|
1816 | * new to Win7, it succeeds in WinXP too), until I can come to a
|
---|
1817 | * resolution as to whether Samba should support this or not. There is
|
---|
1818 | * code to preference unlocking exclusive locks before shared locks,
|
---|
1819 | * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
|
---|
1820 | if (TARGET_IS_SAMBA3(tctx)) {
|
---|
1821 | CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
|
---|
1822 | NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1823 | } else {
|
---|
1824 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1825 | }
|
---|
1826 |
|
---|
1827 | /* cleanup */
|
---|
1828 | io.lockx.in.ulock_cnt = 1;
|
---|
1829 | io.lockx.in.lock_cnt = 0;
|
---|
1830 | status = smb_raw_lock(cli->tree, &io);
|
---|
1831 |
|
---|
1832 | /* XXX Same as above. */
|
---|
1833 | if (TARGET_IS_SAMBA3(tctx)) {
|
---|
1834 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
1835 | } else {
|
---|
1836 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1837 | }
|
---|
1838 |
|
---|
1839 | io.lockx.in.file.fnum = fnum1;
|
---|
1840 | io.lockx.in.locks = &lock1;
|
---|
1841 | status = smb_raw_lock(cli->tree, &io);
|
---|
1842 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1843 |
|
---|
1844 | done:
|
---|
1845 | smbcli_close(cli->tree, fnum1);
|
---|
1846 | smbcli_close(cli->tree, fnum2);
|
---|
1847 | smb_raw_exit(cli->session);
|
---|
1848 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1849 | return ret;
|
---|
1850 | }
|
---|
1851 |
|
---|
1852 | static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
|
---|
1853 | {
|
---|
1854 | union smb_lock io;
|
---|
1855 | NTSTATUS status;
|
---|
1856 | bool ret = true;
|
---|
1857 | int fnum1;
|
---|
1858 | const char *fname = BASEDIR "\\unlock_multiple.txt";
|
---|
1859 | struct smb_lock_entry lock1;
|
---|
1860 | struct smb_lock_entry lock2;
|
---|
1861 | struct smb_lock_entry locks[2];
|
---|
1862 |
|
---|
1863 | torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
|
---|
1864 |
|
---|
1865 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1866 | return false;
|
---|
1867 | }
|
---|
1868 |
|
---|
1869 | fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
1870 | torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
|
---|
1871 | "Failed to create %s - %s\n",
|
---|
1872 | fname, smbcli_errstr(cli->tree)));
|
---|
1873 |
|
---|
1874 | /* Setup initial parameters */
|
---|
1875 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
1876 | io.lockx.in.timeout = 0;
|
---|
1877 |
|
---|
1878 | lock1.pid = cli->session->pid;
|
---|
1879 | lock1.offset = 0;
|
---|
1880 | lock1.count = 10;
|
---|
1881 | lock2.pid = cli->session->pid;
|
---|
1882 | lock2.offset = 10;
|
---|
1883 | lock2.count = 10;
|
---|
1884 |
|
---|
1885 | locks[0] = lock1;
|
---|
1886 | locks[1] = lock2;
|
---|
1887 |
|
---|
1888 | io.lockx.in.file.fnum = fnum1;
|
---|
1889 | io.lockx.in.mode = 0; /* exclusive */
|
---|
1890 |
|
---|
1891 | /** Test1: Take second lock, but not first. */
|
---|
1892 | torture_comment(tctx, " unlock 2 locks, first one not locked. Expect no locks "
|
---|
1893 | "unlocked. \n");
|
---|
1894 |
|
---|
1895 | io.lockx.in.ulock_cnt = 0;
|
---|
1896 | io.lockx.in.lock_cnt = 1;
|
---|
1897 | io.lockx.in.locks = &lock2;
|
---|
1898 | status = smb_raw_lock(cli->tree, &io);
|
---|
1899 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1900 |
|
---|
1901 | /* Try to unlock both locks. */
|
---|
1902 | io.lockx.in.ulock_cnt = 2;
|
---|
1903 | io.lockx.in.lock_cnt = 0;
|
---|
1904 | io.lockx.in.locks = locks;
|
---|
1905 |
|
---|
1906 | status = smb_raw_lock(cli->tree, &io);
|
---|
1907 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
1908 |
|
---|
1909 | /* Second lock should not be unlocked. */
|
---|
1910 | io.lockx.in.ulock_cnt = 0;
|
---|
1911 | io.lockx.in.lock_cnt = 1;
|
---|
1912 | io.lockx.in.locks = &lock2;
|
---|
1913 | status = smb_raw_lock(cli->tree, &io);
|
---|
1914 | CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
---|
1915 |
|
---|
1916 | /* cleanup */
|
---|
1917 | io.lockx.in.ulock_cnt = 1;
|
---|
1918 | io.lockx.in.lock_cnt = 0;
|
---|
1919 | io.lockx.in.locks = &lock2;
|
---|
1920 | status = smb_raw_lock(cli->tree, &io);
|
---|
1921 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1922 |
|
---|
1923 | /** Test2: Take first lock, but not second. */
|
---|
1924 | torture_comment(tctx, " unlock 2 locks, second one not locked. Expect first lock "
|
---|
1925 | "unlocked.\n");
|
---|
1926 |
|
---|
1927 | io.lockx.in.ulock_cnt = 0;
|
---|
1928 | io.lockx.in.lock_cnt = 1;
|
---|
1929 | io.lockx.in.locks = &lock1;
|
---|
1930 | status = smb_raw_lock(cli->tree, &io);
|
---|
1931 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1932 |
|
---|
1933 | /* Try to unlock both locks. */
|
---|
1934 | io.lockx.in.ulock_cnt = 2;
|
---|
1935 | io.lockx.in.lock_cnt = 0;
|
---|
1936 | io.lockx.in.locks = locks;
|
---|
1937 |
|
---|
1938 | status = smb_raw_lock(cli->tree, &io);
|
---|
1939 | CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
|
---|
1940 |
|
---|
1941 | /* First lock should be unlocked. */
|
---|
1942 | io.lockx.in.ulock_cnt = 0;
|
---|
1943 | io.lockx.in.lock_cnt = 1;
|
---|
1944 | io.lockx.in.locks = &lock1;
|
---|
1945 | status = smb_raw_lock(cli->tree, &io);
|
---|
1946 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1947 |
|
---|
1948 | /* cleanup */
|
---|
1949 | io.lockx.in.ulock_cnt = 1;
|
---|
1950 | io.lockx.in.lock_cnt = 0;
|
---|
1951 | io.lockx.in.locks = &lock1;
|
---|
1952 | status = smb_raw_lock(cli->tree, &io);
|
---|
1953 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1954 |
|
---|
1955 | /* Test3: Request 2 locks, second will contend. What happens to the
|
---|
1956 | * first? */
|
---|
1957 | torture_comment(tctx, " request 2 locks, second one will contend. "
|
---|
1958 | "Expect both to fail.\n");
|
---|
1959 |
|
---|
1960 | /* Lock the second range */
|
---|
1961 | io.lockx.in.ulock_cnt = 0;
|
---|
1962 | io.lockx.in.lock_cnt = 1;
|
---|
1963 | io.lockx.in.locks = &lock2;
|
---|
1964 | status = smb_raw_lock(cli->tree, &io);
|
---|
1965 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1966 |
|
---|
1967 | /* Request both locks */
|
---|
1968 | io.lockx.in.ulock_cnt = 0;
|
---|
1969 | io.lockx.in.lock_cnt = 2;
|
---|
1970 | io.lockx.in.locks = locks;
|
---|
1971 |
|
---|
1972 | status = smb_raw_lock(cli->tree, &io);
|
---|
1973 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
1974 |
|
---|
1975 | /* First lock should be unlocked. */
|
---|
1976 | io.lockx.in.ulock_cnt = 0;
|
---|
1977 | io.lockx.in.lock_cnt = 1;
|
---|
1978 | io.lockx.in.locks = &lock1;
|
---|
1979 | status = smb_raw_lock(cli->tree, &io);
|
---|
1980 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1981 |
|
---|
1982 | /* cleanup */
|
---|
1983 | io.lockx.in.ulock_cnt = 2;
|
---|
1984 | io.lockx.in.lock_cnt = 0;
|
---|
1985 | io.lockx.in.locks = locks;
|
---|
1986 | status = smb_raw_lock(cli->tree, &io);
|
---|
1987 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1988 |
|
---|
1989 | /* Test4: Request unlock and lock. The lock contends, is the unlock
|
---|
1990 | * then re-locked? */
|
---|
1991 | torture_comment(tctx, " request unlock and lock, second one will "
|
---|
1992 | "contend. Expect the unlock to succeed.\n");
|
---|
1993 |
|
---|
1994 | /* Lock both ranges */
|
---|
1995 | io.lockx.in.ulock_cnt = 0;
|
---|
1996 | io.lockx.in.lock_cnt = 2;
|
---|
1997 | io.lockx.in.locks = locks;
|
---|
1998 | status = smb_raw_lock(cli->tree, &io);
|
---|
1999 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2000 |
|
---|
2001 | /* Attempt to unlock the first range and lock the second */
|
---|
2002 | io.lockx.in.ulock_cnt = 1;
|
---|
2003 | io.lockx.in.lock_cnt = 1;
|
---|
2004 | io.lockx.in.locks = locks;
|
---|
2005 | status = smb_raw_lock(cli->tree, &io);
|
---|
2006 | CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
2007 |
|
---|
2008 | /* The first lock should've been unlocked */
|
---|
2009 | io.lockx.in.ulock_cnt = 0;
|
---|
2010 | io.lockx.in.lock_cnt = 1;
|
---|
2011 | io.lockx.in.locks = &lock1;
|
---|
2012 | status = smb_raw_lock(cli->tree, &io);
|
---|
2013 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2014 |
|
---|
2015 | /* cleanup */
|
---|
2016 | io.lockx.in.ulock_cnt = 2;
|
---|
2017 | io.lockx.in.lock_cnt = 0;
|
---|
2018 | io.lockx.in.locks = locks;
|
---|
2019 | status = smb_raw_lock(cli->tree, &io);
|
---|
2020 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2021 |
|
---|
2022 | done:
|
---|
2023 | smbcli_close(cli->tree, fnum1);
|
---|
2024 | smb_raw_exit(cli->session);
|
---|
2025 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
2026 | return ret;
|
---|
2027 | }
|
---|
2028 |
|
---|
2029 | /**
|
---|
2030 | * torture_locktest5 covers stacking pretty well, but its missing two tests:
|
---|
2031 | * - stacking an exclusive on top of shared fails
|
---|
2032 | * - stacking two exclusives fail
|
---|
2033 | */
|
---|
2034 | static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
|
---|
2035 | {
|
---|
2036 | union smb_lock io;
|
---|
2037 | NTSTATUS status;
|
---|
2038 | bool ret = true;
|
---|
2039 | int fnum1;
|
---|
2040 | const char *fname = BASEDIR "\\stacking.txt";
|
---|
2041 | struct smb_lock_entry lock1;
|
---|
2042 | struct smb_lock_entry lock2;
|
---|
2043 |
|
---|
2044 | torture_comment(tctx, "Testing stacking:\n");
|
---|
2045 |
|
---|
2046 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
2047 | return false;
|
---|
2048 | }
|
---|
2049 |
|
---|
2050 | io.generic.level = RAW_LOCK_LOCKX;
|
---|
2051 |
|
---|
2052 | fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
2053 | torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
|
---|
2054 | "Failed to create %s - %s\n",
|
---|
2055 | fname, smbcli_errstr(cli->tree)));
|
---|
2056 |
|
---|
2057 | /* Setup initial parameters */
|
---|
2058 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
2059 | io.lockx.in.timeout = 0;
|
---|
2060 |
|
---|
2061 | lock1.pid = cli->session->pid;
|
---|
2062 | lock1.offset = 0;
|
---|
2063 | lock1.count = 10;
|
---|
2064 | lock2.pid = cli->session->pid - 1;
|
---|
2065 | lock2.offset = 0;
|
---|
2066 | lock2.count = 10;
|
---|
2067 |
|
---|
2068 | /**
|
---|
2069 | * Try to take a shared lock, then stack an exclusive.
|
---|
2070 | */
|
---|
2071 | torture_comment(tctx, " stacking an exclusive on top of a shared lock fails.\n");
|
---|
2072 | io.lockx.in.file.fnum = fnum1;
|
---|
2073 | io.lockx.in.locks = &lock1;
|
---|
2074 |
|
---|
2075 | io.lockx.in.ulock_cnt = 0;
|
---|
2076 | io.lockx.in.lock_cnt = 1;
|
---|
2077 | io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
|
---|
2078 | status = smb_raw_lock(cli->tree, &io);
|
---|
2079 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2080 |
|
---|
2081 | io.lockx.in.ulock_cnt = 0;
|
---|
2082 | io.lockx.in.lock_cnt = 1;
|
---|
2083 | io.lockx.in.mode = 0;
|
---|
2084 | status = smb_raw_lock(cli->tree, &io);
|
---|
2085 | CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
|
---|
2086 | NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
2087 |
|
---|
2088 | /* cleanup */
|
---|
2089 | io.lockx.in.ulock_cnt = 1;
|
---|
2090 | io.lockx.in.lock_cnt = 0;
|
---|
2091 | status = smb_raw_lock(cli->tree, &io);
|
---|
2092 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2093 |
|
---|
2094 | /**
|
---|
2095 | * Prove that two exclusive locks do not stack.
|
---|
2096 | */
|
---|
2097 | torture_comment(tctx, " two exclusive locks do not stack.\n");
|
---|
2098 | io.lockx.in.ulock_cnt = 0;
|
---|
2099 | io.lockx.in.lock_cnt = 1;
|
---|
2100 | io.lockx.in.mode = 0;
|
---|
2101 | status = smb_raw_lock(cli->tree, &io);
|
---|
2102 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2103 | status = smb_raw_lock(cli->tree, &io);
|
---|
2104 | CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
|
---|
2105 | NT_STATUS_FILE_LOCK_CONFLICT);
|
---|
2106 |
|
---|
2107 | /* cleanup */
|
---|
2108 | io.lockx.in.ulock_cnt = 1;
|
---|
2109 | io.lockx.in.lock_cnt = 0;
|
---|
2110 | status = smb_raw_lock(cli->tree, &io);
|
---|
2111 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2112 |
|
---|
2113 | done:
|
---|
2114 | smbcli_close(cli->tree, fnum1);
|
---|
2115 | smb_raw_exit(cli->session);
|
---|
2116 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
2117 | return ret;
|
---|
2118 | }
|
---|
2119 |
|
---|
2120 | /**
|
---|
2121 | * Test how 0-byte read requests contend with byte range locks
|
---|
2122 | */
|
---|
2123 | static bool test_zerobyteread(struct torture_context *tctx,
|
---|
2124 | struct smbcli_state *cli)
|
---|
2125 | {
|
---|
2126 | union smb_lock io;
|
---|
2127 | union smb_read rd;
|
---|
2128 | NTSTATUS status;
|
---|
2129 | bool ret = true;
|
---|
2130 | int fnum1, fnum2;
|
---|
2131 | const char *fname = BASEDIR "\\zerobyteread.txt";
|
---|
2132 | struct smb_lock_entry lock1;
|
---|
2133 | uint8_t c = 1;
|
---|
2134 |
|
---|
2135 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
2136 | return false;
|
---|
2137 | }
|
---|
2138 |
|
---|
2139 | io.generic.level = RAW_LOCK_LOCKX;
|
---|
2140 |
|
---|
2141 | fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
2142 | torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
|
---|
2143 | "Failed to create %s - %s\n",
|
---|
2144 | fname, smbcli_errstr(cli->tree)));
|
---|
2145 |
|
---|
2146 | fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
|
---|
2147 | torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
|
---|
2148 | "Failed to create %s - %s\n",
|
---|
2149 | fname, smbcli_errstr(cli->tree)));
|
---|
2150 |
|
---|
2151 | /* Setup initial parameters */
|
---|
2152 | io.lockx.level = RAW_LOCK_LOCKX;
|
---|
2153 | io.lockx.in.timeout = 0;
|
---|
2154 |
|
---|
2155 | lock1.pid = cli->session->pid;
|
---|
2156 | lock1.offset = 0;
|
---|
2157 | lock1.count = 10;
|
---|
2158 |
|
---|
2159 | ZERO_STRUCT(rd);
|
---|
2160 | rd.readx.level = RAW_READ_READX;
|
---|
2161 |
|
---|
2162 | torture_comment(tctx, "Testing zero byte read on lock range:\n");
|
---|
2163 |
|
---|
2164 | /* Take an exclusive lock */
|
---|
2165 | torture_comment(tctx, " taking exclusive lock.\n");
|
---|
2166 | io.lockx.in.ulock_cnt = 0;
|
---|
2167 | io.lockx.in.lock_cnt = 1;
|
---|
2168 | io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
|
---|
2169 | io.lockx.in.file.fnum = fnum1;
|
---|
2170 | io.lockx.in.locks = &lock1;
|
---|
2171 | status = smb_raw_lock(cli->tree, &io);
|
---|
2172 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2173 |
|
---|
2174 | /* Try a zero byte read */
|
---|
2175 | torture_comment(tctx, " reading 0 bytes.\n");
|
---|
2176 | rd.readx.in.file.fnum = fnum2;
|
---|
2177 | rd.readx.in.offset = 5;
|
---|
2178 | rd.readx.in.mincnt = 0;
|
---|
2179 | rd.readx.in.maxcnt = 0;
|
---|
2180 | rd.readx.in.remaining = 0;
|
---|
2181 | rd.readx.in.read_for_execute = false;
|
---|
2182 | rd.readx.out.data = &c;
|
---|
2183 | status = smb_raw_read(cli->tree, &rd);
|
---|
2184 | torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
|
---|
2185 | "zero byte read did not return 0 bytes");
|
---|
2186 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2187 |
|
---|
2188 | /* Unlock lock */
|
---|
2189 | io.lockx.in.ulock_cnt = 1;
|
---|
2190 | io.lockx.in.lock_cnt = 0;
|
---|
2191 | io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
|
---|
2192 | io.lockx.in.file.fnum = fnum1;
|
---|
2193 | io.lockx.in.locks = &lock1;
|
---|
2194 | status = smb_raw_lock(cli->tree, &io);
|
---|
2195 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2196 |
|
---|
2197 | torture_comment(tctx, "Testing zero byte read on zero byte lock "
|
---|
2198 | "range:\n");
|
---|
2199 |
|
---|
2200 | /* Take an exclusive lock */
|
---|
2201 | torture_comment(tctx, " taking exclusive 0-byte lock.\n");
|
---|
2202 | io.lockx.in.ulock_cnt = 0;
|
---|
2203 | io.lockx.in.lock_cnt = 1;
|
---|
2204 | io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
|
---|
2205 | io.lockx.in.file.fnum = fnum1;
|
---|
2206 | io.lockx.in.locks = &lock1;
|
---|
2207 | lock1.offset = 5;
|
---|
2208 | lock1.count = 0;
|
---|
2209 | status = smb_raw_lock(cli->tree, &io);
|
---|
2210 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2211 |
|
---|
2212 | /* Try a zero byte read before the lock */
|
---|
2213 | torture_comment(tctx, " reading 0 bytes before the lock.\n");
|
---|
2214 | rd.readx.in.file.fnum = fnum2;
|
---|
2215 | rd.readx.in.offset = 4;
|
---|
2216 | rd.readx.in.mincnt = 0;
|
---|
2217 | rd.readx.in.maxcnt = 0;
|
---|
2218 | rd.readx.in.remaining = 0;
|
---|
2219 | rd.readx.in.read_for_execute = false;
|
---|
2220 | rd.readx.out.data = &c;
|
---|
2221 | status = smb_raw_read(cli->tree, &rd);
|
---|
2222 | torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
|
---|
2223 | "zero byte read did not return 0 bytes");
|
---|
2224 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2225 |
|
---|
2226 | /* Try a zero byte read on the lock */
|
---|
2227 | torture_comment(tctx, " reading 0 bytes on the lock.\n");
|
---|
2228 | rd.readx.in.file.fnum = fnum2;
|
---|
2229 | rd.readx.in.offset = 5;
|
---|
2230 | rd.readx.in.mincnt = 0;
|
---|
2231 | rd.readx.in.maxcnt = 0;
|
---|
2232 | rd.readx.in.remaining = 0;
|
---|
2233 | rd.readx.in.read_for_execute = false;
|
---|
2234 | rd.readx.out.data = &c;
|
---|
2235 | status = smb_raw_read(cli->tree, &rd);
|
---|
2236 | torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
|
---|
2237 | "zero byte read did not return 0 bytes");
|
---|
2238 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2239 |
|
---|
2240 | /* Try a zero byte read after the lock */
|
---|
2241 | torture_comment(tctx, " reading 0 bytes after the lock.\n");
|
---|
2242 | rd.readx.in.file.fnum = fnum2;
|
---|
2243 | rd.readx.in.offset = 6;
|
---|
2244 | rd.readx.in.mincnt = 0;
|
---|
2245 | rd.readx.in.maxcnt = 0;
|
---|
2246 | rd.readx.in.remaining = 0;
|
---|
2247 | rd.readx.in.read_for_execute = false;
|
---|
2248 | rd.readx.out.data = &c;
|
---|
2249 | status = smb_raw_read(cli->tree, &rd);
|
---|
2250 | torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
|
---|
2251 | "zero byte read did not return 0 bytes");
|
---|
2252 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2253 |
|
---|
2254 | /* Unlock lock */
|
---|
2255 | io.lockx.in.ulock_cnt = 1;
|
---|
2256 | io.lockx.in.lock_cnt = 0;
|
---|
2257 | io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
|
---|
2258 | io.lockx.in.file.fnum = fnum1;
|
---|
2259 | io.lockx.in.locks = &lock1;
|
---|
2260 | status = smb_raw_lock(cli->tree, &io);
|
---|
2261 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
2262 |
|
---|
2263 | done:
|
---|
2264 | smbcli_close(cli->tree, fnum1);
|
---|
2265 | smbcli_close(cli->tree, fnum2);
|
---|
2266 | smb_raw_exit(cli->session);
|
---|
2267 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
2268 | return ret;
|
---|
2269 | }
|
---|
2270 |
|
---|
2271 | /*
|
---|
2272 | basic testing of lock calls
|
---|
2273 | */
|
---|
2274 | struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
|
---|
2275 | {
|
---|
2276 | struct torture_suite *suite = torture_suite_create(mem_ctx, "lock");
|
---|
2277 |
|
---|
2278 | torture_suite_add_1smb_test(suite, "lockx", test_lockx);
|
---|
2279 | torture_suite_add_1smb_test(suite, "lock", test_lock);
|
---|
2280 | torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
|
---|
2281 | torture_suite_add_1smb_test(suite, "async", test_async);
|
---|
2282 | torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
|
---|
2283 | torture_suite_add_1smb_test(suite, "changetype", test_changetype);
|
---|
2284 |
|
---|
2285 | torture_suite_add_1smb_test(suite, "stacking", test_stacking);
|
---|
2286 | torture_suite_add_1smb_test(suite, "unlock", test_unlock);
|
---|
2287 | torture_suite_add_1smb_test(suite, "multiple_unlock",
|
---|
2288 | test_multiple_unlock);
|
---|
2289 | torture_suite_add_1smb_test(suite, "zerobytelocks", test_zerobytelocks);
|
---|
2290 | torture_suite_add_1smb_test(suite, "zerobyteread", test_zerobyteread);
|
---|
2291 |
|
---|
2292 | return suite;
|
---|
2293 | }
|
---|