From 379e159d758cbff40c2ccc79538a8799b08ea3e1 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 27 Nov 2015 18:29:55 +0100 Subject: [PATCH 1/5] s3:smbd: convert file_struct.posix_open to a bitmap with flags This is in preperation of a more fine grained control of POSIX behaviour in the SMB and VFS layers. Inititally we use an uint8_t for the flags bitmap and add a define posix_flags as posix_open in order to avoid breaking the VFS ABI. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11065 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit d698cec1c7e700e57cab46d33df0dde13303b318) --- source3/include/vfs.h | 10 +++++++++- source3/locking/locking.c | 3 ++- source3/modules/vfs_acl_common.c | 4 ++-- source3/param/loadparm.c | 3 ++- source3/smbd/close.c | 6 ++++-- source3/smbd/fileio.c | 8 ++++---- source3/smbd/open.c | 10 ++++++---- source3/smbd/reply.c | 2 +- source3/smbd/smb2_close.c | 2 +- source3/smbd/vfs.c | 4 ++-- 10 files changed, 33 insertions(+), 19 deletions(-) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 9945375..56a9049 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -218,6 +218,9 @@ struct fsp_lease { struct smb2_lease lease; }; +/* VFS ABI stability hack */ +#define posix_flags posix_open + typedef struct files_struct { struct files_struct *next, *prev; uint64_t fnum; @@ -255,7 +258,7 @@ typedef struct files_struct { bool aio_write_behind; bool initial_delete_on_close; /* Only set at NTCreateX if file was created. */ bool delete_on_close; - bool posix_open; + uint8_t posix_flags; bool is_sparse; bool backup_intent; /* Handle was successfully opened with backup intent and opener has privilege to do so. */ @@ -297,6 +300,11 @@ typedef struct files_struct { struct tevent_req *deferred_close; } files_struct; +#define FSP_POSIX_FLAGS_OPEN 0x01 + +#define FSP_POSIX_FLAGS_ALL \ + (FSP_POSIX_FLAGS_OPEN) + struct vuid_cache_entry { struct auth_session_info *session_info; uint64_t vuid; /* SMB2 compat */ diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 7b8bc84..5a97460 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -847,7 +847,8 @@ bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp, e->id = fsp->file_id; e->share_file_id = fsp->fh->gen_id; e->uid = (uint32_t)uid; - e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0; + e->flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ? + SHARE_MODE_FLAG_POSIX_OPEN : 0; e->name_hash = fsp->name_hash; return true; diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c index 625e7cb..f73e80c 100644 --- a/source3/modules/vfs_acl_common.c +++ b/source3/modules/vfs_acl_common.c @@ -1089,7 +1089,7 @@ static int chmod_acl_module_common(struct vfs_handle_struct *handle, static int fchmod_acl_module_common(struct vfs_handle_struct *handle, struct files_struct *fsp, mode_t mode) { - if (fsp->posix_open) { + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { /* Only allow this on POSIX opens. */ return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode); } @@ -1109,7 +1109,7 @@ static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle, static int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle, struct files_struct *fsp, mode_t mode) { - if (fsp->posix_open) { + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { /* Only allow this on POSIX opens. */ return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode); } diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 2f53a74..12510be 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -4342,7 +4342,8 @@ enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp) if (posix_default_lock_was_set) { return posix_cifsx_locktype; } else { - return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK; + return (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ? + POSIX_LOCK : WINDOWS_LOCK; } } diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 0e75bf0..1cb5460 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -327,7 +327,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, if (e->name_hash != fsp->name_hash) { continue; } - if (fsp->posix_open + if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { continue; } @@ -1103,7 +1103,9 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, struct share_mode_entry *e = &lck->data->share_modes[i]; if (is_valid_share_mode_entry(e) && e->name_hash == fsp->name_hash) { - if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { + if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) && + (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) + { continue; } if (serverid_equal(&self, &e->pid) && diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 2fe0432..156c139 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -193,7 +193,7 @@ void trigger_write_time_update(struct files_struct *fsp) { int delay; - if (fsp->posix_open) { + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { /* Don't use delayed writes on POSIX files. */ return; } @@ -238,7 +238,7 @@ void trigger_write_time_update_immediate(struct files_struct *fsp) { struct smb_file_time ft; - if (fsp->posix_open) { + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { /* Don't use delayed writes on POSIX files. */ return; } @@ -284,7 +284,7 @@ void mark_file_modified(files_struct *fsp) } trigger_write_time_update(fsp); - if (fsp->posix_open) { + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { return; } if (!(lp_store_dos_attributes(SNUM(fsp->conn)) || @@ -1047,7 +1047,7 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug int fsp_stat(files_struct *fsp) { if (fsp->fh->fd == -1) { - if (fsp->posix_open) { + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { return SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); } else { return SMB_VFS_STAT(fsp->conn, fsp->fsp_name); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 162e834..154c1a9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -362,7 +362,7 @@ NTSTATUS fd_open(struct connection_struct *conn, * client should be doing this. */ - if (fsp->posix_open || !lp_follow_symlinks(SNUM(conn))) { + if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || !lp_follow_symlinks(SNUM(conn))) { flags |= O_NOFOLLOW; } #endif @@ -945,7 +945,7 @@ static NTSTATUS open_file(files_struct *fsp, access_mask); if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) && - fsp->posix_open && + (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) && S_ISLNK(smb_fname->st.st_ex_mode)) { /* This is a POSIX stat open for delete * or rename on a symlink that points @@ -2705,7 +2705,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->access_mask = open_access_mask; /* We change this to the * requested access_mask after * the open is done. */ - fsp->posix_open = posix_open; + fsp->posix_flags |= posix_open ? FSP_POSIX_FLAGS_OPEN : 0; if (timeval_is_zero(&request_time)) { request_time = fsp->open_time; @@ -3571,7 +3571,9 @@ static NTSTATUS open_directory(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; - fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False; + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + fsp->posix_flags |= FSP_POSIX_FLAGS_ALL; + } status = fsp_set_smb_fname(fsp, smb_dname); if (!NT_STATUS_IS_OK(status)) { file_free(req, fsp); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b6f9992..25aeba1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2669,7 +2669,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, } if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) { - if (fsp->posix_open) { + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { return NT_STATUS_OK; } diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c index ed53e1b..367c9fa 100644 --- a/source3/smbd/smb2_close.c +++ b/source3/smbd/smb2_close.c @@ -231,7 +231,7 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req, return NT_STATUS_NO_MEMORY; } - posix_open = fsp->posix_open; + posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN); smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name); if (smb_fname == NULL) { return NT_STATUS_NO_MEMORY; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 9f3ba6d..0c272a7 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1309,7 +1309,7 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp) int ret; if(fsp->fh->fd == -1) { - if (fsp->posix_open) { + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); } else { ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); @@ -1939,7 +1939,7 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid) path = fsp->fsp_name->base_name; } - if (fsp->posix_open || as_root) { + if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || as_root) { ret = SMB_VFS_LCHOWN(fsp->conn, path, uid, gid); -- 2.5.0 From fe6935e7f54d12fa5ecd8aa68941707c8240f2f0 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 22 Jan 2015 10:00:15 +0100 Subject: [PATCH 2/5] s3:smbd: file_struct: seperate POSIX directory rename cap from POSIX open We need more fine grained control over which POSIX semantics we'd like to enable per file handle. Currently POSIX_FLAGS_OPEN is a kitchensink for all kinds of stuff like: - POSIX unlink - POSIX byte-range locks - POSIX rename - delayed writetime update - more... For CIFS UNIX extensions we use POSIX_FLAGS_ALL so semantics are preserved. OS X clients will enable POSIX rename via AAPL. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11065 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit bf1957584e341473edcd5025b7f77766440d408b) --- source3/include/vfs.h | 4 +++- source3/smbd/reply.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 56a9049..d839be4 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -301,9 +301,11 @@ typedef struct files_struct { } files_struct; #define FSP_POSIX_FLAGS_OPEN 0x01 +#define FSP_POSIX_FLAGS_RENAME 0x02 #define FSP_POSIX_FLAGS_ALL \ - (FSP_POSIX_FLAGS_OPEN) + (FSP_POSIX_FLAGS_OPEN | \ + FSP_POSIX_FLAGS_RENAME) struct vuid_cache_entry { struct auth_session_info *session_info; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 25aeba1..c9d0d81 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2669,7 +2669,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, } if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) { - if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { + if (fsp->posix_flags & (FSP_POSIX_FLAGS_OPEN|FSP_POSIX_FLAGS_RENAME)) { return NT_STATUS_OK; } -- 2.5.0 From 2a5c2840a15500eacf21c28b8bd675eb34cdde59 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 25 Nov 2015 09:12:55 +0100 Subject: [PATCH 3/5] vfs_fruit: add a flag that tracks whether use of AAPL was negotiated Add a flag that tracks whether use of AAPL was negotiated, ensuring we don't enable AAPL features for clients that didn't negotiate it. Torture test that need AAPL must call the new function enable_aapl(). Bug: https://bugzilla.samba.org/show_bug.cgi?id=11065 Signed-off-by: Ralph Boehme (cherry picked from commit 89a7394d679b383920d73fef0d178b8f84bc393f) --- source3/modules/vfs_fruit.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index ecce85d..ae86e93 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -124,7 +124,8 @@ struct fruit_config_data { enum fruit_meta meta; enum fruit_locking locking; enum fruit_encoding encoding; - bool use_aapl; + bool use_aapl; /* config from smb.conf */ + bool nego_aapl; /* client negotiated AAPL */ bool use_copyfile; bool readdir_attr_enabled; bool unix_info_enabled; @@ -1894,6 +1895,9 @@ static NTSTATUS check_aapl(vfs_handle_struct *handle, out_context_blobs, SMB2_CREATE_TAG_AAPL, blob); + if (NT_STATUS_IS_OK(status)) { + config->nego_aapl = true; + } return status; } @@ -3338,16 +3342,20 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, if (!NT_STATUS_IS_OK(status)) { return status; } + fsp = *result; - if (config->copyfile_enabled) { - /* - * Set a flag in the fsp. Gets used in copychunk to - * check whether the special Apple copyfile semantics - * for copychunk should be allowed in a copychunk - * request with a count of 0. - */ - fsp->aapl_copyfile_supported = true; + if (config->nego_aapl) { + if (config->copyfile_enabled) { + /* + * Set a flag in the fsp. Gets used in + * copychunk to check whether the special + * Apple copyfile semantics for copychunk + * should be allowed in a copychunk request + * with a count of 0. + */ + fsp->aapl_copyfile_supported = true; + } } /* -- 2.5.0 From ea7101a3c6692011264e3a144ad718c91ae8ed75 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 22 Jan 2015 10:07:56 +0100 Subject: [PATCH 4/5] vfs_fruit: enable POSIX directory rename semantics Bug: https://bugzilla.samba.org/show_bug.cgi?id=11065 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 1d7bef5a75403f5baec13aa6264dfe763a4b278a) --- source3/modules/vfs_fruit.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index ae86e93..610a690 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -3356,6 +3356,13 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, */ fsp->aapl_copyfile_supported = true; } + + if (fsp->is_directory) { + /* + * Enable POSIX directory rename behaviour + */ + fsp->posix_flags |= FSP_POSIX_FLAGS_RENAME; + } } /* -- 2.5.0 From 94d488780c52ccbfb0e5036762362d318029f86e Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 28 Nov 2015 19:26:47 +0100 Subject: [PATCH 5/5] s4:torture:vfs_fruit: add a test for POSIX rename Bug: https://bugzilla.samba.org/show_bug.cgi?id=11065 Signed-off-by: Ralph Boehme (cherry picked from commit 0f0693d0fa5fa991bb573525f332eba5ceb6ece6) --- source4/torture/vfs/fruit.c | 201 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index 1c1d4ad..8b3f2a6 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -1188,6 +1188,73 @@ static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree, return true; } +static bool enable_aapl(struct torture_context *tctx, + struct smb2_tree *tree1) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + NTSTATUS status; + bool ret = true; + struct smb2_create io; + DATA_BLOB data; + struct smb2_create_blob *aapl = NULL; + uint32_t aapl_server_caps; + uint32_t expexted_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED | + SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR | + SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE | + SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE); + + ZERO_STRUCT(io); + io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; + io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; + io.in.create_disposition = NTCREATEX_DISP_OPEN; + io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE | + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE); + io.in.fname = ""; + + /* + * Issuing an SMB2/CREATE with a suitably formed AAPL context, + * controls behaviour of Apple's SMB2 extensions for the whole + * session! + */ + + data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t)); + SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY); + SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS | + SMB2_CRTCTX_AAPL_VOLUME_CAPS | + SMB2_CRTCTX_AAPL_MODEL_INFO)); + SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR | + SMB2_CRTCTX_AAPL_UNIX_BASED | + SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE)); + + status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add"); + + status = smb2_create(tree1, tctx, &io); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create"); + + status = smb2_util_close(tree1, io.out.file.handle); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close"); + + /* + * Now check returned AAPL context + */ + torture_comment(tctx, "Comparing returned AAPL capabilities\n"); + + aapl = smb2_create_blob_find(&io.out.blobs, + SMB2_CREATE_TAG_AAPL); + torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context"); + torture_assert_goto(tctx, aapl->data.length == 50, ret, done, "bad AAPL size"); + + aapl_server_caps = BVAL(aapl->data.data, 16); + torture_assert_goto(tctx, aapl_server_caps == expexted_scaps, + ret, done, "bad AAPL caps"); + +done: + talloc_free(mem_ctx); + return ret; +} + static bool test_read_atalk_metadata(struct torture_context *tctx, struct smb2_tree *tree1, struct smb2_tree *tree2) @@ -2548,6 +2615,139 @@ done: return ret; } +/* Renaming a directory with open file, should work for OS X AAPL clients */ +static bool test_rename_dir_openfile(struct torture_context *torture, + struct smb2_tree *tree1, + struct smb2_tree *tree2) +{ + bool ret = true; + NTSTATUS status; + union smb_open io; + union smb_close cl; + union smb_setfileinfo sinfo; + struct smb2_handle d1, h1; + const char *renamedir = BASEDIR "-new"; + + smb2_deltree(tree1, BASEDIR); + smb2_util_rmdir(tree1, BASEDIR); + smb2_deltree(tree1, renamedir); + + ZERO_STRUCT(io.smb2); + io.generic.level = RAW_OPEN_SMB2; + io.smb2.in.create_flags = 0; + io.smb2.in.desired_access = 0x0017019f; + io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; + io.smb2.in.share_access = 0; + io.smb2.in.alloc_size = 0; + io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; + io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + io.smb2.in.security_flags = 0; + io.smb2.in.fname = BASEDIR; + + status = smb2_create(tree1, torture, &(io.smb2)); + torture_assert_ntstatus_ok(torture, status, "smb2_create dir"); + d1 = io.smb2.out.file.handle; + + ZERO_STRUCT(io.smb2); + io.generic.level = RAW_OPEN_SMB2; + io.smb2.in.create_flags = 0; + io.smb2.in.desired_access = 0x0017019f; + io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; + io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + io.smb2.in.share_access = 0; + io.smb2.in.alloc_size = 0; + io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; + io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + io.smb2.in.security_flags = 0; + io.smb2.in.fname = BASEDIR "\\file.txt"; + + status = smb2_create(tree1, torture, &(io.smb2)); + torture_assert_ntstatus_ok(torture, status, "smb2_create file"); + h1 = io.smb2.out.file.handle; + + torture_comment(torture, "Renaming directory without AAPL, must fail\n"); + + ZERO_STRUCT(sinfo); + sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; + sinfo.rename_information.in.file.handle = d1; + sinfo.rename_information.in.overwrite = 0; + sinfo.rename_information.in.root_fid = 0; + sinfo.rename_information.in.new_name = renamedir; + status = smb2_setinfo_file(tree1, &sinfo); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_ACCESS_DENIED, + "smb2_setinfo_file"); + + ZERO_STRUCT(cl.smb2); + cl.smb2.level = RAW_CLOSE_SMB2; + cl.smb2.in.file.handle = d1; + status = smb2_close(tree1, &(cl.smb2)); + torture_assert_ntstatus_ok(torture, status, "smb2_close"); + ZERO_STRUCT(d1); + + torture_comment(torture, "Enabling AAPL\n"); + + ret = enable_aapl(torture, tree1); + torture_assert(torture, ret == true, "enable_aapl failed"); + + torture_comment(torture, "Renaming directory with AAPL\n"); + + ZERO_STRUCT(io.smb2); + io.generic.level = RAW_OPEN_SMB2; + io.smb2.in.desired_access = 0x0017019f; + io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; + io.smb2.in.share_access = 0; + io.smb2.in.alloc_size = 0; + io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; + io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + io.smb2.in.security_flags = 0; + io.smb2.in.fname = BASEDIR; + + status = smb2_create(tree1, torture, &(io.smb2)); + torture_assert_ntstatus_ok(torture, status, "smb2_create dir"); + d1 = io.smb2.out.file.handle; + + ZERO_STRUCT(io.smb2); + io.generic.level = RAW_OPEN_SMB2; + io.smb2.in.desired_access = 0x0017019f; + io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; + io.smb2.in.share_access = 0; + io.smb2.in.alloc_size = 0; + io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; + io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + io.smb2.in.security_flags = 0; + io.smb2.in.fname = BASEDIR; + sinfo.rename_information.in.file.handle = d1; + + status = smb2_setinfo_file(tree1, &sinfo); + torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file"); + + ZERO_STRUCT(cl.smb2); + cl.smb2.level = RAW_CLOSE_SMB2; + cl.smb2.in.file.handle = d1; + status = smb2_close(tree1, &(cl.smb2)); + torture_assert_ntstatus_ok(torture, status, "smb2_close"); + ZERO_STRUCT(d1); + + cl.smb2.in.file.handle = h1; + status = smb2_close(tree1, &(cl.smb2)); + torture_assert_ntstatus_ok(torture, status, "smb2_close"); + ZERO_STRUCT(h1); + + torture_comment(torture, "Cleaning up\n"); + + if (h1.data) { + ZERO_STRUCT(cl.smb2); + cl.smb2.level = RAW_CLOSE_SMB2; + cl.smb2.in.file.handle = h1; + status = smb2_close(tree1, &(cl.smb2)); + } + + smb2_deltree(tree1, BASEDIR); + smb2_deltree(tree1, renamedir); + return ret; +} + /* * Note: This test depends on "vfs objects = catia fruit * streams_xattr". Note: To run this test, use @@ -2571,6 +2771,7 @@ struct torture_suite *torture_vfs_fruit(void) torture_suite_add_2ns_smb2_test(suite, "stream names", test_stream_names); torture_suite_add_2ns_smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate); torture_suite_add_2ns_smb2_test(suite, "opening and creating resource fork", test_rfork_create); + torture_suite_add_2ns_smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile); return suite; } -- 2.5.0