mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r20873: Some correctness fixes w.r.t. Samba4 torture BASE-DELETE.
Allow us to correctly refuse to set delete on close on a
non-empty directory. There are still some delete-on-close
wrinkles to be fixed, but I understand how to do that better
now. I'll fix this tomorrow.
Jeremy.
(This used to be commit 0296358858
)
This commit is contained in:
parent
a99840e59e
commit
fd37f98158
@ -37,3 +37,19 @@ BOOL conn_snum_used(int snum)
|
||||
void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck)
|
||||
{
|
||||
}
|
||||
|
||||
NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
|
||||
const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
int dptr_CloseDir(struct dptr_struct *dptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1152,6 +1152,46 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Don't allow delete on close for non-empty directories. */
|
||||
if (fsp->is_directory) {
|
||||
long offset = 0;
|
||||
NTSTATUS status;
|
||||
SMB_STRUCT_STAT st;
|
||||
struct dptr_struct *dirptr;
|
||||
const char *name;
|
||||
|
||||
status = dptr_create(fsp->conn,
|
||||
fsp->fsp_name,
|
||||
False,
|
||||
True,
|
||||
0,
|
||||
"*",
|
||||
True,
|
||||
0,
|
||||
&dirptr);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Read 3 entries. Ignore first 2 (they're . and .. ) */
|
||||
name = dptr_ReadDirName(dirptr, &offset, &st);
|
||||
if (!name) {
|
||||
dptr_CloseDir(dirptr);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
name = dptr_ReadDirName(dirptr, &offset, &st);
|
||||
if (!name) {
|
||||
dptr_CloseDir(dirptr);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
name = dptr_ReadDirName(dirptr, &offset, &st);
|
||||
dptr_CloseDir(dirptr);
|
||||
if (name) {
|
||||
DEBUG(10,("can_set_delete_on_close: got name %s - can't delete\n", name ));
|
||||
return NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
@ -383,7 +383,7 @@ static void dptr_close_oldest(BOOL old)
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
|
||||
const char *wcard, BOOL wcard_has_wild, uint32 attr, int *dptr_hnd_ret)
|
||||
const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
|
||||
{
|
||||
struct dptr_struct *dptr = NULL;
|
||||
struct smb_Dir *dir_hnd;
|
||||
@ -392,8 +392,6 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
|
||||
|
||||
DEBUG(5,("dptr_create dir=%s\n", path));
|
||||
|
||||
*dptr_hnd_ret = -1;
|
||||
|
||||
if (!wcard) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
@ -517,9 +515,8 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
|
||||
DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
|
||||
dptr->dnum,path,expect_close));
|
||||
|
||||
conn->dirptr = dptr;
|
||||
*dptr_ret = dptr;
|
||||
|
||||
*dptr_hnd_ret = dptr->dnum;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -530,6 +527,7 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
|
||||
|
||||
int dptr_CloseDir(struct dptr_struct *dptr)
|
||||
{
|
||||
DLIST_REMOVE(dirptrs, dptr);
|
||||
return CloseDir(dptr->dir_hnd);
|
||||
}
|
||||
|
||||
@ -548,6 +546,11 @@ BOOL dptr_has_wild(struct dptr_struct *dptr)
|
||||
return dptr->has_wild;
|
||||
}
|
||||
|
||||
int dptr_dnum(struct dptr_struct *dptr)
|
||||
{
|
||||
return dptr->dnum;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Return the next visible file name, skipping veto'd and invisible files.
|
||||
****************************************************************************/
|
||||
|
@ -652,11 +652,13 @@ int reply_ntcreate_and_X(connection_struct *conn,
|
||||
if (lp_acl_check_permissions(SNUM(conn))
|
||||
&& (create_disposition != FILE_CREATE)
|
||||
&& (share_access & FILE_SHARE_DELETE)
|
||||
&& (access_mask & DELETE_ACCESS)
|
||||
&& !can_delete_file_in_directory(conn, fname)) {
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
END_PROFILE(SMBntcreateX);
|
||||
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
|
||||
&& (access_mask & DELETE_ACCESS)) {
|
||||
if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
|
||||
!can_delete_file_in_directory(conn, fname)) {
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
END_PROFILE(SMBntcreateX);
|
||||
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1277,10 +1279,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
if (lp_acl_check_permissions(SNUM(conn))
|
||||
&& (create_disposition != FILE_CREATE)
|
||||
&& (share_access & FILE_SHARE_DELETE)
|
||||
&& (access_mask & DELETE_ACCESS)
|
||||
&& !can_delete_file_in_directory(conn, fname)) {
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
|
||||
&& (access_mask & DELETE_ACCESS)) {
|
||||
if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
|
||||
!can_delete_file_in_directory(conn, fname)) {
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
END_PROFILE(SMBntcreateX);
|
||||
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
|
||||
if (ea_len) {
|
||||
|
@ -2110,15 +2110,17 @@ NTSTATUS open_directory(connection_struct *conn,
|
||||
always to be honored on close... See test 19 in Samba4 BASE-DELETE. */
|
||||
if (create_options & FILE_DELETE_ON_CLOSE) {
|
||||
status = can_set_delete_on_close(fsp, True, 0);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
|
||||
TALLOC_FREE(lck);
|
||||
file_free(fsp);
|
||||
return status;
|
||||
}
|
||||
|
||||
set_delete_on_close_token(lck, ¤t_user.ut);
|
||||
lck->initial_delete_on_close = True;
|
||||
lck->modified = True;
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
set_delete_on_close_token(lck, ¤t_user.ut);
|
||||
lck->initial_delete_on_close = True;
|
||||
lck->modified = True;
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(lck);
|
||||
|
@ -4221,6 +4221,11 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
|
||||
if (sbuf.st_mode & S_ISVTX) {
|
||||
SMB_STRUCT_STAT sbuf_file;
|
||||
if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
|
||||
if (errno == ENOENT) {
|
||||
/* If the file doesn't already exist then
|
||||
* yes we'll be able to delete it. */
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
/*
|
||||
|
@ -1013,10 +1013,19 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
||||
p = smb_buf(outbuf) + 3;
|
||||
|
||||
if (status_len == 0) {
|
||||
nt_status = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype,&dptr_num);
|
||||
nt_status = dptr_create(conn,
|
||||
directory,
|
||||
True,
|
||||
expect_close,
|
||||
SVAL(inbuf,smb_pid),
|
||||
mask,
|
||||
mask_contains_wcard,
|
||||
dirtype,
|
||||
&conn->dirptr);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
return ERROR_NT(nt_status);
|
||||
}
|
||||
dptr_num = dptr_dnum(conn->dirptr);
|
||||
} else {
|
||||
dirtype = dptr_attr(dptr_num);
|
||||
}
|
||||
|
@ -1794,13 +1794,23 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
|
||||
/* Save the wildcard match and attribs we are using on this directory -
|
||||
needed as lanman2 assumes these are being saved between calls */
|
||||
|
||||
ntstatus = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype, &dptr_num);
|
||||
ntstatus = dptr_create(conn,
|
||||
directory,
|
||||
False,
|
||||
True,
|
||||
SVAL(inbuf,smb_pid),
|
||||
mask,
|
||||
mask_contains_wcard,
|
||||
dirtype,
|
||||
&conn->dirptr);
|
||||
|
||||
if (!NT_STATUS_IS_OK(ntstatus)) {
|
||||
talloc_destroy(ea_ctx);
|
||||
return ERROR_NT(ntstatus);
|
||||
}
|
||||
|
||||
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
|
||||
dptr_num = dptr_dnum(conn->dirptr);
|
||||
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
|
||||
|
||||
/* We don't need to check for VOL here as this is returned by
|
||||
a different TRANS2 call. */
|
||||
|
Loading…
Reference in New Issue
Block a user