19cda2f3e69a3c197aeffb7d373a93dc2c201fb7
[gd/samba-autobuild/.git] / source4 / torture / smb2 / replay.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    test suite for SMB2 replay
5
6    Copyright (C) Anubhav Rakshit 2014
7    Copyright (C) Stefan Metzmacher 2014
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "../libcli/smb/smbXcli_base.h"
29 #include "lib/cmdline/popt_common.h"
30 #include "auth/credentials/credentials.h"
31 #include "libcli/security/security.h"
32 #include "libcli/resolve/resolve.h"
33 #include "lib/param/param.h"
34 #include "lib/events/events.h"
35
36 #define CHECK_VAL(v, correct) do { \
37         if ((v) != (correct)) { \
38                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
39                                 __location__, #v, (int)v, (int)correct); \
40                 ret = false; \
41                 goto done; \
42         }} while (0)
43
44 #define CHECK_STATUS(status, correct) do { \
45         if (!NT_STATUS_EQUAL(status, correct)) { \
46                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
47                        nt_errstr(status), nt_errstr(correct)); \
48                 ret = false; \
49                 goto done; \
50         }} while (0)
51
52 #define CHECK_CREATED(__io, __created, __attribute)                     \
53         do {                                                            \
54                 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
55                 CHECK_VAL((__io)->out.alloc_size, 0);                   \
56                 CHECK_VAL((__io)->out.size, 0);                         \
57                 CHECK_VAL((__io)->out.file_attr, (__attribute));        \
58                 CHECK_VAL((__io)->out.reserved2, 0);                    \
59         } while(0)
60
61 #define CHECK_HANDLE(__h1, __h2)                                        \
62         do {                                                            \
63                 CHECK_VAL((__h1)->data[0], (__h2)->data[0]);            \
64                 CHECK_VAL((__h1)->data[1], (__h2)->data[1]);            \
65         } while(0)
66
67 #define __IO_OUT_VAL(__io1, __io2, __m) \
68         CHECK_VAL((__io1)->out.__m, (__io2)->out.__m)
69
70 #define CHECK_CREATE_OUT(__io1, __io2)                          \
71         do {                                                    \
72                 CHECK_HANDLE(&(__io1)->out.file.handle,         \
73                              &(__io2)->out.file.handle);        \
74                 __IO_OUT_VAL(__io1, __io2, oplock_level);       \
75                 __IO_OUT_VAL(__io1, __io2, create_action);      \
76                 __IO_OUT_VAL(__io1, __io2, create_time);        \
77                 __IO_OUT_VAL(__io1, __io2, access_time);        \
78                 __IO_OUT_VAL(__io1, __io2, write_time);         \
79                 __IO_OUT_VAL(__io1, __io2, change_time);        \
80                 __IO_OUT_VAL(__io1, __io2, alloc_size);         \
81                 __IO_OUT_VAL(__io1, __io2, size);               \
82                 __IO_OUT_VAL(__io1, __io2, file_attr);          \
83                 __IO_OUT_VAL(__io1, __io2, durable_open);       \
84                 __IO_OUT_VAL(__io1, __io2, durable_open_v2);    \
85                 __IO_OUT_VAL(__io1, __io2, persistent_open);    \
86                 __IO_OUT_VAL(__io1, __io2, timeout);            \
87                 __IO_OUT_VAL(__io1, __io2, blobs.num_blobs);    \
88                 if ((__io1)->out.oplock_level == SMB2_OPLOCK_LEVEL_LEASE) { \
89                         __IO_OUT_VAL(__io1, __io2, lease_response.lease_state);\
90                         __IO_OUT_VAL(__io1, __io2, lease_response.lease_key.data[0]);\
91                         __IO_OUT_VAL(__io1, __io2, lease_response.lease_key.data[1]);\
92                 } \
93         } while(0)
94
95 #define BASEDIR "replaytestdir"
96
97 struct break_info {
98         struct torture_context *tctx;
99         struct smb2_handle handle;
100         uint8_t level;
101         struct smb2_break br;
102         int count;
103         int failures;
104         NTSTATUS failure_status;
105 };
106
107 static struct break_info break_info;
108
109 static void torture_reset_break_info(struct torture_context *tctx,
110                                      struct break_info *r)
111 {
112         ZERO_STRUCTP(r);
113         r->tctx = tctx;
114 }
115
116 static void torture_oplock_ack_callback(struct smb2_request *req)
117 {
118         NTSTATUS status;
119
120         status = smb2_break_recv(req, &break_info.br);
121         if (!NT_STATUS_IS_OK(status)) {
122                 break_info.failures++;
123                 break_info.failure_status = status;
124         }
125
126         return;
127 }
128
129 /**
130  * A general oplock break notification handler.  This should be used when a
131  * test expects to break from batch or exclusive to a lower level.
132  */
133 static bool torture_oplock_ack_handler(struct smb2_transport *transport,
134                                        const struct smb2_handle *handle,
135                                        uint8_t level,
136                                        void *private_data)
137 {
138         struct smb2_tree *tree = private_data;
139         const char *name;
140         struct smb2_request *req;
141
142         ZERO_STRUCT(break_info.br);
143
144         break_info.handle       = *handle;
145         break_info.level        = level;
146         break_info.count++;
147
148         switch (level) {
149         case SMB2_OPLOCK_LEVEL_II:
150                 name = "level II";
151                 break;
152         case SMB2_OPLOCK_LEVEL_NONE:
153                 name = "none";
154                 break;
155         default:
156                 name = "unknown";
157                 break_info.failures++;
158         }
159         torture_comment(break_info.tctx,
160                         "Acking to %s [0x%02X] in oplock handler\n",
161                         name, level);
162
163         break_info.br.in.file.handle    = *handle;
164         break_info.br.in.oplock_level   = level;
165         break_info.br.in.reserved       = 0;
166         break_info.br.in.reserved2      = 0;
167
168         req = smb2_break_send(tree, &break_info.br);
169         req->async.fn = torture_oplock_ack_callback;
170         req->async.private_data = NULL;
171         return true;
172 }
173
174 /**
175  * Timer handler function notifies the registering function that time is up
176  */
177 static void timeout_cb(struct tevent_context *ev,
178                        struct tevent_timer *te,
179                        struct timeval current_time,
180                        void *private_data)
181 {
182         bool *timesup = (bool *)private_data;
183         *timesup = true;
184         return;
185 }
186
187 /**
188  *  Wait a short period of time to receive a single oplock break request
189  */
190 static void torture_wait_for_oplock_break(struct torture_context *tctx)
191 {
192         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
193         struct tevent_timer *te = NULL;
194         struct timeval ne;
195         bool timesup = false;
196         int old_count = break_info.count;
197
198         /* Wait .1 seconds for an oplock break */
199         ne = tevent_timeval_current_ofs(0, 100000);
200
201         te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup);
202         if (te == NULL) {
203                 torture_comment(tctx, "Failed to wait for an oplock break. "
204                                       "test results may not be accurate.");
205                 goto done;
206         }
207
208         while (!timesup && break_info.count < old_count + 1) {
209                 if (tevent_loop_once(tctx->ev) != 0) {
210                         torture_comment(tctx, "Failed to wait for an oplock "
211                                               "break. test results may not be "
212                                               "accurate.");
213                         goto done;
214                 }
215         }
216
217 done:
218         /*
219          * We don't know if the timed event fired and was freed, we received
220          * our oplock break, or some other event triggered the loop.  Thus,
221          * we create a tmp_ctx to be able to safely free/remove the timed
222          * event in all 3 cases.
223          */
224         talloc_free(tmp_ctx);
225
226         return;
227 }
228
229 /**
230  * Test what happens when SMB2_FLAGS_REPLAY_OPERATION is enabled for various
231  * commands. We want to verify if the server returns an error code or not.
232  */
233 static bool test_replay_commands(struct torture_context *tctx, struct smb2_tree *tree)
234 {
235         bool ret = true;
236         NTSTATUS status;
237         struct smb2_handle h;
238         uint8_t buf[200];
239         struct smb2_read rd;
240         union smb_setfileinfo sfinfo;
241         union smb_fileinfo qfinfo;
242         union smb_ioctl ioctl;
243         struct smb2_lock lck;
244         struct smb2_lock_element el[2];
245         struct smb2_flush f;
246         TALLOC_CTX *tmp_ctx = talloc_new(tree);
247         const char *fname = BASEDIR "\\replay_commands.dat";
248         struct smb2_transport *transport = tree->session->transport;
249
250         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
251                 torture_skip(tctx, "SMB 3.X Dialect family required for "
252                                    "Replay tests\n");
253         }
254
255         ZERO_STRUCT(break_info);
256         break_info.tctx = tctx;
257         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
258         tree->session->transport->oplock.private_data = tree;
259
260         status = torture_smb2_testdir(tree, BASEDIR, &h);
261         CHECK_STATUS(status, NT_STATUS_OK);
262         smb2_util_close(tree, h);
263
264         smb2cli_session_start_replay(tree->session->smbXcli);
265
266         torture_comment(tctx, "Try Commands with Replay Flags Enabled\n");
267
268         torture_comment(tctx, "Trying create\n");
269         status = torture_smb2_testfile(tree, fname, &h);
270         CHECK_STATUS(status, NT_STATUS_OK);
271         CHECK_VAL(break_info.count, 0);
272         /*
273          * Wireshark shows that the response has SMB2_FLAGS_REPLAY_OPERATION
274          * flags set. The server should ignore this flag.
275          */
276
277         torture_comment(tctx, "Trying write\n");
278         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
279         CHECK_STATUS(status, NT_STATUS_OK);
280
281         f = (struct smb2_flush) {
282                 .in.file.handle = h
283         };
284         torture_comment(tctx, "Trying flush\n");
285         status = smb2_flush(tree, &f);
286         CHECK_STATUS(status, NT_STATUS_OK);
287
288         rd = (struct smb2_read) {
289                 .in.file.handle = h,
290                 .in.length = 10,
291                 .in.offset = 0,
292                 .in.min_count = 1
293         };
294         torture_comment(tctx, "Trying read\n");
295         status = smb2_read(tree, tmp_ctx, &rd);
296         CHECK_STATUS(status, NT_STATUS_OK);
297         CHECK_VAL(rd.out.data.length, 10);
298
299         sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
300         sfinfo.position_information.in.file.handle = h;
301         sfinfo.position_information.in.position = 0x1000;
302         torture_comment(tctx, "Trying setinfo\n");
303         status = smb2_setinfo_file(tree, &sfinfo);
304         CHECK_STATUS(status, NT_STATUS_OK);
305
306         qfinfo = (union smb_fileinfo) {
307                 .generic.level = RAW_SFILEINFO_POSITION_INFORMATION,
308                 .generic.in.file.handle = h
309         };
310         torture_comment(tctx, "Trying getinfo\n");
311         status = smb2_getinfo_file(tree, tmp_ctx, &qfinfo);
312         CHECK_STATUS(status, NT_STATUS_OK);
313         CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
314
315         ioctl = (union smb_ioctl) {
316                 .smb2.level = RAW_IOCTL_SMB2,
317                 .smb2.in.file.handle = h,
318                 .smb2.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID,
319                 .smb2.in.max_response_size = 64,
320                 .smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL
321         };
322         torture_comment(tctx, "Trying ioctl\n");
323         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
324         CHECK_STATUS(status, NT_STATUS_OK);
325
326         lck = (struct smb2_lock) {
327                 .in.locks = el,
328                 .in.lock_count = 0x0001,
329                 .in.lock_sequence = 0x00000000,
330                 .in.file.handle = h
331         };
332         el[0].reserved          = 0x00000000;
333         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
334                 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
335
336         torture_comment(tctx, "Trying lock\n");
337         el[0].offset            = 0x0000000000000000;
338         el[0].length            = 0x0000000000000100;
339         status = smb2_lock(tree, &lck);
340         CHECK_STATUS(status, NT_STATUS_OK);
341
342         lck.in.file.handle      = h;
343         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
344         status = smb2_lock(tree, &lck);
345         CHECK_STATUS(status, NT_STATUS_OK);
346
347         CHECK_VAL(break_info.count, 0);
348 done:
349         smb2cli_session_stop_replay(tree->session->smbXcli);
350         smb2_util_close(tree, h);
351         smb2_deltree(tree, BASEDIR);
352
353         talloc_free(tmp_ctx);
354
355         return ret;
356 }
357
358 /**
359  * Test replay detection without create GUID on single channel.
360  * Regular creates can not be replayed.
361  * The return code is unaffected of the REPLAY_OPERATION flag.
362  */
363 static bool test_replay_regular(struct torture_context *tctx,
364                                 struct smb2_tree *tree)
365 {
366         NTSTATUS status;
367         TALLOC_CTX *mem_ctx = talloc_new(tctx);
368         struct smb2_handle _h;
369         struct smb2_handle *h = NULL;
370         struct smb2_create io;
371         uint32_t perms = 0;
372         bool ret = true;
373         const char *fname = BASEDIR "\\replay_regular.dat";
374         struct smb2_transport *transport = tree->session->transport;
375
376         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
377                 torture_skip(tctx, "SMB 3.X Dialect family required for "
378                                    "replay tests\n");
379         }
380
381         ZERO_STRUCT(break_info);
382         break_info.tctx = tctx;
383         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
384         tree->session->transport->oplock.private_data = tree;
385
386         smb2_util_unlink(tree, fname);
387         status = torture_smb2_testdir(tree, BASEDIR, &_h);
388         CHECK_STATUS(status, NT_STATUS_OK);
389         smb2_util_close(tree, _h);
390         CHECK_VAL(break_info.count, 0);
391
392         torture_comment(tctx, "No replay detection for regular create\n");
393
394         perms = SEC_STD_SYNCHRONIZE | SEC_STD_READ_CONTROL | SEC_STD_DELETE |
395                 SEC_DIR_WRITE_ATTRIBUTE | SEC_DIR_READ_ATTRIBUTE |
396                 SEC_DIR_WRITE_EA | SEC_FILE_APPEND_DATA |
397                 SEC_FILE_WRITE_DATA;
398
399         io = (struct smb2_create) {
400                 .in.desired_access  = perms,
401                 .in.file_attributes = 0,
402                 .in.create_disposition = NTCREATEX_DISP_CREATE,
403                 .in.share_access    = NTCREATEX_SHARE_ACCESS_DELETE,
404                 .in.create_options  = 0x0,
405                 .in.fname   = fname
406         };
407
408         status = smb2_create(tree, tctx, &io);
409         CHECK_STATUS(status, NT_STATUS_OK);
410         CHECK_VAL(break_info.count, 0);
411         _h = io.out.file.handle;
412         h = &_h;
413         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
414
415         smb2cli_session_start_replay(tree->session->smbXcli);
416         status = smb2_create(tree, tctx, &io);
417         smb2cli_session_stop_replay(tree->session->smbXcli);
418         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
419         CHECK_VAL(break_info.count, 0);
420
421         smb2_util_close(tree, *h);
422         h = NULL;
423         smb2_util_unlink(tree, fname);
424
425         /*
426          * Same experiment with different create disposition.
427          */
428         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
429         status = smb2_create(tree, tctx, &io);
430         CHECK_STATUS(status, NT_STATUS_OK);
431         CHECK_VAL(break_info.count, 0);
432         _h = io.out.file.handle;
433         h = &_h;
434         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
435
436         smb2cli_session_start_replay(tree->session->smbXcli);
437         status = smb2_create(tree, tctx, &io);
438         smb2cli_session_stop_replay(tree->session->smbXcli);
439         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
440         CHECK_VAL(break_info.count, 0);
441
442         smb2_util_close(tree, *h);
443         h = NULL;
444         smb2_util_unlink(tree, fname);
445
446         /*
447          * Now with more generous share mode.
448          */
449         io.in.share_access = smb2_util_share_access("RWD");
450         status = smb2_create(tree, tctx, &io);
451         CHECK_STATUS(status, NT_STATUS_OK);
452         CHECK_VAL(break_info.count, 0);
453         _h = io.out.file.handle;
454         h = &_h;
455         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
456
457         smb2cli_session_start_replay(tree->session->smbXcli);
458         status = smb2_create(tree, tctx, &io);
459         smb2cli_session_stop_replay(tree->session->smbXcli);
460         CHECK_STATUS(status, NT_STATUS_OK);
461         CHECK_VAL(break_info.count, 0);
462
463 done:
464         if (h != NULL) {
465                 smb2_util_close(tree, *h);
466         }
467         smb2_deltree(tree, BASEDIR);
468
469         talloc_free(tree);
470         talloc_free(mem_ctx);
471
472         return ret;
473 }
474
475 /**
476  * Test Durablity V2 Create Replay Detection on Single Channel.
477  */
478 static bool test_replay_dhv2_oplock1(struct torture_context *tctx,
479                                      struct smb2_tree *tree)
480 {
481         NTSTATUS status;
482         TALLOC_CTX *mem_ctx = talloc_new(tctx);
483         struct smb2_handle _h;
484         struct smb2_handle *h = NULL;
485         struct smb2_create io, ref1;
486         struct GUID create_guid = GUID_random();
487         bool ret = true;
488         const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat";
489         struct smb2_transport *transport = tree->session->transport;
490         uint32_t share_capabilities;
491         bool share_is_so;
492
493         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
494                 torture_skip(tctx, "SMB 3.X Dialect family required for "
495                                    "replay tests\n");
496         }
497
498         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
499         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
500
501         ZERO_STRUCT(break_info);
502         break_info.tctx = tctx;
503         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
504         tree->session->transport->oplock.private_data = tree;
505
506         torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
507                               "Channel\n");
508         smb2_util_unlink(tree, fname);
509         status = torture_smb2_testdir(tree, BASEDIR, &_h);
510         CHECK_STATUS(status, NT_STATUS_OK);
511         smb2_util_close(tree, _h);
512         CHECK_VAL(break_info.count, 0);
513
514         smb2_oplock_create_share(&io, fname,
515                         smb2_util_share_access(""),
516                         smb2_util_oplock_level("b"));
517         io.in.durable_open = false;
518         io.in.durable_open_v2 = true;
519         io.in.persistent_open = false;
520         io.in.create_guid = create_guid;
521         io.in.timeout = UINT32_MAX;
522
523         status = smb2_create(tree, mem_ctx, &io);
524         CHECK_STATUS(status, NT_STATUS_OK);
525         ref1 = io;
526         _h = io.out.file.handle;
527         h = &_h;
528         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
529         CHECK_VAL(io.out.durable_open, false);
530         if (share_is_so) {
531                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
532                 CHECK_VAL(io.out.durable_open_v2, false);
533                 CHECK_VAL(io.out.timeout, 0);
534         } else {
535                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
536                 CHECK_VAL(io.out.durable_open_v2, true);
537                 CHECK_VAL(io.out.timeout, io.in.timeout);
538         }
539
540         /*
541          * Replay Durable V2 Create on single channel
542          */
543         smb2cli_session_start_replay(tree->session->smbXcli);
544         status = smb2_create(tree, mem_ctx, &io);
545         smb2cli_session_stop_replay(tree->session->smbXcli);
546         CHECK_STATUS(status, NT_STATUS_OK);
547         CHECK_CREATE_OUT(&io, &ref1);
548         CHECK_VAL(break_info.count, 0);
549
550 done:
551         if (h != NULL) {
552                 smb2_util_close(tree, *h);
553         }
554         smb2_deltree(tree, BASEDIR);
555
556         talloc_free(tree);
557         talloc_free(mem_ctx);
558
559         return ret;
560 }
561
562 /**
563  * Test Durablity V2 Create Replay Detection on Single Channel.
564  * Hand in a different oplock level in the replay.
565  * Server responds with the handed in oplock level and
566  * corresponding durable status, but does not change the
567  * oplock level or durable status of the opened file.
568  */
569 static bool test_replay_dhv2_oplock2(struct torture_context *tctx,
570                                       struct smb2_tree *tree)
571 {
572         NTSTATUS status;
573         TALLOC_CTX *mem_ctx = talloc_new(tctx);
574         struct smb2_handle _h;
575         struct smb2_handle *h = NULL;
576         struct smb2_create io, ref1, ref2;
577         struct GUID create_guid = GUID_random();
578         bool ret = true;
579         const char *fname = BASEDIR "\\replay_dhv2_oplock2.dat";
580         struct smb2_transport *transport = tree->session->transport;
581         uint32_t share_capabilities;
582         bool share_is_so;
583
584         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
585                 torture_skip(tctx, "SMB 3.X Dialect family required for "
586                                    "replay tests\n");
587         }
588
589         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
590         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
591
592         ZERO_STRUCT(break_info);
593         break_info.tctx = tctx;
594         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
595         tree->session->transport->oplock.private_data = tree;
596
597         torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
598                               "Channel\n");
599         smb2_util_unlink(tree, fname);
600         status = torture_smb2_testdir(tree, BASEDIR, &_h);
601         CHECK_STATUS(status, NT_STATUS_OK);
602         smb2_util_close(tree, _h);
603         CHECK_VAL(break_info.count, 0);
604
605         smb2_oplock_create_share(&io, fname,
606                         smb2_util_share_access(""),
607                         smb2_util_oplock_level("b"));
608         io.in.durable_open = false;
609         io.in.durable_open_v2 = true;
610         io.in.persistent_open = false;
611         io.in.create_guid = create_guid;
612         io.in.timeout = UINT32_MAX;
613
614         status = smb2_create(tree, mem_ctx, &io);
615         CHECK_STATUS(status, NT_STATUS_OK);
616         ref1 = io;
617         _h = io.out.file.handle;
618         h = &_h;
619         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
620         CHECK_VAL(io.out.durable_open, false);
621         if (share_is_so) {
622                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
623                 CHECK_VAL(io.out.durable_open_v2, false);
624                 CHECK_VAL(io.out.timeout, 0);
625         } else {
626                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
627                 CHECK_VAL(io.out.durable_open_v2, true);
628                 CHECK_VAL(io.out.timeout, io.in.timeout);
629         }
630
631         /*
632          * Replay durable v2 create on single channel:
633          *
634          * Replay the create with a different oplock (none).
635          * The server replies with the requested oplock level
636          * and also only replies with durable handle based
637          * on whether it could have been granted based on
638          * the requested oplock type.
639          */
640         smb2_oplock_create_share(&io, fname,
641                         smb2_util_share_access(""),
642                         smb2_util_oplock_level(""));
643         io.in.durable_open = false;
644         io.in.durable_open_v2 = true;
645         io.in.persistent_open = false;
646         io.in.create_guid = create_guid;
647         io.in.timeout = UINT32_MAX;
648
649         /*
650          * Adapt the response to the exepected values
651          */
652         ref2 = ref1;
653         ref2.out.oplock_level = smb2_util_oplock_level("");
654         ref2.out.durable_open_v2 = false;
655         ref2.out.timeout = 0;
656         ref2.out.blobs.num_blobs = 0;
657
658         smb2cli_session_start_replay(tree->session->smbXcli);
659         status = smb2_create(tree, mem_ctx, &io);
660         smb2cli_session_stop_replay(tree->session->smbXcli);
661         CHECK_STATUS(status, NT_STATUS_OK);
662         CHECK_CREATE_OUT(&io, &ref2);
663         CHECK_VAL(break_info.count, 0);
664
665         /*
666          * Prove that the open file still has a batch oplock
667          * by breaking it with another open.
668          */
669         smb2_oplock_create_share(&io, fname,
670                         smb2_util_share_access(""),
671                         smb2_util_oplock_level("b"));
672         io.in.durable_open = false;
673         io.in.durable_open_v2 = true;
674         io.in.persistent_open = false;
675         io.in.create_guid = GUID_random();
676         io.in.timeout = UINT32_MAX;
677         status = smb2_create(tree, mem_ctx, &io);
678         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
679
680         if (!share_is_so) {
681                 CHECK_VAL(break_info.count, 1);
682                 CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle);
683                 CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
684                 ZERO_STRUCT(break_info);
685         }
686
687 done:
688         if (h != NULL) {
689                 smb2_util_close(tree, *h);
690         }
691         smb2_deltree(tree, BASEDIR);
692
693         talloc_free(tree);
694         talloc_free(mem_ctx);
695
696         return ret;
697 }
698
699 /**
700  * Test Durablity V2 Create Replay Detection on Single Channel.
701  * Replay with a different share mode. The share mode of
702  * the opened file is not changed by this.
703  */
704 static bool test_replay_dhv2_oplock3(struct torture_context *tctx,
705                                      struct smb2_tree *tree)
706 {
707         NTSTATUS status;
708         TALLOC_CTX *mem_ctx = talloc_new(tctx);
709         struct smb2_handle _h;
710         struct smb2_handle *h = NULL;
711         struct smb2_create io, ref1;
712         struct GUID create_guid = GUID_random();
713         bool ret = true;
714         const char *fname = BASEDIR "\\replay_dhv2_oplock3.dat";
715         struct smb2_transport *transport = tree->session->transport;
716         uint32_t share_capabilities;
717         bool share_is_so;
718
719         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
720                 torture_skip(tctx, "SMB 3.X Dialect family required for "
721                                    "replay tests\n");
722         }
723
724         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
725         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
726
727         ZERO_STRUCT(break_info);
728         break_info.tctx = tctx;
729         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
730         tree->session->transport->oplock.private_data = tree;
731
732         torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
733                               "Channel\n");
734         smb2_util_unlink(tree, fname);
735         status = torture_smb2_testdir(tree, BASEDIR, &_h);
736         CHECK_STATUS(status, NT_STATUS_OK);
737         smb2_util_close(tree, _h);
738         CHECK_VAL(break_info.count, 0);
739
740         smb2_oplock_create_share(&io, fname,
741                         smb2_util_share_access(""),
742                         smb2_util_oplock_level("b"));
743         io.in.durable_open = false;
744         io.in.durable_open_v2 = true;
745         io.in.persistent_open = false;
746         io.in.create_guid = create_guid;
747         io.in.timeout = UINT32_MAX;
748
749         status = smb2_create(tree, mem_ctx, &io);
750         CHECK_STATUS(status, NT_STATUS_OK);
751         ref1 = io;
752         _h = io.out.file.handle;
753         h = &_h;
754         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
755         CHECK_VAL(io.out.durable_open, false);
756         if (share_is_so) {
757                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
758                 CHECK_VAL(io.out.durable_open_v2, false);
759                 CHECK_VAL(io.out.timeout, 0);
760         } else {
761                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
762                 CHECK_VAL(io.out.durable_open_v2, true);
763                 CHECK_VAL(io.out.timeout, io.in.timeout);
764         }
765
766         /*
767          * Replay durable v2 create on single channel:
768          *
769          * Replay the create with a different share mode.
770          * The server replies with the requested share
771          * mode instead of that which is associated to
772          * the handle.
773          */
774         smb2_oplock_create_share(&io, fname,
775                         smb2_util_share_access("RWD"),
776                         smb2_util_oplock_level("b"));
777         io.in.durable_open = false;
778         io.in.durable_open_v2 = true;
779         io.in.persistent_open = false;
780         io.in.create_guid = create_guid;
781         io.in.timeout = UINT32_MAX;
782
783         smb2cli_session_start_replay(tree->session->smbXcli);
784         status = smb2_create(tree, mem_ctx, &io);
785         smb2cli_session_stop_replay(tree->session->smbXcli);
786         CHECK_STATUS(status, NT_STATUS_OK);
787         CHECK_CREATE_OUT(&io, &ref1);
788         CHECK_VAL(break_info.count, 0);
789
790         /*
791          * In order to prove that the different share mode in the
792          * replayed create had no effect on the open file handle,
793          * show that a new create yields NT_STATUS_SHARING_VIOLATION.
794          */
795         smb2_oplock_create_share(&io, fname,
796                         smb2_util_share_access(""),
797                         smb2_util_oplock_level("b"));
798         io.in.durable_open = false;
799         io.in.durable_open_v2 = true;
800         io.in.persistent_open = false;
801         io.in.create_guid = GUID_random();
802         io.in.timeout = UINT32_MAX;
803         status = smb2_create(tree, mem_ctx, &io);
804         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
805
806         if (!share_is_so) {
807                 CHECK_VAL(break_info.count, 1);
808                 CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle);
809                 CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
810                 ZERO_STRUCT(break_info);
811         }
812
813 done:
814         if (h != NULL) {
815                 smb2_util_close(tree, *h);
816         }
817         smb2_deltree(tree, BASEDIR);
818
819         talloc_free(tree);
820         talloc_free(mem_ctx);
821
822         return ret;
823 }
824
825 /**
826  * Test Durablity V2 Create Replay Detection on Single Channel.
827  * Create with an oplock, and replay with a lease.
828  */
829 static bool test_replay_dhv2_oplock_lease(struct torture_context *tctx,
830                                           struct smb2_tree *tree)
831 {
832         NTSTATUS status;
833         TALLOC_CTX *mem_ctx = talloc_new(tctx);
834         struct smb2_handle _h;
835         struct smb2_handle *h = NULL;
836         struct smb2_create io;
837         struct GUID create_guid = GUID_random();
838         bool ret = true;
839         const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat";
840         struct smb2_transport *transport = tree->session->transport;
841         uint32_t share_capabilities;
842         bool share_is_so;
843         uint32_t server_capabilities;
844         struct smb2_lease ls;
845         uint64_t lease_key;
846
847         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
848                 torture_skip(tctx, "SMB 3.X Dialect family required for "
849                                    "replay tests\n");
850         }
851
852         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
853         if (!(server_capabilities & SMB2_CAP_LEASING)) {
854                 torture_skip(tctx, "leases are not supported");
855         }
856
857         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
858         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
859
860         ZERO_STRUCT(break_info);
861         break_info.tctx = tctx;
862         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
863         tree->session->transport->oplock.private_data = tree;
864
865         torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
866                               "Channel\n");
867         smb2_util_unlink(tree, fname);
868         status = torture_smb2_testdir(tree, BASEDIR, &_h);
869         CHECK_STATUS(status, NT_STATUS_OK);
870         smb2_util_close(tree, _h);
871         CHECK_VAL(break_info.count, 0);
872
873         smb2_oplock_create_share(&io, fname,
874                         smb2_util_share_access(""),
875                         smb2_util_oplock_level("b"));
876         io.in.durable_open = false;
877         io.in.durable_open_v2 = true;
878         io.in.persistent_open = false;
879         io.in.create_guid = create_guid;
880         io.in.timeout = UINT32_MAX;
881
882         status = smb2_create(tree, mem_ctx, &io);
883         CHECK_STATUS(status, NT_STATUS_OK);
884         _h = io.out.file.handle;
885         h = &_h;
886         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
887         CHECK_VAL(io.out.durable_open, false);
888         if (share_is_so) {
889                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
890                 CHECK_VAL(io.out.durable_open_v2, false);
891                 CHECK_VAL(io.out.timeout, 0);
892         } else {
893                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
894                 CHECK_VAL(io.out.durable_open_v2, true);
895                 CHECK_VAL(io.out.timeout, io.in.timeout);
896         }
897
898         /*
899          * Replay Durable V2 Create on single channel
900          * but replay it with a lease instead of an oplock.
901          */
902         lease_key = random();
903         smb2_lease_create(&io, &ls, false /* dir */, fname,
904                         lease_key, smb2_util_lease_state("RH"));
905         io.in.durable_open = false;
906         io.in.durable_open_v2 = true;
907         io.in.persistent_open = false;
908         io.in.create_guid = create_guid;
909         io.in.timeout = UINT32_MAX;
910
911         smb2cli_session_start_replay(tree->session->smbXcli);
912         status = smb2_create(tree, mem_ctx, &io);
913         smb2cli_session_stop_replay(tree->session->smbXcli);
914         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
915
916 done:
917         if (h != NULL) {
918                 smb2_util_close(tree, *h);
919         }
920         smb2_deltree(tree, BASEDIR);
921
922         talloc_free(tree);
923         talloc_free(mem_ctx);
924
925         return ret;
926 }
927
928
929 /**
930  * Test durablity v2 create replay detection on single channel.
931  * Variant with leases instead of oplocks:
932  * - open a file with a rh lease
933  * - upgrade to a rwh lease with a second create
934  * - replay the first create.
935  *   ==> it gets back the upgraded lease level
936  */
937 static bool test_replay_dhv2_lease1(struct torture_context *tctx,
938                                     struct smb2_tree *tree)
939 {
940         NTSTATUS status;
941         TALLOC_CTX *mem_ctx = talloc_new(tctx);
942         struct smb2_handle _h1;
943         struct smb2_handle *h1 = NULL;
944         struct smb2_handle _h2;
945         struct smb2_handle *h2 = NULL;
946         struct smb2_create io1, io2, ref1;
947         struct GUID create_guid = GUID_random();
948         bool ret = true;
949         const char *fname = BASEDIR "\\replay2_lease1.dat";
950         struct smb2_transport *transport = tree->session->transport;
951         uint32_t share_capabilities;
952         bool share_is_so;
953         uint32_t server_capabilities;
954         struct smb2_lease ls1, ls2;
955         uint64_t lease_key;
956
957         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
958                 torture_skip(tctx, "SMB 3.X Dialect family required for "
959                                    "replay tests\n");
960         }
961
962         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
963         if (!(server_capabilities & SMB2_CAP_LEASING)) {
964                 torture_skip(tctx, "leases are not supported");
965         }
966
967         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
968         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
969
970         ZERO_STRUCT(break_info);
971         break_info.tctx = tctx;
972         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
973         tree->session->transport->oplock.private_data = tree;
974
975         torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
976                               "on Single Channel\n");
977         smb2_util_unlink(tree, fname);
978         status = torture_smb2_testdir(tree, BASEDIR, &_h1);
979         CHECK_STATUS(status, NT_STATUS_OK);
980         smb2_util_close(tree, _h1);
981         CHECK_VAL(break_info.count, 0);
982
983         lease_key = random();
984
985         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
986                         lease_key, smb2_util_lease_state("RH"));
987         io1.in.durable_open = false;
988         io1.in.durable_open_v2 = true;
989         io1.in.persistent_open = false;
990         io1.in.create_guid = create_guid;
991         io1.in.timeout = UINT32_MAX;
992
993         status = smb2_create(tree, mem_ctx, &io1);
994         CHECK_STATUS(status, NT_STATUS_OK);
995         ref1 = io1;
996         _h1 = io1.out.file.handle;
997         h1 = &_h1;
998         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
999         CHECK_VAL(io1.out.durable_open, false);
1000         CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1001         CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1002         CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1003         if (share_is_so) {
1004                 CHECK_VAL(io1.out.lease_response.lease_state,
1005                           smb2_util_lease_state("R"));
1006                 CHECK_VAL(io1.out.durable_open_v2, false);
1007                 CHECK_VAL(io1.out.timeout, 0);
1008         } else {
1009                 CHECK_VAL(io1.out.lease_response.lease_state,
1010                           smb2_util_lease_state("RH"));
1011                 CHECK_VAL(io1.out.durable_open_v2, true);
1012                 CHECK_VAL(io1.out.timeout, io1.in.timeout);
1013         }
1014
1015         /*
1016          * Upgrade the lease to RWH
1017          */
1018         smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1019                         lease_key, smb2_util_lease_state("RHW"));
1020         io2.in.durable_open = false;
1021         io2.in.durable_open_v2 = true;
1022         io2.in.persistent_open = false;
1023         io2.in.create_guid = GUID_random(); /* new guid... */
1024         io2.in.timeout = UINT32_MAX;
1025
1026         status = smb2_create(tree, mem_ctx, &io2);
1027         CHECK_STATUS(status, NT_STATUS_OK);
1028         _h2 = io2.out.file.handle;
1029         h2 = &_h2;
1030
1031         /*
1032          * Replay Durable V2 Create on single channel.
1033          * We get the io from open #1 but with the
1034          * upgraded lease.
1035          */
1036
1037         /* adapt expected lease in response */
1038         if (!share_is_so) {
1039                 ref1.out.lease_response.lease_state =
1040                         smb2_util_lease_state("RHW");
1041         }
1042
1043         smb2cli_session_start_replay(tree->session->smbXcli);
1044         status = smb2_create(tree, mem_ctx, &io1);
1045         smb2cli_session_stop_replay(tree->session->smbXcli);
1046         CHECK_STATUS(status, NT_STATUS_OK);
1047         CHECK_CREATE_OUT(&io1, &ref1);
1048         CHECK_VAL(break_info.count, 0);
1049
1050 done:
1051         smb2cli_session_stop_replay(tree->session->smbXcli);
1052
1053         if (h1 != NULL) {
1054                 smb2_util_close(tree, *h1);
1055         }
1056         if (h2 != NULL) {
1057                 smb2_util_close(tree, *h2);
1058         }
1059         smb2_deltree(tree, BASEDIR);
1060
1061         talloc_free(tree);
1062         talloc_free(mem_ctx);
1063
1064         return ret;
1065 }
1066
1067 /**
1068  * Test durablity v2 create replay detection on single channel.
1069  * Variant with leases instead of oplocks, where the
1070  * replay does not specify the original lease level but
1071  * just a "R" lease. This still gives the upgraded lease
1072  * level in the reply.
1073  * - open a file with a rh lease
1074  * - upgrade to a rwh lease with a second create
1075  * - replay the first create.
1076  *   ==> it gets back the upgraded lease level
1077  */
1078 static bool test_replay_dhv2_lease2(struct torture_context *tctx,
1079                                     struct smb2_tree *tree)
1080 {
1081         NTSTATUS status;
1082         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1083         struct smb2_handle _h1;
1084         struct smb2_handle *h1 = NULL;
1085         struct smb2_handle _h2;
1086         struct smb2_handle *h2 = NULL;
1087         struct smb2_create io1, io2, ref1;
1088         struct GUID create_guid = GUID_random();
1089         bool ret = true;
1090         const char *fname = BASEDIR "\\replay2_lease2.dat";
1091         struct smb2_transport *transport = tree->session->transport;
1092         uint32_t share_capabilities;
1093         bool share_is_so;
1094         uint32_t server_capabilities;
1095         struct smb2_lease ls1, ls2;
1096         uint64_t lease_key;
1097
1098         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
1099                 torture_skip(tctx, "SMB 3.X Dialect family required for "
1100                                    "replay tests\n");
1101         }
1102
1103         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
1104         if (!(server_capabilities & SMB2_CAP_LEASING)) {
1105                 torture_skip(tctx, "leases are not supported");
1106         }
1107
1108         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
1109         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1110
1111         ZERO_STRUCT(break_info);
1112         break_info.tctx = tctx;
1113         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
1114         tree->session->transport->oplock.private_data = tree;
1115
1116         torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
1117                               "on Single Channel\n");
1118         smb2_util_unlink(tree, fname);
1119         status = torture_smb2_testdir(tree, BASEDIR, &_h1);
1120         CHECK_STATUS(status, NT_STATUS_OK);
1121         smb2_util_close(tree, _h1);
1122         CHECK_VAL(break_info.count, 0);
1123
1124         lease_key = random();
1125
1126         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1127                         lease_key, smb2_util_lease_state("RH"));
1128         io1.in.durable_open = false;
1129         io1.in.durable_open_v2 = true;
1130         io1.in.persistent_open = false;
1131         io1.in.create_guid = create_guid;
1132         io1.in.timeout = UINT32_MAX;
1133
1134         status = smb2_create(tree, mem_ctx, &io1);
1135         CHECK_STATUS(status, NT_STATUS_OK);
1136         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1137         CHECK_VAL(io1.out.durable_open, false);
1138         CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1139         CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1140         CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1141         if (share_is_so) {
1142                 CHECK_VAL(io1.out.lease_response.lease_state,
1143                           smb2_util_lease_state("R"));
1144                 CHECK_VAL(io1.out.durable_open_v2, false);
1145                 CHECK_VAL(io1.out.timeout, 0);
1146         } else {
1147                 CHECK_VAL(io1.out.lease_response.lease_state,
1148                           smb2_util_lease_state("RH"));
1149                 CHECK_VAL(io1.out.durable_open_v2, true);
1150                 CHECK_VAL(io1.out.timeout, io1.in.timeout);
1151         }
1152         ref1 = io1;
1153         _h1 = io1.out.file.handle;
1154         h1 = &_h1;
1155
1156         /*
1157          * Upgrade the lease to RWH
1158          */
1159         smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1160                         lease_key, smb2_util_lease_state("RHW"));
1161         io2.in.durable_open = false;
1162         io2.in.durable_open_v2 = true;
1163         io2.in.persistent_open = false;
1164         io2.in.create_guid = GUID_random(); /* new guid... */
1165         io2.in.timeout = UINT32_MAX;
1166
1167         status = smb2_create(tree, mem_ctx, &io2);
1168         CHECK_STATUS(status, NT_STATUS_OK);
1169         _h2 = io2.out.file.handle;
1170         h2 = &_h2;
1171
1172         /*
1173          * Replay Durable V2 Create on single channel.
1174          * Changing the requested lease level to "R"
1175          * does not change the response:
1176          * We get the reply from open #1 but with the
1177          * upgraded lease.
1178          */
1179
1180         /* adapt the expected response */
1181         if (!share_is_so) {
1182                 ref1.out.lease_response.lease_state =
1183                                         smb2_util_lease_state("RHW");
1184         }
1185
1186         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1187                         lease_key, smb2_util_lease_state("R"));
1188         io1.in.durable_open = false;
1189         io1.in.durable_open_v2 = true;
1190         io1.in.persistent_open = false;
1191         io1.in.create_guid = create_guid;
1192         io1.in.timeout = UINT32_MAX;
1193
1194         smb2cli_session_start_replay(tree->session->smbXcli);
1195         status = smb2_create(tree, mem_ctx, &io1);
1196         smb2cli_session_stop_replay(tree->session->smbXcli);
1197         CHECK_STATUS(status, NT_STATUS_OK);
1198         CHECK_CREATE_OUT(&io1, &ref1);
1199         CHECK_VAL(break_info.count, 0);
1200
1201 done:
1202         smb2cli_session_stop_replay(tree->session->smbXcli);
1203
1204         if (h1 != NULL) {
1205                 smb2_util_close(tree, *h1);
1206         }
1207         if (h2 != NULL) {
1208                 smb2_util_close(tree, *h2);
1209         }
1210         smb2_deltree(tree, BASEDIR);
1211
1212         talloc_free(tree);
1213         talloc_free(mem_ctx);
1214
1215         return ret;
1216 }
1217
1218 /**
1219  * Test durablity v2 create replay detection on single channel.
1220  * create with a lease, and replay with a different lease key
1221  */
1222 static bool test_replay_dhv2_lease3(struct torture_context *tctx,
1223                                     struct smb2_tree *tree)
1224 {
1225         NTSTATUS status;
1226         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1227         struct smb2_handle _h1;
1228         struct smb2_handle *h1 = NULL;
1229         struct smb2_handle _h2;
1230         struct smb2_handle *h2 = NULL;
1231         struct smb2_create io1, io2;
1232         struct GUID create_guid = GUID_random();
1233         bool ret = true;
1234         const char *fname = BASEDIR "\\replay2_lease2.dat";
1235         struct smb2_transport *transport = tree->session->transport;
1236         uint32_t share_capabilities;
1237         bool share_is_so;
1238         uint32_t server_capabilities;
1239         struct smb2_lease ls1, ls2;
1240         uint64_t lease_key;
1241
1242         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
1243                 torture_skip(tctx, "SMB 3.X Dialect family required for "
1244                                    "replay tests\n");
1245         }
1246
1247         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
1248         if (!(server_capabilities & SMB2_CAP_LEASING)) {
1249                 torture_skip(tctx, "leases are not supported");
1250         }
1251
1252         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
1253         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1254
1255         ZERO_STRUCT(break_info);
1256         break_info.tctx = tctx;
1257         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
1258         tree->session->transport->oplock.private_data = tree;
1259
1260         torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
1261                               "on Single Channel\n");
1262         smb2_util_unlink(tree, fname);
1263         status = torture_smb2_testdir(tree, BASEDIR, &_h1);
1264         CHECK_STATUS(status, NT_STATUS_OK);
1265         smb2_util_close(tree, _h1);
1266         CHECK_VAL(break_info.count, 0);
1267
1268         lease_key = random();
1269
1270         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1271                         lease_key, smb2_util_lease_state("RH"));
1272         io1.in.durable_open = false;
1273         io1.in.durable_open_v2 = true;
1274         io1.in.persistent_open = false;
1275         io1.in.create_guid = create_guid;
1276         io1.in.timeout = UINT32_MAX;
1277
1278         status = smb2_create(tree, mem_ctx, &io1);
1279         CHECK_STATUS(status, NT_STATUS_OK);
1280         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1281         CHECK_VAL(io1.out.durable_open, false);
1282         CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1283         CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1284         CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1285         if (share_is_so) {
1286                 CHECK_VAL(io1.out.lease_response.lease_state,
1287                           smb2_util_lease_state("R"));
1288                 CHECK_VAL(io1.out.durable_open_v2, false);
1289                 CHECK_VAL(io1.out.timeout, 0);
1290         } else {
1291                 CHECK_VAL(io1.out.lease_response.lease_state,
1292                           smb2_util_lease_state("RH"));
1293                 CHECK_VAL(io1.out.durable_open_v2, true);
1294                 CHECK_VAL(io1.out.timeout, io1.in.timeout);
1295         }
1296         _h1 = io1.out.file.handle;
1297         h1 = &_h1;
1298
1299         /*
1300          * Upgrade the lease to RWH
1301          */
1302         smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1303                         lease_key, smb2_util_lease_state("RHW"));
1304         io2.in.durable_open = false;
1305         io2.in.durable_open_v2 = true;
1306         io2.in.persistent_open = false;
1307         io2.in.create_guid = GUID_random(); /* new guid... */
1308         io2.in.timeout = UINT32_MAX;
1309
1310         status = smb2_create(tree, mem_ctx, &io2);
1311         CHECK_STATUS(status, NT_STATUS_OK);
1312         _h2 = io2.out.file.handle;
1313         h2 = &_h2;
1314
1315         /*
1316          * Replay Durable V2 Create on single channel.
1317          * use a different lease key.
1318          */
1319
1320         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1321                         random() /* lease key */,
1322                         smb2_util_lease_state("RH"));
1323         io1.in.durable_open = false;
1324         io1.in.durable_open_v2 = true;
1325         io1.in.persistent_open = false;
1326         io1.in.create_guid = create_guid;
1327         io1.in.timeout = UINT32_MAX;
1328
1329         smb2cli_session_start_replay(tree->session->smbXcli);
1330         status = smb2_create(tree, mem_ctx, &io1);
1331         smb2cli_session_stop_replay(tree->session->smbXcli);
1332         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1333
1334 done:
1335         smb2cli_session_stop_replay(tree->session->smbXcli);
1336
1337         if (h1 != NULL) {
1338                 smb2_util_close(tree, *h1);
1339         }
1340         if (h2 != NULL) {
1341                 smb2_util_close(tree, *h2);
1342         }
1343         smb2_deltree(tree, BASEDIR);
1344
1345         talloc_free(tree);
1346         talloc_free(mem_ctx);
1347
1348         return ret;
1349 }
1350
1351 /**
1352  * Test durablity v2 create replay detection on single channel.
1353  * Do the original create with a lease, and do the replay
1354  * with an oplock.
1355  */
1356 static bool test_replay_dhv2_lease_oplock(struct torture_context *tctx,
1357                                           struct smb2_tree *tree)
1358 {
1359         NTSTATUS status;
1360         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1361         struct smb2_handle _h1;
1362         struct smb2_handle *h1 = NULL;
1363         struct smb2_handle _h2;
1364         struct smb2_handle *h2 = NULL;
1365         struct smb2_create io1, io2, ref1;
1366         struct GUID create_guid = GUID_random();
1367         bool ret = true;
1368         const char *fname = BASEDIR "\\replay2_lease1.dat";
1369         struct smb2_transport *transport = tree->session->transport;
1370         uint32_t share_capabilities;
1371         bool share_is_so;
1372         uint32_t server_capabilities;
1373         struct smb2_lease ls1, ls2;
1374         uint64_t lease_key;
1375
1376         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
1377                 torture_skip(tctx, "SMB 3.X Dialect family required for "
1378                                    "replay tests\n");
1379         }
1380
1381         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
1382         if (!(server_capabilities & SMB2_CAP_LEASING)) {
1383                 torture_skip(tctx, "leases are not supported");
1384         }
1385
1386         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
1387         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1388
1389         ZERO_STRUCT(break_info);
1390         break_info.tctx = tctx;
1391         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
1392         tree->session->transport->oplock.private_data = tree;
1393
1394         torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
1395                               "on Single Channel\n");
1396         smb2_util_unlink(tree, fname);
1397         status = torture_smb2_testdir(tree, BASEDIR, &_h1);
1398         CHECK_STATUS(status, NT_STATUS_OK);
1399         smb2_util_close(tree, _h1);
1400         CHECK_VAL(break_info.count, 0);
1401
1402         lease_key = random();
1403
1404         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1405                         lease_key, smb2_util_lease_state("RH"));
1406         io1.in.durable_open = false;
1407         io1.in.durable_open_v2 = true;
1408         io1.in.persistent_open = false;
1409         io1.in.create_guid = create_guid;
1410         io1.in.timeout = UINT32_MAX;
1411
1412         status = smb2_create(tree, mem_ctx, &io1);
1413         CHECK_STATUS(status, NT_STATUS_OK);
1414         ref1 = io1;
1415         _h1 = io1.out.file.handle;
1416         h1 = &_h1;
1417         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1418         CHECK_VAL(io1.out.durable_open, false);
1419         CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1420         CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1421         CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1422         if (share_is_so) {
1423                 CHECK_VAL(io1.out.lease_response.lease_state,
1424                           smb2_util_lease_state("R"));
1425                 CHECK_VAL(io1.out.durable_open_v2, false);
1426                 CHECK_VAL(io1.out.timeout, 0);
1427         } else {
1428                 CHECK_VAL(io1.out.lease_response.lease_state,
1429                           smb2_util_lease_state("RH"));
1430                 CHECK_VAL(io1.out.durable_open_v2, true);
1431                 CHECK_VAL(io1.out.timeout, io1.in.timeout);
1432         }
1433
1434         /*
1435          * Upgrade the lease to RWH
1436          */
1437         smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1438                         lease_key, smb2_util_lease_state("RHW"));
1439         io2.in.durable_open = false;
1440         io2.in.durable_open_v2 = true;
1441         io2.in.persistent_open = false;
1442         io2.in.create_guid = GUID_random(); /* new guid... */
1443         io2.in.timeout = UINT32_MAX;
1444
1445         status = smb2_create(tree, mem_ctx, &io2);
1446         CHECK_STATUS(status, NT_STATUS_OK);
1447         _h2 = io2.out.file.handle;
1448         h2 = &_h2;
1449
1450         /*
1451          * Replay Durable V2 Create on single channel.
1452          * We get the io from open #1 but with the
1453          * upgraded lease.
1454          */
1455
1456         smb2_oplock_create_share(&io2, fname,
1457                         smb2_util_share_access(""),
1458                         smb2_util_oplock_level("b"));
1459         io2.in.durable_open = false;
1460         io2.in.durable_open_v2 = true;
1461         io2.in.persistent_open = false;
1462         io2.in.create_guid = create_guid;
1463         io2.in.timeout = UINT32_MAX;
1464
1465         /* adapt expected lease in response */
1466         if (!share_is_so) {
1467                 ref1.out.lease_response.lease_state =
1468                         smb2_util_lease_state("RHW");
1469         }
1470
1471         smb2cli_session_start_replay(tree->session->smbXcli);
1472         status = smb2_create(tree, mem_ctx, &io1);
1473         smb2cli_session_stop_replay(tree->session->smbXcli);
1474         CHECK_STATUS(status, NT_STATUS_OK);
1475         CHECK_CREATE_OUT(&io1, &ref1);
1476         CHECK_VAL(break_info.count, 0);
1477
1478 done:
1479         smb2cli_session_stop_replay(tree->session->smbXcli);
1480
1481         if (h1 != NULL) {
1482                 smb2_util_close(tree, *h1);
1483         }
1484         if (h2 != NULL) {
1485                 smb2_util_close(tree, *h2);
1486         }
1487         smb2_deltree(tree, BASEDIR);
1488
1489         talloc_free(tree);
1490         talloc_free(mem_ctx);
1491
1492         return ret;
1493 }
1494
1495 static bool test_channel_sequence_table(struct torture_context *tctx,
1496                                         struct smb2_tree *tree,
1497                                         bool do_replay,
1498                                         uint16_t opcode)
1499 {
1500         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1501         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1502         struct smb2_handle handle;
1503         struct smb2_handle *phandle = NULL;
1504         struct smb2_create io;
1505         struct GUID create_guid = GUID_random();
1506         bool ret = true;
1507         const char *fname = BASEDIR "\\channel_sequence.dat";
1508         uint16_t csn = 0;
1509         uint16_t limit = UINT16_MAX - 0x7fff;
1510         int i;
1511         struct {
1512                 uint16_t csn;
1513                 bool csn_rand_low;
1514                 bool csn_rand_high;
1515                 NTSTATUS expected_status;
1516         } tests[] = {
1517                 {
1518                         .csn                    = 0,
1519                         .expected_status        = NT_STATUS_OK,
1520                 },{
1521                         .csn                    = 0x7fff + 1,
1522                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1523                 },{
1524                         .csn                    = 0x7fff + 2,
1525                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1526                 },{
1527                         .csn                    = -1,
1528                         .csn_rand_high          = true,
1529                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1530                 },{
1531                         .csn                    = 0xffff,
1532                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1533                 },{
1534                         .csn                    = 0x7fff,
1535                         .expected_status        = NT_STATUS_OK,
1536                 },{
1537                         .csn                    = 0x7ffe,
1538                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1539                 },{
1540                         .csn                    = 0,
1541                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1542                 },{
1543                         .csn                    = -1,
1544                         .csn_rand_low           = true,
1545                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1546                 },{
1547                         .csn                    = 0x7fff + 1,
1548                         .expected_status        = NT_STATUS_OK,
1549                 },{
1550                         .csn                    = 0xffff,
1551                         .expected_status        = NT_STATUS_OK,
1552                 },{
1553                         .csn                    = 0,
1554                         .expected_status        = NT_STATUS_OK,
1555                 },{
1556                         .csn                    = 1,
1557                         .expected_status        = NT_STATUS_OK,
1558                 },{
1559                         .csn                    = 0,
1560                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1561                 },{
1562                         .csn                    = 1,
1563                         .expected_status        = NT_STATUS_OK,
1564                 },{
1565                         .csn                    = 0xffff,
1566                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
1567                 }
1568         };
1569
1570         smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
1571
1572         csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli);
1573         torture_comment(tctx, "Testing create with channel sequence number: 0x%04x\n", csn);
1574
1575         smb2_oplock_create_share(&io, fname,
1576                         smb2_util_share_access("RWD"),
1577                         smb2_util_oplock_level("b"));
1578         io.in.durable_open = false;
1579         io.in.durable_open_v2 = true;
1580         io.in.create_guid = create_guid;
1581         io.in.timeout = UINT32_MAX;
1582
1583         torture_assert_ntstatus_ok_goto(tctx,
1584                 smb2_create(tree, mem_ctx, &io),
1585                 ret, done, "failed to call smb2_create");
1586
1587         handle = io.out.file.handle;
1588         phandle = &handle;
1589
1590         for (i=0; i <ARRAY_SIZE(tests); i++) {
1591
1592                 const char *opstr = "";
1593                 union smb_fileinfo qfinfo;
1594
1595                 csn = tests[i].csn;
1596
1597                 if (tests[i].csn_rand_low) {
1598                         csn = rand() % limit;
1599                 } else if (tests[i].csn_rand_high) {
1600                         csn = rand() % limit + 0x7fff;
1601                 }
1602
1603                 switch (opcode) {
1604                 case SMB2_OP_WRITE:
1605                         opstr = "write";
1606                         break;
1607                 case SMB2_OP_IOCTL:
1608                         opstr = "ioctl";
1609                         break;
1610                 case SMB2_OP_SETINFO:
1611                         opstr = "setinfo";
1612                         break;
1613                 default:
1614                         break;
1615                 }
1616
1617                 smb2cli_session_reset_channel_sequence(tree->session->smbXcli, csn);
1618                 csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli);
1619
1620                 torture_comment(tctx, "Testing %s (replay: %s) with CSN 0x%04x, expecting: %s\n",
1621                         opstr, do_replay ? "true" : "false", csn,
1622                         nt_errstr(tests[i].expected_status));
1623
1624                 if (do_replay) {
1625                         smb2cli_session_start_replay(tree->session->smbXcli);
1626                 }
1627
1628                 switch (opcode) {
1629                 case SMB2_OP_WRITE: {
1630                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, 255);
1631
1632                         generate_random_buffer(blob.data, blob.length);
1633
1634                         status = smb2_util_write(tree, handle, blob.data, 0, blob.length);
1635                         if (NT_STATUS_IS_OK(status)) {
1636                                 struct smb2_read rd;
1637
1638                                 rd = (struct smb2_read) {
1639                                         .in.file.handle = handle,
1640                                         .in.length = blob.length,
1641                                         .in.offset = 0
1642                                 };
1643
1644                                 torture_assert_ntstatus_ok_goto(tctx,
1645                                         smb2_read(tree, tree, &rd),
1646                                         ret, done, "failed to read after write");
1647
1648                                 torture_assert_data_blob_equal(tctx,
1649                                         rd.out.data, blob,
1650                                         "read/write mismatch");
1651                         }
1652                         break;
1653                 }
1654                 case SMB2_OP_IOCTL: {
1655                         union smb_ioctl ioctl;
1656                         ioctl = (union smb_ioctl) {
1657                                 .smb2.level = RAW_IOCTL_SMB2,
1658                                 .smb2.in.file.handle = handle,
1659                                 .smb2.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID,
1660                                 .smb2.in.max_response_size = 64,
1661                                 .smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL
1662                         };
1663                         status = smb2_ioctl(tree, mem_ctx, &ioctl.smb2);
1664                         break;
1665                 }
1666                 case SMB2_OP_SETINFO: {
1667                         union smb_setfileinfo sfinfo;
1668                         ZERO_STRUCT(sfinfo);
1669                         sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
1670                         sfinfo.generic.in.file.handle = handle;
1671                         sfinfo.position_information.in.position = 0x1000;
1672                         status = smb2_setinfo_file(tree, &sfinfo);
1673                         break;
1674                 }
1675                 default:
1676                         break;
1677                 }
1678
1679                 qfinfo = (union smb_fileinfo) {
1680                         .generic.level = RAW_SFILEINFO_POSITION_INFORMATION,
1681                         .generic.in.file.handle = handle
1682                 };
1683
1684                 torture_assert_ntstatus_ok_goto(tctx,
1685                         smb2_getinfo_file(tree, mem_ctx, &qfinfo),
1686                         ret, done, "failed to read after write");
1687
1688                 if (do_replay) {
1689                         smb2cli_session_stop_replay(tree->session->smbXcli);
1690                 }
1691
1692                 torture_assert_ntstatus_equal_goto(tctx,
1693                         status, tests[i].expected_status,
1694                         ret, done, "got unexpected failure code");
1695
1696         }
1697 done:
1698         if (phandle != NULL) {
1699                 smb2_util_close(tree, *phandle);
1700         }
1701
1702         smb2_util_unlink(tree, fname);
1703
1704         return ret;
1705 }
1706
1707 static bool test_channel_sequence(struct torture_context *tctx,
1708                                   struct smb2_tree *tree)
1709 {
1710         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1711         bool ret = true;
1712         const char *fname = BASEDIR "\\channel_sequence.dat";
1713         struct smb2_transport *transport1 = tree->session->transport;
1714         struct smb2_handle handle;
1715         uint32_t server_capabilities;
1716         uint16_t opcodes[] = { SMB2_OP_WRITE, SMB2_OP_IOCTL, SMB2_OP_SETINFO };
1717         int i;
1718
1719         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
1720                 torture_skip(tctx, "SMB 3.X Dialect family required for "
1721                                    "Replay tests\n");
1722         }
1723
1724         server_capabilities = smb2cli_conn_server_capabilities(
1725                                         tree->session->transport->conn);
1726         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
1727                 torture_skip(tctx,
1728                              "Server does not support multi-channel.");
1729         }
1730
1731         torture_comment(tctx, "Testing channel sequence numbers\n");
1732
1733         torture_assert_ntstatus_ok_goto(tctx,
1734                 torture_smb2_testdir(tree, BASEDIR, &handle),
1735                 ret, done, "failed to setup test directory");
1736
1737         smb2_util_close(tree, handle);
1738         smb2_util_unlink(tree, fname);
1739
1740         for (i=0; i <ARRAY_SIZE(opcodes); i++) {
1741                 torture_assert(tctx,
1742                         test_channel_sequence_table(tctx, tree, false, opcodes[i]),
1743                         "failed to test CSN without replay flag");
1744                 torture_assert(tctx,
1745                         test_channel_sequence_table(tctx, tree, true, opcodes[i]),
1746                         "failed to test CSN with replay flag");
1747         }
1748
1749 done:
1750
1751         smb2_util_unlink(tree, fname);
1752         smb2_deltree(tree, BASEDIR);
1753
1754         talloc_free(tree);
1755         talloc_free(mem_ctx);
1756
1757         return ret;
1758 }
1759
1760 /**
1761  * Test Durablity V2 Create Replay Detection on Multi Channel
1762  */
1763 static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1)
1764 {
1765         const char *host = torture_setting_string(tctx, "host", NULL);
1766         const char *share = torture_setting_string(tctx, "share", NULL);
1767         struct cli_credentials *credentials = cmdline_credentials;
1768         NTSTATUS status;
1769         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1770         struct smb2_handle _h;
1771         struct smb2_handle *h = NULL;
1772         struct smb2_create io;
1773         struct GUID create_guid = GUID_random();
1774         bool ret = true;
1775         const char *fname = BASEDIR "\\replay3.dat";
1776         struct smb2_tree *tree2 = NULL;
1777         struct smb2_transport *transport1 = tree1->session->transport;
1778         struct smb2_transport *transport2 = NULL;
1779         struct smb2_session *session1_1 = tree1->session;
1780         struct smb2_session *session1_2 = NULL;
1781         uint32_t share_capabilities;
1782         bool share_is_so;
1783         uint32_t server_capabilities;
1784
1785         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
1786                 torture_skip(tctx, "SMB 3.X Dialect family required for "
1787                                    "Replay tests\n");
1788         }
1789
1790         server_capabilities = smb2cli_conn_server_capabilities(
1791                                         tree1->session->transport->conn);
1792         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
1793                 torture_skip(tctx,
1794                              "Server does not support multi-channel.");
1795         }
1796
1797         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
1798         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1799
1800         ZERO_STRUCT(break_info);
1801         break_info.tctx = tctx;
1802         transport1->oplock.handler = torture_oplock_ack_handler;
1803         transport1->oplock.private_data = tree1;
1804
1805         torture_comment(tctx, "Replay of DurableHandleReqV2 on Multi "
1806                               "Channel\n");
1807         status = torture_smb2_testdir(tree1, BASEDIR, &_h);
1808         CHECK_STATUS(status, NT_STATUS_OK);
1809         smb2_util_close(tree1, _h);
1810         smb2_util_unlink(tree1, fname);
1811         CHECK_VAL(break_info.count, 0);
1812
1813         /*
1814          * use the 1st channel, 1st session
1815          */
1816         smb2_oplock_create_share(&io, fname,
1817                         smb2_util_share_access(""),
1818                         smb2_util_oplock_level("b"));
1819         io.in.durable_open = false;
1820         io.in.durable_open_v2 = true;
1821         io.in.persistent_open = false;
1822         io.in.create_guid = create_guid;
1823         io.in.timeout = UINT32_MAX;
1824
1825         tree1->session = session1_1;
1826         status = smb2_create(tree1, mem_ctx, &io);
1827         CHECK_STATUS(status, NT_STATUS_OK);
1828         _h = io.out.file.handle;
1829         h = &_h;
1830         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1831         if (share_is_so) {
1832                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1833                 CHECK_VAL(io.out.durable_open_v2, false);
1834                 CHECK_VAL(io.out.timeout, 0);
1835         } else {
1836                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
1837                 CHECK_VAL(io.out.durable_open_v2, true);
1838                 CHECK_VAL(io.out.timeout, io.in.timeout);
1839         }
1840         CHECK_VAL(io.out.durable_open, false);
1841         CHECK_VAL(break_info.count, 0);
1842
1843         status = smb2_connect(tctx,
1844                         host,
1845                         lpcfg_smb_ports(tctx->lp_ctx),
1846                         share,
1847                         lpcfg_resolve_context(tctx->lp_ctx),
1848                         credentials,
1849                         &tree2,
1850                         tctx->ev,
1851                         &transport1->options,
1852                         lpcfg_socket_options(tctx->lp_ctx),
1853                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1854                         );
1855         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1856                         "smb2_connect failed");
1857         transport2 = tree2->session->transport;
1858
1859         transport2->oplock.handler = torture_oplock_ack_handler;
1860         transport2->oplock.private_data = tree2;
1861
1862         /*
1863          * Now bind the 1st session to 2nd transport channel
1864          */
1865         session1_2 = smb2_session_channel(transport2,
1866                         lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1867                         tree2, session1_1);
1868         torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
1869
1870         status = smb2_session_setup_spnego(session1_2,
1871                         cmdline_credentials,
1872                         0 /* previous_session_id */);
1873         CHECK_STATUS(status, NT_STATUS_OK);
1874
1875         /*
1876          * use the 2nd channel, 1st session
1877          */
1878         tree1->session = session1_2;
1879         smb2cli_session_start_replay(tree1->session->smbXcli);
1880         status = smb2_create(tree1, mem_ctx, &io);
1881         smb2cli_session_stop_replay(tree1->session->smbXcli);
1882         CHECK_STATUS(status, NT_STATUS_OK);
1883         _h = io.out.file.handle;
1884         h = &_h;
1885         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1886         if (share_is_so) {
1887                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1888                 CHECK_VAL(io.out.durable_open_v2, false);
1889                 CHECK_VAL(io.out.timeout, 0);
1890         } else {
1891                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
1892                 CHECK_VAL(io.out.durable_open_v2, true);
1893                 CHECK_VAL(io.out.timeout, io.in.timeout);
1894         }
1895         CHECK_VAL(io.out.durable_open, false);
1896         CHECK_VAL(break_info.count, 0);
1897
1898         tree1->session = session1_1;
1899         smb2_util_close(tree1, *h);
1900         h = NULL;
1901
1902 done:
1903         talloc_free(tree2);
1904         tree1->session = session1_1;
1905
1906         if (h != NULL) {
1907                 smb2_util_close(tree1, *h);
1908         }
1909
1910         smb2_util_unlink(tree1, fname);
1911         smb2_deltree(tree1, BASEDIR);
1912
1913         talloc_free(tree1);
1914         talloc_free(mem_ctx);
1915
1916         return ret;
1917 }
1918
1919 /**
1920  * Test Multichannel IO Ordering using ChannelSequence/Channel Epoch number
1921  */
1922 static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1)
1923 {
1924         const char *host = torture_setting_string(tctx, "host", NULL);
1925         const char *share = torture_setting_string(tctx, "share", NULL);
1926         struct cli_credentials *credentials = cmdline_credentials;
1927         NTSTATUS status;
1928         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1929         struct smb2_handle _h1;
1930         struct smb2_handle *h1 = NULL;
1931         struct smb2_create io;
1932         struct GUID create_guid = GUID_random();
1933         uint8_t buf[64];
1934         struct smb2_read rd;
1935         union smb_setfileinfo sfinfo;
1936         bool ret = true;
1937         const char *fname = BASEDIR "\\replay4.dat";
1938         struct smb2_tree *tree2 = NULL;
1939         struct smb2_transport *transport1 = tree1->session->transport;
1940         struct smb2_transport *transport2 = NULL;
1941         struct smb2_session *session1_1 = tree1->session;
1942         struct smb2_session *session1_2 = NULL;
1943         uint16_t curr_cs;
1944         uint32_t share_capabilities;
1945         bool share_is_so;
1946         uint32_t server_capabilities;
1947
1948         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
1949                 torture_skip(tctx, "SMB 3.X Dialect family required for "
1950                                    "Replay tests\n");
1951         }
1952
1953         server_capabilities = smb2cli_conn_server_capabilities(
1954                                         tree1->session->transport->conn);
1955         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
1956                 torture_skip(tctx,
1957                              "Server does not support multi-channel.");
1958         }
1959
1960         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
1961         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1962
1963         ZERO_STRUCT(break_info);
1964         break_info.tctx = tctx;
1965         transport1->oplock.handler = torture_oplock_ack_handler;
1966         transport1->oplock.private_data = tree1;
1967
1968         torture_comment(tctx, "IO Ordering for Multi Channel\n");
1969         status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
1970         CHECK_STATUS(status, NT_STATUS_OK);
1971         smb2_util_close(tree1, _h1);
1972         smb2_util_unlink(tree1, fname);
1973         CHECK_VAL(break_info.count, 0);
1974
1975         /*
1976          * use the 1st channel, 1st session
1977          */
1978
1979         smb2_oplock_create_share(&io, fname,
1980                         smb2_util_share_access(""),
1981                         smb2_util_oplock_level("b"));
1982         io.in.durable_open = false;
1983         io.in.durable_open_v2 = true;
1984         io.in.persistent_open = false;
1985         io.in.create_guid = create_guid;
1986         io.in.timeout = UINT32_MAX;
1987
1988         tree1->session = session1_1;
1989         status = smb2_create(tree1, mem_ctx, &io);
1990         CHECK_STATUS(status, NT_STATUS_OK);
1991         _h1 = io.out.file.handle;
1992         h1 = &_h1;
1993         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1994         if (share_is_so) {
1995                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1996                 CHECK_VAL(io.out.durable_open_v2, false);
1997                 CHECK_VAL(io.out.timeout, 0);
1998         } else {
1999                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
2000                 CHECK_VAL(io.out.durable_open_v2, true);
2001                 CHECK_VAL(io.out.timeout, io.in.timeout);
2002         }
2003         CHECK_VAL(io.out.durable_open, false);
2004         CHECK_VAL(break_info.count, 0);
2005
2006         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2007         CHECK_STATUS(status, NT_STATUS_OK);
2008
2009         /*
2010          * Increment ChannelSequence so that server thinks that there's a
2011          * Channel Failure
2012          */
2013         smb2cli_session_increment_channel_sequence(tree1->session->smbXcli);
2014
2015         /*
2016          * Perform a Read with incremented ChannelSequence
2017          */
2018         rd = (struct smb2_read) {
2019                 .in.file.handle = *h1,
2020                 .in.length = sizeof(buf),
2021                 .in.offset = 0
2022         };
2023         status = smb2_read(tree1, tree1, &rd);
2024         CHECK_STATUS(status, NT_STATUS_OK);
2025
2026         /*
2027          * Performing a Write with Stale ChannelSequence is not allowed by
2028          * server
2029          */
2030         curr_cs = smb2cli_session_reset_channel_sequence(
2031                                                 tree1->session->smbXcli, 0);
2032         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2033         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
2034
2035         /*
2036          * Performing a Write Replay with Stale ChannelSequence is not allowed
2037          * by server
2038          */
2039         smb2cli_session_start_replay(tree1->session->smbXcli);
2040         smb2cli_session_reset_channel_sequence(tree1->session->smbXcli, 0);
2041         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2042         smb2cli_session_stop_replay(tree1->session->smbXcli);
2043         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
2044
2045         /*
2046          * Performing a SetInfo with stale ChannelSequence is not allowed by
2047          * server
2048          */
2049         ZERO_STRUCT(sfinfo);
2050         sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
2051         sfinfo.generic.in.file.handle = *h1;
2052         sfinfo.position_information.in.position = 0x1000;
2053         status = smb2_setinfo_file(tree1, &sfinfo);
2054         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
2055
2056         /*
2057          * Performing a Read with stale ChannelSequence is allowed
2058          */
2059         rd = (struct smb2_read) {
2060                 .in.file.handle = *h1,
2061                 .in.length = ARRAY_SIZE(buf),
2062                 .in.offset = 0
2063         };
2064         status = smb2_read(tree1, tree1, &rd);
2065         CHECK_STATUS(status, NT_STATUS_OK);
2066
2067         status = smb2_connect(tctx,
2068                         host,
2069                         lpcfg_smb_ports(tctx->lp_ctx),
2070                         share,
2071                         lpcfg_resolve_context(tctx->lp_ctx),
2072                         credentials,
2073                         &tree2,
2074                         tctx->ev,
2075                         &transport1->options,
2076                         lpcfg_socket_options(tctx->lp_ctx),
2077                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)
2078                         );
2079         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2080                         "smb2_connect failed");
2081         transport2 = tree2->session->transport;
2082
2083         transport2->oplock.handler = torture_oplock_ack_handler;
2084         transport2->oplock.private_data = tree2;
2085
2086         /*
2087          * Now bind the 1st session to 2nd transport channel
2088          */
2089         session1_2 = smb2_session_channel(transport2,
2090                         lpcfg_gensec_settings(tctx, tctx->lp_ctx),
2091                         tree2, session1_1);
2092         torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
2093
2094         status = smb2_session_setup_spnego(session1_2,
2095                         cmdline_credentials,
2096                         0 /* previous_session_id */);
2097         CHECK_STATUS(status, NT_STATUS_OK);
2098
2099         /*
2100          * use the 2nd channel, 1st session
2101          */
2102         tree1->session = session1_2;
2103
2104         /*
2105          * Write Replay with Correct ChannelSequence is allowed by the server
2106          */
2107         smb2cli_session_start_replay(tree1->session->smbXcli);
2108         smb2cli_session_reset_channel_sequence(tree1->session->smbXcli,
2109                                                curr_cs);
2110         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2111         CHECK_STATUS(status, NT_STATUS_OK);
2112         smb2cli_session_stop_replay(tree1->session->smbXcli);
2113
2114         /*
2115          * See what happens if we change the Buffer and perform a Write Replay.
2116          * This is to show that Write Replay does not really care about the data
2117          */
2118         memset(buf, 'r', ARRAY_SIZE(buf));
2119         smb2cli_session_start_replay(tree1->session->smbXcli);
2120         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2121         CHECK_STATUS(status, NT_STATUS_OK);
2122         smb2cli_session_stop_replay(tree1->session->smbXcli);
2123
2124         /*
2125          * Read back from File to verify what was written
2126          */
2127         rd = (struct smb2_read) {
2128                 .in.file.handle = *h1,
2129                 .in.length = ARRAY_SIZE(buf),
2130                 .in.offset = 0
2131         };
2132         status = smb2_read(tree1, tree1, &rd);
2133         CHECK_STATUS(status, NT_STATUS_OK);
2134
2135         if ((rd.out.data.length != ARRAY_SIZE(buf)) ||
2136                         memcmp(rd.out.data.data, buf, ARRAY_SIZE(buf))) {
2137                 torture_comment(tctx, "Write Replay Data Mismatch\n");
2138         }
2139
2140         tree1->session = session1_1;
2141         smb2_util_close(tree1, *h1);
2142         h1 = NULL;
2143
2144         if (share_is_so) {
2145                 CHECK_VAL(break_info.count, 1);
2146         } else {
2147                 CHECK_VAL(break_info.count, 0);
2148         }
2149 done:
2150         talloc_free(tree2);
2151         tree1->session = session1_1;
2152
2153         if (h1 != NULL) {
2154                 smb2_util_close(tree1, *h1);
2155         }
2156
2157         smb2_util_unlink(tree1, fname);
2158         smb2_deltree(tree1, BASEDIR);
2159
2160         talloc_free(tree1);
2161         talloc_free(mem_ctx);
2162
2163         return ret;
2164 }
2165
2166 /**
2167  * Test Durablity V2 Persistent Create Replay on a Single Channel
2168  */
2169 static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree)
2170 {
2171         NTSTATUS status;
2172         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2173         struct smb2_handle _h;
2174         struct smb2_handle *h = NULL;
2175         struct smb2_create io;
2176         struct GUID create_guid = GUID_random();
2177         bool ret = true;
2178         uint32_t share_capabilities;
2179         bool share_is_ca;
2180         bool share_is_so;
2181         uint32_t server_capabilities;
2182         const char *fname = BASEDIR "\\replay5.dat";
2183         struct smb2_transport *transport = tree->session->transport;
2184         struct smbcli_options options = tree->session->transport->options;
2185         uint8_t expect_oplock = smb2_util_oplock_level("b");
2186         NTSTATUS expect_status = NT_STATUS_DUPLICATE_OBJECTID;
2187
2188         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
2189                 torture_skip(tctx, "SMB 3.X Dialect family required for "
2190                                 "Replay tests\n");
2191         }
2192
2193         server_capabilities = smb2cli_conn_server_capabilities(
2194                                         tree->session->transport->conn);
2195         if (!(server_capabilities & SMB2_CAP_PERSISTENT_HANDLES)) {
2196                 torture_skip(tctx,
2197                              "Server does not support persistent handles.");
2198         }
2199
2200         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
2201
2202         share_is_ca = share_capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
2203         if (!share_is_ca) {
2204                 torture_skip(tctx, "Share is not continuously available.");
2205         }
2206
2207         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
2208         if (share_is_so) {
2209                 expect_oplock = smb2_util_oplock_level("s");
2210                 expect_status = NT_STATUS_FILE_NOT_AVAILABLE;
2211         }
2212
2213         ZERO_STRUCT(break_info);
2214         break_info.tctx = tctx;
2215         transport->oplock.handler = torture_oplock_ack_handler;
2216         transport->oplock.private_data = tree;
2217
2218         torture_comment(tctx, "Replay of Persistent DurableHandleReqV2 on Single "
2219                         "Channel\n");
2220         status = torture_smb2_testdir(tree, BASEDIR, &_h);
2221         CHECK_STATUS(status, NT_STATUS_OK);
2222         smb2_util_close(tree, _h);
2223         smb2_util_unlink(tree, fname);
2224         CHECK_VAL(break_info.count, 0);
2225
2226         smb2_oplock_create_share(&io, fname,
2227                         smb2_util_share_access("RWD"),
2228                         smb2_util_oplock_level("b"));
2229         io.in.durable_open = false;
2230         io.in.durable_open_v2 = true;
2231         io.in.persistent_open = true;
2232         io.in.create_guid = create_guid;
2233         io.in.timeout = UINT32_MAX;
2234
2235         status = smb2_create(tree, mem_ctx, &io);
2236         CHECK_STATUS(status, NT_STATUS_OK);
2237         _h = io.out.file.handle;
2238         h = &_h;
2239         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2240         CHECK_VAL(io.out.oplock_level, expect_oplock);
2241         CHECK_VAL(io.out.durable_open, false);
2242         CHECK_VAL(io.out.durable_open_v2, true);
2243         CHECK_VAL(io.out.persistent_open, true);
2244         CHECK_VAL(io.out.timeout, io.in.timeout);
2245         CHECK_VAL(break_info.count, 0);
2246
2247         /* disconnect, leaving the durable open */
2248         TALLOC_FREE(tree);
2249
2250         if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) {
2251                 torture_warning(tctx, "couldn't reconnect, bailing\n");
2252                 ret = false;
2253                 goto done;
2254         }
2255
2256         /* a re-open of a persistent handle causes an error */
2257         status = smb2_create(tree, mem_ctx, &io);
2258         CHECK_STATUS(status, expect_status);
2259
2260         /* SMB2_FLAGS_REPLAY_OPERATION must be set to open the Persistent Handle */
2261         smb2cli_session_start_replay(tree->session->smbXcli);
2262         smb2cli_session_increment_channel_sequence(tree->session->smbXcli);
2263         status = smb2_create(tree, mem_ctx, &io);
2264         CHECK_STATUS(status, NT_STATUS_OK);
2265         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2266         CHECK_VAL(io.out.durable_open, false);
2267         CHECK_VAL(io.out.persistent_open, true);
2268         CHECK_VAL(io.out.oplock_level, expect_oplock);
2269         _h = io.out.file.handle;
2270         h = &_h;
2271
2272         smb2_util_close(tree, *h);
2273         h = NULL;
2274 done:
2275         if (h != NULL) {
2276                 smb2_util_close(tree, *h);
2277         }
2278
2279         smb2_util_unlink(tree, fname);
2280         smb2_deltree(tree, BASEDIR);
2281
2282         talloc_free(tree);
2283         talloc_free(mem_ctx);
2284
2285         return ret;
2286 }
2287
2288
2289 /**
2290  * Test Error Codes when a DurableHandleReqV2 with matching CreateGuid is
2291  * re-sent with or without SMB2_FLAGS_REPLAY_OPERATION
2292  */
2293 static bool test_replay6(struct torture_context *tctx, struct smb2_tree *tree)
2294 {
2295         NTSTATUS status;
2296         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2297         struct smb2_handle _h;
2298         struct smb2_handle *h = NULL;
2299         struct smb2_create io, ref1;
2300         union smb_fileinfo qfinfo;
2301         struct GUID create_guid = GUID_random();
2302         bool ret = true;
2303         const char *fname = BASEDIR "\\replay6.dat";
2304         struct smb2_transport *transport = tree->session->transport;
2305
2306         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
2307                 torture_skip(tctx, "SMB 3.X Dialect family required for "
2308                                    "replay tests\n");
2309         }
2310
2311         torture_reset_break_info(tctx, &break_info);
2312         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
2313         tree->session->transport->oplock.private_data = tree;
2314
2315         torture_comment(tctx, "Error Codes for DurableHandleReqV2 Replay\n");
2316         smb2_util_unlink(tree, fname);
2317         status = torture_smb2_testdir(tree, BASEDIR, &_h);
2318         CHECK_STATUS(status, NT_STATUS_OK);
2319         smb2_util_close(tree, _h);
2320         torture_wait_for_oplock_break(tctx);
2321         CHECK_VAL(break_info.count, 0);
2322         torture_reset_break_info(tctx, &break_info);
2323
2324         smb2_oplock_create_share(&io, fname,
2325                         smb2_util_share_access("RWD"),
2326                         smb2_util_oplock_level("b"));
2327         io.in.durable_open = false;
2328         io.in.durable_open_v2 = true;
2329         io.in.persistent_open = false;
2330         io.in.create_guid = create_guid;
2331         io.in.timeout = UINT32_MAX;
2332
2333         status = smb2_create(tree, mem_ctx, &io);
2334         CHECK_STATUS(status, NT_STATUS_OK);
2335         ref1 = io;
2336         _h = io.out.file.handle;
2337         h = &_h;
2338         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2339         CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
2340         CHECK_VAL(io.out.durable_open, false);
2341         CHECK_VAL(io.out.durable_open_v2, true);
2342
2343         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2344         io.in.create_disposition = NTCREATEX_DISP_OPEN;
2345         smb2cli_session_start_replay(tree->session->smbXcli);
2346         status = smb2_create(tree, mem_ctx, &io);
2347         smb2cli_session_stop_replay(tree->session->smbXcli);
2348         CHECK_STATUS(status, NT_STATUS_OK);
2349         CHECK_CREATE_OUT(&io, &ref1);
2350         torture_wait_for_oplock_break(tctx);
2351         CHECK_VAL(break_info.count, 0);
2352         torture_reset_break_info(tctx, &break_info);
2353
2354         qfinfo = (union smb_fileinfo) {
2355                 .generic.level = RAW_SFILEINFO_POSITION_INFORMATION,
2356                 .generic.in.file.handle = *h
2357         };
2358         torture_comment(tctx, "Trying getinfo\n");
2359         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
2360         CHECK_STATUS(status, NT_STATUS_OK);
2361         CHECK_VAL(qfinfo.position_information.out.position, 0);
2362
2363         smb2cli_session_start_replay(tree->session->smbXcli);
2364         status = smb2_create(tree, mem_ctx, &io);
2365         smb2cli_session_stop_replay(tree->session->smbXcli);
2366         CHECK_STATUS(status, NT_STATUS_OK);
2367         torture_assert_u64_not_equal_goto(tctx,
2368                 io.out.file.handle.data[0],
2369                 ref1.out.file.handle.data[0],
2370                 ret, done, "data 0");
2371         torture_assert_u64_not_equal_goto(tctx,
2372                 io.out.file.handle.data[1],
2373                 ref1.out.file.handle.data[1],
2374                 ret, done, "data 1");
2375         torture_wait_for_oplock_break(tctx);
2376         CHECK_VAL(break_info.count, 1);
2377         CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
2378         torture_reset_break_info(tctx, &break_info);
2379
2380         /*
2381          * Resend the matching Durable V2 Create without
2382          * SMB2_FLAGS_REPLAY_OPERATION. This triggers an oplock break and still
2383          * gets NT_STATUS_DUPLICATE_OBJECTID
2384          */
2385         status = smb2_create(tree, mem_ctx, &io);
2386         CHECK_STATUS(status, NT_STATUS_DUPLICATE_OBJECTID);
2387         torture_wait_for_oplock_break(tctx);
2388         CHECK_VAL(break_info.count, 0);
2389         torture_reset_break_info(tctx, &break_info);
2390
2391         /*
2392          * According to MS-SMB2 3.3.5.9.10 if Durable V2 Create is replayed and
2393          * FileAttributes or CreateDisposition do not match the earlier Create
2394          * request the Server fails request with
2395          * NT_STATUS_INVALID_PARAMETER. But through this test we see that server
2396          * does not really care about changed FileAttributes or
2397          * CreateDisposition.
2398          */
2399         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2400         io.in.create_disposition = NTCREATEX_DISP_OPEN;
2401         smb2cli_session_start_replay(tree->session->smbXcli);
2402         status = smb2_create(tree, mem_ctx, &io);
2403         smb2cli_session_stop_replay(tree->session->smbXcli);
2404         CHECK_STATUS(status, NT_STATUS_OK);
2405         torture_assert_u64_not_equal_goto(tctx,
2406                 io.out.file.handle.data[0],
2407                 ref1.out.file.handle.data[0],
2408                 ret, done, "data 0");
2409         torture_assert_u64_not_equal_goto(tctx,
2410                 io.out.file.handle.data[1],
2411                 ref1.out.file.handle.data[1],
2412                 ret, done, "data 1");
2413         torture_wait_for_oplock_break(tctx);
2414         CHECK_VAL(break_info.count, 0);
2415
2416 done:
2417         if (h != NULL) {
2418                 smb2_util_close(tree, *h);
2419         }
2420
2421         smb2_util_unlink(tree, fname);
2422         smb2_deltree(tree, BASEDIR);
2423
2424         talloc_free(tree);
2425         talloc_free(mem_ctx);
2426
2427         return ret;
2428 }
2429
2430 struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx)
2431 {
2432         struct torture_suite *suite =
2433                 torture_suite_create(ctx, "replay");
2434
2435         torture_suite_add_1smb2_test(suite, "replay-commands", test_replay_commands);
2436         torture_suite_add_1smb2_test(suite, "replay-regular", test_replay_regular);
2437         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock1", test_replay_dhv2_oplock1);
2438         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2);
2439         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3);
2440         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock-lease", test_replay_dhv2_oplock_lease);
2441         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1",  test_replay_dhv2_lease1);
2442         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2",  test_replay_dhv2_lease2);
2443         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease3",  test_replay_dhv2_lease3);
2444         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock",  test_replay_dhv2_lease_oplock);
2445         torture_suite_add_1smb2_test(suite, "channel-sequence", test_channel_sequence);
2446         torture_suite_add_1smb2_test(suite, "replay3", test_replay3);
2447         torture_suite_add_1smb2_test(suite, "replay4", test_replay4);
2448         torture_suite_add_1smb2_test(suite, "replay5", test_replay5);
2449         torture_suite_add_1smb2_test(suite, "replay6", test_replay6);
2450
2451         suite->description = talloc_strdup(suite, "SMB2 REPLAY tests");
2452
2453         return suite;
2454 }