From 7d899b5e7b7cd26d33fb1e9c9c8a63efabc4b093 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 26 Oct 2007 19:50:55 +0200 Subject: Move some access check functions that are not posix-acl specific to a new source file of their own. Michael (This used to be commit 9dd18bb534bca6b5de6cad9580b48681b36c0832) --- source3/smbd/posix_acls.c | 212 ---------------------------------------------- 1 file changed, 212 deletions(-) (limited to 'source3/smbd/posix_acls.c') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c29d56f524..6e7dae4892 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4125,218 +4125,6 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * return True; } -/**************************************************************************** - Helper function that gets a security descriptor by connection and - file name. - NOTE: This is transitional, in the sense that SMB_VFS_GET_NT_ACL really - should *not* get a files_struct pointer but a connection_struct ptr - (automatic by the vfs handle) and the file name and _use_ that! -****************************************************************************/ -static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, - struct connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - struct security_descriptor **psd) -{ - NTSTATUS status; - struct files_struct *fsp = NULL; - struct security_descriptor *secdesc = NULL; - size_t secdesc_size; - - if (!VALID_STAT(*psbuf)) { - if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { - return map_nt_error_from_unix(errno); - } - } - - /* fake a files_struct ptr: */ - - status = open_file_stat(conn, NULL, fname, psbuf, &fsp); - /* Perhaps it is a directory */ - if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { - status = open_directory(conn, NULL, fname, psbuf, - READ_CONTROL_ACCESS, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_DIRECTORY, - NULL, &fsp); - } - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Unable to open file %s: %s\n", fname, - nt_errstr(status))); - return status; - } - - secdesc_size = SMB_VFS_GET_NT_ACL(fsp, fname, - (OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION), - &secdesc); - if (secdesc_size == 0) { - DEBUG(5, ("Unable to get NT ACL for file %s\n", fname)); - return NT_STATUS_ACCESS_DENIED; - } - - *psd = talloc_move(mem_ctx, &secdesc); - close_file(fsp, NORMAL_CLOSE); - return NT_STATUS_OK; -} - -static bool can_access_file_acl(struct connection_struct *conn, - const char * fname, SMB_STRUCT_STAT *psbuf, - uint32_t access_mask) -{ - bool result; - NTSTATUS status; - uint32_t access_granted; - struct security_descriptor *secdesc = NULL; - - status = conn_get_nt_acl(talloc_tos(), conn, fname, psbuf, &secdesc); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status))); - return false; - } - - result = se_access_check(secdesc, current_user.nt_user_token, - access_mask, &access_granted, &status); - TALLOC_FREE(secdesc); - return result; -} - -/**************************************************************************** - Actually emulate the in-kernel access checking for delete access. We need - this to successfully return ACCESS_DENIED on a file open for delete access. -****************************************************************************/ - -bool can_delete_file_in_directory(connection_struct *conn, const char *fname) -{ - SMB_STRUCT_STAT sbuf; - TALLOC_CTX *ctx = talloc_tos(); - char *dname = NULL; - - if (!CAN_WRITE(conn)) { - return False; - } - - /* Get the parent directory permission mask and owners. */ - if (!parent_dirname_talloc(ctx, - fname, - &dname, - NULL)) { - return False; - } - if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) { - return False; - } - - /* fast paths first */ - - if (!S_ISDIR(sbuf.st_mode)) { - return False; - } - if (current_user.ut.uid == 0 || conn->admin_user) { - /* I'm sorry sir, I didn't know you were root... */ - return True; - } - - /* Check primary owner write access. */ - if (current_user.ut.uid == sbuf.st_uid) { - return (sbuf.st_mode & S_IWUSR) ? True : False; - } - -#ifdef S_ISVTX - /* sticky bit means delete only by owner or root. */ - if (sbuf.st_mode & S_ISVTX) { - SMB_STRUCT_STAT sbuf_file; - if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { - if (errno == ENOENT) { - /* If the file doesn't already exist then - * yes we'll be able to delete it. */ - return True; - } - return False; - } - /* - * Patch from SATOH Fumiyasu - * for bug #3348. Don't assume owning sticky bit - * directory means write access allowed. - */ - if (current_user.ut.uid != sbuf_file.st_uid) { - return False; - } - } -#endif - - /* now for ACL checks */ - - return can_access_file_acl(conn, dname, &sbuf, FILE_WRITE_DATA); -} - -/**************************************************************************** - Actually emulate the in-kernel access checking for read/write access. We need - this to successfully check for ability to write for dos filetimes. - Note this doesn't take into account share write permissions. -****************************************************************************/ - -bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) -{ - if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) { - return False; - } - access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA); - - /* some fast paths first */ - - DEBUG(10,("can_access_file: requesting 0x%x on file %s\n", - (unsigned int)access_mask, fname )); - - if (current_user.ut.uid == 0 || conn->admin_user) { - /* I'm sorry sir, I didn't know you were root... */ - return True; - } - - if (!VALID_STAT(*psbuf)) { - /* Get the file permission mask and owners. */ - if(SMB_VFS_STAT(conn, fname, psbuf) != 0) { - return False; - } - } - - /* Check primary owner access. */ - if (current_user.ut.uid == psbuf->st_uid) { - switch (access_mask) { - case FILE_READ_DATA: - return (psbuf->st_mode & S_IRUSR) ? True : False; - - case FILE_WRITE_DATA: - return (psbuf->st_mode & S_IWUSR) ? True : False; - - default: /* FILE_READ_DATA|FILE_WRITE_DATA */ - - if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) { - return True; - } else { - return False; - } - } - } - - /* now for ACL checks */ - - return can_access_file_acl(conn, fname, psbuf, access_mask); -} - -/**************************************************************************** - Userspace check for write access. - Note this doesn't take into account share write permissions. -****************************************************************************/ - -bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) -{ - return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA); -} - /******************************************************************** Pull the NT ACL from a file on disk or the OpenEventlog() access check. Caller is responsible for freeing the returned security -- cgit