From 8a3070a7c9fe3fad35103435c5c74188866057eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Oct 2011 14:58:32 -0700 Subject: [PATCH] Simplify smbd_check_open_rights() and move all the special casing inside it. --- source3/smbd/open.c | 173 ++++++++++++++++++-------------------------- 1 file changed, 72 insertions(+), 101 deletions(-) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4d70603f53e..973a5d2b472 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -88,29 +88,31 @@ static bool parent_override_delete(connection_struct *conn, ****************************************************************************/ static NTSTATUS smbd_check_open_rights(struct connection_struct *conn, - const struct smb_filename *smb_fname, - uint32_t access_mask, - uint32_t *access_granted) + struct smb_filename *smb_fname, + uint32_t access_mask) { /* Check if we have rights to open. */ NTSTATUS status; struct security_descriptor *sd = NULL; uint32_t rejected_share_access; + uint32_t rejected_mask = 0; rejected_share_access = access_mask & ~(conn->share_access); if (rejected_share_access) { - *access_granted = rejected_share_access; + DEBUG(10, ("smbd_check_open_rights: rejected share access 0x%x " + "on %s (0x%x)\n", + (unsigned int)access_mask, + smb_fname_str_dbg(smb_fname), + (unsigned int)rejected_share_access )); return NT_STATUS_ACCESS_DENIED; } if ((access_mask & DELETE_ACCESS) && !lp_acl_check_permissions(SNUM(conn))) { - *access_granted = access_mask; - DEBUG(10,("smbd_check_open_rights: not checking ACL " "on DELETE_ACCESS on file %s. Granting 0x%x\n", smb_fname_str_dbg(smb_fname), - (unsigned int)*access_granted )); + (unsigned int)access_mask )); return NT_STATUS_OK; } @@ -131,13 +133,13 @@ static NTSTATUS smbd_check_open_rights(struct connection_struct *conn, sd, get_current_nttok(conn), access_mask, - access_granted); + &rejected_mask); DEBUG(10,("smbd_check_open_rights: file %s requesting " "0x%x returning 0x%x (%s)\n", smb_fname_str_dbg(smb_fname), (unsigned int)access_mask, - (unsigned int)*access_granted, + (unsigned int)rejected_mask, nt_errstr(status) )); if (!NT_STATUS_IS_OK(status)) { @@ -150,7 +152,53 @@ static NTSTATUS smbd_check_open_rights(struct connection_struct *conn, TALLOC_FREE(sd); - return status; + if (NT_STATUS_IS_OK(status) || + !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + return status; + } + + /* Here we know status == NT_STATUS_ACCESS_DENIED. */ + if ((access_mask & FILE_WRITE_ATTRIBUTES) && + (rejected_mask & FILE_WRITE_ATTRIBUTES) && + (lp_map_readonly(SNUM(conn)) || + lp_map_archive(SNUM(conn)) || + lp_map_hidden(SNUM(conn)) || + lp_map_system(SNUM(conn)))) { + rejected_mask &= ~FILE_WRITE_ATTRIBUTES; + + DEBUG(10,("smbd_check_open_rights: " + "overrode " + "FILE_WRITE_ATTRIBUTES " + "on file %s\n", + smb_fname_str_dbg(smb_fname))); + } + + if (parent_override_delete(conn, + smb_fname, + access_mask, + rejected_mask)) { + /* Were we trying to do an open + * for delete and didn't get DELETE + * access (only) ? Check if the + * directory allows DELETE_CHILD. + * See here: + * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx + * for details. */ + + rejected_mask &= ~DELETE_ACCESS; + + DEBUG(10,("smbd_check_open_rights: " + "overrode " + "DELETE_ACCESS on " + "file %s\n", + smb_fname_str_dbg(smb_fname))); + } + + if (rejected_mask != 0) { + return NT_STATUS_ACCESS_DENIED; + } else { + return NT_STATUS_OK; + } } static NTSTATUS check_parent_access(struct connection_struct *conn, @@ -579,8 +627,6 @@ static NTSTATUS open_file(files_struct *fsp, } } else { - uint32_t access_granted = 0; - fsp->fh->fd = -1; /* What we used to call a stat open. */ if (!file_existed) { /* File must exist for a stat open. */ @@ -589,79 +635,26 @@ static NTSTATUS open_file(files_struct *fsp, status = smbd_check_open_rights(conn, smb_fname, - access_mask, - &access_granted); - if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { - /* - * On NT_STATUS_ACCESS_DENIED, access_granted - * contains the denied bits. - */ - - if ((access_mask & FILE_WRITE_ATTRIBUTES) && - (access_granted & FILE_WRITE_ATTRIBUTES) && - (lp_map_readonly(SNUM(conn)) || - lp_map_archive(SNUM(conn)) || - lp_map_hidden(SNUM(conn)) || - lp_map_system(SNUM(conn)))) { - access_granted &= ~FILE_WRITE_ATTRIBUTES; - - DEBUG(10,("open_file: " - "overrode " - "FILE_WRITE_" - "ATTRIBUTES " - "on file %s\n", - smb_fname_str_dbg( - smb_fname))); - } + access_mask); - if (parent_override_delete(conn, - smb_fname, - access_mask, - access_granted)) { - /* Were we trying to do a stat open - * for delete and didn't get DELETE - * access (only) ? Check if the - * directory allows DELETE_CHILD. - * See here: - * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx - * for details. */ - - access_granted &= ~DELETE_ACCESS; - - DEBUG(10,("open_file: " - "overrode " - "DELETE_ACCESS on " - "file %s\n", - smb_fname_str_dbg( - smb_fname))); - } - - if (access_granted != 0) { - DEBUG(10,("open_file: Access " - "denied (0x%x) on file " - "%s\n", - access_granted, - smb_fname_str_dbg( - smb_fname))); - return status; - } - - } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) && - fsp->posix_open && - S_ISLNK(smb_fname->st.st_ex_mode)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) && + fsp->posix_open && + S_ISLNK(smb_fname->st.st_ex_mode)) { /* This is a POSIX stat open for delete * or rename on a symlink that points * nowhere. Allow. */ DEBUG(10,("open_file: allowing POSIX " "open on bad symlink %s\n", - smb_fname_str_dbg( - smb_fname))); - } else if (!NT_STATUS_IS_OK(status)) { + smb_fname_str_dbg(smb_fname))); + status = NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("open_file: " - "smbd_check_open_rights on file " - "%s returned %s\n", - smb_fname_str_dbg(smb_fname), - nt_errstr(status) )); + "smbd_check_open_rights on file " + "%s returned %s\n", + smb_fname_str_dbg(smb_fname), + nt_errstr(status) )); return status; } } @@ -2797,29 +2790,7 @@ static NTSTATUS open_directory(connection_struct *conn, } if (info == FILE_WAS_OPENED) { - uint32_t access_granted = 0; - status = smbd_check_open_rights(conn, smb_dname, access_mask, - &access_granted); - - /* Were we trying to do a directory open - * for delete and didn't get DELETE - * access (only) ? Check if the - * directory allows DELETE_CHILD. - * See here: - * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx - * for details. */ - - if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && - parent_override_delete(conn, - smb_dname, - access_mask, - access_granted)) { - DEBUG(10,("open_directory: overrode ACCESS_DENIED " - "on directory %s\n", - smb_fname_str_dbg(smb_dname))); - status = NT_STATUS_OK; - } - + status = smbd_check_open_rights(conn, smb_dname, access_mask); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("open_directory: smbd_check_open_rights on " "file %s failed with %s\n", -- 2.34.1