diff options
-rw-r--r-- | source3/smbd/proto.h | 4 | ||||
-rw-r--r-- | source3/smbd/reply.c | 7 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 56 |
3 files changed, 51 insertions, 16 deletions
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index fe9076647e..151ae78ec3 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -1059,6 +1059,10 @@ int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf); /* The following definitions come from smbd/trans2.c */ +NTSTATUS check_access(connection_struct *conn, + files_struct *fsp, + const struct smb_filename *smb_fname, + uint32_t access_mask); uint64_t smb_roundup(connection_struct *conn, uint64_t val); uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf); NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 18ebca1ce2..7dd3260f0b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1275,6 +1275,13 @@ void reply_setatr(struct smb_request *req) else mode &= ~FILE_ATTRIBUTE_DIRECTORY; + status = check_access(conn, NULL, smb_fname, + FILE_WRITE_ATTRIBUTES); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + if (file_set_dosmode(conn, smb_fname, mode, NULL, false) != 0) { reply_nterror(req, map_nt_error_from_unix(errno)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0e831ecff9..024979c200 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -50,6 +50,30 @@ static char *store_file_unix_basic_info2(connection_struct *conn, const SMB_STRUCT_STAT *psbuf); /******************************************************************** + The canonical "check access" based on object handle or path function. +********************************************************************/ + +NTSTATUS check_access(connection_struct *conn, + files_struct *fsp, + const struct smb_filename *smb_fname, + uint32_t access_mask) +{ + if (fsp) { + if (!(fsp->access_mask & access_mask)) { + return NT_STATUS_ACCESS_DENIED; + } + } else { + NTSTATUS status = smbd_check_access_rights(conn, + smb_fname, + access_mask); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + return NT_STATUS_OK; +} + +/******************************************************************** Roundup a value to the nearest allocation roundup size boundary. Only do this for Windows clients. ********************************************************************/ @@ -504,14 +528,16 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname, struct ea_list *ea_list) { + NTSTATUS status; char *fname = NULL; if (!lp_ea_support(SNUM(conn))) { return NT_STATUS_EAS_NOT_SUPPORTED; } - if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) { - return NT_STATUS_ACCESS_DENIED; + status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* For now setting EAs on streams isn't supported. */ @@ -5540,6 +5566,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn, /**************************************************************************** Deal with setting the dosmode from any of the setfilepathinfo functions. + NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been + done before calling this function. ****************************************************************************/ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, @@ -5724,10 +5752,6 @@ static NTSTATUS smb_info_set_ea(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) { - return NT_STATUS_ACCESS_DENIED; - } - status = set_ea(conn, fsp, smb_fname, ea_list); return status; @@ -5771,10 +5795,6 @@ static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - if (!(fsp->access_mask & FILE_WRITE_EA)) { - return NT_STATUS_ACCESS_DENIED; - } - status = set_ea(conn, fsp, fsp->fsp_name, ea_list); DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n", @@ -6514,8 +6534,9 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) { - return NT_STATUS_ACCESS_DENIED; + status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Set the attributes */ @@ -6554,6 +6575,7 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname) { + NTSTATUS status; struct smb_file_time ft; ZERO_STRUCT(ft); @@ -6572,8 +6594,9 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, DEBUG(10,("smb_set_info_standard: file %s\n", smb_fname_str_dbg(smb_fname))); - if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) { - return NT_STATUS_ACCESS_DENIED; + status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES); + if (!NT_STATUS_IS_OK(status)) { + return status; } return smb_set_file_time(conn, @@ -6946,8 +6969,9 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, } #endif - if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) { - return NT_STATUS_ACCESS_DENIED; + status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* |