889ecd73c72c165a60c2d4bd48a6b7a449e4868f
[metze/samba/wip.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_FILEINFO_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 Durability 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 Durability 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 Durability 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 Durability 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 durability 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 durability 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 durability 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 durability 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_FILEINFO_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 Durability 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         NTSTATUS status;
1768         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1769         struct smb2_handle _h;
1770         struct smb2_handle *h = NULL;
1771         struct smb2_create io;
1772         struct GUID create_guid = GUID_random();
1773         bool ret = true;
1774         const char *fname = BASEDIR "\\replay3.dat";
1775         struct smb2_tree *tree2 = NULL;
1776         struct smb2_transport *transport1 = tree1->session->transport;
1777         struct smb2_transport *transport2 = NULL;
1778         struct smb2_session *session1_1 = tree1->session;
1779         struct smb2_session *session1_2 = NULL;
1780         uint32_t share_capabilities;
1781         bool share_is_so;
1782         uint32_t server_capabilities;
1783
1784         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
1785                 torture_skip(tctx, "SMB 3.X Dialect family required for "
1786                                    "Replay tests\n");
1787         }
1788
1789         server_capabilities = smb2cli_conn_server_capabilities(
1790                                         tree1->session->transport->conn);
1791         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
1792                 torture_skip(tctx,
1793                              "Server does not support multi-channel.");
1794         }
1795
1796         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
1797         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1798
1799         ZERO_STRUCT(break_info);
1800         break_info.tctx = tctx;
1801         transport1->oplock.handler = torture_oplock_ack_handler;
1802         transport1->oplock.private_data = tree1;
1803
1804         torture_comment(tctx, "Replay of DurableHandleReqV2 on Multi "
1805                               "Channel\n");
1806         status = torture_smb2_testdir(tree1, BASEDIR, &_h);
1807         CHECK_STATUS(status, NT_STATUS_OK);
1808         smb2_util_close(tree1, _h);
1809         smb2_util_unlink(tree1, fname);
1810         CHECK_VAL(break_info.count, 0);
1811
1812         /*
1813          * use the 1st channel, 1st session
1814          */
1815         smb2_oplock_create_share(&io, fname,
1816                         smb2_util_share_access(""),
1817                         smb2_util_oplock_level("b"));
1818         io.in.durable_open = false;
1819         io.in.durable_open_v2 = true;
1820         io.in.persistent_open = false;
1821         io.in.create_guid = create_guid;
1822         io.in.timeout = UINT32_MAX;
1823
1824         tree1->session = session1_1;
1825         status = smb2_create(tree1, mem_ctx, &io);
1826         CHECK_STATUS(status, NT_STATUS_OK);
1827         _h = io.out.file.handle;
1828         h = &_h;
1829         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1830         if (share_is_so) {
1831                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1832                 CHECK_VAL(io.out.durable_open_v2, false);
1833                 CHECK_VAL(io.out.timeout, 0);
1834         } else {
1835                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
1836                 CHECK_VAL(io.out.durable_open_v2, true);
1837                 CHECK_VAL(io.out.timeout, io.in.timeout);
1838         }
1839         CHECK_VAL(io.out.durable_open, false);
1840         CHECK_VAL(break_info.count, 0);
1841
1842         status = smb2_connect(tctx,
1843                         host,
1844                         lpcfg_smb_ports(tctx->lp_ctx),
1845                         share,
1846                         lpcfg_resolve_context(tctx->lp_ctx),
1847                         popt_get_cmdline_credentials(),
1848                         &tree2,
1849                         tctx->ev,
1850                         &transport1->options,
1851                         lpcfg_socket_options(tctx->lp_ctx),
1852                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1853                         );
1854         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1855                         "smb2_connect failed");
1856         transport2 = tree2->session->transport;
1857
1858         transport2->oplock.handler = torture_oplock_ack_handler;
1859         transport2->oplock.private_data = tree2;
1860
1861         /*
1862          * Now bind the 1st session to 2nd transport channel
1863          */
1864         session1_2 = smb2_session_channel(transport2,
1865                         lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1866                         tree2, session1_1);
1867         torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
1868
1869         status = smb2_session_setup_spnego(session1_2,
1870                         popt_get_cmdline_credentials(),
1871                         0 /* previous_session_id */);
1872         CHECK_STATUS(status, NT_STATUS_OK);
1873
1874         /*
1875          * use the 2nd channel, 1st session
1876          */
1877         tree1->session = session1_2;
1878         smb2cli_session_start_replay(tree1->session->smbXcli);
1879         status = smb2_create(tree1, mem_ctx, &io);
1880         smb2cli_session_stop_replay(tree1->session->smbXcli);
1881         CHECK_STATUS(status, NT_STATUS_OK);
1882         _h = io.out.file.handle;
1883         h = &_h;
1884         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1885         if (share_is_so) {
1886                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1887                 CHECK_VAL(io.out.durable_open_v2, false);
1888                 CHECK_VAL(io.out.timeout, 0);
1889         } else {
1890                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
1891                 CHECK_VAL(io.out.durable_open_v2, true);
1892                 CHECK_VAL(io.out.timeout, io.in.timeout);
1893         }
1894         CHECK_VAL(io.out.durable_open, false);
1895         CHECK_VAL(break_info.count, 0);
1896
1897         tree1->session = session1_1;
1898         smb2_util_close(tree1, *h);
1899         h = NULL;
1900
1901 done:
1902         talloc_free(tree2);
1903         tree1->session = session1_1;
1904
1905         if (h != NULL) {
1906                 smb2_util_close(tree1, *h);
1907         }
1908
1909         smb2_util_unlink(tree1, fname);
1910         smb2_deltree(tree1, BASEDIR);
1911
1912         talloc_free(tree1);
1913         talloc_free(mem_ctx);
1914
1915         return ret;
1916 }
1917
1918 /**
1919  * Test Multichannel IO Ordering using ChannelSequence/Channel Epoch number
1920  */
1921 static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1)
1922 {
1923         const char *host = torture_setting_string(tctx, "host", NULL);
1924         const char *share = torture_setting_string(tctx, "share", NULL);
1925         NTSTATUS status;
1926         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1927         struct smb2_handle _h1;
1928         struct smb2_handle *h1 = NULL;
1929         struct smb2_create io;
1930         struct GUID create_guid = GUID_random();
1931         uint8_t buf[64];
1932         struct smb2_read rd;
1933         union smb_setfileinfo sfinfo;
1934         bool ret = true;
1935         const char *fname = BASEDIR "\\replay4.dat";
1936         struct smb2_tree *tree2 = NULL;
1937         struct smb2_transport *transport1 = tree1->session->transport;
1938         struct smb2_transport *transport2 = NULL;
1939         struct smb2_session *session1_1 = tree1->session;
1940         struct smb2_session *session1_2 = NULL;
1941         uint16_t curr_cs;
1942         uint32_t share_capabilities;
1943         bool share_is_so;
1944         uint32_t server_capabilities;
1945
1946         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
1947                 torture_skip(tctx, "SMB 3.X Dialect family required for "
1948                                    "Replay tests\n");
1949         }
1950
1951         server_capabilities = smb2cli_conn_server_capabilities(
1952                                         tree1->session->transport->conn);
1953         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
1954                 torture_skip(tctx,
1955                              "Server does not support multi-channel.");
1956         }
1957
1958         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
1959         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1960
1961         ZERO_STRUCT(break_info);
1962         break_info.tctx = tctx;
1963         transport1->oplock.handler = torture_oplock_ack_handler;
1964         transport1->oplock.private_data = tree1;
1965
1966         torture_comment(tctx, "IO Ordering for Multi Channel\n");
1967         status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
1968         CHECK_STATUS(status, NT_STATUS_OK);
1969         smb2_util_close(tree1, _h1);
1970         smb2_util_unlink(tree1, fname);
1971         CHECK_VAL(break_info.count, 0);
1972
1973         /*
1974          * use the 1st channel, 1st session
1975          */
1976
1977         smb2_oplock_create_share(&io, fname,
1978                         smb2_util_share_access(""),
1979                         smb2_util_oplock_level("b"));
1980         io.in.durable_open = false;
1981         io.in.durable_open_v2 = true;
1982         io.in.persistent_open = false;
1983         io.in.create_guid = create_guid;
1984         io.in.timeout = UINT32_MAX;
1985
1986         tree1->session = session1_1;
1987         status = smb2_create(tree1, mem_ctx, &io);
1988         CHECK_STATUS(status, NT_STATUS_OK);
1989         _h1 = io.out.file.handle;
1990         h1 = &_h1;
1991         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1992         if (share_is_so) {
1993                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1994                 CHECK_VAL(io.out.durable_open_v2, false);
1995                 CHECK_VAL(io.out.timeout, 0);
1996         } else {
1997                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
1998                 CHECK_VAL(io.out.durable_open_v2, true);
1999                 CHECK_VAL(io.out.timeout, io.in.timeout);
2000         }
2001         CHECK_VAL(io.out.durable_open, false);
2002         CHECK_VAL(break_info.count, 0);
2003
2004         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2005         CHECK_STATUS(status, NT_STATUS_OK);
2006
2007         /*
2008          * Increment ChannelSequence so that server thinks that there's a
2009          * Channel Failure
2010          */
2011         smb2cli_session_increment_channel_sequence(tree1->session->smbXcli);
2012
2013         /*
2014          * Perform a Read with incremented ChannelSequence
2015          */
2016         rd = (struct smb2_read) {
2017                 .in.file.handle = *h1,
2018                 .in.length = sizeof(buf),
2019                 .in.offset = 0
2020         };
2021         status = smb2_read(tree1, tree1, &rd);
2022         CHECK_STATUS(status, NT_STATUS_OK);
2023
2024         /*
2025          * Performing a Write with Stale ChannelSequence is not allowed by
2026          * server
2027          */
2028         curr_cs = smb2cli_session_reset_channel_sequence(
2029                                                 tree1->session->smbXcli, 0);
2030         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2031         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
2032
2033         /*
2034          * Performing a Write Replay with Stale ChannelSequence is not allowed
2035          * by server
2036          */
2037         smb2cli_session_start_replay(tree1->session->smbXcli);
2038         smb2cli_session_reset_channel_sequence(tree1->session->smbXcli, 0);
2039         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2040         smb2cli_session_stop_replay(tree1->session->smbXcli);
2041         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
2042
2043         /*
2044          * Performing a SetInfo with stale ChannelSequence is not allowed by
2045          * server
2046          */
2047         ZERO_STRUCT(sfinfo);
2048         sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
2049         sfinfo.generic.in.file.handle = *h1;
2050         sfinfo.position_information.in.position = 0x1000;
2051         status = smb2_setinfo_file(tree1, &sfinfo);
2052         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
2053
2054         /*
2055          * Performing a Read with stale ChannelSequence is allowed
2056          */
2057         rd = (struct smb2_read) {
2058                 .in.file.handle = *h1,
2059                 .in.length = ARRAY_SIZE(buf),
2060                 .in.offset = 0
2061         };
2062         status = smb2_read(tree1, tree1, &rd);
2063         CHECK_STATUS(status, NT_STATUS_OK);
2064
2065         status = smb2_connect(tctx,
2066                         host,
2067                         lpcfg_smb_ports(tctx->lp_ctx),
2068                         share,
2069                         lpcfg_resolve_context(tctx->lp_ctx),
2070                         popt_get_cmdline_credentials(),
2071                         &tree2,
2072                         tctx->ev,
2073                         &transport1->options,
2074                         lpcfg_socket_options(tctx->lp_ctx),
2075                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)
2076                         );
2077         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2078                         "smb2_connect failed");
2079         transport2 = tree2->session->transport;
2080
2081         transport2->oplock.handler = torture_oplock_ack_handler;
2082         transport2->oplock.private_data = tree2;
2083
2084         /*
2085          * Now bind the 1st session to 2nd transport channel
2086          */
2087         session1_2 = smb2_session_channel(transport2,
2088                         lpcfg_gensec_settings(tctx, tctx->lp_ctx),
2089                         tree2, session1_1);
2090         torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
2091
2092         status = smb2_session_setup_spnego(session1_2,
2093                         popt_get_cmdline_credentials(),
2094                         0 /* previous_session_id */);
2095         CHECK_STATUS(status, NT_STATUS_OK);
2096
2097         /*
2098          * use the 2nd channel, 1st session
2099          */
2100         tree1->session = session1_2;
2101
2102         /*
2103          * Write Replay with Correct ChannelSequence is allowed by the server
2104          */
2105         smb2cli_session_start_replay(tree1->session->smbXcli);
2106         smb2cli_session_reset_channel_sequence(tree1->session->smbXcli,
2107                                                curr_cs);
2108         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2109         CHECK_STATUS(status, NT_STATUS_OK);
2110         smb2cli_session_stop_replay(tree1->session->smbXcli);
2111
2112         /*
2113          * See what happens if we change the Buffer and perform a Write Replay.
2114          * This is to show that Write Replay does not really care about the data
2115          */
2116         memset(buf, 'r', ARRAY_SIZE(buf));
2117         smb2cli_session_start_replay(tree1->session->smbXcli);
2118         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
2119         CHECK_STATUS(status, NT_STATUS_OK);
2120         smb2cli_session_stop_replay(tree1->session->smbXcli);
2121
2122         /*
2123          * Read back from File to verify what was written
2124          */
2125         rd = (struct smb2_read) {
2126                 .in.file.handle = *h1,
2127                 .in.length = ARRAY_SIZE(buf),
2128                 .in.offset = 0
2129         };
2130         status = smb2_read(tree1, tree1, &rd);
2131         CHECK_STATUS(status, NT_STATUS_OK);
2132
2133         if ((rd.out.data.length != ARRAY_SIZE(buf)) ||
2134                         memcmp(rd.out.data.data, buf, ARRAY_SIZE(buf))) {
2135                 torture_comment(tctx, "Write Replay Data Mismatch\n");
2136         }
2137
2138         tree1->session = session1_1;
2139         smb2_util_close(tree1, *h1);
2140         h1 = NULL;
2141
2142         if (share_is_so) {
2143                 CHECK_VAL(break_info.count, 1);
2144         } else {
2145                 CHECK_VAL(break_info.count, 0);
2146         }
2147 done:
2148         talloc_free(tree2);
2149         tree1->session = session1_1;
2150
2151         if (h1 != NULL) {
2152                 smb2_util_close(tree1, *h1);
2153         }
2154
2155         smb2_util_unlink(tree1, fname);
2156         smb2_deltree(tree1, BASEDIR);
2157
2158         talloc_free(tree1);
2159         talloc_free(mem_ctx);
2160
2161         return ret;
2162 }
2163
2164 /**
2165  * Test Durability V2 Persistent Create Replay on a Single Channel
2166  */
2167 static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree)
2168 {
2169         NTSTATUS status;
2170         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2171         struct smb2_handle _h;
2172         struct smb2_handle *h = NULL;
2173         struct smb2_create io;
2174         struct GUID create_guid = GUID_random();
2175         bool ret = true;
2176         uint32_t share_capabilities;
2177         bool share_is_ca;
2178         bool share_is_so;
2179         uint32_t server_capabilities;
2180         const char *fname = BASEDIR "\\replay5.dat";
2181         struct smb2_transport *transport = tree->session->transport;
2182         struct smbcli_options options = tree->session->transport->options;
2183         uint8_t expect_oplock = smb2_util_oplock_level("b");
2184         NTSTATUS expect_status = NT_STATUS_DUPLICATE_OBJECTID;
2185
2186         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
2187                 torture_skip(tctx, "SMB 3.X Dialect family required for "
2188                                 "Replay tests\n");
2189         }
2190
2191         server_capabilities = smb2cli_conn_server_capabilities(
2192                                         tree->session->transport->conn);
2193         if (!(server_capabilities & SMB2_CAP_PERSISTENT_HANDLES)) {
2194                 torture_skip(tctx,
2195                              "Server does not support persistent handles.");
2196         }
2197
2198         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
2199
2200         share_is_ca = share_capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
2201         if (!share_is_ca) {
2202                 torture_skip(tctx, "Share is not continuously available.");
2203         }
2204
2205         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
2206         if (share_is_so) {
2207                 expect_oplock = smb2_util_oplock_level("s");
2208                 expect_status = NT_STATUS_FILE_NOT_AVAILABLE;
2209         }
2210
2211         ZERO_STRUCT(break_info);
2212         break_info.tctx = tctx;
2213         transport->oplock.handler = torture_oplock_ack_handler;
2214         transport->oplock.private_data = tree;
2215
2216         torture_comment(tctx, "Replay of Persistent DurableHandleReqV2 on Single "
2217                         "Channel\n");
2218         status = torture_smb2_testdir(tree, BASEDIR, &_h);
2219         CHECK_STATUS(status, NT_STATUS_OK);
2220         smb2_util_close(tree, _h);
2221         smb2_util_unlink(tree, fname);
2222         CHECK_VAL(break_info.count, 0);
2223
2224         smb2_oplock_create_share(&io, fname,
2225                         smb2_util_share_access("RWD"),
2226                         smb2_util_oplock_level("b"));
2227         io.in.durable_open = false;
2228         io.in.durable_open_v2 = true;
2229         io.in.persistent_open = true;
2230         io.in.create_guid = create_guid;
2231         io.in.timeout = UINT32_MAX;
2232
2233         status = smb2_create(tree, mem_ctx, &io);
2234         CHECK_STATUS(status, NT_STATUS_OK);
2235         _h = io.out.file.handle;
2236         h = &_h;
2237         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2238         CHECK_VAL(io.out.oplock_level, expect_oplock);
2239         CHECK_VAL(io.out.durable_open, false);
2240         CHECK_VAL(io.out.durable_open_v2, true);
2241         CHECK_VAL(io.out.persistent_open, true);
2242         CHECK_VAL(io.out.timeout, io.in.timeout);
2243         CHECK_VAL(break_info.count, 0);
2244
2245         /* disconnect, leaving the durable open */
2246         TALLOC_FREE(tree);
2247
2248         if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) {
2249                 torture_warning(tctx, "couldn't reconnect, bailing\n");
2250                 ret = false;
2251                 goto done;
2252         }
2253
2254         /* a re-open of a persistent handle causes an error */
2255         status = smb2_create(tree, mem_ctx, &io);
2256         CHECK_STATUS(status, expect_status);
2257
2258         /* SMB2_FLAGS_REPLAY_OPERATION must be set to open the Persistent Handle */
2259         smb2cli_session_start_replay(tree->session->smbXcli);
2260         smb2cli_session_increment_channel_sequence(tree->session->smbXcli);
2261         status = smb2_create(tree, mem_ctx, &io);
2262         CHECK_STATUS(status, NT_STATUS_OK);
2263         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2264         CHECK_VAL(io.out.durable_open, false);
2265         CHECK_VAL(io.out.persistent_open, true);
2266         CHECK_VAL(io.out.oplock_level, expect_oplock);
2267         _h = io.out.file.handle;
2268         h = &_h;
2269
2270         smb2_util_close(tree, *h);
2271         h = NULL;
2272 done:
2273         if (h != NULL) {
2274                 smb2_util_close(tree, *h);
2275         }
2276
2277         smb2_util_unlink(tree, fname);
2278         smb2_deltree(tree, BASEDIR);
2279
2280         talloc_free(tree);
2281         talloc_free(mem_ctx);
2282
2283         return ret;
2284 }
2285
2286
2287 /**
2288  * Test Error Codes when a DurableHandleReqV2 with matching CreateGuid is
2289  * re-sent with or without SMB2_FLAGS_REPLAY_OPERATION
2290  */
2291 static bool test_replay6(struct torture_context *tctx, struct smb2_tree *tree)
2292 {
2293         NTSTATUS status;
2294         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2295         struct smb2_handle _h;
2296         struct smb2_handle *h = NULL;
2297         struct smb2_create io, ref1;
2298         union smb_fileinfo qfinfo;
2299         struct GUID create_guid = GUID_random();
2300         bool ret = true;
2301         const char *fname = BASEDIR "\\replay6.dat";
2302         struct smb2_transport *transport = tree->session->transport;
2303
2304         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
2305                 torture_skip(tctx, "SMB 3.X Dialect family required for "
2306                                    "replay tests\n");
2307         }
2308
2309         torture_reset_break_info(tctx, &break_info);
2310         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
2311         tree->session->transport->oplock.private_data = tree;
2312
2313         torture_comment(tctx, "Error Codes for DurableHandleReqV2 Replay\n");
2314         smb2_util_unlink(tree, fname);
2315         status = torture_smb2_testdir(tree, BASEDIR, &_h);
2316         CHECK_STATUS(status, NT_STATUS_OK);
2317         smb2_util_close(tree, _h);
2318         torture_wait_for_oplock_break(tctx);
2319         CHECK_VAL(break_info.count, 0);
2320         torture_reset_break_info(tctx, &break_info);
2321
2322         smb2_oplock_create_share(&io, fname,
2323                         smb2_util_share_access("RWD"),
2324                         smb2_util_oplock_level("b"));
2325         io.in.durable_open = false;
2326         io.in.durable_open_v2 = true;
2327         io.in.persistent_open = false;
2328         io.in.create_guid = create_guid;
2329         io.in.timeout = UINT32_MAX;
2330
2331         status = smb2_create(tree, mem_ctx, &io);
2332         CHECK_STATUS(status, NT_STATUS_OK);
2333         ref1 = io;
2334         _h = io.out.file.handle;
2335         h = &_h;
2336         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2337         CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
2338         CHECK_VAL(io.out.durable_open, false);
2339         CHECK_VAL(io.out.durable_open_v2, true);
2340
2341         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2342         io.in.create_disposition = NTCREATEX_DISP_OPEN;
2343         smb2cli_session_start_replay(tree->session->smbXcli);
2344         status = smb2_create(tree, mem_ctx, &io);
2345         smb2cli_session_stop_replay(tree->session->smbXcli);
2346         CHECK_STATUS(status, NT_STATUS_OK);
2347         CHECK_CREATE_OUT(&io, &ref1);
2348         torture_wait_for_oplock_break(tctx);
2349         CHECK_VAL(break_info.count, 0);
2350         torture_reset_break_info(tctx, &break_info);
2351
2352         qfinfo = (union smb_fileinfo) {
2353                 .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
2354                 .generic.in.file.handle = *h
2355         };
2356         torture_comment(tctx, "Trying getinfo\n");
2357         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
2358         CHECK_STATUS(status, NT_STATUS_OK);
2359         CHECK_VAL(qfinfo.position_information.out.position, 0);
2360
2361         smb2cli_session_start_replay(tree->session->smbXcli);
2362         status = smb2_create(tree, mem_ctx, &io);
2363         smb2cli_session_stop_replay(tree->session->smbXcli);
2364         CHECK_STATUS(status, NT_STATUS_OK);
2365         torture_assert_u64_not_equal_goto(tctx,
2366                 io.out.file.handle.data[0],
2367                 ref1.out.file.handle.data[0],
2368                 ret, done, "data 0");
2369         torture_assert_u64_not_equal_goto(tctx,
2370                 io.out.file.handle.data[1],
2371                 ref1.out.file.handle.data[1],
2372                 ret, done, "data 1");
2373         torture_wait_for_oplock_break(tctx);
2374         CHECK_VAL(break_info.count, 1);
2375         CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
2376         torture_reset_break_info(tctx, &break_info);
2377
2378         /*
2379          * Resend the matching Durable V2 Create without
2380          * SMB2_FLAGS_REPLAY_OPERATION. This triggers an oplock break and still
2381          * gets NT_STATUS_DUPLICATE_OBJECTID
2382          */
2383         status = smb2_create(tree, mem_ctx, &io);
2384         CHECK_STATUS(status, NT_STATUS_DUPLICATE_OBJECTID);
2385         torture_wait_for_oplock_break(tctx);
2386         CHECK_VAL(break_info.count, 0);
2387         torture_reset_break_info(tctx, &break_info);
2388
2389         /*
2390          * According to MS-SMB2 3.3.5.9.10 if Durable V2 Create is replayed and
2391          * FileAttributes or CreateDisposition do not match the earlier Create
2392          * request the Server fails request with
2393          * NT_STATUS_INVALID_PARAMETER. But through this test we see that server
2394          * does not really care about changed FileAttributes or
2395          * CreateDisposition.
2396          */
2397         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2398         io.in.create_disposition = NTCREATEX_DISP_OPEN;
2399         smb2cli_session_start_replay(tree->session->smbXcli);
2400         status = smb2_create(tree, mem_ctx, &io);
2401         smb2cli_session_stop_replay(tree->session->smbXcli);
2402         CHECK_STATUS(status, NT_STATUS_OK);
2403         torture_assert_u64_not_equal_goto(tctx,
2404                 io.out.file.handle.data[0],
2405                 ref1.out.file.handle.data[0],
2406                 ret, done, "data 0");
2407         torture_assert_u64_not_equal_goto(tctx,
2408                 io.out.file.handle.data[1],
2409                 ref1.out.file.handle.data[1],
2410                 ret, done, "data 1");
2411         torture_wait_for_oplock_break(tctx);
2412         CHECK_VAL(break_info.count, 0);
2413
2414 done:
2415         if (h != NULL) {
2416                 smb2_util_close(tree, *h);
2417         }
2418
2419         smb2_util_unlink(tree, fname);
2420         smb2_deltree(tree, BASEDIR);
2421
2422         talloc_free(tree);
2423         talloc_free(mem_ctx);
2424
2425         return ret;
2426 }
2427
2428 struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx)
2429 {
2430         struct torture_suite *suite =
2431                 torture_suite_create(ctx, "replay");
2432
2433         torture_suite_add_1smb2_test(suite, "replay-commands", test_replay_commands);
2434         torture_suite_add_1smb2_test(suite, "replay-regular", test_replay_regular);
2435         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock1", test_replay_dhv2_oplock1);
2436         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2);
2437         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3);
2438         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock-lease", test_replay_dhv2_oplock_lease);
2439         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1",  test_replay_dhv2_lease1);
2440         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2",  test_replay_dhv2_lease2);
2441         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease3",  test_replay_dhv2_lease3);
2442         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock",  test_replay_dhv2_lease_oplock);
2443         torture_suite_add_1smb2_test(suite, "channel-sequence", test_channel_sequence);
2444         torture_suite_add_1smb2_test(suite, "replay3", test_replay3);
2445         torture_suite_add_1smb2_test(suite, "replay4", test_replay4);
2446         torture_suite_add_1smb2_test(suite, "replay5", test_replay5);
2447         torture_suite_add_1smb2_test(suite, "replay6", test_replay6);
2448
2449         suite->description = talloc_strdup(suite, "SMB2 REPLAY tests");
2450
2451         return suite;
2452 }