The branch, master has been updated
       via  a354758 s4:torture:smb2: add durable_open_basic2 test: test durable 
open against all lease types
       via  976f980 s4:torture:smb2: add a new durable_open_basic1 test: test 
open against all oplock types
       via  f8aeca1 s4:torture:smb2: check wheter open was durable in existing 
tests
       via  530cd2a s4:libcli: in smb2_create_recv, map 
SMB2_CREATE_DURABLE_HANDLE_RESPONSE buffer smb2_create.out.durable_open
       via  d01b248 source4/libcli: add bool durable_open to smb2_create.out.
       via  de967f2 s4:torture: test also break semantics between batch-oplocks 
and leases
       via  69ca2bd s4:torture:smb2: adapt comment in durable-open.lease test 
according to current information.
       via  5975e8a s4:torture:smb2: fix the durable_open test to succeed 
against w7 and w2k8r2
      from  f30f71c Fix bug #8548 - winbind_samlogon_retry_loop ignores 
logon_parameters flags.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit a354758da50d09341bbea237548de52e3821a198
Author: Michael Adam <ob...@samba.org>
Date:   Sat Oct 29 17:28:38 2011 +0200

    s4:torture:smb2: add durable_open_basic2 test: test durable open against 
all lease types
    
    Autobuild-User: Michael Adam <ob...@samba.org>
    Autobuild-Date: Sun Oct 30 20:17:16 CET 2011 on sn-devel-104

commit 976f9806c9255202bd3c3d2f927d2d854f7034f8
Author: Michael Adam <ob...@samba.org>
Date:   Sat Oct 29 17:26:53 2011 +0200

    s4:torture:smb2: add a new durable_open_basic1 test: test open against all 
oplock types

commit f8aeca1018cf036b3294f2d6807fd35b2de2c44b
Author: Michael Adam <ob...@samba.org>
Date:   Sat Oct 29 17:25:00 2011 +0200

    s4:torture:smb2: check wheter open was durable in existing tests

commit 530cd2aac6178570c182b6f33364c7d3c6316c00
Author: Michael Adam <ob...@samba.org>
Date:   Sat Oct 29 13:18:05 2011 +0200

    s4:libcli: in smb2_create_recv, map SMB2_CREATE_DURABLE_HANDLE_RESPONSE 
buffer smb2_create.out.durable_open

commit d01b248d4f6260c9d67a82e6497f8f4c99666a4c
Author: Michael Adam <ob...@samba.org>
Date:   Sat Oct 29 13:16:07 2011 +0200

    source4/libcli: add bool durable_open to smb2_create.out.
    
    The server gives indication whether the open was durable
    we should record this.

commit de967f22fc9e5a6f9f95be90e882935761295917
Author: Michael Adam <ob...@samba.org>
Date:   Sat Oct 29 14:48:58 2011 +0200

    s4:torture: test also break semantics between batch-oplocks and leases
    
    This must have been a typo (listing EXCLUSIVE twice).
    But BATCH and EXCLUSIVE oplocks apparently share the
    same break semantics with respect to leases.

commit 69ca2bd048fa8ec98ab668baf651d3e84f7e919c
Author: Michael Adam <ob...@samba.org>
Date:   Sun Oct 30 18:40:00 2011 +0100

    s4:torture:smb2: adapt comment in durable-open.lease test according to 
current information.

commit 5975e8a3f46f3d6f99d997d36f874141f80b9c33
Author: Michael Adam <ob...@samba.org>
Date:   Sat Oct 29 11:56:48 2011 +0200

    s4:torture:smb2: fix the durable_open test to succeed against w7 and w2k8r2
    
    When a first client that has a durable open with share read/write/delete
    and a read-write-handle lease on the file disconnects, a second
    client will succeed in opening the file and the new client will be
    given a RWH-lease if requested, not only a RH-lease, as was previously
    checked in the test.
    
    This might have been a bug in win7 build 7000, which is what the
    comments in the test give as reference.

-----------------------------------------------------------------------

Summary of changes:
 source4/libcli/raw/interfaces.h     |    1 +
 source4/libcli/smb2/create.c        |    7 +
 source4/torture/smb2/durable_open.c |  270 ++++++++++++++++++++++++++++++++++-
 source4/torture/smb2/lease.c        |    2 +-
 4 files changed, 278 insertions(+), 2 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index 7bb5255..7aba48b 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -1741,6 +1741,7 @@ union smb_open {
                        uint32_t maximal_access;
                        uint8_t on_disk_id[32];
                        struct smb2_lease lease_response;
+                       bool durable_open;
 
                        /* tagged blobs in the reply */
                        struct smb2_create_blobs blobs;
diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c
index 4e15064..438651f 100644
--- a/source4/libcli/smb2/create.c
+++ b/source4/libcli/smb2/create.c
@@ -274,6 +274,13 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, 
TALLOC_CTX *mem_ctx, struct
                        io->out.lease_response.lease_flags = IVAL(data, 20);
                        io->out.lease_response.lease_duration = BVAL(data, 24);
                }
+               if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNQ) == 
0) {
+                       if (io->out.blobs.blobs[i].data.length != 8) {
+                               smb2_request_destroy(req);
+                               return NT_STATUS_INVALID_NETWORK_RESPONSE;
+                       }
+                       io->out.durable_open = true;
+               }
        }
 
        data_blob_free(&blob);
diff --git a/source4/torture/smb2/durable_open.c 
b/source4/torture/smb2/durable_open.c
index 544f404..33ce1e9 100644
--- a/source4/torture/smb2/durable_open.c
+++ b/source4/torture/smb2/durable_open.c
@@ -49,6 +49,261 @@
                CHECK_VAL((__io)->out.reserved2, 0);                    \
        } while(0)
 
+
+static inline uint32_t map_lease(const char *ls)
+{
+       uint32_t val = 0;
+       int i;
+
+       for (i = 0; i < strlen(ls); i++) {
+               switch (ls[i]) {
+               case 'R':
+                       val |= SMB2_LEASE_READ;
+                       break;
+               case 'H':
+                       val |= SMB2_LEASE_HANDLE;
+                       break;
+               case 'W':
+                       val |= SMB2_LEASE_WRITE;
+                       break;
+               }
+       }
+
+       return val;
+}
+
+/**
+ * basic durable_open test.
+ * durable state should only be granted when requested
+ * along with a batch oplock or a handle lease.
+ *
+ * This test tests durable open with all possible oplock types.
+ */
+
+struct durable_open_vs_oplock {
+       uint8_t level;
+       bool expected;
+};
+
+#define NUM_OPLOCK_OPEN_TESTS 4
+struct durable_open_vs_oplock 
durable_open_vs_oplock_table[NUM_OPLOCK_OPEN_TESTS] =
+{
+       { SMB2_OPLOCK_LEVEL_NONE, false },
+       { SMB2_OPLOCK_LEVEL_II, false },
+       { SMB2_OPLOCK_LEVEL_EXCLUSIVE, false },
+       { SMB2_OPLOCK_LEVEL_BATCH, true },
+};
+
+static bool test_one_durable_open_basic1(struct torture_context *tctx,
+                                        struct smb2_tree *tree,
+                                        const char *fname,
+                                        struct smb2_create io,
+                                        struct durable_open_vs_oplock test)
+{
+       NTSTATUS status;
+       TALLOC_CTX *mem_ctx = talloc_new(tctx);
+       struct smb2_handle _h;
+       struct smb2_handle *h = NULL;
+       bool ret = true;
+
+       smb2_util_unlink(tree, fname);
+
+       io.in.fname = fname;
+       io.in.oplock_level = test.level;
+       status = smb2_create(tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       _h = io.out.file.handle;
+       h = &_h;
+       CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+       CHECK_VAL(io.out.durable_open, test.expected);
+       CHECK_VAL(io.out.oplock_level, test.level);
+
+done:
+       if (h != NULL) {
+               smb2_util_close(tree, *h);
+       }
+       smb2_util_unlink(tree, fname);
+       talloc_free(mem_ctx);
+
+       return ret;
+}
+
+bool test_durable_open_basic1(struct torture_context *tctx,
+                             struct smb2_tree *tree)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(tctx);
+       struct smb2_create io;
+       char fname[256];
+       bool ret = true;
+       int i;
+
+       /* Choose a random name in case the state is left a little funky. */
+       snprintf(fname, 256, "durable_open_basic1_%s.dat", 
generate_random_str(tctx, 8));
+
+       smb2_util_unlink(tree, fname);
+
+       ZERO_STRUCT(io);
+       io.in.security_flags            = 0x00;
+       io.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
+       io.in.create_flags              = 0x00000000;
+       io.in.reserved                  = 0x00000000;
+       io.in.desired_access            = SEC_RIGHTS_FILE_ALL;
+       io.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
+       io.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
+                                         NTCREATEX_SHARE_ACCESS_WRITE |
+                                         NTCREATEX_SHARE_ACCESS_DELETE;
+       io.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
+       io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
+                                         NTCREATEX_OPTIONS_ASYNC_ALERT |
+                                         NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
+                                         0x00200000;
+       io.in.durable_open              = true;
+       io.in.fname                     = fname;
+
+       /* test various oplock levels with durable open */
+
+       for (i = 0; i < NUM_OPLOCK_OPEN_TESTS; i++) {
+               ret = test_one_durable_open_basic1(tctx,
+                                                  tree,
+                                                  fname,
+                                                  io,
+                                                  
durable_open_vs_oplock_table[i]);
+               if (ret == false) {
+                       goto done;
+               }
+       }
+
+done:
+       smb2_util_unlink(tree, fname);
+       talloc_free(tree);
+       talloc_free(mem_ctx);
+
+       return ret;
+}
+
+/**
+ * basic durable_open test.
+ * durable state should only be granted when requested
+ * along with a batch oplock or a handle lease.
+ *
+ * This test tests durable open with all valid lease types.
+ */
+
+struct durable_open_vs_lease {
+       const char *type;
+       bool expected;
+};
+
+#define NUM_LEASE_OPEN_TESTS 5
+struct durable_open_vs_lease durable_open_vs_lease_table[NUM_LEASE_OPEN_TESTS] 
=
+{
+       { "", false },
+       { "R", false },
+       { "RW", false },
+       { "RH", true },
+       { "RHW", true },
+};
+
+static bool test_one_durable_open_basic2(struct torture_context *tctx,
+                                        struct smb2_tree *tree,
+                                        const char *fname,
+                                        struct smb2_create io,
+                                        struct durable_open_vs_lease test)
+{
+       NTSTATUS status;
+       TALLOC_CTX *mem_ctx = talloc_new(tctx);
+       struct smb2_handle _h;
+       struct smb2_handle *h = NULL;
+       bool ret = true;
+       struct smb2_lease ls;
+       uint64_t lease;
+
+       smb2_util_unlink(tree, fname);
+
+       io.in.fname = fname;
+       io.in.oplock_level = SMB2_OPLOCK_LEVEL_LEASE;
+
+       lease = random();
+
+       ZERO_STRUCT(ls);
+       ls.lease_key.data[0] = lease;
+       ls.lease_key.data[1] = ~lease;
+       ls.lease_state = map_lease(test.type);
+       io.in.lease_request = &ls;
+
+       status = smb2_create(tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       _h = io.out.file.handle;
+       h = &_h;
+       CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+       CHECK_VAL(io.out.durable_open, test.expected);
+       CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
+       CHECK_VAL(io.out.lease_response.lease_key.data[0], lease);
+       CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease);
+       CHECK_VAL(io.out.lease_response.lease_state, map_lease(test.type));
+done:
+       if (h != NULL) {
+               smb2_util_close(tree, *h);
+       }
+       smb2_util_unlink(tree, fname);
+       talloc_free(mem_ctx);
+
+       return ret;
+}
+
+bool test_durable_open_basic2(struct torture_context *tctx,
+                             struct smb2_tree *tree)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(tctx);
+       struct smb2_create io;
+       char fname[256];
+       bool ret = true;
+       int i;
+
+       /* Choose a random name in case the state is left a little funky. */
+       snprintf(fname, 256, "durable_open_basic2_%s.dat", 
generate_random_str(tctx, 8));
+
+       smb2_util_unlink(tree, fname);
+
+       ZERO_STRUCT(io);
+       io.in.security_flags            = 0x00;
+       io.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
+       io.in.create_flags              = 0x00000000;
+       io.in.reserved                  = 0x00000000;
+       io.in.desired_access            = SEC_RIGHTS_FILE_ALL;
+       io.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
+       io.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
+                                         NTCREATEX_SHARE_ACCESS_WRITE |
+                                         NTCREATEX_SHARE_ACCESS_DELETE;
+       io.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
+       io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
+                                         NTCREATEX_OPTIONS_ASYNC_ALERT |
+                                         NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
+                                         0x00200000;
+       io.in.durable_open              = true;
+       io.in.fname                     = fname;
+
+       /* test various oplock levels with durable open */
+
+       for (i = 0; i < NUM_LEASE_OPEN_TESTS; i++) {
+               ret = test_one_durable_open_basic2(tctx,
+                                                  tree,
+                                                  fname,
+                                                  io,
+                                                  
durable_open_vs_lease_table[i]);
+               if (ret == false) {
+                       goto done;
+               }
+       }
+
+done:
+       smb2_util_unlink(tree, fname);
+       talloc_free(tree);
+       talloc_free(mem_ctx);
+
+       return ret;
+}
+
 /*
    basic testing of SMB2 durable opens
    regarding the position information on the handle
@@ -92,6 +347,7 @@ bool test_durable_open_file_position(struct torture_context 
*tctx,
        CHECK_STATUS(status, NT_STATUS_OK);
        h1 = io1.out.file.handle;
        CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+       CHECK_VAL(io1.out.durable_open, true);
        CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
 
        /* TODO: check extra blob content */
@@ -138,6 +394,7 @@ bool test_durable_open_file_position(struct torture_context 
*tctx,
 
        status = smb2_create(tree2, mem_ctx, &io2);
        CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VAL(io2.out.durable_open, true);
        CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
        CHECK_VAL(io2.out.reserved, 0x00);
        CHECK_VAL(io2.out.create_action, NTCREATEX_ACTION_EXISTED);
@@ -217,6 +474,7 @@ bool test_durable_open_oplock(struct torture_context *tctx,
        CHECK_STATUS(status, NT_STATUS_OK);
        h1 = io1.out.file.handle;
        CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+       CHECK_VAL(io1.out.durable_open, true);
        CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
 
        /* Disconnect after getting the batch */
@@ -232,6 +490,7 @@ bool test_durable_open_oplock(struct torture_context *tctx,
        CHECK_STATUS(status, NT_STATUS_OK);
        h2 = io2.out.file.handle;
        CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+       CHECK_VAL(io2.out.durable_open, true);
        CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
 
        /* What if tree1 tries to come back and reclaim? */
@@ -321,6 +580,7 @@ bool test_durable_open_lease(struct torture_context *tctx,
        status = smb2_create(tree1, mem_ctx, &io1);
        CHECK_STATUS(status, NT_STATUS_OK);
        h1 = io1.out.file.handle;
+       CHECK_VAL(io1.out.durable_open, true);
        CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
 
        CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
@@ -337,17 +597,21 @@ bool test_durable_open_lease(struct torture_context *tctx,
         * Windows7 (build 7000) will grant an RH lease immediate (not an RHW?)
         * even if the original client is gone. (ZML: This seems like a bug. It
         * should give some time for the client to reconnect! And why RH?)
+        * 
+        * obnox: Current windows 7 and w2k8r2 grant RHW instead of RH.
+        * Test is adapted accordingly.
         */
        status = smb2_create(tree2, mem_ctx, &io2);
        CHECK_STATUS(status, NT_STATUS_OK);
        h2 = io2.out.file.handle;
+       CHECK_VAL(io2.out.durable_open, true);
        CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
 
        CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
        CHECK_VAL(io2.out.lease_response.lease_key.data[0], lease2);
        CHECK_VAL(io2.out.lease_response.lease_key.data[1], ~lease2);
        CHECK_VAL(io2.out.lease_response.lease_state,
-           SMB2_LEASE_READ|SMB2_LEASE_HANDLE);
+           SMB2_LEASE_READ|SMB2_LEASE_HANDLE|SMB2_LEASE_WRITE);
 
        /* What if tree1 tries to come back and reclaim? */
        if (!torture_smb2_connection(tctx, &tree1)) {
@@ -432,6 +696,7 @@ bool test_durable_open_lock(struct torture_context *tctx,
        h = io.out.file.handle;
        CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
 
+       CHECK_VAL(io.out.durable_open, true);
        CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
        CHECK_VAL(io.out.lease_response.lease_key.data[0], lease);
        CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease);
@@ -545,6 +810,7 @@ bool test_durable_open_open(struct torture_context *tctx,
        status = smb2_create(tree1, mem_ctx, &io1);
        CHECK_STATUS(status, NT_STATUS_OK);
        h1 = io1.out.file.handle;
+       CHECK_VAL(io1.out.durable_open, true);
        CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
 
        CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
@@ -601,6 +867,8 @@ struct torture_suite *torture_smb2_durable_open_init(void)
        struct torture_suite *suite =
            torture_suite_create(talloc_autofree_context(), "durable-open");
 
+       torture_suite_add_1smb2_test(suite, "basic1", test_durable_open_basic1);
+       torture_suite_add_1smb2_test(suite, "basic2", test_durable_open_basic2);
        torture_suite_add_2smb2_test(suite, "file-position",
            test_durable_open_file_position);
        torture_suite_add_2smb2_test(suite, "oplock", test_durable_open_oplock);
diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c
index 564394f..3d3f17d 100644
--- a/source4/torture/smb2/lease.c
+++ b/source4/torture/smb2/lease.c
@@ -550,7 +550,7 @@ static inline uint32_t oplock(const char *op) {
                case 'x':
                        return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
                case 'b':
-                       return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
+                       return SMB2_OPLOCK_LEVEL_BATCH;
                default:
                        continue;
                }


-- 
Samba Shared Repository

Reply via email to