1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

smbd: fix check_any_access_fsp() for non-fsa fsps

smbd_check_access_rights_fsp() requires *all* rights in access_mask to
be granted by the underlying ACL, but the semantics of this function
is supposed to grant access if any one of the rights in
access_requested is allowed.

Fix this by looping over the requested access mask. If
smbd_check_access_rights_fsp() returns sucess, mask will be non-null
and when assigned to access_granted, the subsequent check will pass,
fail otherwise.

I'm not doing an early exit on purpose because a subsequent commit
adds additional security checks that are done in the subsequent code
path common for fsa and non-fsa fsps.

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>
This commit is contained in:
Ralph Boehme 2023-12-21 10:58:09 +01:00
parent 96b577c380
commit bf497819e6
2 changed files with 30 additions and 10 deletions

View File

@ -1061,7 +1061,7 @@ NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
struct smb_filename *smb_fname);
NTSTATUS refuse_symlink_fsp(const struct files_struct *fsp);
NTSTATUS check_any_access_fsp(struct files_struct *fsp,
uint32_t access_mask);
uint32_t access_requested);
uint64_t smb_roundup(connection_struct *conn, uint64_t val);
bool samba_private_attr_name(const char *unix_ea_name);
NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,

View File

@ -75,20 +75,40 @@ NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
}
/**
* Check that one or more of the rights in access_mask are
* allowed. Iow, access_mask can contain more then one right and
* Check that one or more of the rights in access mask are
* allowed. Iow, access_requested can contain more then one right and
* it is sufficient having only one of those granted to pass.
**/
NTSTATUS check_any_access_fsp(struct files_struct *fsp,
uint32_t access_mask)
uint32_t access_requested)
{
if (!fsp->fsp_flags.is_fsa) {
return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
fsp,
false,
access_mask);
uint32_t access_granted = 0;
NTSTATUS status;
if (fsp->fsp_flags.is_fsa) {
access_granted = fsp->access_mask;
} else {
uint32_t mask = 1;
while (mask != 0) {
if (!(mask & access_requested)) {
mask <<= 1;
continue;
}
status = smbd_check_access_rights_fsp(
fsp->conn->cwd_fsp,
fsp,
false,
mask);
if (NT_STATUS_IS_OK(status)) {
break;
}
mask <<= 1;
}
access_granted = mask;
}
if (!(fsp->access_mask & access_mask)) {
if ((access_granted & access_requested) == 0) {
return NT_STATUS_ACCESS_DENIED;
}
return NT_STATUS_OK;