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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.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 
32 #define CHECK_STATUS(status, correct) do { \
33 	if (!NT_STATUS_EQUAL(status, correct)) { \
34 		printf("(%s) Incorrect status %s - should be %s\n", \
35 		       __location__, nt_errstr(status), nt_errstr(correct)); \
36 		ret = False; \
37 		goto done; \
38 	}} while (0)
39 
40 #define BASEDIR "\\testlock"
41 
42 
43 /*
44   test SMBlock and SMBunlock ops
45 */
test_lock(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)46 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
47 {
48 	union smb_lock io;
49 	NTSTATUS status;
50 	BOOL ret = True;
51 	int fnum;
52 	const char *fname = BASEDIR "\\test.txt";
53 
54 	if (!torture_setup_dir(cli, BASEDIR)) {
55 		return False;
56 	}
57 
58 	printf("Testing RAW_LOCK_LOCK\n");
59 	io.generic.level = RAW_LOCK_LOCK;
60 
61 	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
62 	if (fnum == -1) {
63 		printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
64 		ret = False;
65 		goto done;
66 	}
67 
68 	printf("Trying 0/0 lock\n");
69 	io.lock.level = RAW_LOCK_LOCK;
70 	io.lock.in.file.fnum = fnum;
71 	io.lock.in.count = 0;
72 	io.lock.in.offset = 0;
73 	status = smb_raw_lock(cli->tree, &io);
74 	CHECK_STATUS(status, NT_STATUS_OK);
75 	cli->session->pid++;
76 	status = smb_raw_lock(cli->tree, &io);
77 	CHECK_STATUS(status, NT_STATUS_OK);
78 	cli->session->pid--;
79 	io.lock.level = RAW_LOCK_UNLOCK;
80 	status = smb_raw_lock(cli->tree, &io);
81 	CHECK_STATUS(status, NT_STATUS_OK);
82 
83 	printf("Trying 0/1 lock\n");
84 	io.lock.level = RAW_LOCK_LOCK;
85 	io.lock.in.file.fnum = fnum;
86 	io.lock.in.count = 1;
87 	io.lock.in.offset = 0;
88 	status = smb_raw_lock(cli->tree, &io);
89 	CHECK_STATUS(status, NT_STATUS_OK);
90 	cli->session->pid++;
91 	status = smb_raw_lock(cli->tree, &io);
92 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
93 	cli->session->pid--;
94 	io.lock.level = RAW_LOCK_UNLOCK;
95 	status = smb_raw_lock(cli->tree, &io);
96 	CHECK_STATUS(status, NT_STATUS_OK);
97 	io.lock.level = RAW_LOCK_UNLOCK;
98 	status = smb_raw_lock(cli->tree, &io);
99 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
100 
101 	printf("Trying 0xEEFFFFFF lock\n");
102 	io.lock.level = RAW_LOCK_LOCK;
103 	io.lock.in.file.fnum = fnum;
104 	io.lock.in.count = 4000;
105 	io.lock.in.offset = 0xEEFFFFFF;
106 	status = smb_raw_lock(cli->tree, &io);
107 	CHECK_STATUS(status, NT_STATUS_OK);
108 	cli->session->pid++;
109 	status = smb_raw_lock(cli->tree, &io);
110 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
111 	cli->session->pid--;
112 	io.lock.level = RAW_LOCK_UNLOCK;
113 	status = smb_raw_lock(cli->tree, &io);
114 	CHECK_STATUS(status, NT_STATUS_OK);
115 	io.lock.level = RAW_LOCK_UNLOCK;
116 	status = smb_raw_lock(cli->tree, &io);
117 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
118 
119 	printf("Trying 0xEF000000 lock\n");
120 	io.lock.level = RAW_LOCK_LOCK;
121 	io.lock.in.file.fnum = fnum;
122 	io.lock.in.count = 4000;
123 	io.lock.in.offset = 0xEEFFFFFF;
124 	status = smb_raw_lock(cli->tree, &io);
125 	CHECK_STATUS(status, NT_STATUS_OK);
126 	cli->session->pid++;
127 	status = smb_raw_lock(cli->tree, &io);
128 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
129 	cli->session->pid--;
130 	io.lock.level = RAW_LOCK_UNLOCK;
131 	status = smb_raw_lock(cli->tree, &io);
132 	CHECK_STATUS(status, NT_STATUS_OK);
133 	io.lock.level = RAW_LOCK_UNLOCK;
134 	status = smb_raw_lock(cli->tree, &io);
135 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
136 
137 	printf("Trying max lock\n");
138 	io.lock.level = RAW_LOCK_LOCK;
139 	io.lock.in.file.fnum = fnum;
140 	io.lock.in.count = 4000;
141 	io.lock.in.offset = 0xEF000000;
142 	status = smb_raw_lock(cli->tree, &io);
143 	CHECK_STATUS(status, NT_STATUS_OK);
144 	cli->session->pid++;
145 	status = smb_raw_lock(cli->tree, &io);
146 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
147 	cli->session->pid--;
148 	io.lock.level = RAW_LOCK_UNLOCK;
149 	status = smb_raw_lock(cli->tree, &io);
150 	CHECK_STATUS(status, NT_STATUS_OK);
151 	io.lock.level = RAW_LOCK_UNLOCK;
152 	status = smb_raw_lock(cli->tree, &io);
153 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
154 
155 	printf("Trying wrong pid unlock\n");
156 	io.lock.level = RAW_LOCK_LOCK;
157 	io.lock.in.file.fnum = fnum;
158 	io.lock.in.count = 4002;
159 	io.lock.in.offset = 10001;
160 	status = smb_raw_lock(cli->tree, &io);
161 	CHECK_STATUS(status, NT_STATUS_OK);
162 	cli->session->pid++;
163 	io.lock.level = RAW_LOCK_UNLOCK;
164 	status = smb_raw_lock(cli->tree, &io);
165 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
166 	cli->session->pid--;
167 	status = smb_raw_lock(cli->tree, &io);
168 	CHECK_STATUS(status, NT_STATUS_OK);
169 
170 done:
171 	smbcli_close(cli->tree, fnum);
172 	smb_raw_exit(cli->session);
173 	smbcli_deltree(cli->tree, BASEDIR);
174 	return ret;
175 }
176 
177 
178 /*
179   test locking&X ops
180 */
test_lockx(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)181 static BOOL test_lockx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
182 {
183 	union smb_lock io;
184 	struct smb_lock_entry lock[1];
185 	NTSTATUS status;
186 	BOOL ret = True;
187 	int fnum;
188 	const char *fname = BASEDIR "\\test.txt";
189 
190 	if (!torture_setup_dir(cli, BASEDIR)) {
191 		return False;
192 	}
193 
194 	printf("Testing RAW_LOCK_LOCKX\n");
195 	io.generic.level = RAW_LOCK_LOCKX;
196 
197 	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
198 	if (fnum == -1) {
199 		printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
200 		ret = False;
201 		goto done;
202 	}
203 
204 	io.lockx.level = RAW_LOCK_LOCKX;
205 	io.lockx.in.file.fnum = fnum;
206 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
207 	io.lockx.in.timeout = 0;
208 	io.lockx.in.ulock_cnt = 0;
209 	io.lockx.in.lock_cnt = 1;
210 	lock[0].pid = cli->session->pid;
211 	lock[0].offset = 10;
212 	lock[0].count = 1;
213 	io.lockx.in.locks = &lock[0];
214 	status = smb_raw_lock(cli->tree, &io);
215 	CHECK_STATUS(status, NT_STATUS_OK);
216 
217 
218 	printf("Trying 0xEEFFFFFF lock\n");
219 	io.lockx.in.ulock_cnt = 0;
220 	io.lockx.in.lock_cnt = 1;
221 	lock[0].count = 4000;
222 	lock[0].offset = 0xEEFFFFFF;
223 	status = smb_raw_lock(cli->tree, &io);
224 	CHECK_STATUS(status, NT_STATUS_OK);
225 	lock[0].pid++;
226 	status = smb_raw_lock(cli->tree, &io);
227 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
228 	lock[0].pid--;
229 	io.lockx.in.ulock_cnt = 1;
230 	io.lockx.in.lock_cnt = 0;
231 	status = smb_raw_lock(cli->tree, &io);
232 	CHECK_STATUS(status, NT_STATUS_OK);
233 	status = smb_raw_lock(cli->tree, &io);
234 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
235 
236 	printf("Trying 0xEF000000 lock\n");
237 	io.lockx.in.ulock_cnt = 0;
238 	io.lockx.in.lock_cnt = 1;
239 	lock[0].count = 4000;
240 	lock[0].offset = 0xEF000000;
241 	status = smb_raw_lock(cli->tree, &io);
242 	CHECK_STATUS(status, NT_STATUS_OK);
243 	lock[0].pid++;
244 	status = smb_raw_lock(cli->tree, &io);
245 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
246 	lock[0].pid--;
247 	io.lockx.in.ulock_cnt = 1;
248 	io.lockx.in.lock_cnt = 0;
249 	status = smb_raw_lock(cli->tree, &io);
250 	CHECK_STATUS(status, NT_STATUS_OK);
251 	status = smb_raw_lock(cli->tree, &io);
252 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
253 
254 	printf("Trying zero lock\n");
255 	io.lockx.in.ulock_cnt = 0;
256 	io.lockx.in.lock_cnt = 1;
257 	lock[0].count = 0;
258 	lock[0].offset = ~0;
259 	status = smb_raw_lock(cli->tree, &io);
260 	CHECK_STATUS(status, NT_STATUS_OK);
261 	lock[0].pid++;
262 	status = smb_raw_lock(cli->tree, &io);
263 	CHECK_STATUS(status, NT_STATUS_OK);
264 	lock[0].pid--;
265 	io.lockx.in.ulock_cnt = 1;
266 	io.lockx.in.lock_cnt = 0;
267 	status = smb_raw_lock(cli->tree, &io);
268 	CHECK_STATUS(status, NT_STATUS_OK);
269 	status = smb_raw_lock(cli->tree, &io);
270 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
271 
272 	printf("Trying max lock\n");
273 	io.lockx.in.ulock_cnt = 0;
274 	io.lockx.in.lock_cnt = 1;
275 	lock[0].count = 0;
276 	lock[0].offset = ~0;
277 	status = smb_raw_lock(cli->tree, &io);
278 	CHECK_STATUS(status, NT_STATUS_OK);
279 	lock[0].pid++;
280 	status = smb_raw_lock(cli->tree, &io);
281 	CHECK_STATUS(status, NT_STATUS_OK);
282 	lock[0].pid--;
283 	io.lockx.in.ulock_cnt = 1;
284 	io.lockx.in.lock_cnt = 0;
285 	status = smb_raw_lock(cli->tree, &io);
286 	CHECK_STATUS(status, NT_STATUS_OK);
287 	status = smb_raw_lock(cli->tree, &io);
288 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
289 
290 	printf("Trying 2^63\n");
291 	io.lockx.in.ulock_cnt = 0;
292 	io.lockx.in.lock_cnt = 1;
293 	lock[0].count = 1;
294 	lock[0].offset = 1;
295 	lock[0].offset <<= 63;
296 	status = smb_raw_lock(cli->tree, &io);
297 	CHECK_STATUS(status, NT_STATUS_OK);
298 	lock[0].pid++;
299 	status = smb_raw_lock(cli->tree, &io);
300 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
301 	lock[0].pid--;
302 	io.lockx.in.ulock_cnt = 1;
303 	io.lockx.in.lock_cnt = 0;
304 	status = smb_raw_lock(cli->tree, &io);
305 	CHECK_STATUS(status, NT_STATUS_OK);
306 	status = smb_raw_lock(cli->tree, &io);
307 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
308 
309 	printf("Trying 2^63 - 1\n");
310 	io.lockx.in.ulock_cnt = 0;
311 	io.lockx.in.lock_cnt = 1;
312 	lock[0].count = 1;
313 	lock[0].offset = 1;
314 	lock[0].offset <<= 63;
315 	lock[0].offset--;
316 	status = smb_raw_lock(cli->tree, &io);
317 	CHECK_STATUS(status, NT_STATUS_OK);
318 	lock[0].pid++;
319 	status = smb_raw_lock(cli->tree, &io);
320 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
321 	lock[0].pid--;
322 	io.lockx.in.ulock_cnt = 1;
323 	io.lockx.in.lock_cnt = 0;
324 	status = smb_raw_lock(cli->tree, &io);
325 	CHECK_STATUS(status, NT_STATUS_OK);
326 	status = smb_raw_lock(cli->tree, &io);
327 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
328 
329 	printf("Trying max lock 2\n");
330 	io.lockx.in.ulock_cnt = 0;
331 	io.lockx.in.lock_cnt = 1;
332 	lock[0].count = 1;
333 	lock[0].offset = ~0;
334 	status = smb_raw_lock(cli->tree, &io);
335 	CHECK_STATUS(status, NT_STATUS_OK);
336 	lock[0].pid++;
337 	lock[0].count = 2;
338 	status = smb_raw_lock(cli->tree, &io);
339 	CHECK_STATUS(status, NT_STATUS_OK);
340 	lock[0].pid--;
341 	io.lockx.in.ulock_cnt = 1;
342 	io.lockx.in.lock_cnt = 0;
343 	lock[0].count = 1;
344 	status = smb_raw_lock(cli->tree, &io);
345 	CHECK_STATUS(status, NT_STATUS_OK);
346 	status = smb_raw_lock(cli->tree, &io);
347 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
348 
349 done:
350 	smbcli_close(cli->tree, fnum);
351 	smb_raw_exit(cli->session);
352 	smbcli_deltree(cli->tree, BASEDIR);
353 	return ret;
354 }
355 
356 
357 /*
358   test high pid
359 */
test_pidhigh(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)360 static BOOL test_pidhigh(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
361 {
362 	union smb_lock io;
363 	struct smb_lock_entry lock[1];
364 	NTSTATUS status;
365 	BOOL ret = True;
366 	int fnum;
367 	const char *fname = BASEDIR "\\test.txt";
368 	uint8_t c = 1;
369 
370 	if (!torture_setup_dir(cli, BASEDIR)) {
371 		return False;
372 	}
373 
374 	printf("Testing high pid\n");
375 	io.generic.level = RAW_LOCK_LOCKX;
376 
377 	cli->session->pid = 1;
378 
379 	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
380 	if (fnum == -1) {
381 		printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
382 		ret = False;
383 		goto done;
384 	}
385 
386 	if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
387 		printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
388 		ret = False;
389 		goto done;
390 	}
391 
392 	io.lockx.level = RAW_LOCK_LOCKX;
393 	io.lockx.in.file.fnum = fnum;
394 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
395 	io.lockx.in.timeout = 0;
396 	io.lockx.in.ulock_cnt = 0;
397 	io.lockx.in.lock_cnt = 1;
398 	lock[0].pid = cli->session->pid;
399 	lock[0].offset = 0;
400 	lock[0].count = 0xFFFFFFFF;
401 	io.lockx.in.locks = &lock[0];
402 	status = smb_raw_lock(cli->tree, &io);
403 	CHECK_STATUS(status, NT_STATUS_OK);
404 
405 	if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
406 		printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
407 		ret = False;
408 		goto done;
409 	}
410 
411 	cli->session->pid |= 0x10000;
412 
413 	cli->session->pid = 2;
414 
415 	if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
416 		printf("pid is incorrect handled for read with lock!\n");
417 		ret = False;
418 		goto done;
419 	}
420 
421 	cli->session->pid = 0x10001;
422 
423 	if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
424 		printf("High pid is used on this server!\n");
425 		ret = False;
426 	} else {
427 		printf("High pid is not used on this server (correct)\n");
428 	}
429 
430 done:
431 	smbcli_close(cli->tree, fnum);
432 	smb_raw_exit(cli->session);
433 	smbcli_deltree(cli->tree, BASEDIR);
434 	return ret;
435 }
436 
437 
438 /*
439   test locking&X async operation
440 */
test_async(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)441 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
442 {
443 	struct smbcli_session *session;
444 	struct smb_composite_sesssetup setup;
445 	struct smbcli_tree *tree;
446 	union smb_tcon tcon;
447 	const char *host, *share;
448 	union smb_lock io;
449 	struct smb_lock_entry lock[2];
450 	NTSTATUS status;
451 	BOOL ret = True;
452 	int fnum;
453 	const char *fname = BASEDIR "\\test.txt";
454 	time_t t;
455 	struct smbcli_request *req;
456 
457 	if (!torture_setup_dir(cli, BASEDIR)) {
458 		return False;
459 	}
460 
461 	printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
462 	io.generic.level = RAW_LOCK_LOCKX;
463 
464 	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
465 	if (fnum == -1) {
466 		printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
467 		ret = False;
468 		goto done;
469 	}
470 
471 	io.lockx.level = RAW_LOCK_LOCKX;
472 	io.lockx.in.file.fnum = fnum;
473 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
474 	io.lockx.in.timeout = 0;
475 	io.lockx.in.ulock_cnt = 0;
476 	io.lockx.in.lock_cnt = 1;
477 	lock[0].pid = cli->session->pid;
478 	lock[0].offset = 100;
479 	lock[0].count = 10;
480 	io.lockx.in.locks = &lock[0];
481 	status = smb_raw_lock(cli->tree, &io);
482 	CHECK_STATUS(status, NT_STATUS_OK);
483 
484 	t = time(NULL);
485 
486 	printf("testing cancel by CANCEL_LOCK\n");
487 
488 	/* setup a timed lock */
489 	io.lockx.in.timeout = 10000;
490 	req = smb_raw_lock_send(cli->tree, &io);
491 	if (req == NULL) {
492 		printf("Failed to setup timed lock (%s)\n", __location__);
493 		ret = False;
494 		goto done;
495 	}
496 
497 	/* cancel the wrong range */
498 	lock[0].offset = 0;
499 	io.lockx.in.timeout = 0;
500 	io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
501 	status = smb_raw_lock(cli->tree, &io);
502 	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
503 
504 	/* cancel with the wrong bits set */
505 	lock[0].offset = 100;
506 	io.lockx.in.timeout = 0;
507 	io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
508 	status = smb_raw_lock(cli->tree, &io);
509 	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
510 
511 	/* cancel the right range */
512 	lock[0].offset = 100;
513 	io.lockx.in.timeout = 0;
514 	io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
515 	status = smb_raw_lock(cli->tree, &io);
516 	CHECK_STATUS(status, NT_STATUS_OK);
517 
518 	/* receive the failed lock request */
519 	status = smbcli_request_simple_recv(req);
520 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
521 
522 	if (time(NULL) > t+2) {
523 		printf("lock cancel was not immediate (%s)\n", __location__);
524 		ret = False;
525 		goto done;
526 	}
527 
528 	printf("testing cancel by unlock\n");
529 	io.lockx.in.ulock_cnt = 0;
530 	io.lockx.in.lock_cnt = 1;
531 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
532 	io.lockx.in.timeout = 0;
533 	status = smb_raw_lock(cli->tree, &io);
534 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
535 
536 	io.lockx.in.timeout = 5000;
537 	req = smb_raw_lock_send(cli->tree, &io);
538 	if (req == NULL) {
539 		printf("Failed to setup timed lock (%s)\n", __location__);
540 		ret = False;
541 		goto done;
542 	}
543 
544 	io.lockx.in.ulock_cnt = 1;
545 	io.lockx.in.lock_cnt = 0;
546 	status = smb_raw_lock(cli->tree, &io);
547 	CHECK_STATUS(status, NT_STATUS_OK);
548 
549 	t = time(NULL);
550 	status = smbcli_request_simple_recv(req);
551 	CHECK_STATUS(status, NT_STATUS_OK);
552 
553 	if (time(NULL) > t+2) {
554 		printf("lock cancel by unlock was not immediate (%s) - took %d secs\n",
555 		       __location__, (int)(time(NULL)-t));
556 		ret = False;
557 		goto done;
558 	}
559 
560 	printf("testing cancel by close\n");
561 	io.lockx.in.ulock_cnt = 0;
562 	io.lockx.in.lock_cnt = 1;
563 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
564 	io.lockx.in.timeout = 0;
565 	status = smb_raw_lock(cli->tree, &io);
566 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
567 
568 	t = time(NULL);
569 	io.lockx.in.timeout = 10000;
570 	req = smb_raw_lock_send(cli->tree, &io);
571 	if (req == NULL) {
572 		printf("Failed to setup timed lock (%s)\n", __location__);
573 		ret = False;
574 		goto done;
575 	}
576 
577 	status = smbcli_close(cli->tree, fnum);
578 	CHECK_STATUS(status, NT_STATUS_OK);
579 
580 	status = smbcli_request_simple_recv(req);
581 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
582 
583 	if (time(NULL) > t+2) {
584 		printf("lock cancel by close was not immediate (%s)\n", __location__);
585 		ret = False;
586 		goto done;
587 	}
588 
589 	printf("create a new sessions\n");
590 	session = smbcli_session_init(cli->transport, mem_ctx, False);
591 	setup.in.sesskey = cli->transport->negotiate.sesskey;
592 	setup.in.capabilities = cli->transport->negotiate.capabilities;
593 	setup.in.workgroup = lp_workgroup();
594 	setup.in.credentials = cmdline_credentials;
595 	status = smb_composite_sesssetup(session, &setup);
596 	CHECK_STATUS(status, NT_STATUS_OK);
597 	session->vuid = setup.out.vuid;
598 
599 	printf("create new tree context\n");
600 	share = lp_parm_string(-1, "torture", "share");
601 	host  = lp_parm_string(-1, "torture", "host");
602 	tree = smbcli_tree_init(session, mem_ctx, False);
603 	tcon.generic.level = RAW_TCON_TCONX;
604 	tcon.tconx.in.flags = 0;
605 	tcon.tconx.in.password = data_blob(NULL, 0);
606 	tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
607 	tcon.tconx.in.device = "A:";
608 	status = smb_raw_tcon(tree, mem_ctx, &tcon);
609 	CHECK_STATUS(status, NT_STATUS_OK);
610 	tree->tid = tcon.tconx.out.tid;
611 
612 	printf("testing cancel by exit\n");
613 	fname = BASEDIR "\\test_exit.txt";
614 	fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
615 	if (fnum == -1) {
616 		printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
617 		ret = False;
618 		goto done;
619 	}
620 	io.lockx.level = RAW_LOCK_LOCKX;
621 	io.lockx.in.file.fnum = fnum;
622 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
623 	io.lockx.in.timeout = 0;
624 	io.lockx.in.ulock_cnt = 0;
625 	io.lockx.in.lock_cnt = 1;
626 	lock[0].pid = session->pid;
627 	lock[0].offset = 100;
628 	lock[0].count = 10;
629 	io.lockx.in.locks = &lock[0];
630 	status = smb_raw_lock(tree, &io);
631 	CHECK_STATUS(status, NT_STATUS_OK);
632 
633 	io.lockx.in.ulock_cnt = 0;
634 	io.lockx.in.lock_cnt = 1;
635 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
636 	io.lockx.in.timeout = 0;
637 	status = smb_raw_lock(tree, &io);
638 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
639 
640 	io.lockx.in.timeout = 10000;
641 	t = time(NULL);
642 	req = smb_raw_lock_send(tree, &io);
643 	if (req == NULL) {
644 		printf("Failed to setup timed lock (%s)\n", __location__);
645 		ret = False;
646 		goto done;
647 	}
648 
649 	status = smb_raw_exit(session);
650 	CHECK_STATUS(status, NT_STATUS_OK);
651 
652 	status = smbcli_request_simple_recv(req);
653 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
654 
655 	if (time(NULL) > t+2) {
656 		printf("lock cancel by exit was not immediate (%s)\n", __location__);
657 		ret = False;
658 		goto done;
659 	}
660 
661 	printf("testing cancel by ulogoff\n");
662 	fname = BASEDIR "\\test_ulogoff.txt";
663 	fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
664 	if (fnum == -1) {
665 		printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
666 		ret = False;
667 		goto done;
668 	}
669 	io.lockx.level = RAW_LOCK_LOCKX;
670 	io.lockx.in.file.fnum = fnum;
671 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
672 	io.lockx.in.timeout = 0;
673 	io.lockx.in.ulock_cnt = 0;
674 	io.lockx.in.lock_cnt = 1;
675 	lock[0].pid = session->pid;
676 	lock[0].offset = 100;
677 	lock[0].count = 10;
678 	io.lockx.in.locks = &lock[0];
679 	status = smb_raw_lock(tree, &io);
680 	CHECK_STATUS(status, NT_STATUS_OK);
681 
682 	io.lockx.in.ulock_cnt = 0;
683 	io.lockx.in.lock_cnt = 1;
684 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
685 	io.lockx.in.timeout = 0;
686 	status = smb_raw_lock(tree, &io);
687 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
688 
689 	io.lockx.in.timeout = 10000;
690 	t = time(NULL);
691 	req = smb_raw_lock_send(tree, &io);
692 	if (req == NULL) {
693 		printf("Failed to setup timed lock (%s)\n", __location__);
694 		ret = False;
695 		goto done;
696 	}
697 
698 	status = smb_raw_ulogoff(session);
699 	CHECK_STATUS(status, NT_STATUS_OK);
700 
701 	status = smbcli_request_simple_recv(req);
702 	if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
703 		printf("lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
704 			nt_errstr(status));
705 		smb_tree_disconnect(tree);
706 		smb_raw_exit(session);
707 		goto done;
708 	}
709 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
710 
711 	if (time(NULL) > t+2) {
712 		printf("lock cancel by ulogoff was not immediate (%s)\n", __location__);
713 		ret = False;
714 		goto done;
715 	}
716 
717 	printf("testing cancel by tdis\n");
718 	tree->session = cli->session;
719 
720 	fname = BASEDIR "\\test_tdis.txt";
721 	fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
722 	if (fnum == -1) {
723 		printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
724 		ret = False;
725 		goto done;
726 	}
727 	io.lockx.level = RAW_LOCK_LOCKX;
728 	io.lockx.in.file.fnum = fnum;
729 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
730 	io.lockx.in.timeout = 0;
731 	io.lockx.in.ulock_cnt = 0;
732 	io.lockx.in.lock_cnt = 1;
733 	lock[0].pid = cli->session->pid;
734 	lock[0].offset = 100;
735 	lock[0].count = 10;
736 	io.lockx.in.locks = &lock[0];
737 	status = smb_raw_lock(tree, &io);
738 	CHECK_STATUS(status, NT_STATUS_OK);
739 
740 	status = smb_raw_lock(tree, &io);
741 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
742 
743 	io.lockx.in.timeout = 10000;
744 	t = time(NULL);
745 	req = smb_raw_lock_send(tree, &io);
746 	if (req == NULL) {
747 		printf("Failed to setup timed lock (%s)\n", __location__);
748 		ret = False;
749 		goto done;
750 	}
751 
752 	status = smb_tree_disconnect(tree);
753 	CHECK_STATUS(status, NT_STATUS_OK);
754 
755 	status = smbcli_request_simple_recv(req);
756 	CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
757 
758 	if (time(NULL) > t+2) {
759 		printf("lock cancel by tdis was not immediate (%s)\n", __location__);
760 		ret = False;
761 		goto done;
762 	}
763 
764 done:
765 	smb_raw_exit(cli->session);
766 	smbcli_deltree(cli->tree, BASEDIR);
767 	return ret;
768 }
769 
770 /*
771   test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
772 */
test_errorcode(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)773 static BOOL test_errorcode(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
774 {
775 	union smb_lock io;
776 	union smb_open op;
777 	struct smb_lock_entry lock[2];
778 	NTSTATUS status;
779 	BOOL ret = True;
780 	int fnum, fnum2;
781 	const char *fname;
782 	struct smbcli_request *req;
783 	time_t start;
784 	int t;
785 
786 	if (!torture_setup_dir(cli, BASEDIR)) {
787 		return False;
788 	}
789 
790 	printf("Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
791 
792 	printf("testing with timeout = 0\n");
793 	fname = BASEDIR "\\test0.txt";
794 	t = 0;
795 
796 	/*
797 	 * the first run is with t = 0,
798 	 * the second with t > 0 (=1)
799 	 */
800 next_run:
801 	/*
802 	 * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
803 	 * this demonstrates that the cache is per fnum
804 	 */
805 	op.openx.level = RAW_OPEN_OPENX;
806 	op.openx.in.fname = fname;
807 	op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
808 	op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS;
809 	op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
810 	op.openx.in.search_attrs = 0;
811 	op.openx.in.file_attrs = 0;
812 	op.openx.in.write_time = 0;
813 	op.openx.in.size = 0;
814 	op.openx.in.timeout = 0;
815 
816 	status = smb_raw_open(cli->tree, mem_ctx, &op);
817 	CHECK_STATUS(status, NT_STATUS_OK);
818 	fnum = op.openx.out.file.fnum;
819 
820 	status = smb_raw_open(cli->tree, mem_ctx, &op);
821 	CHECK_STATUS(status, NT_STATUS_OK);
822 	fnum2 = op.openx.out.file.fnum;
823 
824 	io.lockx.level = RAW_LOCK_LOCKX;
825 	io.lockx.in.file.fnum = fnum;
826 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
827 	io.lockx.in.timeout = t;
828 	io.lockx.in.ulock_cnt = 0;
829 	io.lockx.in.lock_cnt = 1;
830 	lock[0].pid = cli->session->pid;
831 	lock[0].offset = 100;
832 	lock[0].count = 10;
833 	io.lockx.in.locks = &lock[0];
834 	status = smb_raw_lock(cli->tree, &io);
835 	CHECK_STATUS(status, NT_STATUS_OK);
836 
837 	/*
838 	 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
839 	 * this also demonstrates that the error code cache is per file handle
840 	 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
841 	 */
842 	io.lockx.in.file.fnum = fnum2;
843 	status = smb_raw_lock(cli->tree, &io);
844 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
845 
846 	io.lockx.in.file.fnum = fnum;
847 	status = smb_raw_lock(cli->tree, &io);
848 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
849 
850 	/* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
851 	io.lockx.in.file.fnum = fnum;
852 	status = smb_raw_lock(cli->tree, &io);
853 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
854 
855 	io.lockx.in.file.fnum = fnum2;
856 	status = smb_raw_lock(cli->tree, &io);
857 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
858 
859 	io.lockx.in.file.fnum = fnum;
860 	status = smb_raw_lock(cli->tree, &io);
861 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
862 
863 	io.lockx.in.file.fnum = fnum2;
864 	status = smb_raw_lock(cli->tree, &io);
865 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
866 
867 	/* demonstrate that the smbpid doesn't matter */
868 	lock[0].pid++;
869 	io.lockx.in.file.fnum = fnum;
870 	status = smb_raw_lock(cli->tree, &io);
871 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
872 
873 	io.lockx.in.file.fnum = fnum2;
874 	status = smb_raw_lock(cli->tree, &io);
875 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
876 	lock[0].pid--;
877 
878 	/*
879 	 * demonstrate the a successful lock with count = 0 and the same offset,
880 	 * doesn't reset the error cache
881 	 */
882 	lock[0].offset = 100;
883 	lock[0].count = 0;
884 	io.lockx.in.file.fnum = fnum;
885 	status = smb_raw_lock(cli->tree, &io);
886 	CHECK_STATUS(status, NT_STATUS_OK);
887 
888 	io.lockx.in.file.fnum = fnum2;
889 	status = smb_raw_lock(cli->tree, &io);
890 	CHECK_STATUS(status, NT_STATUS_OK);
891 
892 	lock[0].offset = 100;
893 	lock[0].count = 10;
894 	io.lockx.in.file.fnum = fnum;
895 	status = smb_raw_lock(cli->tree, &io);
896 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
897 
898 	io.lockx.in.file.fnum = fnum2;
899 	status = smb_raw_lock(cli->tree, &io);
900 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
901 
902 	/*
903 	 * demonstrate the a successful lock with count = 0 and outside the locked range,
904 	 * doesn't reset the error cache
905 	 */
906 	lock[0].offset = 110;
907 	lock[0].count = 0;
908 	io.lockx.in.file.fnum = fnum;
909 	status = smb_raw_lock(cli->tree, &io);
910 	CHECK_STATUS(status, NT_STATUS_OK);
911 
912 	io.lockx.in.file.fnum = fnum2;
913 	status = smb_raw_lock(cli->tree, &io);
914 	CHECK_STATUS(status, NT_STATUS_OK);
915 
916 	lock[0].offset = 100;
917 	lock[0].count = 10;
918 	io.lockx.in.file.fnum = fnum;
919 	status = smb_raw_lock(cli->tree, &io);
920 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
921 
922 	io.lockx.in.file.fnum = fnum2;
923 	status = smb_raw_lock(cli->tree, &io);
924 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
925 
926 	lock[0].offset = 99;
927 	lock[0].count = 0;
928 	io.lockx.in.file.fnum = fnum;
929 	status = smb_raw_lock(cli->tree, &io);
930 	CHECK_STATUS(status, NT_STATUS_OK);
931 
932 	io.lockx.in.file.fnum = fnum2;
933 	status = smb_raw_lock(cli->tree, &io);
934 	CHECK_STATUS(status, NT_STATUS_OK);
935 
936 	lock[0].offset = 100;
937 	lock[0].count = 10;
938 	io.lockx.in.file.fnum = fnum;
939 	status = smb_raw_lock(cli->tree, &io);
940 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
941 
942 	io.lockx.in.file.fnum = fnum2;
943 	status = smb_raw_lock(cli->tree, &io);
944 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
945 
946 	/* demonstrate that a changing count doesn't reset the error cache */
947 	lock[0].offset = 100;
948 	lock[0].count = 5;
949 	io.lockx.in.file.fnum = fnum;
950 	status = smb_raw_lock(cli->tree, &io);
951 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
952 
953 	io.lockx.in.file.fnum = fnum2;
954 	status = smb_raw_lock(cli->tree, &io);
955 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
956 
957 	lock[0].offset = 100;
958 	lock[0].count = 15;
959 	io.lockx.in.file.fnum = fnum;
960 	status = smb_raw_lock(cli->tree, &io);
961 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
962 
963 	io.lockx.in.file.fnum = fnum2;
964 	status = smb_raw_lock(cli->tree, &io);
965 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
966 
967 	/*
968 	 * demonstrate the a lock with count = 0 and inside the locked range,
969 	 * fails and resets the error cache
970 	 */
971 	lock[0].offset = 101;
972 	lock[0].count = 0;
973 	io.lockx.in.file.fnum = fnum;
974 	status = smb_raw_lock(cli->tree, &io);
975 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
976 	status = smb_raw_lock(cli->tree, &io);
977 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
978 
979 	io.lockx.in.file.fnum = fnum2;
980 	status = smb_raw_lock(cli->tree, &io);
981 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
982 	status = smb_raw_lock(cli->tree, &io);
983 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
984 
985 	lock[0].offset = 100;
986 	lock[0].count = 10;
987 	io.lockx.in.file.fnum = fnum;
988 	status = smb_raw_lock(cli->tree, &io);
989 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
990 	status = smb_raw_lock(cli->tree, &io);
991 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
992 
993 	io.lockx.in.file.fnum = fnum2;
994 	status = smb_raw_lock(cli->tree, &io);
995 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
996 	status = smb_raw_lock(cli->tree, &io);
997 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
998 
999 	/* demonstrate the a changing offset, resets the error cache */
1000 	lock[0].offset = 105;
1001 	lock[0].count = 10;
1002 	io.lockx.in.file.fnum = fnum;
1003 	status = smb_raw_lock(cli->tree, &io);
1004 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1005 	status = smb_raw_lock(cli->tree, &io);
1006 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1007 
1008 	io.lockx.in.file.fnum = fnum2;
1009 	status = smb_raw_lock(cli->tree, &io);
1010 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1011 	status = smb_raw_lock(cli->tree, &io);
1012 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1013 
1014 	lock[0].offset = 100;
1015 	lock[0].count = 10;
1016 	io.lockx.in.file.fnum = fnum;
1017 	status = smb_raw_lock(cli->tree, &io);
1018 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1019 	status = smb_raw_lock(cli->tree, &io);
1020 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1021 
1022 	io.lockx.in.file.fnum = fnum2;
1023 	status = smb_raw_lock(cli->tree, &io);
1024 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1025 	status = smb_raw_lock(cli->tree, &io);
1026 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1027 
1028 	lock[0].offset = 95;
1029 	lock[0].count = 9;
1030 	io.lockx.in.file.fnum = fnum;
1031 	status = smb_raw_lock(cli->tree, &io);
1032 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1033 	status = smb_raw_lock(cli->tree, &io);
1034 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1035 
1036 	io.lockx.in.file.fnum = fnum2;
1037 	status = smb_raw_lock(cli->tree, &io);
1038 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1039 	status = smb_raw_lock(cli->tree, &io);
1040 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1041 
1042 	lock[0].offset = 100;
1043 	lock[0].count = 10;
1044 	io.lockx.in.file.fnum = fnum;
1045 	status = smb_raw_lock(cli->tree, &io);
1046 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1047 	status = smb_raw_lock(cli->tree, &io);
1048 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1049 
1050 	io.lockx.in.file.fnum = fnum2;
1051 	status = smb_raw_lock(cli->tree, &io);
1052 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1053 	status = smb_raw_lock(cli->tree, &io);
1054 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1055 
1056 	/*
1057 	 * demonstrate the a successful lock in a different range,
1058 	 * doesn't reset the cache, the failing lock on the 2nd handle
1059 	 * resets the resets the cache
1060 	 */
1061 	lock[0].offset = 120;
1062 	lock[0].count = 15;
1063 	io.lockx.in.file.fnum = fnum;
1064 	status = smb_raw_lock(cli->tree, &io);
1065 	CHECK_STATUS(status, NT_STATUS_OK);
1066 
1067 	io.lockx.in.file.fnum = fnum2;
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 	lock[0].offset = 100;
1072 	lock[0].count = 10;
1073 	io.lockx.in.file.fnum = fnum;
1074 	status = smb_raw_lock(cli->tree, &io);
1075 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1076 	status = smb_raw_lock(cli->tree, &io);
1077 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1078 
1079 	io.lockx.in.file.fnum = fnum2;
1080 	status = smb_raw_lock(cli->tree, &io);
1081 	CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1082 	status = smb_raw_lock(cli->tree, &io);
1083 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1084 
1085 	/* end of the loop */
1086 	if (t == 0) {
1087 		smb_raw_exit(cli->session);
1088 		printf("testing with timeout > 0 (=1)\n");
1089 		fname = BASEDIR "\\test1.txt";
1090 		t = 1;
1091 		goto next_run;
1092 	}
1093 
1094 	/*
1095 	 * the following 3 test sections demonstrate that
1096 	 * the cache is only set when the error is reported
1097 	 * to the client (after the timeout went by)
1098 	 */
1099 	smb_raw_exit(cli->session);
1100 	printf("testing a conflict while a lock is pending\n");
1101 	fname = BASEDIR "\\test2.txt";
1102 	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1103 	if (fnum == -1) {
1104 		printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1105 		ret = False;
1106 		goto done;
1107 	}
1108 	io.lockx.level = RAW_LOCK_LOCKX;
1109 	io.lockx.in.file.fnum = fnum;
1110 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1111 	io.lockx.in.timeout = 0;
1112 	io.lockx.in.ulock_cnt = 0;
1113 	io.lockx.in.lock_cnt = 1;
1114 	lock[0].pid = cli->session->pid;
1115 	lock[0].offset = 100;
1116 	lock[0].count = 10;
1117 	io.lockx.in.locks = &lock[0];
1118 	status = smb_raw_lock(cli->tree, &io);
1119 	CHECK_STATUS(status, NT_STATUS_OK);
1120 
1121 	start = time(NULL);
1122 	io.lockx.in.timeout = 1000;
1123 	req = smb_raw_lock_send(cli->tree, &io);
1124 	if (req == NULL) {
1125 		printf("Failed to setup timed lock (%s)\n", __location__);
1126 		ret = False;
1127 		goto done;
1128 	}
1129 
1130 	io.lockx.in.timeout = 0;
1131 	lock[0].offset = 105;
1132 	lock[0].count = 10;
1133 	status = smb_raw_lock(cli->tree, &io);
1134 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1135 
1136 	status = smbcli_request_simple_recv(req);
1137 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1138 
1139 	status = smb_raw_lock(cli->tree, &io);
1140 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1141 
1142 	if (time(NULL) < start+1) {
1143 		printf("lock comes back to early (%s)\n", __location__);
1144 		ret = False;
1145 		goto done;
1146 	}
1147 
1148 	smbcli_close(cli->tree, fnum);
1149 	fname = BASEDIR "\\test3.txt";
1150 	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1151 	if (fnum == -1) {
1152 		printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1153 		ret = False;
1154 		goto done;
1155 	}
1156 	io.lockx.level = RAW_LOCK_LOCKX;
1157 	io.lockx.in.file.fnum = fnum;
1158 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1159 	io.lockx.in.timeout = 0;
1160 	io.lockx.in.ulock_cnt = 0;
1161 	io.lockx.in.lock_cnt = 1;
1162 	lock[0].pid = cli->session->pid;
1163 	lock[0].offset = 100;
1164 	lock[0].count = 10;
1165 	io.lockx.in.locks = &lock[0];
1166 	status = smb_raw_lock(cli->tree, &io);
1167 	CHECK_STATUS(status, NT_STATUS_OK);
1168 
1169 	start = time(NULL);
1170 	io.lockx.in.timeout = 1000;
1171 	req = smb_raw_lock_send(cli->tree, &io);
1172 	if (req == NULL) {
1173 		printf("Failed to setup timed lock (%s)\n", __location__);
1174 		ret = False;
1175 		goto done;
1176 	}
1177 
1178 	io.lockx.in.timeout = 0;
1179 	lock[0].offset = 105;
1180 	lock[0].count = 10;
1181 	status = smb_raw_lock(cli->tree, &io);
1182 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1183 
1184 	status = smbcli_request_simple_recv(req);
1185 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1186 
1187 	lock[0].offset = 100;
1188 	lock[0].count = 10;
1189 	status = smb_raw_lock(cli->tree, &io);
1190 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1191 
1192 	if (time(NULL) < start+1) {
1193 		printf("lock comes back to early (%s)\n", __location__);
1194 		ret = False;
1195 		goto done;
1196 	}
1197 
1198 	smbcli_close(cli->tree, fnum);
1199 	fname = BASEDIR "\\test4.txt";
1200 	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1201 	if (fnum == -1) {
1202 		printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1203 		ret = False;
1204 		goto done;
1205 	}
1206 	io.lockx.level = RAW_LOCK_LOCKX;
1207 	io.lockx.in.file.fnum = fnum;
1208 	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1209 	io.lockx.in.timeout = 0;
1210 	io.lockx.in.ulock_cnt = 0;
1211 	io.lockx.in.lock_cnt = 1;
1212 	lock[0].pid = cli->session->pid;
1213 	lock[0].offset = 100;
1214 	lock[0].count = 10;
1215 	io.lockx.in.locks = &lock[0];
1216 	status = smb_raw_lock(cli->tree, &io);
1217 	CHECK_STATUS(status, NT_STATUS_OK);
1218 
1219 	start = time(NULL);
1220 	io.lockx.in.timeout = 1000;
1221 	req = smb_raw_lock_send(cli->tree, &io);
1222 	if (req == NULL) {
1223 		printf("Failed to setup timed lock (%s)\n", __location__);
1224 		ret = False;
1225 		goto done;
1226 	}
1227 
1228 	io.lockx.in.timeout = 0;
1229 	status = smb_raw_lock(cli->tree, &io);
1230 	CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1231 
1232 	status = smbcli_request_simple_recv(req);
1233 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1234 
1235 	status = smb_raw_lock(cli->tree, &io);
1236 	CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1237 
1238 	if (time(NULL) < start+1) {
1239 		printf("lock comes back to early (%s)\n", __location__);
1240 		ret = False;
1241 		goto done;
1242 	}
1243 
1244 done:
1245 	smb_raw_exit(cli->session);
1246 	smbcli_deltree(cli->tree, BASEDIR);
1247 	return ret;
1248 }
1249 
1250 
1251 /*
1252   test LOCKING_ANDX_CHANGE_LOCKTYPE
1253 */
test_changetype(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1254 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1255 {
1256 	union smb_lock io;
1257 	struct smb_lock_entry lock[2];
1258 	NTSTATUS status;
1259 	BOOL ret = True;
1260 	int fnum;
1261 	uint8_t c = 0;
1262 	const char *fname = BASEDIR "\\test.txt";
1263 
1264 	if (!torture_setup_dir(cli, BASEDIR)) {
1265 		return False;
1266 	}
1267 
1268 	printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1269 	io.generic.level = RAW_LOCK_LOCKX;
1270 
1271 	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1272 	if (fnum == -1) {
1273 		printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1274 		ret = False;
1275 		goto done;
1276 	}
1277 
1278 	io.lockx.level = RAW_LOCK_LOCKX;
1279 	io.lockx.in.file.fnum = fnum;
1280 	io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1281 	io.lockx.in.timeout = 0;
1282 	io.lockx.in.ulock_cnt = 0;
1283 	io.lockx.in.lock_cnt = 1;
1284 	lock[0].pid = cli->session->pid;
1285 	lock[0].offset = 100;
1286 	lock[0].count = 10;
1287 	io.lockx.in.locks = &lock[0];
1288 	status = smb_raw_lock(cli->tree, &io);
1289 	CHECK_STATUS(status, NT_STATUS_OK);
1290 
1291 	if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1292 		printf("allowed write on read locked region (%s)\n", __location__);
1293 		ret = False;
1294 		goto done;
1295 	}
1296 
1297 	/* windows server don't seem to support this */
1298 	io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1299 	status = smb_raw_lock(cli->tree, &io);
1300 	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1301 
1302 	if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1303 		printf("allowed write after lock change (%s)\n", __location__);
1304 		ret = False;
1305 		goto done;
1306 	}
1307 
1308 done:
1309 	smbcli_close(cli->tree, fnum);
1310 	smb_raw_exit(cli->session);
1311 	smbcli_deltree(cli->tree, BASEDIR);
1312 	return ret;
1313 }
1314 
1315 
1316 /*
1317    basic testing of lock calls
1318 */
torture_raw_lock(struct torture_context * torture)1319 BOOL torture_raw_lock(struct torture_context *torture)
1320 {
1321 	struct smbcli_state *cli;
1322 	BOOL ret = True;
1323 	TALLOC_CTX *mem_ctx;
1324 
1325 	if (!torture_open_connection(&cli, 0)) {
1326 		return False;
1327 	}
1328 
1329 	mem_ctx = talloc_init("torture_raw_lock");
1330 
1331 	ret &= test_lockx(cli, mem_ctx);
1332 	ret &= test_lock(cli, mem_ctx);
1333 	ret &= test_pidhigh(cli, mem_ctx);
1334 	ret &= test_async(cli, mem_ctx);
1335 	ret &= test_errorcode(cli, mem_ctx);
1336 	ret &= test_changetype(cli, mem_ctx);
1337 
1338 	torture_close_connection(cli);
1339 	talloc_free(mem_ctx);
1340 	return ret;
1341 }
1342