summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/proto.h4
-rw-r--r--source3/smbd/reply.c7
-rw-r--r--source3/smbd/trans2.c56
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;
}
/*