The branch, master has been updated
via 95e1998a4a8 tests: Check symlinks are readable as reparse points
via 34be8ef5962 smbd: Return NT_STATUS_STOPPED_ON_SYMLINK
via cc0ed15fecc smbd: Always init symlink_err in
filename_convert_dirfsp_nosymlink()
via 239df72787f smbd: Create the proper error blob for
STOPPED_ON_SYMLINK
via 2065778b5cd smbd: Prepare smbd_smb2_create_recv() to return a
symlink error
via 647b711e4e1 tests: Fix test_symlinkerror_absolute_inshare
via 63d877342a2 tests: Reparse point dirs are shown as
REPARSE_POINT|DIRECTORY
via 70f424657f0 tests: Reparse point files are shown as
FILE_ATTRIBUTE_REPARSE_POINT
via ed239d3f297 smbd: Allow a symlink as lcomp when asking for
REPARSE_POINT
via 0d8b71f0b6c smbd: Fix the turning an absolute symlink into a
relative one
via 259517d7aec smbd: Set fsp->fsp_flags.posix_open in
openat_pathref_fsp_lcomp()
via 4a46c6a8827 smbd: Allow symlinks to be read via GET_REPARSE_POINT
via c87269f528a smbd: Prepare fdos_mode() for handling symlinks in smb2
via 61259bf9aab libsmb: Retry the open with OPEN_REPARSE_POINT on
IO_REPARSE_TAG_NOT_HANDLED
via 079d95da0bb smbd: Make filename_convert_dirfsp_nosymlink() public
via 76f51569061 smbd: Revert "smbd: Simplify filename_convert_dirfsp()"
via ec64f81df92 smbd: Pass "create_options" to
filename_create_ucf_flags()
from fee31b6cb2b ctdb-common: Map ENOENT for a missing event script to
ENOEXEC
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 95e1998a4a853287563b6eb84a3ca4a18d9fe271
Author: Volker Lendecke <[email protected]>
Date: Wed May 17 10:54:49 2023 +0200
tests: Check symlinks are readable as reparse points
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
Autobuild-User(master): Ralph Böhme <[email protected]>
Autobuild-Date(master): Fri Nov 22 11:05:33 UTC 2024 on atb-devel-224
commit 34be8ef596291686e35e90e00c4da99de6cd55f3
Author: Volker Lendecke <[email protected]>
Date: Wed Nov 20 12:56:33 2024 +0100
smbd: Return NT_STATUS_STOPPED_ON_SYMLINK
Do this for "follow symlinks = now" and smb2 unix extensions
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit cc0ed15feccfed8748619d0ee309f12dbe4f77e0
Author: Volker Lendecke <[email protected]>
Date: Wed Nov 20 12:54:05 2024 +0100
smbd: Always init symlink_err in filename_convert_dirfsp_nosymlink()
Make sure that we don't leave symlink_err in the caller
uninitialized.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 239df72787f4680b39d2f2a4a0d5be9feb34ad6d
Author: Volker Lendecke <[email protected]>
Date: Wed Nov 20 11:13:12 2024 +0100
smbd: Create the proper error blob for STOPPED_ON_SYMLINK
Unused so far, our lowerlevel routines so far never return
NT_STATUS_STOPPED_ON_SYMLINK. Also see the NULL passed as
"symlink_reparse", this will change soon. Separate patch for easier
review.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 2065778b5cdcfa20b5a667f5bdc551c22393ce90
Author: Volker Lendecke <[email protected]>
Date: Wed Nov 20 13:18:25 2024 +0100
smbd: Prepare smbd_smb2_create_recv() to return a symlink error
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 647b711e4e11c70a16be542be34e3c4b999664e0
Author: Volker Lendecke <[email protected]>
Date: Tue May 16 17:32:28 2023 +0200
tests: Fix test_symlinkerror_absolute_inshare
This tests converting an absolute into a relative target. Reflect that
in the flags expected from the STOPPED_ON_SYMLINK error response.
As of this patch it's still knownfail, so irrelevant. But soon this test
will
succeed.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 63d877342a2772eab9ad9f601fe9554cbdc6a329
Author: Volker Lendecke <[email protected]>
Date: Mon Jan 9 18:30:05 2023 +0100
tests: Reparse point dirs are shown as REPARSE_POINT|DIRECTORY
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 70f424657f0b846ed51ae55287e3a715e086534d
Author: Volker Lendecke <[email protected]>
Date: Mon Jan 9 18:24:23 2023 +0100
tests: Reparse point files are shown as FILE_ATTRIBUTE_REPARSE_POINT
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit ed239d3f297b6ea4dc64ed9818ebc6ca2720753e
Author: Volker Lendecke <[email protected]>
Date: Wed Nov 20 12:02:54 2024 +0100
smbd: Allow a symlink as lcomp when asking for REPARSE_POINT
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 0d8b71f0b6c953d031caff0c37a309646dc57c57
Author: Volker Lendecke <[email protected]>
Date: Sun Feb 4 11:45:22 2024 +0100
smbd: Fix the turning an absolute symlink into a relative one
If dirfsp is the share root, we end up with a "/." at the end of
subdir_path. subdir_of() does not cover that case. fsp_fullbasepath()
takes care of that case and also avoids a talloc.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 259517d7aec73280b7e02f3695f826561e76f82f
Author: Volker Lendecke <[email protected]>
Date: Wed Jan 31 19:48:48 2024 +0100
smbd: Set fsp->fsp_flags.posix_open in openat_pathref_fsp_lcomp()
Not sure why this wasn't caught as a bug yet...
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 4a46c6a88273ea765b142299d6cf33d5ec93588a
Author: Volker Lendecke <[email protected]>
Date: Wed Dec 21 16:42:12 2022 +0100
smbd: Allow symlinks to be read via GET_REPARSE_POINT
... to be used soon
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit c87269f528ae7758ed8b5a793d724596ab35a697
Author: Volker Lendecke <[email protected]>
Date: Tue Nov 19 15:35:58 2024 +0100
smbd: Prepare fdos_mode() for handling symlinks in smb2
We should show all special files as NORMAL|REPARSE_POINT, except
symlinks for SMB1 Posix Extensions. IFREG and IFDIR are handled via
our xattr mechanisms.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 61259bf9aabfa1d207b3d4bfeac0860f54f5cd4d
Author: Volker Lendecke <[email protected]>
Date: Wed May 3 16:44:34 2023 +0200
libsmb: Retry the open with OPEN_REPARSE_POINT on IO_REPARSE_TAG_NOT_HANDLED
If we get that error message, we want to look at the reparse point as
such. This does not affect normal files, but soon we will need it in
our tests.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 079d95da0bb190c9b26fde46aef53eacd3eff72e
Author: Volker Lendecke <[email protected]>
Date: Fri Dec 16 16:35:00 2022 +0100
smbd: Make filename_convert_dirfsp_nosymlink() public
To be used directly in smb2_create.c
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 76f5156906139559d4414fe9bf1b4938780000c5
Author: Volker Lendecke <[email protected]>
Date: Tue Nov 19 11:48:12 2024 +0100
smbd: Revert "smbd: Simplify filename_convert_dirfsp()"
This reverts commit bd30c9c128c203c3ed4b123b651862a9953f6cf2.
While this does indeed slightly simplify code, it simplifies too much: Soon
we
will need filename_convert_dirfsp_nosymlink raw without looking at
UCF_LCOMP_LNK_OK. So in hindsight this went too far.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit ec64f81df92355e0e48cd774f4bc54192b0f0074
Author: Volker Lendecke <[email protected]>
Date: Fri Feb 2 21:16:46 2024 +0100
smbd: Pass "create_options" to filename_create_ucf_flags()
OPEN_REPARSE_POINT will trigger symlinks not being followed but
returned, even if we have "follow symlinks = yes". Prepare for setting
UCF_LCOMP_LNK_OK for this case in a central place.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
-----------------------------------------------------------------------
Summary of changes:
python/samba/tests/reparsepoints.py | 13 ++
python/samba/tests/smb2symlink.py | 43 +++--
selftest/knownfail.d/symlink | 4 -
source3/include/proto.h | 12 ++
source3/libsmb/cli_smb2_fnum.c | 78 +++++++-
source3/modules/util_reparse.c | 44 +++++
source3/script/tests/test_smbclient_s3.sh | 10 +-
source3/smbd/dosmode.c | 26 ++-
source3/smbd/filename.c | 59 +++---
source3/smbd/files.c | 15 +-
source3/smbd/open.c | 34 ++--
source3/smbd/proto.h | 4 +-
source3/smbd/smb1_nttrans.c | 8 +-
source3/smbd/smb1_reply.c | 16 +-
source3/smbd/smb2_create.c | 286 ++++++++++++++++++++++++++++--
15 files changed, 537 insertions(+), 115 deletions(-)
delete mode 100644 selftest/knownfail.d/symlink
Changeset truncated at 500 lines:
diff --git a/python/samba/tests/reparsepoints.py
b/python/samba/tests/reparsepoints.py
index a8d506d48d6..40d7de3f63b 100644
--- a/python/samba/tests/reparsepoints.py
+++ b/python/samba/tests/reparsepoints.py
@@ -198,6 +198,10 @@ class ReparsePoints(samba.tests.libsmb.LibsmbTests):
conn.close(fd)
dirents = conn.list("", filename)
+ self.assertEqual(
+ dirents[0]["attrib"],
+ libsmb.FILE_ATTRIBUTE_REPARSE_POINT|
+ libsmb.FILE_ATTRIBUTE_ARCHIVE)
self.assertEqual(
dirents[0]["reparse_tag"],
libsmb.IO_REPARSE_TAG_SYMLINK)
@@ -247,6 +251,15 @@ class ReparsePoints(samba.tests.libsmb.LibsmbTests):
conn.delete_on_close(dir_fd, 1)
conn.close(dir_fd)
+ dirents = conn.list("", dirname)
+ self.assertEqual(
+ dirents[0]["attrib"],
+ libsmb.FILE_ATTRIBUTE_REPARSE_POINT|
+ libsmb.FILE_ATTRIBUTE_DIRECTORY)
+ self.assertEqual(dirents[0]["reparse_tag"], 0x80000025)
+
+ self.clean_file(conn, dirname)
+
# Only empty directories can carry reparse points
def test_create_reparse_nonempty_directory(self):
diff --git a/python/samba/tests/smb2symlink.py
b/python/samba/tests/smb2symlink.py
index a2b34aee639..f9cd4a23cd6 100644
--- a/python/samba/tests/smb2symlink.py
+++ b/python/samba/tests/smb2symlink.py
@@ -55,13 +55,19 @@ class Smb2SymlinkTests(samba.tests.libsmb.LibsmbTests):
self.creds)
return (smb1, smb2)
- def create_symlink(self, conn, target, symlink):
- self.clean_file(conn, symlink)
- if (conn.protocol() < libsmb.PROTOCOL_SMB2_02 and conn.have_posix()):
- conn.smb1_symlink(target, symlink)
+ def create_symlink(self, conn1, conn2, target, symlink,
+ expect_tgt=None):
+
+ if expect_tgt is None:
+ expect_tgt = target
+
+ self.clean_file(conn1, symlink)
+ if (conn1.protocol() < libsmb.PROTOCOL_SMB2_02 and
+ conn1.have_posix()):
+ conn1.smb1_symlink(target, symlink)
else:
flags = 0 if target[0]=='/' else 1
- syml = conn.create(
+ syml = conn1.create(
symlink,
DesiredAccess=sec.SEC_FILE_READ_ATTRIBUTE|
sec.SEC_FILE_WRITE_ATTRIBUTE|
@@ -70,8 +76,19 @@ class Smb2SymlinkTests(samba.tests.libsmb.LibsmbTests):
CreateDisposition=libsmb.FILE_OPEN_IF,
CreateOptions=libsmb.FILE_OPEN_REPARSE_POINT)
b = reparse_symlink.symlink_put(target, target, 0, 1)
- conn.fsctl(syml, libsmb.FSCTL_SET_REPARSE_POINT, b, 0)
- conn.close(syml)
+ conn1.fsctl(syml, libsmb.FSCTL_SET_REPARSE_POINT, b, 0)
+ conn1.close(syml)
+
+ fd = conn2.create(symlink,
+ DesiredAccess=sec.SEC_FILE_WRITE_ATTRIBUTE,
+ CreateOptions=libsmb.FILE_OPEN_REPARSE_POINT,
+ CreateDisposition=libsmb.FILE_OPEN)
+ blob = conn2.fsctl(fd, libsmb.FSCTL_GET_REPARSE_POINT, b'', 1024)
+ conn2.close(fd)
+
+ (tag,(subst,_,_,_)) = reparse_symlink.get(blob)
+ self.assertEqual(tag, "IO_REPARSE_TAG_SYMLINK")
+ self.assertEqual(expect_tgt, subst)
def assert_symlink_exception(self, e, expect):
self.assertEqual(e.args[0], ntstatus.NT_STATUS_STOPPED_ON_SYMLINK)
@@ -91,7 +108,7 @@ class Smb2SymlinkTests(samba.tests.libsmb.LibsmbTests):
target="foo"
suffix="bar"
- self.create_symlink(smb1, target, symlink)
+ self.create_symlink(smb1, smb2, target, symlink);
with self.assertRaises(NTSTATUSError) as e:
fd = smb2.create_ex(f'{symlink}\\{suffix}')
@@ -111,7 +128,7 @@ class Smb2SymlinkTests(samba.tests.libsmb.LibsmbTests):
symlink="syml"
target="foo"
- self.create_symlink(smb1, target, symlink)
+ self.create_symlink(smb1, smb2, target, symlink);
with self.assertRaises(NTSTATUSError) as e:
fd = smb2.create_ex(f'{symlink}')
@@ -135,7 +152,7 @@ class Smb2SymlinkTests(samba.tests.libsmb.LibsmbTests):
for target in ["/etc", "//foo/bar", "/"]:
- self.create_symlink(smb1, target, symlink)
+ self.create_symlink(smb1, smb2, target, symlink)
with self.assertRaises(NTSTATUSError) as e:
fd = smb2.create_ex(f'{symlink}')
@@ -159,7 +176,7 @@ class Smb2SymlinkTests(samba.tests.libsmb.LibsmbTests):
rel_dest="dst"
target=f'{shareroot}/{rel_dest}'
- self.create_symlink(smb1, target, symlink)
+ self.create_symlink(smb1, smb2, target, symlink, rel_dest)
with self.assertRaises(NTSTATUSError) as e:
fd = smb2.create_ex(f'{symlink}')
@@ -169,7 +186,7 @@ class Smb2SymlinkTests(samba.tests.libsmb.LibsmbTests):
{ 'unparsed_path_length' : 0,
'substitute_name' : rel_dest,
'print_name' : rel_dest,
- 'flags' : 0 })
+ 'flags' : 1 })
self.clean_file(smb1, symlink)
@@ -199,7 +216,7 @@ class Smb2SymlinkTests(samba.tests.libsmb.LibsmbTests):
smb1.mkdir("sub")
self.addCleanup(self.clean_file, smb1, "sub")
- self.create_symlink(smb1, f'{localpath}/sub1', "sub/lnk")
+ self.create_symlink(smb1, smb2, f'{localpath}/sub1', "sub/lnk")
self.addCleanup(self.clean_file, smb1, "sub/lnk")
smb1.mkdir("sub1")
diff --git a/selftest/knownfail.d/symlink b/selftest/knownfail.d/symlink
deleted file mode 100644
index 64135666aec..00000000000
--- a/selftest/knownfail.d/symlink
+++ /dev/null
@@ -1,4 +0,0 @@
-^samba.tests.smb2symlink.samba.tests.smb2symlink.Smb2SymlinkTests.test_symlinkerror_directory
-^samba.tests.smb2symlink.samba.tests.smb2symlink.Smb2SymlinkTests.test_symlinkerror_file
-^samba.tests.smb2symlink.samba.tests.smb2symlink.Smb2SymlinkTests.test_symlinkerror_absolute_outside_share
-^samba.tests.smb2symlink.samba.tests.smb2symlink.Smb2SymlinkTests.test_symlinkerror_absolute_inshare
diff --git a/source3/include/proto.h b/source3/include/proto.h
index ee28afa6a56..8b446fa9f9e 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -713,6 +713,18 @@ NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
const char *target,
size_t unparsed,
char **_relative);
+struct reparse_data_buffer;
+NTSTATUS
+filename_convert_dirfsp_nosymlink(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ struct files_struct *basedir,
+ const char *name_in,
+ uint32_t ucf_flags,
+ NTTIME twrp,
+ struct files_struct **_dirfsp,
+ struct smb_filename **_smb_fname,
+ struct smb_filename **_smb_fname_rel,
+ struct reparse_data_buffer **_symlink_err);
NTSTATUS filename_convert_dirfsp_rel(TALLOC_CTX *mem_ctx,
connection_struct *conn,
struct files_struct *basedir,
diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index 95b4385bc9f..f9a82089709 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -204,7 +204,16 @@ static char *smb2_dfs_share_path(TALLOC_CTX *ctx,
***************************************************************/
struct cli_smb2_create_fnum_state {
+ struct tevent_context *ev;
struct cli_state *cli;
+ char *fname;
+ struct cli_smb2_create_flags create_flags;
+ uint32_t impersonation_level;
+ uint32_t desired_access;
+ uint32_t file_attributes;
+ uint32_t share_access;
+ uint32_t create_disposition;
+ uint32_t create_options;
struct smb2_create_blobs in_cblobs;
struct smb2_create_blobs out_cblobs;
struct smb_create_returns cr;
@@ -243,17 +252,25 @@ struct tevent_req *cli_smb2_create_fnum_send(
if (req == NULL) {
return NULL;
}
+ state->ev = ev;
state->cli = cli;
+ state->create_flags = create_flags;
+ state->impersonation_level = impersonation_level;
+ state->desired_access = desired_access;
+ state->file_attributes = file_attributes;
+ state->share_access = share_access;
+ state->create_disposition = create_disposition;
+
+ if (cli->backup_intent) {
+ create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
+ }
+ state->create_options = create_options;
fname = talloc_strdup(state, fname_in);
if (tevent_req_nomem(fname, req)) {
return tevent_req_post(req, ev);
}
- if (cli->backup_intent) {
- create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
- }
-
if (cli->smb2.client_smb311_posix) {
uint8_t modebuf[4] = {
0,
@@ -316,15 +333,21 @@ struct tevent_req *cli_smb2_create_fnum_send(
/* Or end in a '\' */
if (fname_len > 0 && fname[fname_len-1] == '\\') {
- fname[fname_len-1] = '\0';
+ fname_len -= 1;
}
- subreq = smb2cli_create_send(state, ev,
+ state->fname = talloc_strndup(state, fname, fname_len);
+ if (tevent_req_nomem(state->fname, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = smb2cli_create_send(state,
+ ev,
cli->conn,
cli->timeout,
cli->smb2.session,
cli->smb2.tcon,
- fname,
+ state->fname,
flags_to_smb2_oplock(create_flags),
impersonation_level,
desired_access,
@@ -352,6 +375,7 @@ static void cli_smb2_create_fnum_done(struct tevent_req
*subreq)
req, struct cli_smb2_create_fnum_state);
uint64_t fid_persistent, fid_volatile;
struct smb2_create_blob *posix = NULL;
+ struct cli_state *cli = state->cli;
NTSTATUS status;
status = smb2cli_create_recv(subreq,
@@ -362,6 +386,46 @@ static void cli_smb2_create_fnum_done(struct tevent_req
*subreq)
&state->out_cblobs,
&state->symlink);
TALLOC_FREE(subreq);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED)) {
+
+ if (state->create_options & FILE_OPEN_REPARSE_POINT) {
+ /*
+ * Should not happen, but you never know...
+ */
+ tevent_req_nterror(
+ req, NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED);
+ return;
+ }
+
+ state->create_options |= FILE_OPEN_REPARSE_POINT;
+
+ subreq = smb2cli_create_send(state,
+ state->ev,
+ cli->conn,
+ cli->timeout,
+ cli->smb2.session,
+ cli->smb2.tcon,
+ state->fname,
+ flags_to_smb2_oplock(
+ state->create_flags),
+ state->impersonation_level,
+ state->desired_access,
+ state->file_attributes,
+ state->share_access,
+ state->create_disposition,
+ state->create_options,
+ &state->in_cblobs);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq,
+ cli_smb2_create_fnum_done,
+ req);
+ state->subreq = subreq;
+ return;
+ }
+
if (tevent_req_nterror(req, status)) {
return;
}
diff --git a/source3/modules/util_reparse.c b/source3/modules/util_reparse.c
index 2694410be4f..60373d7fd4e 100644
--- a/source3/modules/util_reparse.c
+++ b/source3/modules/util_reparse.c
@@ -154,6 +154,45 @@ static NTSTATUS fsctl_get_reparse_point_dev(struct
files_struct *fsp,
fsp, &reparse_data, ctx, _out_data, max_out_len, _out_len);
}
+static NTSTATUS fsctl_get_reparse_point_lnk(struct files_struct *fsp,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **_out_data,
+ uint32_t max_out_len,
+ uint32_t *_out_len)
+{
+ struct reparse_data_buffer *reparse = NULL;
+ struct smb_filename *parent_fname = NULL;
+ struct smb_filename *base_name = NULL;
+ NTSTATUS status;
+
+ status = parent_pathref(talloc_tos(),
+ fsp->conn->cwd_fsp,
+ fsp->fsp_name,
+ &parent_fname,
+ &base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("parent_pathref(%s) failed: %s\n",
+ fsp_str_dbg(fsp),
+ nt_errstr(status));
+ return status;
+ }
+
+ status = read_symlink_reparse(talloc_tos(),
+ parent_fname->fsp,
+ base_name,
+ &reparse);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("read_symlink_reparse failed: %s\n",
+ nt_errstr(status));
+ return status;
+ }
+
+ status = fsctl_get_reparse_point_int(
+ fsp, reparse, mem_ctx, _out_data, max_out_len, _out_len);
+ TALLOC_FREE(reparse);
+ return status;
+}
+
NTSTATUS fsctl_get_reparse_point(struct files_struct *fsp,
TALLOC_CTX *mem_ctx,
uint32_t *_reparse_tag,
@@ -212,6 +251,11 @@ NTSTATUS fsctl_get_reparse_point(struct files_struct *fsp,
max_out_len,
&out_len);
break;
+ case S_IFLNK:
+ DBG_DEBUG("%s is a symlink\n", fsp_str_dbg(fsp));
+ status = fsctl_get_reparse_point_lnk(
+ fsp, mem_ctx, &out_data, max_out_len, &out_len);
+ break;
default:
break;
}
diff --git a/source3/script/tests/test_smbclient_s3.sh
b/source3/script/tests/test_smbclient_s3.sh
index cbff5026ee7..35a283a8546 100755
--- a/source3/script/tests/test_smbclient_s3.sh
+++ b/source3/script/tests/test_smbclient_s3.sh
@@ -1343,11 +1343,17 @@ EOF
return 1
fi
- echo "$out" | grep 'NT_STATUS_OBJECT_NAME_NOT_FOUND'
+ if [ "$PROTOCOL" = "SMB3" ]; then
+ expected_error="NT_STATUS_STOPPED_ON_SYMLINK"
+ else
+ expected_error="NT_STATUS_OBJECT_NAME_NOT_FOUND"
+ fi
+
+ echo "$out" | grep "$expected_error"
ret=$?
if [ $ret -ne 0 ]; then
echo "$out"
- echo "failed - should get NT_STATUS_OBJECT_NAME_NOT_FOUND
getting \\nosymlinks\\source"
+ echo "failed - should get ${expected_error} getting
\\nosymlinks\\source"
return 1
fi
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index f39f8a7d15b..0de348883e4 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -721,16 +721,28 @@ uint32_t fdos_mode(struct files_struct *fsp)
}
switch (fsp->fsp_name->st.st_ex_mode & S_IFMT) {
- case S_IFLNK:
- return FILE_ATTRIBUTE_NORMAL;
+ case S_IFREG:
+ case S_IFDIR:
break;
- case S_IFIFO:
- case S_IFSOCK:
- case S_IFBLK:
- case S_IFCHR:
- return FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_REPARSE_POINT;
+ case S_IFLNK:
+ if (fsp->fsp_flags.posix_open &&
+ !conn_using_smb2(fsp->conn->sconn)) {
+ /*
+ * SMB1 posix doesn't like the reparse point flag
+ */
+ result = FILE_ATTRIBUTE_NORMAL;
+ } else {
+ /*
+ * Everybody else wants to see symlinks as
+ * reparse points
+ */
+ result = FILE_ATTRIBUTE_NORMAL |
+ FILE_ATTRIBUTE_REPARSE_POINT;
+ }
+
break;
default:
+ return FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_REPARSE_POINT;
break;
}
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 0c2e365c239..554df2fd1f8 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -41,11 +41,7 @@ uint32_t ucf_flags_from_smb_request(struct smb_request *req)
}
if (req->posix_pathnames) {
- ucf_flags |= UCF_POSIX_PATHNAMES;
-
- if (!conn_using_smb2(req->sconn)) {
- ucf_flags |= UCF_LCOMP_LNK_OK;
- }
+ ucf_flags |= (UCF_POSIX_PATHNAMES|UCF_LCOMP_LNK_OK);
}
if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
ucf_flags |= UCF_DFS_PATHNAME;
@@ -57,7 +53,9 @@ uint32_t ucf_flags_from_smb_request(struct smb_request *req)
return ucf_flags;
}
-uint32_t filename_create_ucf_flags(struct smb_request *req, uint32_t
create_disposition)
+uint32_t filename_create_ucf_flags(struct smb_request *req,
+ uint32_t create_disposition,
+ uint32_t create_options)
{
uint32_t ucf_flags = 0;
@@ -75,6 +73,10 @@ uint32_t filename_create_ucf_flags(struct smb_request *req,
uint32_t create_disp
break;
}
+ if (create_options & FILE_OPEN_REPARSE_POINT) {
+ ucf_flags |= UCF_LCOMP_LNK_OK;
+ }
+
return ucf_flags;
}
@@ -664,17 +666,17 @@ fail:
* Split up name_in as sent by the client into a directory pathref fsp
* and a relative smb_filename.
*/
-static NTSTATUS filename_convert_dirfsp_nosymlink(
- TALLOC_CTX *mem_ctx,
- connection_struct *conn,
- struct files_struct *basedir,
- const char *name_in,
- uint32_t ucf_flags,
- NTTIME twrp,
- struct files_struct **_dirfsp,
- struct smb_filename **_smb_fname,
- struct smb_filename **_smb_fname_rel,
- struct reparse_data_buffer **_symlink_err)
+NTSTATUS
+filename_convert_dirfsp_nosymlink(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ struct files_struct *basedir,
+ const char *name_in,
+ uint32_t ucf_flags,
+ NTTIME twrp,
+ struct files_struct **_dirfsp,
+ struct smb_filename **_smb_fname,
+ struct smb_filename **_smb_fname_rel,
+ struct reparse_data_buffer **_symlink_err)
{
struct smb_filename *smb_dirname = NULL;
struct smb_filename *smb_fname_rel = NULL;
@@ -802,8 +804,6 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
}
lnk->unparsed_path_length = unparsed;
- *_symlink_err = symlink_err;
-
--
Samba Shared Repository