1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

Fix bug #6082 - smbd_gpfs_getacl failed: Windows client can´t rename or delete file

This fixes the generic rename/delete problem for 3.3.0 and above.
Fixed slightly differently to discussions, user viewable modified
ACLs are not a good idea :-).
Jeremy.
This commit is contained in:
Jeremy Allison 2009-02-02 17:10:27 -08:00
parent df4e38fcc3
commit 553818add8
4 changed files with 54 additions and 20 deletions

View File

@ -1259,7 +1259,7 @@ struct bitmap {
/* Mapping of access rights to UNIX perms. for a UNIX directory. */
#define UNIX_DIRECTORY_ACCESS_RWX FILE_GENERIC_ALL
#define UNIX_DIRECTORY_ACCESS_R FILE_GENERIC_READ
#define UNIX_DIRECTORY_ACCESS_W FILE_GENERIC_WRITE
#define UNIX_DIRECTORY_ACCESS_W (FILE_GENERIC_WRITE|FILE_DELETE_CHILD)
#define UNIX_DIRECTORY_ACCESS_X FILE_GENERIC_EXECUTE
#if 0

View File

@ -149,7 +149,9 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
}
/*
the main entry point for access checking.
The main entry point for access checking. If returning ACCESS_DENIED
this function returns the denied bits in the uint32_t pointed
to by the access_granted pointer.
*/
NTSTATUS se_access_check(const struct security_descriptor *sd,
const NT_USER_TOKEN *token,
@ -238,6 +240,7 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
done:
if (bits_remaining != 0) {
*access_granted = bits_remaining;
return NT_STATUS_ACCESS_DENIED;
}

View File

@ -113,16 +113,11 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname)
* having the DELETE bit on the file itself and second if that does
* not help, by the DELETE_CHILD bit on the containing directory.
*
* Here we check the other way round because with just posix
* permissions looking at the file itself will never grant DELETE, so
* by looking at the directory first we save one get_acl call.
* Here we only check the directory permissions, we will
* check the file DELETE permission separately.
*/
if (can_access_file_acl(conn, dname, FILE_DELETE_CHILD)) {
return true;
}
return can_access_file_acl(conn, fname, DELETE_ACCESS);
return can_access_file_acl(conn, dname, FILE_DELETE_CHILD);
}
/****************************************************************************

View File

@ -67,13 +67,15 @@ NTSTATUS smb1_file_se_access_check(const struct security_descriptor *sd,
static NTSTATUS check_open_rights(struct connection_struct *conn,
const char *fname,
uint32_t access_mask)
uint32_t access_mask,
uint32_t *access_granted)
{
/* Check if we have rights to open. */
NTSTATUS status;
uint32_t access_granted = 0;
struct security_descriptor *sd;
*access_granted = 0;
status = SMB_VFS_GET_NT_ACL(conn, fname,
(OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
@ -90,9 +92,17 @@ static NTSTATUS check_open_rights(struct connection_struct *conn,
status = smb1_file_se_access_check(sd,
conn->server_info->ptok,
access_mask,
&access_granted);
access_granted);
TALLOC_FREE(sd);
DEBUG(10,("check_open_rights: file %s requesting "
"0x%x returning 0x%x (%s)\n",
fname,
(unsigned int)access_mask,
(unsigned int)*access_granted,
nt_errstr(status) ));
return status;
}
@ -415,14 +425,35 @@ static NTSTATUS open_file(files_struct *fsp,
} else {
fsp->fh->fd = -1; /* What we used to call a stat open. */
if (file_existed) {
uint32_t access_granted = 0;
status = check_open_rights(conn,
path,
access_mask);
access_mask,
&access_granted);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("open_file: Access denied on "
"file %s\n",
path));
return status;
/* Were we trying to do a stat open
* for delete and didn't get DELETE
* access (only) ? Check if the
* directory allows DELETE_CHILD.
* See here:
* http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx
* for details. */
if (!(NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
(access_mask & DELETE_ACCESS) &&
(access_granted == DELETE_ACCESS) &&
can_delete_file_in_directory(conn, path))) {
DEBUG(10, ("open_file: Access denied on "
"file %s\n",
path));
return status;
}
DEBUG(10,("open_file: overrode ACCESS_DENIED "
"on file %s\n",
path ));
}
}
}
@ -2395,9 +2426,11 @@ static NTSTATUS open_directory(connection_struct *conn,
}
if (info == FILE_WAS_OPENED) {
uint32_t access_granted = 0;
status = check_open_rights(conn,
fname,
access_mask);
access_mask,
&access_granted);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("open_directory: check_open_rights on "
"file %s failed with %s\n",
@ -2826,8 +2859,11 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
&& (create_disposition != FILE_CREATE)
&& (share_access & FILE_SHARE_DELETE)
&& (access_mask & DELETE_ACCESS)
&& (!can_delete_file_in_directory(conn, fname))) {
&& (!(can_delete_file_in_directory(conn, fname) ||
can_access_file_acl(conn, fname, DELETE_ACCESS)))) {
status = NT_STATUS_ACCESS_DENIED;
DEBUG(10,("create_file_unixpath: open file %s "
"for delete ACCESS_DENIED\n", fname ));
goto fail;
}