From 2e1192dff8201efee327e70ecae446e2c5511c0b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Jul 2021 17:50:49 -0700 Subject: [PATCH 1/3] s3: selftest: Add a test for vfs_streams_depot with the target path outside of the share. Mark as knownfail.d/simpleserver_streams BUG: https://bugzilla.samba.org/show_bug.cgi?id=14760 Signed-off-by: Jeremy Allison --- selftest/knownfail.d/simpleserver_streams | 6 ++++++ selftest/target/Samba3.pm | 10 ++++++++++ source3/selftest/tests.py | 5 +++++ 3 files changed, 21 insertions(+) create mode 100644 selftest/knownfail.d/simpleserver_streams diff --git a/selftest/knownfail.d/simpleserver_streams b/selftest/knownfail.d/simpleserver_streams new file mode 100644 index 00000000000..2b7412999de --- /dev/null +++ b/selftest/knownfail.d/simpleserver_streams @@ -0,0 +1,6 @@ +^samba3.smb2.streams.names\(simpleserver\) +^samba3.smb2.streams.io\(simpleserver\) +^samba3.smb2.streams.names3\(simpleserver\) +^samba3.smb2.streams.delete\(simpleserver\) +^samba3.smb2.streams.zero-byte\(simpleserver\) +^samba3.smb2.streams.sharemodes\(simpleserver\) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index d0ef659da99..3fe6c194ed8 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1458,6 +1458,11 @@ sub setup_simpleserver print "PROVISIONING simple server..."; my $prefix_abs = abs_path($path); + mkdir($prefix_abs, 0777); + + my $external_streams_depot="$prefix_abs/external_streams_depot"; + remove_tree($external_streams_depot); + mkdir($external_streams_depot, 0777); my $simpleserver_options = " lanman auth = yes @@ -1531,6 +1536,11 @@ sub setup_simpleserver [hidenewfiles] path = $prefix_abs/share hide new files timeout = 5 + +[external_streams_depot] + path = $prefix_abs/share + read only = no + streams_depot:directory = $external_streams_depot "; my $vars = $self->provision( diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index a232deb99de..812114c2374 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -978,6 +978,11 @@ plansmbtorture4testsuite( "fileserver:local", '//foo/bar -U%') +plansmbtorture4testsuite( + "smb2.streams", + "simpleserver", + '//$SERVER/external_streams_depot -U$USERNAME%$PASSWORD') + test = 'rpc.lsa.lookupsids' auth_options = ["", "ntlm", "spnego", "spnego,ntlm", "spnego,smb1", "spnego,smb2"] signseal_options = ["", ",connect", ",packet", ",sign", ",seal"] -- 2.30.2 From 1070f3f7940e8cb4aabe8bdb3623cf8936edf83b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 Jul 2021 14:52:32 -0700 Subject: [PATCH 2/3] s3: VFS: vfs_streams_depot: Factor out the code that gets the absolute stream rootdir into a function. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14760 Signed-off-by: Jeremy Allison --- source3/modules/vfs_streams_depot.c | 50 +++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index d9abf1d71b9..d3b511d3132 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -129,6 +129,39 @@ static bool mark_file_valid(vfs_handle_struct *handle, return true; } +/* + * Return the root of the stream directory. Can be + * external to the share definition but by default + * is "handle->conn->connectpath/.streams". + * + * Note that this is an *absolute* path, starting + * with '/', so the dirfsp being used in the + * calls below isn't looked at. + */ + +static char *stream_rootdir(vfs_handle_struct *handle, + TALLOC_CTX *ctx) +{ + const struct loadparm_substitution *lp_sub = + loadparm_s3_global_substitution(); + char *tmp; + + tmp = talloc_asprintf(ctx, + "%s/.streams", + handle->conn->connectpath); + if (tmp == NULL) { + errno = ENOMEM; + return NULL; + } + + return lp_parm_substituted_string(ctx, + lp_sub, + SNUM(handle->conn), + "streams_depot", + "directory", + tmp); +} + /** * Given an smb_filename, determine the stream directory using the file's * base_name. @@ -137,14 +170,12 @@ static char *stream_dir(vfs_handle_struct *handle, const struct smb_filename *smb_fname, const SMB_STRUCT_STAT *base_sbuf, bool create_it) { - const struct loadparm_substitution *lp_sub = - loadparm_s3_global_substitution(); uint32_t hash; struct smb_filename *smb_fname_hash = NULL; char *result = NULL; SMB_STRUCT_STAT base_sbuf_tmp; + char *tmp = NULL; uint8_t first, second; - char *tmp; char *id_hex; struct file_id id; uint8_t id_buf[16]; @@ -159,17 +190,8 @@ static char *stream_dir(vfs_handle_struct *handle, check_valid = lp_parm_bool(SNUM(handle->conn), "streams_depot", "check_valid", true); - tmp = talloc_asprintf(talloc_tos(), "%s/.streams", - handle->conn->connectpath); - - if (tmp == NULL) { - errno = ENOMEM; - goto fail; - } - - rootdir = lp_parm_substituted_string(talloc_tos(), lp_sub, - SNUM(handle->conn), "streams_depot", "directory", - tmp); + rootdir = stream_rootdir(handle, + talloc_tos()); if (rootdir == NULL) { errno = ENOMEM; goto fail; -- 2.30.2 From d41741a8870411beedbc9db8135ea003002e9591 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 Jul 2021 15:10:41 -0700 Subject: [PATCH 3/3] s3: VFS: streams_depot: Allow "streams directory" outside of share path to work again. As we're dealing with absolute paths here, we just need to temporarily replace the connectpath whilst enumerating streams. Remove knownfail file. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14760 Signed-off-by: Jeremy Allison --- selftest/knownfail.d/simpleserver_streams | 6 ------ source3/modules/vfs_streams_depot.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) delete mode 100644 selftest/knownfail.d/simpleserver_streams diff --git a/selftest/knownfail.d/simpleserver_streams b/selftest/knownfail.d/simpleserver_streams deleted file mode 100644 index 2b7412999de..00000000000 --- a/selftest/knownfail.d/simpleserver_streams +++ /dev/null @@ -1,6 +0,0 @@ -^samba3.smb2.streams.names\(simpleserver\) -^samba3.smb2.streams.io\(simpleserver\) -^samba3.smb2.streams.names3\(simpleserver\) -^samba3.smb2.streams.delete\(simpleserver\) -^samba3.smb2.streams.zero-byte\(simpleserver\) -^samba3.smb2.streams.sharemodes\(simpleserver\) diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index d3b511d3132..973edeeda24 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -544,6 +544,8 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, void *private_data) { char *dirname; + char *rootdir = NULL; + char *orig_connectpath = NULL; struct smb_filename *dir_smb_fname = NULL; struct smb_Dir *dir_hnd = NULL; const char *dname = NULL; @@ -576,8 +578,26 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, return NT_STATUS_NO_MEMORY; } + /* + * For OpenDir to succeed if the stream rootdir is outside + * the share path, we must temporarily swap out the connect + * path for this share. We're dealing with absolute paths + * here so we don't care about chdir calls. + */ + rootdir = stream_rootdir(handle, talloc_tos()); + if (rootdir == NULL) { + TALLOC_FREE(dir_smb_fname); + TALLOC_FREE(dirname); + return NT_STATUS_NO_MEMORY; + } + + orig_connectpath = handle->conn->connectpath; + handle->conn->connectpath = rootdir; + dir_hnd = OpenDir(talloc_tos(), handle->conn, dir_smb_fname, NULL, 0); if (dir_hnd == NULL) { + handle->conn->connectpath = orig_connectpath; + TALLOC_FREE(rootdir); TALLOC_FREE(dir_smb_fname); TALLOC_FREE(dirname); return map_nt_error_from_unix(errno); @@ -600,6 +620,9 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, TALLOC_FREE(talloced); } + /* Restore the original connectpath. */ + handle->conn->connectpath = orig_connectpath; + TALLOC_FREE(rootdir); TALLOC_FREE(dir_smb_fname); TALLOC_FREE(dir_hnd); -- 2.30.2