diff options
-rw-r--r-- | source3/smbd/open.c | 126 |
1 files changed, 83 insertions, 43 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dde1d0dd4b..b134e8f0fd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1126,6 +1126,65 @@ static void schedule_defer_open(struct share_mode_lock *lck, } /**************************************************************************** + Work out what access_mask to use from what the client sent us. +****************************************************************************/ + +static NTSTATUS calculate_access_mask(connection_struct *conn, + const char *fname, + bool file_existed, + uint32_t access_mask, + uint32_t *access_mask_out) +{ + NTSTATUS status; + + /* + * Convert GENERIC bits to specific bits. + */ + + se_map_generic(&access_mask, &file_generic_mapping); + + /* Calculate MAXIMUM_ALLOWED_ACCESS if requested. */ + if (access_mask & MAXIMUM_ALLOWED_ACCESS) { + if (file_existed) { + struct security_descriptor *sd; + uint32_t access_granted = 0; + + 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, ("calculate_access_mask: Could not get acl " + "on file %s: %s\n", + fname, + nt_errstr(status))); + return NT_STATUS_ACCESS_DENIED; + } + + status = se_access_check(sd, conn->server_info->ptok, + access_mask, &access_granted); + + TALLOC_FREE(sd); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("calculate_access_mask: Access denied on " + "file %s: when calculating maximum access\n", + fname)); + return NT_STATUS_ACCESS_DENIED; + } + + access_mask = access_granted; + } else { + access_mask = FILE_GENERIC_ALL; + } + } + + *access_mask_out = access_mask; + return NT_STATUS_OK; +} + +/**************************************************************************** Open a file with a share mode. ****************************************************************************/ @@ -1361,47 +1420,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } } - /* - * Convert GENERIC bits to specific bits. - */ - - se_map_generic(&access_mask, &file_generic_mapping); - - /* Calculate MAXIMUM_ALLOWED_ACCESS if requested. */ - if (access_mask & MAXIMUM_ALLOWED_ACCESS) { - if (file_existed) { - struct security_descriptor *sd; - uint32_t access_granted = 0; - - 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, ("open_file_ntcreate: Could not get acl " - "on file %s: %s\n", - fname, - nt_errstr(status))); - return NT_STATUS_ACCESS_DENIED; - } - - status = se_access_check(sd, conn->server_info->ptok, - access_mask, &access_granted); - - TALLOC_FREE(sd); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("open_file_ntcreate: Access denied on " - "file %s: when calculating maximum access\n", - fname)); - return NT_STATUS_ACCESS_DENIED; - } - - access_mask = access_granted; - } else { - access_mask = FILE_GENERIC_ALL; - } + status = calculate_access_mask(conn, fname, file_existed, + access_mask, + &access_mask); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_file_ntcreate: calculate_access_mask " + "on file %s returned %s\n", + fname, + nt_errstr(status))); + return status; } open_access_mask = access_mask; @@ -2162,6 +2189,17 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_NOT_A_DIRECTORY; } + status = calculate_access_mask(conn, fname, dir_existed, + access_mask, + &access_mask); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_directory: calculate_access_mask " + "on file %s returned %s\n", + fname, + nt_errstr(status))); + return status; + } + switch( create_disposition ) { case FILE_OPEN: @@ -2255,8 +2293,10 @@ NTSTATUS open_directory(connection_struct *conn, fsp->share_access = share_access; fsp->fh->private_options = create_options; - fsp->access_mask = access_mask; - + /* + * According to Samba4, SEC_FILE_READ_ATTRIBUTE is always granted, + */ + fsp->access_mask = access_mask | FILE_READ_ATTRIBUTES; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; |