The branch, master has been updated
       via  5334b79142e32c39c56cea2e9c0d5b08e2f217ca (commit)
      from  4b6401ab2cce8319abe0f8176bb460d51bd4a390 (commit)

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


- Log -----------------------------------------------------------------
commit 5334b79142e32c39c56cea2e9c0d5b08e2f217ca
Author: Aravind <aravind.sriniva...@isilon.com>
Date:   Tue Jul 7 07:11:56 2009 -0700

    torture/smb2: Adding SMB2 Directory enumeration torture tests.
    
    * Most of the tests were ported from SMB torture tests.
    * Added one new tests which checks the behavior of the file_index field
      present in SMB2_FIND struct.
    * Added one new test to check the enumeration of directories containing
      lots of files (~2000 files) with name lengths varying from 1 to 200 char.

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

Summary of changes:
 source4/torture/smb2/config.mk |    1 +
 source4/torture/smb2/dir.c     | 1289 +++++++++++++++++++++++++++++++++++++++-
 source4/torture/smb2/smb2.c    |    1 +
 3 files changed, 1265 insertions(+), 26 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/torture/smb2/config.mk b/source4/torture/smb2/config.mk
index bc4fc15..b321b41 100644
--- a/source4/torture/smb2/config.mk
+++ b/source4/torture/smb2/config.mk
@@ -22,6 +22,7 @@ TORTURE_SMB2_OBJ_FILES = $(addprefix $(torturesrcdir)/smb2/, \
                smb2.o \
                durable_open.o \
                oplocks.o \
+               dir.o \
                lease.o \
                create.o \
                read.o \
diff --git a/source4/torture/smb2/dir.c b/source4/torture/smb2/dir.c
index 58cf222..79672ef 100644
--- a/source4/torture/smb2/dir.c
+++ b/source4/torture/smb2/dir.c
@@ -1,20 +1,22 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    SMB2 dir list test suite
 
    Copyright (C) Andrew Tridgell 2005
-   
+   Copyright (C) Zachary Loafman 2009
+   Copyright (C) Aravind Srinivasan 2009
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -22,72 +24,1307 @@
 #include "includes.h"
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
+#include "libcli/smb_composite/smb_composite.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "libcli/libcli.h"
 
 #include "torture/torture.h"
 #include "torture/smb2/proto.h"
+#include "torture/util.h"
+
+#include "system/filesys.h"
+
+#define CHECK_STATUS(status, correct) do { \
+       if (!NT_STATUS_EQUAL(status, correct)) { \
+               torture_result(tctx, TORTURE_FAIL, __location__": \
+                      Incorrect status %s - should be %s", \
+                      nt_errstr(status), nt_errstr(correct)); \
+               ret = false; \
+               goto done; \
+       }} while (0)
+
+#define CHECK_VALUE(v, correct) torture_assert_int_equal(tctx, (v), \
+                               (correct), "incorrect value");
+
+#define DNAME  "smb2_dir"
+#define NFILES 100
+
+struct file_elem {
+       char *name;
+       bool found;
+};
+
+static NTSTATUS populate_tree(struct torture_context *tctx,
+                             TALLOC_CTX *mem_ctx,
+                             struct smb2_tree *tree,
+                             struct file_elem *files,
+                             int nfiles,
+                             struct smb2_handle *h_out)
+{
+       struct smb2_create create;
+       NTSTATUS status;
+       bool ret;
+       int i;
+
+       smb2_deltree(tree, DNAME);
+
+       ZERO_STRUCT(create);
+       create.in.desired_access = SEC_RIGHTS_DIR_ALL;
+       create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+       create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+       create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+                                NTCREATEX_SHARE_ACCESS_WRITE |
+                                NTCREATEX_SHARE_ACCESS_DELETE;
+       create.in.create_disposition = NTCREATEX_DISP_CREATE;
+       create.in.fname = DNAME;
+
+       status = smb2_create(tree, mem_ctx, &create);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       *h_out = create.out.file.handle;
+
+       ZERO_STRUCT(create);
+       create.in.desired_access = SEC_RIGHTS_FILE_ALL;
+       create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+       create.in.create_disposition = NTCREATEX_DISP_CREATE;
+
+       for (i = 0; i < nfiles; i++) {
+               files[i].name = generate_random_str(tctx, 8);
+               create.in.fname = talloc_asprintf(mem_ctx, "%s\\%s",
+                   DNAME, files[i].name);
+               status = smb2_create(tree, mem_ctx, &create);
+               CHECK_STATUS(status, NT_STATUS_OK);
+               smb2_util_close(tree, create.out.file.handle);
+       }
+ done:
+       return status;
+}
 
 /*
   test find continue
 */
-static bool torture_smb2_find_dir(struct smb2_tree *tree)
+
+static bool test_find(struct torture_context *tctx,
+                     struct smb2_tree *tree)
 {
-       struct smb2_handle handle;
-       NTSTATUS status;
-       int i;
+       TALLOC_CTX *mem_ctx = talloc_new(tctx);
+       struct smb2_handle h;
        struct smb2_find f;
-       bool ret = true;
        union smb_search_data *d;
+       struct file_elem files[NFILES] = {};
+       NTSTATUS status;
+       bool ret = true;
        uint_t count;
+       int i, j, file_count = 0;
 
-       status = smb2_util_roothandle(tree, &handle);
-       if (!NT_STATUS_IS_OK(status)) {
-               return false;
+       status = populate_tree(tctx, mem_ctx, tree, files, NFILES, &h);
+
+       ZERO_STRUCT(f);
+       f.in.file.handle        = h;
+       f.in.pattern            = "*";
+       f.in.continue_flags     = SMB2_CONTINUE_FLAG_SINGLE;
+       f.in.max_response_size  = 0x100;
+       f.in.level              = SMB2_FIND_BOTH_DIRECTORY_INFO;
+
+       do {
+               status = smb2_find_level(tree, tree, &f, &count, &d);
+               if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
+                       break;
+               CHECK_STATUS(status, NT_STATUS_OK);
+
+               for (i = 0; i < count; i++) {
+                       bool expected;
+                       const char *found = d[i].both_directory_info.name.s;
+
+                       if (!strcmp(found, ".") || !strcmp(found, ".."))
+                               continue;
+
+                       expected = false;
+                       for (j = 0; j < NFILES; j++) {
+                               if (!strcmp(files[j].name, found)) {
+                                       files[j].found = true;
+                                       expected = true;
+                                       break;
+                               }
+                       }
+
+                       if (expected)
+                               continue;
+
+                       torture_result(tctx, TORTURE_FAIL,
+                           "(%s): didn't expect %s\n",
+                           __location__, found);
+                       ret = false;
+                       goto done;
+               }
+
+               file_count = file_count + i;
+               f.in.continue_flags = 0;
+               f.in.max_response_size  = 4096;
+       } while (count != 0);
+
+       CHECK_VALUE(file_count, NFILES + 2);
+
+       for (i = 0; i < NFILES; i++) {
+               if (files[j].found)
+                       continue;
+
+               torture_result(tctx, TORTURE_FAIL,
+                   "(%s): expected to find %s, but didn't\n",
+                   __location__, files[j].name);
+               ret = false;
+               goto done;
        }
 
+ done:
+       smb2_deltree(tree, DNAME);
+       talloc_free(mem_ctx);
+
+       return ret;
+}
+
+/*
+  test fixed enumeration
+*/
+
+static bool test_fixed(struct torture_context *tctx,
+                      struct smb2_tree *tree)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(tctx);
+       struct smb2_create create;
+       struct smb2_handle h, h2;
+       struct smb2_find f;
+       union smb_search_data *d;
+       struct file_elem files[NFILES] = {};
+       NTSTATUS status;
+       bool ret = true;
+       uint_t count;
+       int i;
+
+       status = populate_tree(tctx, mem_ctx, tree, files, NFILES, &h);
+
+       ZERO_STRUCT(create);
+       create.in.desired_access = SEC_RIGHTS_DIR_ALL;
+       create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+       create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+       create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+                                NTCREATEX_SHARE_ACCESS_WRITE |
+                                NTCREATEX_SHARE_ACCESS_DELETE;
+       create.in.create_disposition = NTCREATEX_DISP_OPEN;
+       create.in.fname = DNAME;
+
+       status = smb2_create(tree, mem_ctx, &create);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       h2 = create.out.file.handle;
+
        ZERO_STRUCT(f);
-       f.in.file.handle        = handle;
+       f.in.file.handle        = h;
        f.in.pattern            = "*";
        f.in.continue_flags     = SMB2_CONTINUE_FLAG_SINGLE;
        f.in.max_response_size  = 0x100;
        f.in.level              = SMB2_FIND_BOTH_DIRECTORY_INFO;
 
+       /* Start enumeration on h, then delete all from h2 */
+       status = smb2_find_level(tree, tree, &f, &count, &d);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       f.in.file.handle        = h2;
+
        do {
                status = smb2_find_level(tree, tree, &f, &count, &d);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("SMB2_FIND_ID_BOTH_DIRECTORY_INFO failed - 
%s\n", nt_errstr(status));
+               if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
                        break;
+               CHECK_STATUS(status, NT_STATUS_OK);
+
+               for (i = 0; i < count; i++) {
+                       const char *found = d[i].both_directory_info.name.s;
+                       char *path = talloc_asprintf(mem_ctx, "%s\\%s",
+                           DNAME, found);
+
+                       if (!strcmp(found, ".") || !strcmp(found, ".."))
+                               continue;
+
+                       status = smb2_util_unlink(tree, path);
+                       CHECK_STATUS(status, NT_STATUS_OK);
+
+                       talloc_free(path);
                }
 
-               printf("Got %d files\n", count);
-               for (i=0;i<count;i++) {
-                       printf("\t'%s'\n", 
-                              d[i].both_directory_info.name.s);
+               f.in.continue_flags = 0;
+               f.in.max_response_size  = 4096;
+       } while (count != 0);
+
+       /* Now finish h enumeration. */
+       f.in.file.handle = h;
+
+       do {
+               status = smb2_find_level(tree, tree, &f, &count, &d);
+               if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
+                       break;
+               CHECK_STATUS(status, NT_STATUS_OK);
+
+               for (i = 0; i < count; i++) {
+                       const char *found = d[i].both_directory_info.name.s;
+
+                       if (!strcmp(found, ".") || !strcmp(found, ".."))
+                               continue;
+
+                       torture_result(tctx, TORTURE_FAIL,
+                           "(%s): didn't expect %s\n",
+                           __location__, found);
+                       ret = false;
+                       goto done;
                }
+
                f.in.continue_flags = 0;
                f.in.max_response_size  = 4096;
        } while (count != 0);
 
+ done:
+       smb2_util_close(tree, h);
+       smb2_util_close(tree, h2);
+       smb2_deltree(tree, DNAME);
+       talloc_free(mem_ctx);
 
        return ret;
 }
 
+static struct {
+       const char *name;
+       uint8_t level;
+       enum smb_search_data_level data_level;
+       int name_offset;
+       int resume_key_offset;
+       uint32_t capability_mask;
+       NTSTATUS status;
+       union smb_search_data data;
+} levels[] = {
+       {"SMB2_FIND_DIRECTORY_INFO",
+        SMB2_FIND_DIRECTORY_INFO, RAW_SEARCH_DATA_DIRECTORY_INFO,
+        offsetof(union smb_search_data, directory_info.name.s),
+        offsetof(union smb_search_data, directory_info.file_index),
+       },
+       {"SMB2_FIND_FULL_DIRECTORY_INFO",
+        SMB2_FIND_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
+        offsetof(union smb_search_data, full_directory_info.name.s),
+        offsetof(union smb_search_data, full_directory_info.file_index),
+       },
+       {"SMB2_FIND_NAME_INFO",
+        SMB2_FIND_NAME_INFO, RAW_SEARCH_DATA_NAME_INFO,
+        offsetof(union smb_search_data, name_info.name.s),
+        offsetof(union smb_search_data, name_info.file_index),
+       },
+       {"SMB2_FIND_BOTH_DIRECTORY_INFO",
+        SMB2_FIND_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
+        offsetof(union smb_search_data, both_directory_info.name.s),
+        offsetof(union smb_search_data, both_directory_info.file_index),
+       },
+       {"SMB2_FIND_ID_FULL_DIRECTORY_INFO",
+        SMB2_FIND_ID_FULL_DIRECTORY_INFO, 
RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO,
+        offsetof(union smb_search_data, id_full_directory_info.name.s),
+        offsetof(union smb_search_data, id_full_directory_info.file_index),
+       },
+       {"SMB2_FIND_ID_BOTH_DIRECTORY_INFO",
+        SMB2_FIND_ID_BOTH_DIRECTORY_INFO, 
RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO,
+        offsetof(union smb_search_data, id_both_directory_info.name.s),
+        offsetof(union smb_search_data, id_both_directory_info.file_index),
+       }
+};
+
+/*
+  extract the name from a smb_data structure and level
+*/
+static const char *extract_name(union smb_search_data *data,
+                               uint8_t level,
+                               enum smb_search_data_level data_level)
+{
+       int i;
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               if (level == levels[i].level &&
+                   data_level == levels[i].data_level) {
+                       return *(const char **)(levels[i].name_offset + (char 
*)data);
+               }
+       }
+       return NULL;
+}
+
+/* find a level in the table by name */
+static union smb_search_data *find(const char *name)
+{
+       int i;
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               if (NT_STATUS_IS_OK(levels[i].status) &&
+                   strcmp(levels[i].name, name) == 0) {
+                       return &levels[i].data;
+               }
+       }
+       return NULL;
+}
+
+static bool fill_level_data(TALLOC_CTX *mem_ctx,
+                           union smb_search_data *data,
+                           union smb_search_data *d,
+                           uint_t count,
+                           uint8_t level,
+                           enum smb_search_data_level data_level)
+{
+       int i;
+       const char *sname = NULL;
+       for (i=0; i < count ; i++) {
+               sname = extract_name(&d[i], level, data_level);
+               if (sname == NULL)
+                       return false;
+               if (!strcmp(sname, ".") || !strcmp(sname, ".."))
+                       continue;
+               *data = d[i];
+       }
+       return true;
+}
+
+
+NTSTATUS torture_single_file_search(struct smb2_tree *tree,
+                                   TALLOC_CTX *mem_ctx,
+                                   const char *pattern,
+                                   uint8_t level,
+                                   enum smb_search_data_level data_level,
+                                   int index,
+                                   union smb_search_data *d,
+                                   uint_t *count,
+                                   struct smb2_handle *h)
+{
+       struct smb2_find f;
+       NTSTATUS status;
+
+       ZERO_STRUCT(f);
+       f.in.file.handle        = *h;
+       f.in.pattern            = pattern;
+       f.in.continue_flags     = SMB2_CONTINUE_FLAG_RESTART;
+       f.in.max_response_size  = 0x100;
+       f.in.level              = level;
+
+       status = smb2_find_level(tree, tree, &f, count, &d);
+       if (NT_STATUS_IS_OK(status))
+               fill_level_data(mem_ctx, &levels[index].data, d, *count, level,
+                               data_level);
+       return status;
+}
+
+/*
+   basic testing of all File Information Classes using a single file
+*/
+static bool test_one_file(struct torture_context *tctx,
+                         struct smb2_tree *tree)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(tctx);
+       bool ret = true;
+       const char *fname =  "torture_search.txt";
+       NTSTATUS status;
+       int i;
+       uint_t count;
+       union smb_fileinfo all_info2, alt_info, internal_info;
+       union smb_search_data *s;
+       union smb_search_data d;
+       struct smb2_handle h, h2;
+
+       status = torture_smb2_testdir(tree, DNAME, &h);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       status = smb2_create_complex_file(tree, DNAME "\\torture_search.txt",
+                                         &h2);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       /* call all the File Information Classes */
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               torture_comment(tctx, "testing %s %d\n", levels[i].name,
+                               levels[i].level);
+
+               levels[i].status = torture_single_file_search(tree, mem_ctx,
+                                  fname, levels[i].level, levels[i].data_level,
+                                  i, &d, &count, &h);
+               CHECK_STATUS(levels[i].status, NT_STATUS_OK);
+       }
+
+       /* get the all_info file into to check against */
+       all_info2.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+       all_info2.generic.in.file.handle = h2;
+       status = smb2_getinfo_file(tree, tctx, &all_info2);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "RAW_FILEINFO_ALL_INFO failed");
+
+       alt_info.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
+       alt_info.generic.in.file.handle = h2;
+       status = smb2_getinfo_file(tree, tctx, &alt_info);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "RAW_FILEINFO_ALT_NAME_INFO failed");
+
+       internal_info.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION;
+       internal_info.generic.in.file.handle = h2;
+       status = smb2_getinfo_file(tree, tctx, &internal_info);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "RAW_FILEINFO_INTERNAL_INFORMATION failed");


-- 
Samba Shared Repository

Reply via email to