mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
smbd: move access override for previous versions to the SMB layer
Doing the previous version access checks and semantics at the SMB layer means we can simplify the shadow_copy2 and remove the kludge. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13688 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org> Autobuild-User(master): Ralph Böhme <slow@samba.org> Autobuild-Date(master): Mon Jan 8 16:58:26 UTC 2024 on atb-devel-224
This commit is contained in:
parent
fd4e41144a
commit
f14a706569
@ -1556,7 +1556,6 @@ static int shadow_copy2_openat(vfs_handle_struct *handle,
|
|||||||
struct smb_filename *smb_fname = NULL;
|
struct smb_filename *smb_fname = NULL;
|
||||||
time_t timestamp = 0;
|
time_t timestamp = 0;
|
||||||
char *stripped = NULL;
|
char *stripped = NULL;
|
||||||
bool is_converted = false;
|
|
||||||
int saved_errno = 0;
|
int saved_errno = 0;
|
||||||
int ret;
|
int ret;
|
||||||
bool ok;
|
bool ok;
|
||||||
@ -1573,12 +1572,11 @@ static int shadow_copy2_openat(vfs_handle_struct *handle,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = shadow_copy2_strip_snapshot_converted(talloc_tos(),
|
ok = shadow_copy2_strip_snapshot(talloc_tos(),
|
||||||
handle,
|
handle,
|
||||||
smb_fname,
|
smb_fname,
|
||||||
×tamp,
|
×tamp,
|
||||||
&stripped,
|
&stripped);
|
||||||
&is_converted);
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
TALLOC_FREE(smb_fname);
|
TALLOC_FREE(smb_fname);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1586,16 +1584,6 @@ static int shadow_copy2_openat(vfs_handle_struct *handle,
|
|||||||
if (timestamp == 0) {
|
if (timestamp == 0) {
|
||||||
TALLOC_FREE(stripped);
|
TALLOC_FREE(stripped);
|
||||||
TALLOC_FREE(smb_fname);
|
TALLOC_FREE(smb_fname);
|
||||||
if (is_converted) {
|
|
||||||
/*
|
|
||||||
* Just pave over the user requested mode and use
|
|
||||||
* O_RDONLY. Later attempts by the client to write on
|
|
||||||
* the handle will fail in the pwrite() syscall with
|
|
||||||
* EINVAL which we carefully map to EROFS. In sum, this
|
|
||||||
* matches Windows behaviour.
|
|
||||||
*/
|
|
||||||
how.flags &= ~(O_WRONLY | O_RDWR | O_CREAT);
|
|
||||||
}
|
|
||||||
return SMB_VFS_NEXT_OPENAT(handle,
|
return SMB_VFS_NEXT_OPENAT(handle,
|
||||||
dirfsp,
|
dirfsp,
|
||||||
smb_fname_in,
|
smb_fname_in,
|
||||||
@ -1616,14 +1604,6 @@ static int shadow_copy2_openat(vfs_handle_struct *handle,
|
|||||||
}
|
}
|
||||||
TALLOC_FREE(stripped);
|
TALLOC_FREE(stripped);
|
||||||
|
|
||||||
/*
|
|
||||||
* Just pave over the user requested mode and use O_RDONLY. Later
|
|
||||||
* attempts by the client to write on the handle will fail in the
|
|
||||||
* pwrite() syscall with EINVAL which we carefully map to EROFS. In sum,
|
|
||||||
* this matches Windows behaviour.
|
|
||||||
*/
|
|
||||||
how.flags &= ~(O_WRONLY | O_RDWR | O_CREAT);
|
|
||||||
|
|
||||||
ret = SMB_VFS_NEXT_OPENAT(handle,
|
ret = SMB_VFS_NEXT_OPENAT(handle,
|
||||||
dirfsp,
|
dirfsp,
|
||||||
smb_fname,
|
smb_fname,
|
||||||
|
@ -3629,7 +3629,8 @@ static int disposition_to_open_flags(uint32_t create_disposition)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int calculate_open_access_flags(uint32_t access_mask,
|
static int calculate_open_access_flags(uint32_t access_mask,
|
||||||
uint32_t private_flags)
|
uint32_t private_flags,
|
||||||
|
NTTIME twrp)
|
||||||
{
|
{
|
||||||
bool need_write, need_read;
|
bool need_write, need_read;
|
||||||
|
|
||||||
@ -3638,6 +3639,15 @@ static int calculate_open_access_flags(uint32_t access_mask,
|
|||||||
* mean the same thing under DOS and Unix.
|
* mean the same thing under DOS and Unix.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (twrp != 0) {
|
||||||
|
/*
|
||||||
|
* Pave over the user requested mode and force O_RDONLY for the
|
||||||
|
* file handle. Windows allows opening a VSS file with O_RDWR,
|
||||||
|
* even though actual writes on the handle will fail.
|
||||||
|
*/
|
||||||
|
return O_RDONLY;
|
||||||
|
}
|
||||||
|
|
||||||
need_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA));
|
need_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA));
|
||||||
if (!need_write) {
|
if (!need_write) {
|
||||||
return O_RDONLY;
|
return O_RDONLY;
|
||||||
@ -3803,6 +3813,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
|
|||||||
bool posix_open = False;
|
bool posix_open = False;
|
||||||
bool new_file_created = False;
|
bool new_file_created = False;
|
||||||
bool first_open_attempt = true;
|
bool first_open_attempt = true;
|
||||||
|
bool is_twrp = (smb_fname_atname->twrp != 0);
|
||||||
NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
|
NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
|
||||||
mode_t new_unx_mode = (mode_t)0;
|
mode_t new_unx_mode = (mode_t)0;
|
||||||
mode_t unx_mode = (mode_t)0;
|
mode_t unx_mode = (mode_t)0;
|
||||||
@ -3962,6 +3973,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
|
|||||||
smb_fname_str_dbg(smb_fname) ));
|
smb_fname_str_dbg(smb_fname) ));
|
||||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
if (is_twrp) {
|
||||||
|
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_CREATE:
|
case FILE_CREATE:
|
||||||
@ -3977,11 +3991,24 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
|
|||||||
}
|
}
|
||||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||||
}
|
}
|
||||||
|
if (is_twrp) {
|
||||||
|
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_SUPERSEDE:
|
case FILE_SUPERSEDE:
|
||||||
case FILE_OVERWRITE_IF:
|
case FILE_OVERWRITE_IF:
|
||||||
|
if (is_twrp) {
|
||||||
|
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case FILE_OPEN_IF:
|
case FILE_OPEN_IF:
|
||||||
|
if (is_twrp) {
|
||||||
|
if (!file_existed) {
|
||||||
|
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
|
create_disposition = FILE_OPEN;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return NT_STATUS_INVALID_PARAMETER;
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
@ -4054,7 +4081,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
|
|||||||
* mean the same thing under DOS and Unix.
|
* mean the same thing under DOS and Unix.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags |= calculate_open_access_flags(access_mask, private_flags);
|
flags |= calculate_open_access_flags(access_mask,
|
||||||
|
private_flags,
|
||||||
|
smb_fname->twrp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Currently we only look at FILE_WRITE_THROUGH for create options.
|
* Currently we only look at FILE_WRITE_THROUGH for create options.
|
||||||
@ -4785,6 +4814,10 @@ static NTSTATUS open_directory(connection_struct *conn,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (smb_fname_atname->twrp != 0) {
|
||||||
|
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
|
|
||||||
status = mkdir_internal(conn,
|
status = mkdir_internal(conn,
|
||||||
parent_dir_fname,
|
parent_dir_fname,
|
||||||
smb_fname_atname,
|
smb_fname_atname,
|
||||||
@ -4813,6 +4846,9 @@ static NTSTATUS open_directory(connection_struct *conn,
|
|||||||
status = NT_STATUS_OK;
|
status = NT_STATUS_OK;
|
||||||
info = FILE_WAS_OPENED;
|
info = FILE_WAS_OPENED;
|
||||||
} else {
|
} else {
|
||||||
|
if (smb_fname_atname->twrp != 0) {
|
||||||
|
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
status = mkdir_internal(conn,
|
status = mkdir_internal(conn,
|
||||||
parent_dir_fname,
|
parent_dir_fname,
|
||||||
smb_fname_atname,
|
smb_fname_atname,
|
||||||
|
Loading…
Reference in New Issue
Block a user