Allow server manager to close open files selected by id.
authorJeremy Allison <jra@samba.org>
Tue, 27 May 2008 18:23:59 +0000 (11:23 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 27 May 2008 18:25:46 +0000 (11:25 -0700)
Jeremy.
(This used to be commit 7eeed8bb41059ec2bddedb6a71deddeec7f33af2)

source3/include/messages.h
source3/locking/locking.c
source3/rpc_server/srv_srvsvc_nt.c
source3/smbd/close.c
source3/smbd/oplock.c
source3/smbd/server.c

index 8f0112acc500eca832a7576f3130736d33333f38..b3ac5e4d980d6dcb61b63036f79cff23236246c9 100644 (file)
  */
 #define MSG_SMB_BRL_VALIDATE           0x0311
 #define MSG_SMB_RELEASE_IP             0x0312
+/*
+ * Close a specific file given a share entry.
+ */
+#define MSG_SMB_CLOSE_FILE             0x0313
 
 /* winbind messages */
 #define MSG_WINBIND_FINISHED           0x0401
index 17131d9194bf5ab2b2d006a28842850369ba4a3b..accd3f701444f604fcff60fd653f2314e6c15c85 100644 (file)
@@ -443,7 +443,7 @@ static TDB_DATA locking_key(const struct file_id *id, struct file_id *tmp)
  Print out a share mode.
 ********************************************************************/
 
-char *share_mode_str(TALLOC_CTX *ctx, int num, struct share_mode_entry *e)
+char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
 {
        return talloc_asprintf(ctx, "share_mode_entry[%d]: %s "
                 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
index 9ffe9a569feea0eba44688416a0346cad0800efe..6f7b2320715d98e840340981059d196dfe15c47a 100644 (file)
@@ -2399,14 +2399,67 @@ WERROR _srvsvc_NetNameValidate(pipes_struct *p,
        return WERR_OK;
 }
 
+/*******************************************************************
+********************************************************************/
+
+static void enum_file_close_fn( const struct share_mode_entry *e,
+                          const char *sharepath, const char *fname,
+                         void *private_data )
+{
+       char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
+       struct srvsvc_NetFileClose *r =
+               (struct srvsvc_NetFileClose *)private_data;
+       uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
+
+       if (fid != r->in.fid) {
+               return; /* Not this file. */
+       }
+
+       if (!process_exists(e->pid) ) {
+               return;
+       }
+
+       /* Ok - send the close message. */
+       DEBUG(10,("enum_file_close_fn: request to close file %s, %s\n",
+               sharepath,
+               share_mode_str(talloc_tos(), 0, e) ));
+
+       share_mode_entry_to_message(msg, e);
+
+       r->out.result = ntstatus_to_werror(
+                       messaging_send_buf(smbd_messaging_context(),
+                               e->pid, MSG_SMB_CLOSE_FILE,
+                               (uint8 *)msg,
+                               MSG_SMB_SHARE_MODE_ENTRY_SIZE));
+}
+
 /********************************************************************
+ Close a file given a 32-bit file id.
 ********************************************************************/
 
 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
 {
-       return WERR_ACCESS_DENIED;
-}
+       struct current_user user;
+       SE_PRIV se_diskop = SE_DISK_OPERATOR;
+       bool is_disk_op;
+
+       DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
+
+       get_current_user(&user,p);
 
+       is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
+
+       if (user.ut.uid != sec_initial_uid() && !is_disk_op) {
+               return WERR_ACCESS_DENIED;
+       }
+
+       /* enum_file_close_fn sends the close message to
+        * the relevent smbd process. */
+
+       r->out.result = WERR_BADFILE;
+       share_mode_forall( enum_file_close_fn, (void *)r);
+       return r->out.result;
+}
 
 /********************************************************************
 ********************************************************************/
index df188bafe1d4afa03ae3500dc9df9cbc1c92fdc6..818b4c70a8ce1cff6ff15caf0c4dcf97091d4142 100644 (file)
@@ -736,3 +736,37 @@ NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
 
        return status;
 }
+
+/****************************************************************************
+ Deal with an (authorized) message to close a file given the share mode
+ entry.
+****************************************************************************/
+
+void msg_close_file(struct messaging_context *msg_ctx,
+                       void *private_data,
+                       uint32_t msg_type,
+                       struct server_id server_id,
+                       DATA_BLOB *data)
+{
+       files_struct *fsp = NULL;
+       struct share_mode_entry e;
+
+       message_to_share_mode_entry(&e, (char *)data->data);
+
+       if(DEBUGLVL(10)) {
+               char *sm_str = share_mode_str(NULL, 0, &e);
+               if (!sm_str) {
+                       smb_panic("talloc failed");
+               }
+               DEBUG(10,("msg_close_file: got request to close share mode "
+                       "entry %s\n", sm_str));
+               TALLOC_FREE(sm_str);
+       }
+
+       fsp = file_find_dif(e.id, e.share_file_id);
+       if (!fsp) {
+               DEBUG(10,("msg_close_file: failed to find file.\n"));
+               return;
+       }
+       close_file(fsp, NORMAL_CLOSE);
+}
index c3409547fe02c0636d725fbaf1d29008f1d8a952..23411294df508b2bb4af2ae0db1e00c80560ebb0 100644 (file)
@@ -824,7 +824,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
  Linearize a share mode entry struct to an internal oplock break message.
 ****************************************************************************/
 
-void share_mode_entry_to_message(char *msg, struct share_mode_entry *e)
+void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e)
 {
        SIVAL(msg,0,(uint32)e->pid.pid);
        SSVAL(msg,4,e->op_mid);
index cf02589864c66b4baf8f46cd6f8c2c9ebaac9c40..035469cd629621b2220f7299fa208e42202ebb3c 100644 (file)
@@ -1392,6 +1392,8 @@ extern void build_options(bool screen);
                           MSG_SMB_FORCE_TDIS, msg_force_tdis);
        messaging_register(smbd_messaging_context(), NULL,
                           MSG_SMB_RELEASE_IP, msg_release_ip);
+       messaging_register(smbd_messaging_context(), NULL,
+                          MSG_SMB_CLOSE_FILE, msg_close_file);
 
        if ((lp_keepalive() != 0)
            && !(event_add_idle(smbd_event_context(), NULL,