summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/messages.h4
-rw-r--r--source3/locking/locking.c2
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c57
-rw-r--r--source3/smbd/close.c34
-rw-r--r--source3/smbd/oplock.c2
-rw-r--r--source3/smbd/server.c2
6 files changed, 97 insertions, 4 deletions
diff --git a/source3/include/messages.h b/source3/include/messages.h
index 8f0112acc5..b3ac5e4d98 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -87,6 +87,10 @@
*/
#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
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 17131d9194..accd3f7014 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -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, "
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 9ffe9a569f..6f7b232071 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -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;
+}
/********************************************************************
********************************************************************/
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index df188bafe1..818b4c70a8 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -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);
+}
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index c3409547fe..23411294df 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -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);
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index cf02589864..035469cd62 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -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,