diff --git a/docs-xml/smbdotconf/tuning/checkparentdirectorydeleteonclose.xml b/docs-xml/smbdotconf/tuning/checkparentdirectorydeleteonclose.xml new file mode 100644 index 00000000000..1de06091dd7 --- /dev/null +++ b/docs-xml/smbdotconf/tuning/checkparentdirectorydeleteonclose.xml @@ -0,0 +1,13 @@ + + + A Windows SMB server prevents the client from creating files in a + directory that has the delete-on-close flag set. By default Samba doesn't + perform this check as this check is a quite expensive operation in Samba. + + + +no + diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index 7854f57a158..efad4a10f03 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -2998,6 +2998,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) lpcfg_do_global_parameter(lp_ctx, "prefork children", "1"); + lpcfg_do_global_parameter(lp_ctx, "check parent directory delete on close", "no"); + for (i = 0; parm_table[i].label; i++) { if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) { lp_ctx->flags[i] |= FLAG_DEFAULT; diff --git a/selftest/knownfail.d/samba3.base.delete b/selftest/knownfail.d/samba3.base.delete deleted file mode 100644 index 6129ca7a66c..00000000000 --- a/selftest/knownfail.d/samba3.base.delete +++ /dev/null @@ -1,2 +0,0 @@ -samba3.base.delete.deltest20\(nt4_dc\) -samba3.base.delete.deltest20\(ad_dc\) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index f2dcdd1489b..ee7c3be9a9d 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -231,6 +231,7 @@ sub setup_nt4_dc($$) rpc_daemon:lsasd = fork rpc_daemon:fssd = fork fss: sequence timeout = 1 + check parent directory delete on close = yes "; my $vars = $self->provision($path, "SAMBA-TEST", diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index c161ee082a0..123bf6c3a91 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1815,6 +1815,7 @@ sub provision_ad_dc($$$$$$) smbd:writetimeupdatedelay = 500000 create mask = 755 dos filemode = yes + check parent directory delete on close = yes dcerpc endpoint servers = -winreg -srvsvc diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 096c23f4fb3..b1b502c117e 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -244,6 +244,7 @@ static const struct loadparm_service _sDefault = .smb_encrypt = SMB_SIGNING_DEFAULT, .kernel_share_modes = true, .durable_handles = true, + .check_parent_directory_delete_on_close = false, .param_opt = NULL, .dummy = "" }; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e55c3941092..5817bdbe9ae 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -253,6 +253,11 @@ NTSTATUS check_parent_access(struct connection_struct *conn, struct security_descriptor *parent_sd = NULL; uint32_t access_granted = 0; struct smb_filename *parent_smb_fname = NULL; + struct share_mode_lock *lck = NULL; + struct file_id id = {0}; + uint32_t name_hash; + bool delete_on_close_set; + int ret; if (!parent_dirname(talloc_tos(), smb_fname->base_name, @@ -320,7 +325,45 @@ NTSTATUS check_parent_access(struct connection_struct *conn, return status; } - return NT_STATUS_OK; + if (!(access_mask & (SEC_DIR_ADD_FILE | SEC_DIR_ADD_SUBDIR))) { + return NT_STATUS_OK; + } + if (!lp_check_parent_directory_delete_on_close(SNUM(conn))) { + return NT_STATUS_OK; + } + + /* Check if the directory has delete-on-close set */ + ret = SMB_VFS_STAT(conn, parent_smb_fname); + if (ret != 0) { + status = map_nt_error_from_unix(errno); + goto out; + } + + id = SMB_VFS_FILE_ID_CREATE(conn, &parent_smb_fname->st); + + status = file_name_hash(conn, parent_smb_fname->base_name, &name_hash); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + lck = get_existing_share_mode_lock(talloc_tos(), id); + if (lck == NULL) { + status = NT_STATUS_OK; + goto out; + } + + delete_on_close_set = is_delete_on_close_set(lck, name_hash); + if (delete_on_close_set) { + status = NT_STATUS_DELETE_PENDING; + goto out; + } + + status = NT_STATUS_OK; + +out: + TALLOC_FREE(lck); + TALLOC_FREE(parent_smb_fname); + return status; } /****************************************************************************