1
0
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:
Ralph Boehme 2023-12-15 11:59:36 +01:00
parent fd4e41144a
commit f14a706569
2 changed files with 43 additions and 27 deletions

View File

@ -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,
&timestamp, &timestamp,
&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,

View File

@ -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,