The branch, master has been updated via 93b6db3328c s3: smbd: Convert smb_file_rename_information() to use filename_convert_dirfsp(). via 0e7a151c2f7 s3: smbd: Convert smb_file_link_information() to use filename_convert_dirfsp(). via e960f4b30bf s3: smbd: Convert smb2_file_rename_information() to use filename_convert_dirfsp(). via 3b3cab81884 s3: smbd: Convert smb_set_file_unix_hlink() to use filename_convert_dirfsp(). via 22403ec72ef s3: smbd: Convert reply_ntrename() to use filename_convert_dirfsp(). via 8b667db0f7d s3: smbd: Convert reply_mv() to use filename_convert_dirfsp(). via b14e4f59255 s3: smbd: Convert reply_mkdir() to use filename_convert_dirfsp(). via 79257334c22 s3: smbd: Convert reply_unlink() to use filename_convert_dirfsp(). via dc309e60623 s3: smbd: Convert cmd_utime() to use filename_convert_dirfsp(). via ab9397726ef s3: smbd: Convert smbd_smb2_create_durable_lease_check() to use filename_convert_dirfsp(). via c3737300ed9 s3: smbd: Convert _srvsvc_NetSetFileSecurity() to use filename_convert_dirfsp(). via d89ec90c87b s3: smbd: Convert _srvsvc_NetGetFileSecurity() to use filename_convert_dirfsp(). via 1006b1af4b7 s3: smbd: Convert call_trans2setfilepathinfo() to use filename_convert_dirfsp(). via a9ed7f6064c s3: smbd: Convert call_trans2qfilepathinfo() to use filename_convert_dirfsp(). via c71368a080b s3: smbd: Convert reply_setatr() to use filename_convert_dirfsp(). via a457d59e985 s3: smbd: Convert reply_getatr() to use filename_convert_dirfsp(). via 2a9d7beb9e3 s3: smbd: Add dirfsp parameter to create_directory(). via a6c34ec3c25 s3: smbd: Add src_dirfsp and dst_dirfsp parameters to copy_internals(). via b80e51137c3 s3: smbd: Add old_dirfsp and new_dirfsp parameters to hardlink_internals(). via 1d658bbe65a s3: smbd: Add dst_dirfsp parameter to rename_internals_fsp(). via 0b33ec49e38 s3: smbd: Add dirfsp parameter to unlink_internals(). via d9f144acb64 s3: smbd: Add src_dirfsp and dst_dirfsp parameters to rename_internals(). via beb10e8bbe4 s3: smbd: In reply_ntrename(), don't call filename_convert() if we know it's a stream rename. via c673ca15c56 s3: smbd: Tweak the logic of smb2_file_rename_information(). via b9006f33b4f s3: smbd: Inside filename_convert_dirfsp_nosymlink(), don't require UCF_PREP_CREATEFILE when parsing a stream name that doesn't already exist. via 2c4719a0cda s3: smbd: In filename_convert_dirfsp(), don't let an SMB1+POSIX client see a symlink to a directory with no permissions. via 5249cb3d0fd s3: smbd: In filename_convert_dirfsp_nosymlink(), in SMB1-only POSIX mode, allow a pathname referencing a symlink to be returned. via 6fd8f7fd18f s3: smbd: In filename_convert_dirfsp(), allow SMB1+POSIX to traverse non-terminal symlinks. from 766151bf5b7 lib:replace: Only include <sys/mount.h> on non-Linux systems
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 93b6db3328cef0fea864480b3047cc6f17b05a0f Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 12:38:47 2022 -0700 s3: smbd: Convert smb_file_rename_information() to use filename_convert_dirfsp(). There is only one last user of filename_convert(), in filename_convert_smb1_search_path(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Tue Aug 2 20:46:38 UTC 2022 on sn-devel-184 commit 0e7a151c2f76c8746ad2a374447f6e3233516dee Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 12:32:07 2022 -0700 s3: smbd: Convert smb_file_link_information() to use filename_convert_dirfsp(). One less use of filename_convert(). Later we should optimize this by passing in the src_dirfsp from the caller. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit e960f4b30bf735aa50edffca96641f8607c9353d Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 12:29:22 2022 -0700 s3: smbd: Convert smb2_file_rename_information() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 3b3cab818842c8768b3ae3e5c30d01cce925b9e7 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 12:23:36 2022 -0700 s3: smbd: Convert smb_set_file_unix_hlink() to use filename_convert_dirfsp(). One less use of filename_convert(). Later we should optimize this by passing in the src_dirfsp from the caller. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 22403ec72ef9d448be03121098de12f757c7f61d Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 12:18:47 2022 -0700 s3: smbd: Convert reply_ntrename() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 8b667db0f7d59875e38feb5b14a339eefc8f1c79 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 12:09:34 2022 -0700 s3: smbd: Convert reply_mv() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit b14e4f592551b2a8310fd0529ce503b8abaf87bf Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 12:04:47 2022 -0700 s3: smbd: Convert reply_mkdir() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 79257334c22823de3587caacdd430655112e888b Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 11:52:36 2022 -0700 s3: smbd: Convert reply_unlink() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit dc309e60623701b992d42898ce07f6537300ae22 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 10:56:28 2022 -0700 s3: smbd: Convert cmd_utime() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit ab9397726efd075274f1f8c4c75f8dedac2b95e7 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 10:54:03 2022 -0700 s3: smbd: Convert smbd_smb2_create_durable_lease_check() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit c3737300ed9ba62da1dc343d94f76b886ec12317 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 10:48:18 2022 -0700 s3: smbd: Convert _srvsvc_NetSetFileSecurity() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit d89ec90c87b3c52c9d0d9d371da123ffe6630d56 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 10:46:25 2022 -0700 s3: smbd: Convert _srvsvc_NetGetFileSecurity() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 1006b1af4b733df70a667982e07c14c7e1aa4d62 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 10:41:25 2022 -0700 s3: smbd: Convert call_trans2setfilepathinfo() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit a9ed7f6064cae00345a1030fb51a10c43b8cf12a Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 10:39:12 2022 -0700 s3: smbd: Convert call_trans2qfilepathinfo() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit c71368a080b9357c9c320ac5bfb41095205cfb59 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 10:33:31 2022 -0700 s3: smbd: Convert reply_setatr() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit a457d59e98547177944b8a4c198b8d86e3c23d0f Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 10:30:02 2022 -0700 s3: smbd: Convert reply_getatr() to use filename_convert_dirfsp(). One less use of filename_convert(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 2a9d7beb9e33316ac185d5cbd0e498502474b4e8 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 12:01:21 2022 -0700 s3: smbd: Add dirfsp parameter to create_directory(). Not yet used but passed down to SMB_VFS_CREATE(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit a6c34ec3c2598ad364444da829b9fff23996cebc Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 11:49:35 2022 -0700 s3: smbd: Add src_dirfsp and dst_dirfsp parameters to copy_internals(). Not yet used. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit b80e51137c3b39b36d124eb6a1e028b692d0a863 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 11:43:21 2022 -0700 s3: smbd: Add old_dirfsp and new_dirfsp parameters to hardlink_internals(). Not yet used. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 1d658bbe65a5a037efa403250c9513a50b5dc8be Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 11:25:48 2022 -0700 s3: smbd: Add dst_dirfsp parameter to rename_internals_fsp(). Not yet used, but when this is fully plumbed though we can look at optimizing and removing the code inside rename_internals_fsp() that currently gets it's own dst_dirfsp. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 0b33ec49e385f279fbb495173017b2be45e9d206 Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 11:17:47 2022 -0700 s3: smbd: Add dirfsp parameter to unlink_internals(). Not yet used but passed to SMB_VFS_CREATE(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit d9f144acb64911b20e81b8948fcdc4ca0636891c Author: Jeremy Allison <j...@samba.org> Date: Thu Jul 28 11:08:17 2022 -0700 s3: smbd: Add src_dirfsp and dst_dirfsp parameters to rename_internals(). Not yet used (but passed to SMB_VFS_CREATE_FILE()). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit beb10e8bbe4909b6bcc70da89c11560e04e483e9 Author: Jeremy Allison <j...@samba.org> Date: Fri Jul 29 14:07:50 2022 -0700 s3: smbd: In reply_ntrename(), don't call filename_convert() if we know it's a stream rename. There is no point in calling filename_convert() on a raw stream name. It can never find the file anyway (and never returns a valid smb_fname->fsp). Use the same logic as SMB2_FILE_RENAME_INFORMATION_INTERNAL now does and generate smb_fname_new directly. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit c673ca15c56feef41501643244ebfe15a48c8d2c Author: Jeremy Allison <j...@samba.org> Date: Fri Jul 29 14:38:17 2022 -0700 s3: smbd: Tweak the logic of smb2_file_rename_information(). There's no point in calling filename_convert() and then just ignoring the returned smb_fname if it's a raw stream name. Only call filename_convert() if we know it isn't a raw stream name. Ignore stream/non-stream mismatches in src and dst in smb2_file_rename_information, let rename_internals_fsp() take care of that as the error returns inside rename_internals_fsp() are tested by raw.streams. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit b9006f33b4fbe97ef09ae4e6c4d25eadf9b2b46d Author: Jeremy Allison <j...@samba.org> Date: Mon Aug 1 11:40:14 2022 -0700 s3: smbd: Inside filename_convert_dirfsp_nosymlink(), don't require UCF_PREP_CREATEFILE when parsing a stream name that doesn't already exist. We don't require it for a new file. Without this change, we have to add UCF_PREP_CREATEFILE to the destination flags when we are doing renames to a destination stream name, but not when doing renames to a destination file name, which makes for inconsistent API use. filename_convert_dirfsp() is now a drop in replacement for filename_convert(), even for the ugly SMB1 POSIX cases. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 2c4719a0cda0061bf331227e25cb4534a4c0eb9c Author: Jeremy Allison <j...@samba.org> Date: Mon Aug 1 17:55:23 2022 -0700 s3: smbd: In filename_convert_dirfsp(), don't let an SMB1+POSIX client see a symlink to a directory with no permissions. This isn't 100% correct, but it gets us close enough to the old behavior for SMB1+POSIX libsmbclient. If we went through a symlink, and we got NT_STATUS_ACCESS_DENIED on the directory containing the target, just don't allow the client to see the intermediate path. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 5249cb3d0fdfe96c4bc65a6338d798feada590ec Author: Jeremy Allison <j...@samba.org> Date: Mon Aug 1 14:24:31 2022 -0700 s3: smbd: In filename_convert_dirfsp_nosymlink(), in SMB1-only POSIX mode, allow a pathname referencing a symlink to be returned. Doesn't contain a valid smb_fname->fsp pointer of course, and is only used by the SMB1 code to take a reference to a smylink name for manipulation (unlinkat, readlinkat etc.). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 6fd8f7fd18f6491c906f9281d316c87aab854f67 Author: Jeremy Allison <j...@samba.org> Date: Mon Aug 1 14:40:54 2022 -0700 s3: smbd: In filename_convert_dirfsp(), allow SMB1+POSIX to traverse non-terminal symlinks. This is the behavior of filename_convert() and we need to allow it for the legacy SMB1+POSIX libsmbclient libraries already deployed out there. When we add SMB2 POSIX we must disallow symlink traversal over any symlinks, the client must resolve symlinks locally. Add a note to show this is where we need to add an error for SMB2+POSIX names with UCF_POSIX_PATHNAMES set. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/modules/vfs_crossrename.c | 2 + source3/printing/nt_printing.c | 4 +- source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 34 +++++---- source3/smbd/filename.c | 58 +++++++++++++--- source3/smbd/open.c | 6 +- source3/smbd/proto.h | 12 +++- source3/smbd/smb1_nttrans.c | 84 ++++++++++++++-------- source3/smbd/smb1_reply.c | 112 ++++++++++++++++++++---------- source3/smbd/smb1_trans2.c | 39 +++++++---- source3/smbd/smb2_create.c | 12 +++- source3/smbd/smb2_nttrans.c | 6 +- source3/smbd/smb2_reply.c | 9 ++- source3/smbd/smb2_trans2.c | 106 ++++++++++++++++++---------- source3/torture/cmd_vfs.c | 14 ++-- 14 files changed, 345 insertions(+), 153 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/modules/vfs_crossrename.c b/source3/modules/vfs_crossrename.c index 930eec02739..042144bfc4d 100644 --- a/source3/modules/vfs_crossrename.c +++ b/source3/modules/vfs_crossrename.c @@ -115,7 +115,9 @@ static NTSTATUS copy_reg(vfs_handle_struct *handle, status = copy_internals(talloc_tos(), handle->conn, NULL, + srcfsp, /* src_dirfsp */ full_fname_src, + dstfsp, /* dst_dirfsp */ full_fname_dst, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 0929e532436..dc54a194f65 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -1577,7 +1577,7 @@ WERROR move_driver_to_download_area(const struct auth_session_info *session_info DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name)); - nt_status = create_directory(conn, NULL, smb_dname); + nt_status = create_directory(conn, NULL, NULL, smb_dname); if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) { DEBUG(0, ("failed to create driver destination directory: %s\n", @@ -2042,7 +2042,7 @@ static NTSTATUS driver_unlink_internals(connection_struct *conn, goto err_out; } - status = unlink_internals(conn, NULL, 0, smb_fname); + status = unlink_internals(conn, NULL, 0, NULL, smb_fname); err_out: talloc_free(tmp_ctx); return status; diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c index b6f2b34b8e8..c5b39ed9cb6 100644 --- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c +++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c @@ -2498,9 +2498,11 @@ WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p, struct conn_struct_tos *c = NULL; connection_struct *conn = NULL; struct sec_desc_buf *sd_buf = NULL; + struct files_struct *dirfsp = NULL; files_struct *fsp = NULL; int snum; uint32_t ucf_flags = 0; + NTTIME twrp = 0; ZERO_STRUCT(st); @@ -2532,12 +2534,13 @@ WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p, } conn = c->conn; - nt_status = filename_convert(frame, - conn, - r->in.file, - ucf_flags, - 0, - &smb_fname); + nt_status = filename_convert_dirfsp(frame, + conn, + r->in.file, + ucf_flags, + twrp, + &dirfsp, + &smb_fname); if (!NT_STATUS_IS_OK(nt_status)) { werr = ntstatus_to_werror(nt_status); goto error_exit; @@ -2546,7 +2549,7 @@ WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p, nt_status = SMB_VFS_CREATE_FILE( conn, /* conn */ NULL, /* req */ - NULL, /* dirfsp */ + dirfsp, /* dirfsp */ smb_fname, /* fname */ FILE_READ_ATTRIBUTES, /* access_mask */ FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */ @@ -2627,6 +2630,7 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p, loadparm_s3_global_substitution(); struct smb_filename *smb_fname = NULL; char *servicename = NULL; + struct files_struct *dirfsp = NULL; files_struct *fsp = NULL; SMB_STRUCT_STAT st; NTSTATUS nt_status; @@ -2637,6 +2641,7 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p, struct security_descriptor *psd = NULL; uint32_t security_info_sent = 0; uint32_t ucf_flags = 0; + NTTIME twrp = 0; ZERO_STRUCT(st); @@ -2670,12 +2675,13 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p, } conn = c->conn; - nt_status = filename_convert(frame, - conn, - r->in.file, - ucf_flags, - 0, - &smb_fname); + nt_status = filename_convert_dirfsp(frame, + conn, + r->in.file, + ucf_flags, + twrp, + &dirfsp, + &smb_fname); if (!NT_STATUS_IS_OK(nt_status)) { werr = ntstatus_to_werror(nt_status); goto error_exit; @@ -2684,7 +2690,7 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p, nt_status = SMB_VFS_CREATE_FILE( conn, /* conn */ NULL, /* req */ - NULL, /* dirfsp */ + dirfsp, /* dirfsp */ smb_fname, /* fname */ FILE_WRITE_ATTRIBUTES, /* access_mask */ FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */ diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3f0c395fd8f..3e90b8dd71b 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -2907,6 +2907,28 @@ static NTSTATUS filename_convert_dirfsp_nosymlink( char *normalized = NULL; if (VALID_STAT(smb_fname_rel->st)) { +#if defined(WITH_SMB1SERVER) + /* + * In SMB1 posix mode, if this is a symlink, + * allow access to the name with a NULL smb_fname->fsp. + */ + if (!conn->sconn->using_smb2 && + posix && + S_ISLNK(smb_fname_rel->st.st_ex_mode)) { + SMB_ASSERT(smb_fname_rel->fsp == NULL); + SMB_ASSERT(streamname == NULL); + + smb_fname = full_path_from_dirfsp_atname( + mem_ctx, + smb_dirname->fsp, + smb_fname_rel); + if (smb_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + goto done; + } +#endif /* * NT_STATUS_OBJECT_NAME_NOT_FOUND is * misleading: The object exists but might be @@ -3003,8 +3025,7 @@ static NTSTATUS filename_convert_dirfsp_nosymlink( goto done; } - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) && - (ucf_flags & UCF_PREP_CREATEFILE)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { /* * Creating a new stream * @@ -3073,6 +3094,22 @@ next: &substitute, &unparsed); +#if defined(WITH_SMB1SERVER) + /* + * This isn't 100% correct, but it gets us close enough + * to the old behavior for SMB1+POSIX libsmbclient. If we went through a + * symlink, and we got NT_STATUS_ACCESS_DENIED on the directory + * containing the target, just don't allow the client to see the + * intermediate path. + */ + if (!conn->sconn->using_smb2 && + (ucf_flags & UCF_POSIX_PATHNAMES) && + symlink_redirects > 0 && + NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } +#endif + if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) { return status; } @@ -3081,12 +3118,17 @@ next: return NT_STATUS_OBJECT_PATH_NOT_FOUND; } - if (ucf_flags & UCF_POSIX_PATHNAMES) { - /* - * SMB1 posix never traverses symlinks - */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } + /* + * Right now, SMB2 and SMB1 always traverse symlinks + * within the share. SMB1+POSIX traverses non-terminal + * symlinks within the share. + * + * When we add SMB2+POSIX we need to return + * a NT_STATUS_STOPPED_ON_SYMLINK error here, using the + * symlink target data read below if SMB2+POSIX has + * UCF_POSIX_PATHNAMES set to cause the client to + * resolve all symlinks locally. + */ target = symlink_target_path(mem_ctx, name_in, substitute, unparsed); if (target == NULL) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ee61137ab9d..30628cc4fd0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -4765,7 +4765,9 @@ static NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_OK; } -NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, +NTSTATUS create_directory(connection_struct *conn, + struct smb_request *req, + struct files_struct *dirfsp, struct smb_filename *smb_dname) { NTSTATUS status; @@ -4774,7 +4776,7 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ - NULL, /* dirfsp */ + dirfsp, /* dirfsp */ smb_dname, /* fname */ FILE_READ_ATTRIBUTES, /* access_mask */ FILE_SHARE_NONE, /* share_access */ diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 341c98cde71..0d541d15466 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -698,7 +698,9 @@ NTSTATUS set_sd_blob(files_struct *fsp, uint8_t *data, uint32_t sd_len, NTSTATUS copy_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, + struct files_struct *src_dirfsp, struct smb_filename *smb_fname_src, + struct files_struct *dst_dirfsp, struct smb_filename *smb_fname_dst, uint32_t attrs); NTSTATUS smbd_do_query_security_desc(connection_struct *conn, @@ -745,7 +747,9 @@ NTSTATUS send_break_message(struct messaging_context *msg_ctx, struct deferred_open_record; bool is_deferred_open_async(const struct deferred_open_record *rec); bool defer_smb1_sharing_violation(struct smb_request *req); -NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, +NTSTATUS create_directory(connection_struct *conn, + struct smb_request *req, + struct files_struct *dirfsp, struct smb_filename *smb_dname); void msg_file_was_renamed(struct messaging_context *msg, void *private_data, @@ -973,6 +977,7 @@ void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_s NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, uint32_t dirtype, + struct files_struct *dirfsp, struct smb_filename *smb_fname); ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp, off_t startpos, size_t nread); @@ -983,6 +988,7 @@ ssize_t sendfile_short_send(struct smbXsrv_connection *xconn, size_t smb_maxcnt); NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, + struct files_struct *dst_dirfsp, struct smb_filename *smb_fname_dst_in, const char *dst_original_lcomp, uint32_t attrs, @@ -990,7 +996,9 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, NTSTATUS rename_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, + struct files_struct *src_dirfsp, struct smb_filename *smb_fname_src, + struct files_struct *dst_dirfsp, struct smb_filename *smb_fname_dst, const char *dst_original_lcomp, uint32_t attrs, @@ -1139,7 +1147,9 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, bool overwrite_if_exists, + struct files_struct *old_dirfsp, const struct smb_filename *smb_fname_old, + struct files_struct *new_dirfsp, struct smb_filename *smb_fname_new); NTSTATUS smb_set_file_time(connection_struct *conn, files_struct *fsp, diff --git a/source3/smbd/smb1_nttrans.c b/source3/smbd/smb1_nttrans.c index acb09fb7650..cd68ecd2590 100644 --- a/source3/smbd/smb1_nttrans.c +++ b/source3/smbd/smb1_nttrans.c @@ -1401,7 +1401,9 @@ void reply_ntcancel(struct smb_request *req) void reply_ntrename(struct smb_request *req) { connection_struct *conn = req->conn; + struct files_struct *src_dirfsp = NULL; struct smb_filename *smb_fname_old = NULL; + struct files_struct *dst_dirfsp = NULL; struct smb_filename *smb_fname_new = NULL; char *oldname = NULL; char *newname = NULL; @@ -1410,7 +1412,9 @@ void reply_ntrename(struct smb_request *req) NTSTATUS status; uint32_t attrs; uint32_t ucf_flags_src = ucf_flags_from_smb_request(req); + NTTIME src_twrp = 0; uint32_t ucf_flags_dst = ucf_flags_from_smb_request(req); + NTTIME dst_twrp = 0; uint16_t rename_type; TALLOC_CTX *ctx = talloc_tos(); bool stream_rename = false; @@ -1463,12 +1467,16 @@ void reply_ntrename(struct smb_request *req) } } - /* rename_internals() calls unix_convert(), so don't call it here. */ - status = filename_convert(ctx, conn, - oldname, - ucf_flags_src, - 0, - &smb_fname_old); + if (ucf_flags_src & UCF_GMT_PATHNAME) { + extract_snapshot_token(oldname, &src_twrp); + } + status = filename_convert_dirfsp(ctx, + conn, + oldname, + ucf_flags_src, + src_twrp, + &src_dirfsp, + &smb_fname_old); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { @@ -1491,32 +1499,46 @@ void reply_ntrename(struct smb_request *req) goto out; } - status = filename_convert(ctx, conn, - newname, - ucf_flags_dst, - 0, - &smb_fname_new); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status, - NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, - NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - goto out; - } - reply_nterror(req, status); - goto out; - } - if (stream_rename) { - /* smb_fname_new must be the same as smb_fname_old. */ - TALLOC_FREE(smb_fname_new->base_name); - smb_fname_new->base_name = talloc_strdup(smb_fname_new, - smb_fname_old->base_name); - if (!smb_fname_new->base_name) { + /* + * No point in calling filename_convert() + * on a raw stream name. It can never find + * the file anyway. Use the same logic as + * SMB2_FILE_RENAME_INFORMATION_INTERNAL + * and generate smb_fname_new directly. + */ + smb_fname_new = synthetic_smb_fname(talloc_tos(), + smb_fname_old->base_name, + newname, + NULL, + smb_fname_old->twrp, + smb_fname_old->flags); + if (smb_fname_new == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } + } else { + if (ucf_flags_dst & UCF_GMT_PATHNAME) { + extract_snapshot_token(newname, &dst_twrp); + } + status = filename_convert_dirfsp(ctx, + conn, + newname, + ucf_flags_dst, + dst_twrp, + &dst_dirfsp, + &smb_fname_new); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_PATH_NOT_COVERED)) { + reply_botherror(req, + NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + goto out; + } + reply_nterror(req, status); + goto out; + } } DEBUG(3,("reply_ntrename: %s -> %s\n", @@ -1528,7 +1550,9 @@ void reply_ntrename(struct smb_request *req) status = rename_internals(ctx, conn, req, + src_dirfsp, smb_fname_old, + dst_dirfsp, smb_fname_new, dst_original_lcomp, attrs, @@ -1540,14 +1564,18 @@ void reply_ntrename(struct smb_request *req) conn, req, false, + src_dirfsp, smb_fname_old, + dst_dirfsp, smb_fname_new); break; case RENAME_FLAG_COPY: status = copy_internals(ctx, conn, req, + src_dirfsp, smb_fname_old, + dst_dirfsp, smb_fname_new, attrs); break; diff --git a/source3/smbd/smb1_reply.c b/source3/smbd/smb1_reply.c index de38817ea76..fcfd670163d 100644 --- a/source3/smbd/smb1_reply.c +++ b/source3/smbd/smb1_reply.c @@ -682,13 +682,19 @@ void reply_getatr(struct smb_request *req) size = 0; mtime = 0; } else { + struct files_struct *dirfsp = NULL; uint32_t ucf_flags = ucf_flags_from_smb_request(req); - status = filename_convert(ctx, - conn, - fname, - ucf_flags, - 0, - &smb_fname); + NTTIME twrp = 0; + if (ucf_flags & UCF_GMT_PATHNAME) { + extract_snapshot_token(fname, &twrp); + } + status = filename_convert_dirfsp(ctx, + conn, + fname, + ucf_flags, + twrp, + &dirfsp, + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -762,12 +768,14 @@ void reply_setatr(struct smb_request *req) struct smb_file_time ft; connection_struct *conn = req->conn; struct smb_filename *smb_fname = NULL; + struct files_struct *dirfsp = NULL; char *fname = NULL; int mode; time_t mtime; const char *p; NTSTATUS status; uint32_t ucf_flags = ucf_flags_from_smb_request(req); + NTTIME twrp = 0; TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBsetatr); @@ -785,12 +793,16 @@ void reply_setatr(struct smb_request *req) goto out; } - status = filename_convert(ctx, - conn, - fname, - ucf_flags, - 0, -- Samba Shared Repository