smbd: Pass "file_id" explicitly to send_break_message()
[samba.git] / source3 / smbd / open.c
index e55c394109204ba1147a2fc116954fffbd324725..be9e601bb1518dc07babdbcd8605f43c50263c4a 100644 (file)
@@ -253,6 +253,11 @@ NTSTATUS check_parent_access(struct connection_struct *conn,
        struct security_descriptor *parent_sd = NULL;
        uint32_t access_granted = 0;
        struct smb_filename *parent_smb_fname = NULL;
+       struct share_mode_lock *lck = NULL;
+       struct file_id id = {0};
+       uint32_t name_hash;
+       bool delete_on_close_set;
+       int ret;
 
        if (!parent_dirname(talloc_tos(),
                                smb_fname->base_name,
@@ -320,7 +325,45 @@ NTSTATUS check_parent_access(struct connection_struct *conn,
                return status;
        }
 
-       return NT_STATUS_OK;
+       if (!(access_mask & (SEC_DIR_ADD_FILE | SEC_DIR_ADD_SUBDIR))) {
+               return NT_STATUS_OK;
+       }
+       if (!lp_check_parent_directory_delete_on_close(SNUM(conn))) {
+               return NT_STATUS_OK;
+       }
+
+       /* Check if the directory has delete-on-close set */
+       ret = SMB_VFS_STAT(conn, parent_smb_fname);
+       if (ret != 0) {
+               status = map_nt_error_from_unix(errno);
+               goto out;
+       }
+
+       id = SMB_VFS_FILE_ID_CREATE(conn, &parent_smb_fname->st);
+
+       status = file_name_hash(conn, parent_smb_fname->base_name, &name_hash);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
+       lck = get_existing_share_mode_lock(talloc_tos(), id);
+       if (lck == NULL) {
+               status = NT_STATUS_OK;
+               goto out;
+       }
+
+       delete_on_close_set = is_delete_on_close_set(lck, name_hash);
+       if (delete_on_close_set) {
+               status = NT_STATUS_DELETE_PENDING;
+               goto out;
+       }
+
+       status = NT_STATUS_OK;
+
+out:
+       TALLOC_FREE(lck);
+       TALLOC_FREE(parent_smb_fname);
+       return status;
 }
 
 /****************************************************************************
@@ -1501,6 +1544,7 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u
 
 #if defined(DEVELOPER)
 static void validate_my_share_entries(struct smbd_server_connection *sconn,
+                                     const struct file_id id,
                                      int num,
                                      struct share_mode_entry *share_entry)
 {
@@ -1520,11 +1564,11 @@ static void validate_my_share_entries(struct smbd_server_connection *sconn,
                return;
        }
 
-       fsp = file_find_dif(sconn, share_entry->id,
-                           share_entry->share_file_id);
+       fsp = file_find_dif(sconn, id, share_entry->share_file_id);
        if (!fsp) {
-               DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
-                        share_mode_str(talloc_tos(), num, share_entry) ));
+               DBG_ERR("PANIC : %s\n",
+                       share_mode_str(talloc_tos(), num, &id,
+                                      share_entry));
                smb_panic("validate_my_share_entries: Cannot match a "
                          "share entry with an open file\n");
        }
@@ -1538,8 +1582,9 @@ static void validate_my_share_entries(struct smbd_server_connection *sconn,
  panic:
        {
                char *str;
-               DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
-                        share_mode_str(talloc_tos(), num, share_entry) ));
+               DBG_ERR("validate_my_share_entries: PANIC : %s\n",
+                       share_mode_str(talloc_tos(), num, &id,
+                                      share_entry));
                str = talloc_asprintf(talloc_tos(),
                        "validate_my_share_entries: "
                        "file %s, oplock_type = 0x%x, op_type = 0x%x\n",
@@ -1611,7 +1656,7 @@ static NTSTATUS open_mode_check(connection_struct *conn,
 
 #if defined(DEVELOPER)
        for(i = 0; i < lck->data->num_share_modes; i++) {
-               validate_my_share_entries(conn->sconn, i,
+               validate_my_share_entries(conn->sconn, lck->data->id, i,
                                          &lck->data->share_modes[i]);
        }
 #endif
@@ -1645,8 +1690,9 @@ static NTSTATUS open_mode_check(connection_struct *conn,
  */
 
 NTSTATUS send_break_message(struct messaging_context *msg_ctx,
-                                  const struct share_mode_entry *exclusive,
-                                  uint16_t break_to)
+                           const struct file_id *id,
+                           const struct share_mode_entry *exclusive,
+                           uint16_t break_to)
 {
        NTSTATUS status;
        char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
@@ -1656,7 +1702,7 @@ NTSTATUS send_break_message(struct messaging_context *msg_ctx,
                   server_id_str_buf(exclusive->pid, &tmp)));
 
        /* Create the message. */
-       share_mode_entry_to_message(msg, exclusive);
+       share_mode_entry_to_message(msg, id, exclusive);
 
        /* Overload entry->op_type */
        /*
@@ -1882,8 +1928,8 @@ static bool delay_for_oplock(files_struct *fsp,
 
                DEBUG(10, ("breaking from %d to %d\n",
                           (int)e_lease_type, (int)break_to));
-               send_break_message(fsp->conn->sconn->msg_ctx, e,
-                                  break_to);
+               send_break_message(fsp->conn->sconn->msg_ctx, &fsp->file_id,
+                                  e, break_to);
                if (e_lease_type & delay_mask) {
                        delay = true;
                }
@@ -4938,7 +4984,7 @@ static NTSTATUS lease_match(connection_struct *conn,
                                continue;
                        }
 
-                       send_break_message(conn->sconn->msg_ctx, e,
+                       send_break_message(conn->sconn->msg_ctx, &d->id, e,
                                           SMB2_LEASE_NONE);
 
                        /*