Make smbd_check_open_rights() static.
[kai/samba.git] / source3 / smbd / open.c
index 1e21799868e5a61f9d0d53225d68329ee78694f1..976bb6fdb407b03a7568db7b831de752632c8a64 100644 (file)
@@ -68,7 +68,7 @@ NTSTATUS smb1_file_se_access_check(struct connection_struct *conn,
  Check if we have open rights.
 ****************************************************************************/
 
-NTSTATUS smbd_check_open_rights(struct 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)
@@ -191,6 +191,25 @@ static NTSTATUS check_parent_access(struct connection_struct *conn,
        return NT_STATUS_OK;
 }
 
+/****************************************************************************
+ If the requester wanted DELETE_ACCESS and was only rejected because
+ the file ACL didn't include DELETE_ACCESS, see if the parent ACL
+ ovverrides this.
+****************************************************************************/
+
+static bool parent_override_delete(connection_struct *conn,
+                                       struct smb_filename *smb_fname,
+                                       uint32_t access_mask,
+                                       uint32_t rejected_mask)
+{
+       if ((access_mask & DELETE_ACCESS) &&
+                   (rejected_mask == DELETE_ACCESS) &&
+                   can_delete_file_in_directory(conn, smb_fname)) {
+               return true;
+       }
+       return false;
+}
+
 /****************************************************************************
  fd support routines - attempt to do a dos_open.
 ****************************************************************************/
@@ -560,87 +579,90 @@ 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) {
-                       uint32_t access_granted = 0;
+               if (!file_existed) {
+                       /* File must exist for a stat open. */
+                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               }
 
-                       status = smbd_check_open_rights(conn,
-                                       smb_fname,
-                                       access_mask,
-                                       &access_granted);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               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)));
-                                       }
+               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 & DELETE_ACCESS) &&
-                                           (access_granted & DELETE_ACCESS) &&
-                                           can_delete_file_in_directory(conn,
-                                               smb_fname)) {
-                                               /* 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_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)));
+                       }
 
-                                       if (access_granted != 0) {
-                                               DEBUG(10,("open_file: Access "
-                                                         "denied on file "
-                                                         "%s\n",
-                                                         smb_fname_str_dbg(
-                                                                 smb_fname)));
-                                               return status;
-                                       }
-                               } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
+                       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)) {
-                                       /* 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 {
-                                       DEBUG(10,("open_file: "
-                                                 "smbd_check_open_rights on file "
-                                                 "%s returned %s\n",
-                                                 smb_fname_str_dbg(smb_fname),
-                                                 nt_errstr(status) ));
-                                       return status;
-                               }
-                       }
+                       /* 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)) {
+                       DEBUG(10,("open_file: "
+                                 "smbd_check_open_rights on file "
+                                 "%s returned %s\n",
+                                 smb_fname_str_dbg(smb_fname),
+                                 nt_errstr(status) ));
+                       return status;
                }
        }
 
@@ -2787,10 +2809,11 @@ static NTSTATUS open_directory(connection_struct *conn,
                 * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx
                 * for details. */
 
-               if ((NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
-                       (access_mask & DELETE_ACCESS) &&
-                       (access_granted == DELETE_ACCESS) &&
-                       can_delete_file_in_directory(conn, smb_dname))) {
+               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)));