diff options
-rw-r--r-- | source3/include/messages.h | 4 | ||||
-rw-r--r-- | source3/locking/locking.c | 2 | ||||
-rw-r--r-- | source3/rpc_server/srv_srvsvc_nt.c | 57 | ||||
-rw-r--r-- | source3/smbd/close.c | 34 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 2 | ||||
-rw-r--r-- | source3/smbd/server.c | 2 |
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, |