[SCM] Samba Shared Repository - branch master updated
Jeremy Allison
jra at samba.org
Tue Sep 3 17:32:03 UTC 2019
The branch, master has been updated
via 3355601fe85 s3/4: libsmbclient test. Test using smbc_telldir/smbc_lseekdir with smbc_readdir/smbc_readdirplus/smbc_getdents.
via 0d9b1645499 s3: libsmbclient: Fix smbc_lseekdir() to work with smbc_readdirplus().
via 754cec7756b s3: libsmbclient: Ensure SMBC_getdents_ctx() also updates the readdirplus pointers.
via 3d82b7d11cd s3: libsmbclient: Ensure SMBC_readdirplus_ctx() also updates the readdir pointers.
via 4bca8e097f5 s3: libsmbclient: Ensure SMBC_readdir_ctx() also updates the readdirplus pointers.
from efd4832c2cf CVE-2019-10197: smbd: split change_to_user_impersonate() out of change_to_user_internal()
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 3355601fe8541994cc41f5ed800aab9b6a2294f4
Author: Jeremy Allison <jra at samba.org>
Date: Mon Aug 26 11:22:35 2019 -0700
s3/4: libsmbclient test. Test using smbc_telldir/smbc_lseekdir with smbc_readdir/smbc_readdirplus/smbc_getdents.
Ensure that for file access you can mix any of these
three access methods for directory entries and the
returned names/structs stay in sync across telldir/seekdir
changes.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Ralph Böhme <slow at samba.org>
Autobuild-User(master): Jeremy Allison <jra at samba.org>
Autobuild-Date(master): Tue Sep 3 17:31:29 UTC 2019 on sn-devel-184
commit 0d9b1645499ce12a79a137d3482434aa5d2eb47c
Author: Jeremy Allison <jra at samba.org>
Date: Mon Aug 26 10:18:28 2019 -0700
s3: libsmbclient: Fix smbc_lseekdir() to work with smbc_readdirplus().
If returning files the dir_list and the dirplus_list have exactly the same
entries, we just need to keep the next pointers in sync on seek.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Ralph Böhme <slow at samba.org>
commit 754cec7756b2ddb1cfcc3984265f01cb366beb76
Author: Jeremy Allison <jra at samba.org>
Date: Mon Aug 26 10:07:32 2019 -0700
s3: libsmbclient: Ensure SMBC_getdents_ctx() also updates the readdirplus pointers.
If we are returning file entries, we
have a duplicate list in dirplus.
Update dirplus_next also so readdir and
readdirplus are kept in sync.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Ralph Böhme <slow at samba.org>
commit 3d82b7d11cd7b78adc6b3642e64e3a8f251de869
Author: Jeremy Allison <jra at samba.org>
Date: Mon Aug 26 10:02:47 2019 -0700
s3: libsmbclient: Ensure SMBC_readdirplus_ctx() also updates the readdir pointers.
If we are returning file entries, we
have a duplicate list in dir_list.
Update dir_next also so readdir and
readdirplus are kept in sync.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Ralph Böhme <slow at samba.org>
commit 4bca8e097f5a909c628daa4dbfa932ddc1725ebc
Author: Jeremy Allison <jra at samba.org>
Date: Mon Aug 26 09:54:06 2019 -0700
s3: libsmbclient: Ensure SMBC_readdir_ctx() also updates the readdirplus pointers.
If we are returning file entries, we
have a duplicate list in dirplus.
Update dirplus_next also so readdir and
readdirplus are kept in sync.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Ralph Böhme <slow at samba.org>
-----------------------------------------------------------------------
Summary of changes:
source3/libsmb/libsmb_dir.c | 102 ++++++---
source3/selftest/tests.py | 3 +-
source4/torture/libsmbclient/libsmbclient.c | 340 ++++++++++++++++++++++++++++
3 files changed, 418 insertions(+), 27 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
index 886aa626509..df606c4adfe 100644
--- a/source3/libsmb/libsmb_dir.c
+++ b/source3/libsmb/libsmb_dir.c
@@ -1174,6 +1174,17 @@ SMBC_readdir_ctx(SMBCCTX *context,
dir->dir_next = dir->dir_next->next;
+ /*
+ * If we are returning file entries, we
+ * have a duplicate list in dirplus.
+ *
+ * Update dirplus_next also so readdir and
+ * readdirplus are kept in sync.
+ */
+ if (dir->dirplus_list != NULL) {
+ dir->dirplus_next = dir->dirplus_next->next;
+ }
+
TALLOC_FREE(frame);
return dirp;
}
@@ -1220,6 +1231,17 @@ SMBC_readdirplus_ctx(SMBCCTX *context,
}
dir->dirplus_next = dir->dirplus_next->next;
+ /*
+ * If we are returning file entries, we
+ * have a duplicate list in dir_list
+ *
+ * Update dir_next also so readdir and
+ * readdirplus are kept in sync.
+ */
+ if (dir->dir_list) {
+ dir->dir_next = dir->dir_next->next;
+ }
+
TALLOC_FREE(frame);
return smb_finfo;
}
@@ -1336,6 +1358,17 @@ SMBC_getdents_ctx(SMBCCTX *context,
}
dir->dir_next = dirlist = dirlist -> next;
+
+ /*
+ * If we are returning file entries, we
+ * have a duplicate list in dirplus.
+ *
+ * Update dirplus_next also so readdir and
+ * readdirplus are kept in sync.
+ */
+ if (dir->dirplus_list != NULL) {
+ dir->dirplus_next = dir->dirplus_next->next;
+ }
}
TALLOC_FREE(frame);
@@ -1639,35 +1672,43 @@ SMBC_telldir_ctx(SMBCCTX *context,
/*
* A routine to run down the list and see if the entry is OK
+ * Modifies the dir list and the dirplus list (if it exists)
+ * to point at the correct next entry on success.
*/
-static struct smbc_dir_list *
-check_dir_ent(struct smbc_dir_list *list,
- struct smbc_dirent *dirent)
+static bool update_dir_ents(SMBCFILE *dir, struct smbc_dirent *dirent)
{
+ struct smbc_dir_list *tmp_dir = dir->dir_list;
+ struct smbc_dirplus_list *tmp_dirplus = dir->dirplus_list;
- /* Run down the list looking for what we want */
-
- if (dirent) {
-
- struct smbc_dir_list *tmp = list;
-
- while (tmp) {
-
- if (tmp->dirent == dirent)
- return tmp;
-
- tmp = tmp->next;
+ /*
+ * Run down the list looking for what we want.
+ * If we're enumerating files both dir_list
+ * and dirplus_list contain the same entry
+ * list, as they were seeded from the same
+ * cli_list callback.
+ *
+ * If we're enumerating servers then
+ * dirplus_list will be NULL, so don't
+ * update in that case.
+ */
+ while (tmp_dir != NULL) {
+ if (tmp_dir->dirent == dirent) {
+ dir->dir_next = tmp_dir;
+ if (tmp_dirplus != NULL) {
+ dir->dirplus_next = tmp_dirplus;
+ }
+ return true;
+ }
+ tmp_dir = tmp_dir->next;
+ if (tmp_dirplus != NULL) {
+ tmp_dirplus = tmp_dirplus->next;
}
-
}
-
- return NULL; /* Not found, or an error */
-
+ return false;
}
-
/*
* Routine to seek on a directory
*/
@@ -1679,8 +1720,8 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
{
long int l_offset = offset; /* Handle problems of size */
struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset;
- struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL;
TALLOC_CTX *frame = talloc_stackframe();
+ bool ok;
if (!context || !context->internal->initialized) {
@@ -1703,6 +1744,10 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
if (dirent == NULL) { /* Seek to the begining of the list */
dir->dir_next = dir->dir_list;
+
+ /* Do the same for dirplus. */
+ dir->dirplus_next = dir->dirplus_list;
+
TALLOC_FREE(frame);
return 0;
@@ -1710,21 +1755,26 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
if (offset == -1) { /* Seek to the end of the list */
dir->dir_next = NULL;
+
+ /* Do the same for dirplus. */
+ dir->dirplus_next = NULL;
+
TALLOC_FREE(frame);
return 0;
}
- /* Now, run down the list and make sure that the entry is OK */
- /* This may need to be changed if we change the format of the list */
+ /*
+ * Run down the list and make sure that the entry is OK.
+ * Update the position of both dir and dirplus lists.
+ */
- if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) {
+ ok = update_dir_ents(dir, dirent);
+ if (!ok) {
errno = EINVAL; /* Bad entry */
TALLOC_FREE(frame);
return -1;
}
- dir->dir_next = list_ent;
-
TALLOC_FREE(frame);
return 0;
}
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 8bdc7038362..589c3347b84 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -509,7 +509,8 @@ nbt = ["nbt.dgram"]
libsmbclient = ["libsmbclient.version", "libsmbclient.initialize",
"libsmbclient.configuration", "libsmbclient.setConfiguration",
"libsmbclient.options", "libsmbclient.opendir",
- "libsmbclient.list_shares", "libsmbclient.readdirplus"]
+ "libsmbclient.list_shares", "libsmbclient.readdirplus",
+ "libsmbclient.readdirplus_seek"]
vfs = [
"vfs.fruit",
diff --git a/source4/torture/libsmbclient/libsmbclient.c b/source4/torture/libsmbclient/libsmbclient.c
index f9154e8a19c..7bc407ac905 100644
--- a/source4/torture/libsmbclient/libsmbclient.c
+++ b/source4/torture/libsmbclient/libsmbclient.c
@@ -18,6 +18,7 @@
*/
#include "includes.h"
+#include "system/dir.h"
#include "torture/smbtorture.h"
#include "auth/credentials/credentials.h"
#include "lib/cmdline/popt_common.h"
@@ -375,6 +376,343 @@ static bool torture_libsmbclient_readdirplus(struct torture_context *tctx)
return true;
}
+static bool torture_libsmbclient_readdirplus_seek(struct torture_context *tctx)
+{
+ SMBCCTX *ctx;
+ int ret = -1;
+ int dhandle = -1;
+ int fhandle = -1;
+ const char *dname = NULL;
+ const char *full_filename[100] = {0};
+ const char *filename[100] = {0};
+ const struct libsmb_file_info *direntries[102] = {0};
+ unsigned int i = 0;
+ const char *smburl = torture_setting_string(tctx, "smburl", NULL);
+ bool success = false;
+ off_t telldir_50 = (off_t)-1;
+ off_t telldir_20 = (off_t)-1;
+ size_t getdentries_size = 0;
+ struct smbc_dirent *getdentries = NULL;
+ struct smbc_dirent *dirent_20 = NULL;
+ const struct libsmb_file_info *direntries_20 = NULL;
+
+ if (smburl == NULL) {
+ torture_fail(tctx,
+ "option --option=torture:smburl="
+ "smb://user:password@server/share missing\n");
+ }
+
+ DEBUG(0,("torture_libsmbclient_readdirplus_seek start\n"));
+
+ torture_assert(tctx, torture_libsmbclient_init_context(tctx, &ctx), "");
+ smbc_set_context(ctx);
+
+ dname = talloc_asprintf(tctx,
+ "%s/rd_seek",
+ smburl);
+ if (dname == NULL) {
+ torture_fail_goto(tctx,
+ done,
+ "talloc fail\n");
+ }
+
+ /* Ensure the files don't exist. */
+ for (i = 0; i < 100; i++) {
+ filename[i] = talloc_asprintf(tctx,
+ "test_readdirplus_%u.txt",
+ i);
+ if (full_filename == NULL) {
+ torture_fail_goto(tctx,
+ done,
+ "talloc fail\n");
+ }
+ full_filename[i] = talloc_asprintf(tctx,
+ "%s/%s",
+ dname,
+ filename[i]);
+ if (full_filename == NULL) {
+ torture_fail_goto(tctx,
+ done,
+ "talloc fail\n");
+ }
+ (void)smbc_unlink(full_filename[i]);
+ }
+ /* Ensure the directory doesn't exist. */
+ (void)smbc_rmdir(dname);
+
+ /* Create containing directory. */
+ ret = smbc_mkdir(dname, 0777);
+ if (ret != 0) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "failed to create directory '%s': %s",
+ dname,
+ strerror(errno)));
+ }
+
+ DEBUG(0,("torture_libsmbclient_readdirplus_seek create\n"));
+
+ /* Create them. */
+ for (i = 0; i < 100; i++) {
+ fhandle = smbc_creat(full_filename[i], 0666);
+ if (fhandle < 0) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "failed to create file '%s': %s",
+ full_filename[i],
+ strerror(errno)));
+ }
+ ret = smbc_close(fhandle);
+ torture_assert_int_equal_goto(tctx,
+ ret,
+ 0,
+ success,
+ done,
+ talloc_asprintf(tctx,
+ "failed to close handle for '%s'",
+ full_filename[i]));
+ }
+
+ DEBUG(0,("torture_libsmbclient_readdirplus_seek enum\n"));
+
+ /* Now enumerate the directory. */
+ dhandle = smbc_opendir(dname);
+ if (dhandle < 0) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "failed to obtain "
+ "directory handle for '%s' : %s",
+ dname,
+ strerror(errno)));
+ }
+
+ /* Read all the files. 100 we created plus . and .. */
+ for (i = 0; i < 102; i++) {
+ bool found = false;
+ unsigned int j;
+
+ direntries[i] = smbc_readdirplus(dhandle);
+ if (direntries[i] == NULL) {
+ break;
+ }
+
+ /* Store at offset 50. */
+ if (i == 50) {
+ telldir_50 = smbc_telldir(dhandle);
+ if (telldir_50 == (off_t)-1) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "telldir failed file %s\n",
+ direntries[i]->name));
+ }
+ }
+
+ if (ISDOT(direntries[i]->name)) {
+ continue;
+ }
+ if (ISDOTDOT(direntries[i]->name)) {
+ continue;
+ }
+
+ /* Ensure all our files exist. */
+ for (j = 0; j < 100; j++) {
+ if (strcmp(direntries[i]->name,
+ filename[j]) == 0) {
+ found = true;
+ }
+ }
+ if (!found) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "failed to find file %s\n",
+ direntries[i]->name));
+ }
+ }
+
+ /*
+ * We're seeking on in-memory lists here, so
+ * whilst the handle is open we really should
+ * get the same files back in the same order.
+ */
+
+ ret = smbc_lseekdir(dhandle, telldir_50);
+ torture_assert_int_equal_goto(tctx,
+ ret,
+ 0,
+ success,
+ done,
+ talloc_asprintf(tctx,
+ "failed to seek (50) directory handle for '%s'",
+ dname));
+
+ DEBUG(0,("torture_libsmbclient_readdirplus_seek seek\n"));
+
+ for (i = 51; i < 102; i++) {
+ const struct libsmb_file_info *entry =
+ smbc_readdirplus(dhandle);
+ if (entry != direntries[i]) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "after seek - failed to find "
+ "file %s - got %s\n",
+ direntries[i]->name,
+ entry->name));
+ }
+ }
+
+ /* Seek back to the start. */
+ ret = smbc_lseekdir(dhandle, 0);
+ torture_assert_int_equal_goto(tctx,
+ ret,
+ 0,
+ success,
+ done,
+ talloc_asprintf(tctx,
+ "failed to seek directory handle to start for '%s'",
+ dname));
+
+ /*
+ * Mix getdents/readdir/readdirplus with lseek to ensure
+ * we get the same result.
+ */
+
+ /* Allocate the space for 20 entries.
+ * Tricky as we need to allocate 20 struct smbc_dirent's + space
+ * for the name lengths.
+ */
+ getdentries_size = 20 * (sizeof(struct smbc_dirent) +
+ strlen("test_readdirplus_1000.txt") + 1);
+
+ getdentries = (struct smbc_dirent *)talloc_array_size(tctx,
+ getdentries_size,
+ 1);
+
+ ret = smbc_getdents(dhandle, getdentries, getdentries_size);
+ torture_assert_goto(tctx,
+ (ret != -1),
+ success,
+ done,
+ talloc_asprintf(tctx,
+ "smbd_getdents(1) for '%s' failed\n",
+ dname));
+
+ telldir_20 = smbc_telldir(dhandle);
+ if (telldir_20 == (off_t)-1) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "telldir (20) failed\n"));
+ }
+ /* Read another 20. */
+ ret = smbc_getdents(dhandle, getdentries, getdentries_size);
+ torture_assert_goto(tctx,
+ (ret != -1),
+ success,
+ done,
+ talloc_asprintf(tctx,
+ "smbd_getdents(2) for '%s' failed\n",
+ dname));
+
+ /* Seek back to 20. */
+ ret = smbc_lseekdir(dhandle, telldir_20);
+ torture_assert_int_equal_goto(tctx,
+ ret,
+ 0,
+ success,
+ done,
+ talloc_asprintf(tctx,
+ "failed to seek (20) directory handle for '%s'",
+ dname));
+
+ /* Read with readdir. */
+ dirent_20 = smbc_readdir(dhandle);
+ if (dirent_20 == NULL) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "smbc_readdir (20) failed\n"));
+ }
+
+ /* Ensure the getdents and readdir names are the same. */
+ ret = strcmp(dirent_20->name, getdentries[0].name);
+ if (ret != 0) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "after seek (20) readdir name missmatch "
+ "file %s - got %s\n",
+ dirent_20->name,
+ getdentries[0].name));
+ }
+
+ /* Seek back to 20. */
+ ret = smbc_lseekdir(dhandle, telldir_20);
+ torture_assert_int_equal_goto(tctx,
+ ret,
+ 0,
+ success,
+ done,
+ talloc_asprintf(tctx,
+ "failed to seek (20) directory handle for '%s'",
+ dname));
+ /* Read with readdirplus. */
+ direntries_20 = smbc_readdirplus(dhandle);
+ if (direntries_20 == NULL) {
+ torture_fail_goto(tctx,
+ done,
+ talloc_asprintf(tctx,
+ "smbc_readdirplus (20) failed\n"));
+ }
+
+ /* Ensure the readdirplus and readdir names are the same. */
--
Samba Shared Repository
More information about the samba-cvs
mailing list