diff options
Diffstat (limited to 'source/smbd/dir.c')
-rw-r--r-- | source/smbd/dir.c | 76 |
1 files changed, 72 insertions, 4 deletions
diff --git a/source/smbd/dir.c b/source/smbd/dir.c index c2735c032a..604db984af 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -24,6 +24,8 @@ This module implements directory related functions for Samba. */ +extern struct current_user current_user; + /* "Special" directory offsets. */ #define END_OF_DIRECTORY_OFFSET ((long)-1) #define START_OF_DIRECTORY_OFFSET ((long)0) @@ -921,8 +923,13 @@ bool get_dir_entry(TALLOC_CTX *ctx, use it for anything security sensitive. ********************************************************************/ -static bool user_can_read_file(connection_struct *conn, char *name) +static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { + SEC_DESC *psd = NULL; + files_struct *fsp; + NTSTATUS status; + uint32 access_granted; + /* * If user is a member of the Admin group * we never hide files from them. @@ -932,7 +939,38 @@ static bool user_can_read_file(connection_struct *conn, char *name) return True; } - return can_access_file_acl(conn, name, FILE_READ_DATA); + SMB_ASSERT(VALID_STAT(*pst)); + + /* Pseudo-open the file (note - no fd's created). */ + + if(S_ISDIR(pst->st_mode)) { + status = open_directory(conn, NULL, name, pst, + READ_CONTROL_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, /* no create options. */ + FILE_ATTRIBUTE_DIRECTORY, + NULL, &fsp); + } else { + status = open_file_stat(conn, NULL, name, pst, &fsp); + } + + if (!NT_STATUS_IS_OK(status)) { + return False; + } + + /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ + status = SMB_VFS_FGET_NT_ACL(fsp, + (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); + close_file(fsp, NORMAL_CLOSE); + + /* No access if SD get failed. */ + if (!NT_STATUS_IS_OK(status)) { + return False; + } + + return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA, + &access_granted, &status); } /******************************************************************* @@ -944,6 +982,12 @@ static bool user_can_read_file(connection_struct *conn, char *name) static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { + SEC_DESC *psd = NULL; + files_struct *fsp; + int info; + NTSTATUS status; + uint32 access_granted; + /* * If user is a member of the Admin group * we never hide files from them. @@ -959,9 +1003,33 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ if(S_ISDIR(pst->st_mode)) { return True; + } else { + status = open_file_ntcreate(conn, NULL, name, pst, + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + INTERNAL_OPEN_ONLY, + &info, &fsp); + } + + if (!NT_STATUS_IS_OK(status)) { + return False; + } + + /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ + status = SMB_VFS_FGET_NT_ACL(fsp, + (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); + close_file(fsp, NORMAL_CLOSE); + + /* No access if SD get failed. */ + if (!NT_STATUS_IS_OK(status)) { + return False; } - return can_write_to_file(conn, name, pst); + return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA, + &access_granted, &status); } /******************************************************************* @@ -1035,7 +1103,7 @@ bool is_visible_file(connection_struct *conn, const char *dir_path, const char * } /* Honour _hide unreadable_ option */ - if (hide_unreadable && !user_can_read_file(conn, entry)) { + if (hide_unreadable && !user_can_read_file(conn, entry, pst)) { DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry )); SAFE_FREE(entry); return False; |