diff options
-rw-r--r-- | source3/include/proto.h | 4 | ||||
-rw-r--r-- | source3/modules/vfs_acl_xattr.c | 2 | ||||
-rw-r--r-- | source3/smbd/open.c | 81 | ||||
-rw-r--r-- | source4/torture/raw/acls.c | 2 |
4 files changed, 85 insertions, 4 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 254c33d075..0d4404b339 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -8040,6 +8040,10 @@ void reply_nttranss(struct smb_request *req); /* The following definitions come from smbd/open.c */ +NTSTATUS smb1_file_se_access_check(const struct security_descriptor *sd, + const NT_USER_TOKEN *token, + uint32_t access_desired, + uint32_t *access_granted); NTSTATUS fd_close(files_struct *fsp); bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, uint32 *paccess_mask, diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index c3b27f81a5..5dfe43e55b 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -437,7 +437,7 @@ static int open_acl_xattr(vfs_handle_struct *handle, &pdesc); if (NT_STATUS_IS_OK(status)) { /* See if we can access it. */ - status = se_access_check(pdesc, + status = smb1_file_se_access_check(pdesc, handle->conn->server_info->ptok, fsp->access_mask, &access_granted); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b134e8f0fd..480352beda 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,6 +30,56 @@ struct deferred_open_record { }; /**************************************************************************** + SMB1 file varient of se_access_check. Never test FILE_READ_ATTRIBUTES. +****************************************************************************/ + +NTSTATUS smb1_file_se_access_check(const struct security_descriptor *sd, + const NT_USER_TOKEN *token, + uint32_t access_desired, + uint32_t *access_granted) +{ + return se_access_check(sd, + token, + (access_desired & ~FILE_READ_ATTRIBUTES), + access_granted); +} + +/**************************************************************************** + Check if we have open rights. +****************************************************************************/ + +static NTSTATUS check_open_rights(struct connection_struct *conn, + const char *fname, + uint32_t access_mask) +{ + /* Check if we have rights to open. */ + NTSTATUS status; + uint32_t access_granted = 0; + struct security_descriptor *sd; + + status = SMB_VFS_GET_NT_ACL(conn, fname, + (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION),&sd); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("check_open_rights: Could not get acl " + "on %s: %s\n", + fname, + nt_errstr(status))); + return status; + } + + status = smb1_file_se_access_check(sd, + conn->server_info->ptok, + access_mask, + &access_granted); + + TALLOC_FREE(sd); + return status; +} + +/**************************************************************************** fd support routines - attempt to do a dos_open. ****************************************************************************/ @@ -337,6 +387,17 @@ static NTSTATUS open_file(files_struct *fsp, } else { fsp->fh->fd = -1; /* What we used to call a stat open. */ + if (file_existed) { + status = check_open_rights(conn, + path, + access_mask); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_file: Access denied on " + "file %s\n", + path)); + return status; + } + } } if (!file_existed) { @@ -1146,6 +1207,7 @@ static NTSTATUS calculate_access_mask(connection_struct *conn, /* Calculate MAXIMUM_ALLOWED_ACCESS if requested. */ if (access_mask & MAXIMUM_ALLOWED_ACCESS) { if (file_existed) { + struct security_descriptor *sd; uint32_t access_granted = 0; @@ -1162,8 +1224,10 @@ static NTSTATUS calculate_access_mask(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } - status = se_access_check(sd, conn->server_info->ptok, - access_mask, &access_granted); + status = smb1_file_se_access_check(sd, + conn->server_info->ptok, + access_mask, + &access_granted); TALLOC_FREE(sd); @@ -2274,6 +2338,19 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_NOT_A_DIRECTORY; } + if (info == FILE_WAS_OPENED) { + status = check_open_rights(conn, + fname, + access_mask); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_directory: check_open_rights on " + "file %s failed with %s\n", + fname, + nt_errstr(status))); + return status; + } + } + status = file_new(req, conn, &fsp); if(!NT_STATUS_IS_OK(status)) { return status; diff --git a/source4/torture/raw/acls.c b/source4/torture/raw/acls.c index 2a67bd98c5..862b96ac17 100644 --- a/source4/torture/raw/acls.c +++ b/source4/torture/raw/acls.c @@ -1088,7 +1088,7 @@ static bool test_owner_bits(struct torture_context *tctx, { NTSTATUS status; union smb_open io; - const char *fname = BASEDIR "\\generic.txt"; + const char *fname = BASEDIR "\\test_owner_bits.txt"; bool ret = true; int fnum = -1, i; union smb_fileinfo q; |