1
0
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:
Jeremy Allison 2007-01-18 06:19:24 +00:00 committed by Gerald (Jerry) Carter
parent a99840e59e
commit fd37f98158
8 changed files with 111 additions and 21 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.
****************************************************************************/

View File

@ -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) {

View File

@ -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, &current_user.ut);
lck->initial_delete_on_close = True;
lck->modified = True;
if (NT_STATUS_IS_OK(status)) {
set_delete_on_close_token(lck, &current_user.ut);
lck->initial_delete_on_close = True;
lck->modified = True;
}
}
TALLOC_FREE(lck);

View File

@ -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;
}
/*

View File

@ -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);
}

View File

@ -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. */