From: Ralph Boehme Date: Sat, 27 Sep 2025 11:01:32 +0000 (+0200) Subject: smbtorture: add test "smb2.lease.lease-epoch" X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ca0363e5a7f53cde4ae7223c36f21c2ae12318f9;p=thirdparty%2Fsamba.git smbtorture: add test "smb2.lease.lease-epoch" Verifies the lease epoch is not incremented by the server (returns what the client sent in the request) if a lease was not granted ie lease_level=NONE. Test passes against Windows 2025. From MS-SMB2 3.3.5.9.11 "Handling the SMB2_CREATE_REQUEST_LEASE_V2 Create Context": If the object store succeeds this request, Lease.LeaseState MUST be set to the new caching state. The server MUST increment Lease.Epoch by 1. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15933 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke --- diff --git a/selftest/knownfail.d/samba3.smb2.lease b/selftest/knownfail.d/samba3.smb2.lease new file mode 100644 index 00000000000..d1bc4209385 --- /dev/null +++ b/selftest/knownfail.d/samba3.smb2.lease @@ -0,0 +1 @@ +^samba3.smb2.lease.lease-epoch\(fileserver\) diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c index 9696ddc11da..ec97ae6b59c 100644 --- a/source4/torture/smb2/lease.c +++ b/source4/torture/smb2/lease.c @@ -6090,6 +6090,104 @@ done: return ret; } +/* + * Verifies the lease epoch is not incremented by the server (returns what the + * client sent in the request) if a lease was not granted ie lease_level=NONE. + */ +static bool test_lease_epoch(struct torture_context *tctx, + struct smb2_tree *tree) +{ + struct smb2_create c; + struct smb2_lease ls1; + struct smb2_handle h1 = {}; + struct smb2_write wr; + char dat = 'x'; + DATA_BLOB data = (DATA_BLOB) {.data = (uint8_t *)&dat, .length = 1}; + struct smb2_lock lck = {0}; + struct smb2_lock_element el[1]; + uint64_t lease1 = 1; + struct GUID create_guid = GUID_random(); + char *fname = NULL; + NTSTATUS status; + bool ret = true; + + fname = talloc_asprintf(tctx, "lease_break-%ld.dat", random()); + torture_assert_not_null_goto(tctx, fname, ret, done, + "talloc_asprintf failed\n"); + + c = (struct smb2_create) { + .in.desired_access = SEC_RIGHTS_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.create_disposition = NTCREATEX_DISP_OPEN_IF, + .in.fname = fname, + }; + + status = smb2_create(tree, tctx, &c); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_create failed\n"); + h1 = c.out.file.handle; + + ZERO_STRUCT(wr); + wr.in.file.handle = h1; + wr.in.offset = 0; + wr.in.data = data; + status = smb2_write(tree, &wr); + torture_assert_ntstatus_ok(tctx, status, "smb2_write failed\n"); + + ZERO_ARRAY(el); + ZERO_STRUCT(lck); + el[0].offset = 0; + el[0].length = 1; + el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; + lck.in.locks = el; + lck.in.lock_count = 1; + lck.in.file.handle = h1; + + status = smb2_lock(tree, &lck); + torture_assert_ntstatus_equal_goto( + tctx, status, NT_STATUS_OK, + ret, done, "smb2_lock failed\n"); + + + smb2_lease_v2_create_share(&c, + &ls1, + false, + fname, + smb2_util_share_access("RWD"), + lease1, + NULL, + smb2_util_lease_state("R"), + 100); + c.in.durable_open_v2 = true; + c.in.create_guid = create_guid; + status = smb2_create(tree, tree, &c); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_create failed\n"); + + torture_assert_int_equal_goto( + tctx, + c.out.oplock_level, + SMB2_OPLOCK_LEVEL_LEASE, + ret, done, + "Bad lease level\n"); + torture_assert_int_equal_goto( + tctx, + c.out.lease_response_v2.lease_state, + 0, + ret, done, + "Bad lease level\n"); + torture_assert_int_equal_goto( + tctx, + c.out.lease_response_v2.lease_epoch, + 100, + ret, + done, + "Bad lease epoch\n"); + +done: + return ret; +} + struct torture_suite *torture_smb2_lease_init(TALLOC_CTX *ctx) { struct torture_suite *suite = @@ -6154,6 +6252,7 @@ struct torture_suite *torture_smb2_lease_init(TALLOC_CTX *ctx) test_initial_delete_disconnect); torture_suite_add_2smb2_test(suite, "rename_dir_openfile", torture_rename_dir_openfile); + torture_suite_add_1smb2_test(suite, "lease-epoch", test_lease_epoch); suite->description = talloc_strdup(suite, "SMB2-LEASE tests");