From e3880fa759cfa03222262327854fe7bbe585fe01 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 11:30:20 +0000 Subject: r2660: - converted the libcli/raw/ library to use talloc_increase_ref_count() rather than manual reference counts - properly support SMBexit in the cifs and posix backends - added a logoff method to all backends With these changes the RAW-CONTEXT test now passes against the posix backend (This used to be commit c315d6ac1cc40546fde1474702a6d66d07ee13c8) --- source4/include/cli_context.h | 12 -------- source4/libcli/cliconnect.c | 12 ++------ source4/libcli/raw/clisession.c | 50 ++++++++++++++++++++------------ source4/libcli/raw/clisocket.c | 28 +++++++++--------- source4/libcli/raw/clitransport.c | 34 +++++++++++----------- source4/libcli/raw/clitree.c | 38 +++++++++++------------- source4/librpc/rpc/dcerpc_smb.c | 4 +-- source4/librpc/rpc/dcerpc_util.c | 2 +- source4/ntvfs/cifs/vfs_cifs.c | 25 ++++++++++++++-- source4/ntvfs/ipc/vfs_ipc.c | 43 +++++++++++++++++++++++++-- source4/ntvfs/nbench/vfs_nbench.c | 14 +++++++++ source4/ntvfs/ntvfs.h | 3 ++ source4/ntvfs/posix/pvfs_open.c | 53 ++++++++++++++++++++++++++++++++-- source4/ntvfs/posix/pvfs_qfileinfo.c | 2 +- source4/ntvfs/posix/pvfs_read.c | 3 +- source4/ntvfs/posix/pvfs_setfileinfo.c | 2 +- source4/ntvfs/posix/pvfs_write.c | 4 +-- source4/ntvfs/posix/vfs_posix.c | 10 +------ source4/ntvfs/posix/vfs_posix.h | 8 +++++ source4/ntvfs/simple/vfs_simple.c | 11 ++++++- source4/rpc_server/dcerpc_server.c | 4 --- source4/smb_server/reply.c | 40 ++++++++++++++++--------- source4/torture/basic/secleak.c | 2 +- source4/torture/raw/context.c | 20 ++++++++++--- 24 files changed, 285 insertions(+), 139 deletions(-) diff --git a/source4/include/cli_context.h b/source4/include/cli_context.h index 1bfa8dfd24..fa6e293cd9 100644 --- a/source4/include/cli_context.h +++ b/source4/include/cli_context.h @@ -63,9 +63,6 @@ struct smbcli_negotiate { /* this is the context for a SMB socket associated with the socket itself */ struct smbcli_socket { - /* when the reference count reaches zero then the socket is destroyed */ - int reference_count; - struct in_addr dest_ip; /* dest hostname (which may or may not be a DNS name) */ char *hostname; @@ -99,9 +96,6 @@ struct smbcli_options { /* this is the context for the client transport layer */ struct smbcli_transport { - /* when the reference count reaches zero then the transport is destroyed */ - int reference_count; - /* socket level info */ struct smbcli_socket *socket; @@ -184,9 +178,6 @@ struct smbcli_transport { /* this is the context for the session layer */ struct smbcli_session { - /* when the reference count reaches zero then the session is destroyed */ - int reference_count; - /* transport layer info */ struct smbcli_transport *transport; @@ -207,9 +198,6 @@ struct smbcli_session { smbcli_tree context: internal state for a tree connection. */ struct smbcli_tree { - /* when the reference count reaches zero then the tree is destroyed */ - int reference_count; - /* session layer info */ struct smbcli_session *session; diff --git a/source4/libcli/cliconnect.c b/source4/libcli/cliconnect.c index 27caaa9df9..f772070305 100644 --- a/source4/libcli/cliconnect.c +++ b/source4/libcli/cliconnect.c @@ -31,13 +31,13 @@ BOOL smbcli_socket_connect(struct smbcli_state *cli, const char *server) if (!sock) return False; if (!smbcli_sock_connect_byname(sock, server, 0)) { - smbcli_sock_close(sock); + talloc_free(sock); return False; } cli->transport = smbcli_transport_init(sock); if (!cli->transport) { - smbcli_sock_close(sock); + talloc_free(sock); return False; } @@ -112,8 +112,6 @@ NTSTATUS smbcli_send_tconX(struct smbcli_state *cli, const char *sharename, cli->tree = smbcli_tree_init(cli->session); if (!cli->tree) return NT_STATUS_UNSUCCESSFUL; - cli->tree->reference_count++; - mem_ctx = talloc_init("tcon"); if (!mem_ctx) { return NT_STATUS_NO_MEMORY; @@ -188,7 +186,6 @@ NTSTATUS smbcli_full_connection(struct smbcli_state **ret_cli, (*ret_cli)->tree = tree; (*ret_cli)->session = tree->session; (*ret_cli)->transport = tree->session->transport; - tree->reference_count++; done: talloc_free(mem_ctx); @@ -225,9 +222,6 @@ struct smbcli_state *smbcli_state_init(void) void smbcli_shutdown(struct smbcli_state *cli) { if (!cli) return; - if (cli->tree) { - cli->tree->reference_count++; - smbcli_tree_close(cli->tree); - } + talloc_free(cli->tree); talloc_free(cli); } diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c index 516da2fa2e..0c6c80d94c 100644 --- a/source4/libcli/raw/clisession.c +++ b/source4/libcli/raw/clisession.c @@ -26,6 +26,17 @@ if (!req) return NULL; \ } while (0) + +/* + destroy a smbcli_session +*/ +static int session_destroy(void *ptr) +{ + struct smbcli_session *session = ptr; + talloc_free(session->transport); + return 0; +} + /**************************************************************************** Initialize the session context ****************************************************************************/ @@ -42,20 +53,10 @@ struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport) session->transport = transport; session->pid = (uint16_t)getpid(); session->vuid = UID_FIELD_INVALID; - session->transport->reference_count++; - return session; -} + talloc_set_destructor(session, session_destroy); -/**************************************************************************** -reduce reference_count and destroy is <= 0 -****************************************************************************/ -void smbcli_session_close(struct smbcli_session *session) -{ - session->reference_count--; - if (session->reference_count <= 0) { - smbcli_transport_close(session->transport); - } + return session; } /**************************************************************************** @@ -590,16 +591,27 @@ NTSTATUS smb_raw_ulogoff(struct smbcli_session *session) /**************************************************************************** - Send a SMBexit -****************************************************************************/ -NTSTATUS smb_raw_exit(struct smbcli_session *session) + Send a exit (async send) +*****************************************************************************/ +struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session) { struct smbcli_request *req; - req = smbcli_request_setup_session(session, SMBexit, 0, 0); + SETUP_REQUEST_SESSION(SMBexit, 0, 0); - if (smbcli_request_send(req)) { - smbcli_request_receive(req); + if (!smbcli_request_send(req)) { + smbcli_request_destroy(req); + return NULL; } - return smbcli_request_destroy(req); + + return req; +} + +/**************************************************************************** + Send a exit (sync interface) +*****************************************************************************/ +NTSTATUS smb_raw_exit(struct smbcli_session *session) +{ + struct smbcli_request *req = smb_raw_exit_send(session); + return smbcli_request_simple_recv(req); } diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c index 8481bc73e2..37188f4e77 100644 --- a/source4/libcli/raw/clisocket.c +++ b/source4/libcli/raw/clisocket.c @@ -21,6 +21,18 @@ #include "includes.h" +/* + destroy a socket + */ +static int sock_destructor(void *ptr) +{ + struct smbcli_socket *sock = ptr; + if (sock->fd != -1) { + close(sock->fd); + sock->fd = -1; + } + return 0; +} /* create a smbcli_socket context @@ -37,11 +49,13 @@ struct smbcli_socket *smbcli_sock_init(void) ZERO_STRUCTP(sock); sock->fd = -1; sock->port = 0; + /* 20 second default timeout */ sock->timeout = 20000; - sock->hostname = NULL; + talloc_set_destructor(sock, sock_destructor); + return sock; } @@ -96,18 +110,6 @@ void smbcli_sock_dead(struct smbcli_socket *sock) } } -/**************************************************************************** - reduce socket reference count - if it becomes zero then close -****************************************************************************/ -void smbcli_sock_close(struct smbcli_socket *sock) -{ - sock->reference_count--; - if (sock->reference_count <= 0) { - smbcli_sock_dead(sock); - talloc_free(sock); - } -} - /**************************************************************************** Set socket options on a open connection. ****************************************************************************/ diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c index d70ceceab3..eb1d3631ee 100644 --- a/source4/libcli/raw/clitransport.c +++ b/source4/libcli/raw/clitransport.c @@ -41,6 +41,21 @@ static void smbcli_transport_event_handler(struct event_context *ev, struct fd_e } } +/* + destroy a transport + */ +static int transport_destructor(void *ptr) +{ + struct smbcli_transport *transport = ptr; + + smbcli_transport_dead(transport); + event_remove_fd(transport->event.ctx, transport->event.fde); + event_remove_timed(transport->event.ctx, transport->event.te); + event_context_destroy(transport->event.ctx); + talloc_free(transport->socket); + return 0; +} + /* create a transport structure based on an established socket */ @@ -67,8 +82,6 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock) smbcli_init_signing(transport); - transport->socket->reference_count++; - ZERO_STRUCT(transport->called); fde.fd = sock->fd; @@ -79,22 +92,9 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock) transport->event.fde = event_add_fd(transport->event.ctx, &fde); - return transport; -} + talloc_set_destructor(transport, transport_destructor); -/* - decrease reference count on a transport, and destroy if it becomes - zero -*/ -void smbcli_transport_close(struct smbcli_transport *transport) -{ - transport->reference_count--; - if (transport->reference_count <= 0) { - event_remove_fd(transport->event.ctx, transport->event.fde); - event_remove_timed(transport->event.ctx, transport->event.te); - event_context_destroy(transport->event.ctx); - smbcli_sock_close(transport->socket); - } + return transport; } /* diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c index e3a1a6d341..e0072a31b1 100644 --- a/source4/libcli/raw/clitree.c +++ b/source4/libcli/raw/clitree.c @@ -26,6 +26,15 @@ if (!req) return NULL; \ } while (0) +/* + destroy a smbcli_tree +*/ +static int tree_destructor(void *ptr) +{ + struct smbcli_tree *tree = ptr; + talloc_free(tree->session); + return 0; +} /**************************************************************************** Initialize the tree context @@ -41,24 +50,11 @@ struct smbcli_tree *smbcli_tree_init(struct smbcli_session *session) ZERO_STRUCTP(tree); tree->session = session; - tree->session->reference_count++; + talloc_set_destructor(tree, tree_destructor); return tree; } -/**************************************************************************** -reduce reference count on a tree and destroy if <= 0 -****************************************************************************/ -void smbcli_tree_close(struct smbcli_tree *tree) -{ - if (!tree) return; - tree->reference_count--; - if (tree->reference_count <= 0) { - smbcli_session_close(tree->session); - } -} - - /**************************************************************************** Send a tconX (async send) ****************************************************************************/ @@ -202,7 +198,7 @@ NTSTATUS smbcli_tree_full_connection(struct smbcli_tree **ret_tree, transport = smbcli_transport_init(sock); if (!transport) { - smbcli_sock_close(sock); + talloc_free(sock); return NT_STATUS_NO_MEMORY; } @@ -211,7 +207,7 @@ NTSTATUS smbcli_tree_full_connection(struct smbcli_tree **ret_tree, choose_called_name(&called, dest_host, 0x20); if (!smbcli_transport_connect(transport, &calling, &called)) { - smbcli_transport_close(transport); + talloc_free(transport); return NT_STATUS_UNSUCCESSFUL; } @@ -219,13 +215,13 @@ NTSTATUS smbcli_tree_full_connection(struct smbcli_tree **ret_tree, /* negotiate protocol options with the server */ status = smb_raw_negotiate(transport); if (!NT_STATUS_IS_OK(status)) { - smbcli_transport_close(transport); + talloc_free(transport); return status; } session = smbcli_session_init(transport); if (!session) { - smbcli_transport_close(transport); + talloc_free(transport); return NT_STATUS_NO_MEMORY; } @@ -251,7 +247,7 @@ NTSTATUS smbcli_tree_full_connection(struct smbcli_tree **ret_tree, status = smb_raw_session_setup(session, mem_ctx, &setup); if (!NT_STATUS_IS_OK(status)) { - smbcli_session_close(session); + talloc_free(session); talloc_free(mem_ctx); return status; } @@ -260,7 +256,7 @@ NTSTATUS smbcli_tree_full_connection(struct smbcli_tree **ret_tree, tree = smbcli_tree_init(session); if (!tree) { - smbcli_session_close(session); + talloc_free(session); talloc_free(mem_ctx); return NT_STATUS_NO_MEMORY; } @@ -284,7 +280,7 @@ NTSTATUS smbcli_tree_full_connection(struct smbcli_tree **ret_tree, SAFE_FREE(in_path); if (!NT_STATUS_IS_OK(status)) { - smbcli_tree_close(tree); + talloc_free(tree); talloc_free(mem_ctx); return status; } diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c index dac95f5aec..09c5f3772c 100644 --- a/source4/librpc/rpc/dcerpc_smb.c +++ b/source4/librpc/rpc/dcerpc_smb.c @@ -334,7 +334,7 @@ static NTSTATUS smb_shutdown_pipe(struct dcerpc_pipe *p) c.close.in.fnum = smb->fnum; c.close.in.write_time = 0; smb_raw_close(smb->tree, &c); - smbcli_tree_close(smb->tree); + talloc_free(smb->tree); return NT_STATUS_OK; } @@ -443,7 +443,7 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p, smb->tree = tree; (*p)->transport.private = smb; - tree->reference_count++; + talloc_increase_ref_count(tree); return NT_STATUS_OK; } diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 43cced0543..be83d6bed1 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -486,7 +486,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p, /* this ensures that the reference count is decremented so a pipe close will really close the link */ - smbcli_tree_close(cli->tree); + talloc_free(cli->tree); (*p)->flags = binding->flags; diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index 2ae41a674c..3931792ee8 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -162,7 +162,7 @@ static NTSTATUS cvfs_disconnect(struct smbsrv_tcon *tcon, int depth) struct cvfs_private *private = tcon->ntvfs_private_list[depth]; smb_tree_disconnect(private->tree); - smbcli_tree_close(private->tree); + talloc_free(private->tree); return NT_STATUS_OK; } @@ -517,11 +517,29 @@ static NTSTATUS cvfs_close(struct smbsrv_request *req, union smb_close *io) } /* - exit - closing files? + exit - closing files open by the pid */ static NTSTATUS cvfs_exit(struct smbsrv_request *req) { - return NT_STATUS_NOT_SUPPORTED; + NTVFS_GET_PRIVATE(cvfs_private, private, req); + struct smbcli_request *c_req; + + if (!req->async.send_fn) { + return smb_raw_exit(private->tree->session); + } + + c_req = smb_raw_exit_send(private->tree->session); + + SIMPLE_ASYNC_TAIL; +} + +/* + logoff - closing files open by the user +*/ +static NTSTATUS cvfs_logoff(struct smbsrv_request *req) +{ + /* we can't do this right in the cifs backend .... */ + return NT_STATUS_OK; } /* @@ -699,6 +717,7 @@ NTSTATUS ntvfs_cifs_init(void) ops.search_next = cvfs_search_next; ops.search_close = cvfs_search_close; ops.trans = cvfs_trans; + ops.logoff = cvfs_logoff; if (lp_parm_bool(-1, "cifs", "maptrans2", False)) { ops.trans2 = cvfs_trans2; diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index ce6629739a..33e1287d21 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -43,6 +43,13 @@ struct ipc_private { uint16_t fnum; struct dcesrv_connection *dce_conn; uint16_t ipc_state; + /* we need to remember the session it was opened on, + as it is illegal to operate on someone elses fnum */ + struct smbsrv_session *session; + + /* we need to remember the client pid that + opened the file so SMBexit works */ + uint16_t smbpid; } *pipe_list; }; @@ -262,6 +269,9 @@ static NTSTATUS ipc_open_generic(struct smbsrv_request *req, const char *fname, DLIST_ADD(private->pipe_list, p); + p->smbpid = req->smbpid; + p->session = req->session; + *ps = p; return NT_STATUS_OK; @@ -514,11 +524,39 @@ static NTSTATUS ipc_close(struct smbsrv_request *req, union smb_close *io) } /* - exit - closing files? + exit - closing files */ static NTSTATUS ipc_exit(struct smbsrv_request *req) { - return NT_STATUS_ACCESS_DENIED; + NTVFS_GET_PRIVATE(ipc_private, private, req); + struct pipe_state *p, *next; + + for (p=private->pipe_list; p; p=next) { + next = p->next; + if (p->smbpid == req->smbpid) { + pipe_shutdown(private, p); + } + } + + return NT_STATUS_OK; +} + +/* + logoff - closing files open by the user +*/ +static NTSTATUS ipc_logoff(struct smbsrv_request *req) +{ + NTVFS_GET_PRIVATE(ipc_private, private, req); + struct pipe_state *p, *next; + + for (p=private->pipe_list; p; p=next) { + next = p->next; + if (p->session == req->session) { + pipe_shutdown(private, p); + } + } + + return NT_STATUS_OK; } /* @@ -733,6 +771,7 @@ NTSTATUS ntvfs_ipc_init(void) ops.search_next = ipc_search_next; ops.search_close = ipc_search_close; ops.trans = ipc_trans; + ops.logoff = ipc_logoff; /* register ourselves with the NTVFS subsystem. */ ret = register_backend("ntvfs", &ops); diff --git a/source4/ntvfs/nbench/vfs_nbench.c b/source4/ntvfs/nbench/vfs_nbench.c index eebf6f1dde..90b5d43bd6 100644 --- a/source4/ntvfs/nbench/vfs_nbench.c +++ b/source4/ntvfs/nbench/vfs_nbench.c @@ -475,6 +475,19 @@ static NTSTATUS nbench_exit(struct smbsrv_request *req) return status; } +/* + logoff - closing files +*/ +static NTSTATUS nbench_logoff(struct smbsrv_request *req) +{ + NTVFS_GET_PRIVATE(nbench_private, private, req); + NTSTATUS status; + + PASS_THRU_REQ(req, logoff, (req)); + + return status; +} + /* lock a byte range */ @@ -672,6 +685,7 @@ NTSTATUS ntvfs_nbench_init(void) ops.search_next = nbench_search_next; ops.search_close = nbench_search_close; ops.trans = nbench_trans; + ops.logoff = nbench_logoff; /* we don't register a trans2 handler as we want to be able to log individual trans2 requests */ diff --git a/source4/ntvfs/ntvfs.h b/source4/ntvfs/ntvfs.h index c9cf6de1e0..96434f44e2 100644 --- a/source4/ntvfs/ntvfs.h +++ b/source4/ntvfs/ntvfs.h @@ -74,6 +74,9 @@ struct ntvfs_ops { /* trans interface - used by IPC backend for pipes and RAP calls */ NTSTATUS (*trans)(struct smbsrv_request *req, struct smb_trans2 *trans); + + /* logoff - called when a vuid is closed */ + NTSTATUS (*logoff)(struct smbsrv_request *req); }; diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a1c6dcdcfe..f3bec4085e 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -27,11 +27,16 @@ /* find open file handle given fnum */ -struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, uint16_t fnum) +struct pvfs_file *pvfs_find_fd(struct smbsrv_request *req, uint16_t fnum) { + NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); struct pvfs_file *f; for (f=pvfs->open_files;f;f=f->next) { if (f->fnum == fnum) { + if (req->session != f->session) { + DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", fnum)); + return NULL; + } return f; } } @@ -146,6 +151,8 @@ do_open: f->fnum = fd; f->fd = fd; f->name = talloc_steal(f, name); + f->session = req->session; + f->smbpid = req->smbpid; /* setup a destructor to avoid file descriptor leaks on abnormal termination */ @@ -183,7 +190,7 @@ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) return NT_STATUS_INVALID_LEVEL; } - f = pvfs_find_fd(pvfs, io->close.in.fnum); + f = pvfs_find_fd(req, io->close.in.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } @@ -202,3 +209,45 @@ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) return status; } + +/* + logoff - close all file descriptors open by a vuid +*/ +NTSTATUS pvfs_logoff(struct smbsrv_request *req) +{ + NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); + struct pvfs_file *f, *next; + + for (f=pvfs->open_files;f;f=next) { + next = f->next; + if (f->session == req->session) { + talloc_set_destructor(f, NULL); + DLIST_REMOVE(pvfs->open_files, f); + talloc_free(f); + } + } + + return NT_STATUS_OK; +} + + +/* + exit - close files for the current pid +*/ +NTSTATUS pvfs_exit(struct smbsrv_request *req) +{ + NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); + struct pvfs_file *f, *next; + + for (f=pvfs->open_files;f;f=next) { + next = f->next; + if (f->smbpid == req->smbpid) { + talloc_set_destructor(f, NULL); + DLIST_REMOVE(pvfs->open_files, f); + talloc_free(f); + } + } + + return NT_STATUS_OK; +} + diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index 649036b09a..81706bcfe8 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -114,7 +114,7 @@ NTSTATUS pvfs_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info) return ntvfs_map_qfileinfo(req, info, pvfs->ops); } - f = pvfs_find_fd(pvfs, info->generic.in.fnum); + f = pvfs_find_fd(req, info->generic.in.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_read.c b/source4/ntvfs/posix/pvfs_read.c index cbb0317638..72ac00a32d 100644 --- a/source4/ntvfs/posix/pvfs_read.c +++ b/source4/ntvfs/posix/pvfs_read.c @@ -36,7 +36,8 @@ NTSTATUS pvfs_read(struct smbsrv_request *req, union smb_read *rd) return NT_STATUS_NOT_SUPPORTED; } - f = pvfs_find_fd(pvfs, rd->readx.in.fnum); + + f = pvfs_find_fd(req, rd->readx.in.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index c2c58415be..2ea2fdaf8e 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -33,7 +33,7 @@ NTSTATUS pvfs_setfileinfo(struct smbsrv_request *req, struct utimbuf unix_times; struct pvfs_file *f; - f = pvfs_find_fd(pvfs, info->generic.file.fnum); + f = pvfs_find_fd(req, info->generic.file.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c index ac9d23b88f..02ba1b8228 100644 --- a/source4/ntvfs/posix/pvfs_write.c +++ b/source4/ntvfs/posix/pvfs_write.c @@ -35,7 +35,7 @@ NTSTATUS pvfs_write(struct smbsrv_request *req, union smb_write *wr) switch (wr->generic.level) { case RAW_WRITE_WRITEX: - f = pvfs_find_fd(pvfs, wr->writex.in.fnum); + f = pvfs_find_fd(req, wr->writex.in.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } @@ -53,7 +53,7 @@ NTSTATUS pvfs_write(struct smbsrv_request *req, union smb_write *wr) return NT_STATUS_OK; case RAW_WRITE_WRITE: - f = pvfs_find_fd(pvfs, wr->write.in.fnum); + f = pvfs_find_fd(req, wr->write.in.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index 8705317b2a..7ae7c6759a 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -160,15 +160,6 @@ static NTSTATUS pvfs_flush(struct smbsrv_request *req, struct smb_flush *io) return NT_STATUS_NOT_IMPLEMENTED; } -/* - exit - closing files? -*/ -static NTSTATUS pvfs_exit(struct smbsrv_request *req) -{ - DEBUG(0,("pvfs_exit not implemented\n")); - return NT_STATUS_NOT_SUPPORTED; -} - /* lock a byte range */ @@ -241,6 +232,7 @@ NTSTATUS ntvfs_posix_init(void) ops.search_next = pvfs_search_next; ops.search_close = pvfs_search_close; ops.trans = pvfs_trans; + ops.logoff = pvfs_logoff; /* register ourselves with the NTVFS subsystem. We register under the name 'default' as we wish to be the default diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index bfb1fbf7ca..96ab7f85b2 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -107,6 +107,14 @@ struct pvfs_file { int fd; uint16_t fnum; struct pvfs_filename *name; + + /* we need to remember the session it was opened on, + as it is illegal to operate on someone elses fnum */ + struct smbsrv_session *session; + + /* we need to remember the client pid that + opened the file so SMBexit works */ + uint16_t smbpid; }; diff --git a/source4/ntvfs/simple/vfs_simple.c b/source4/ntvfs/simple/vfs_simple.c index 5b2fe9df56..f60646ed77 100644 --- a/source4/ntvfs/simple/vfs_simple.c +++ b/source4/ntvfs/simple/vfs_simple.c @@ -589,13 +589,21 @@ static NTSTATUS svfs_close(struct smbsrv_request *req, union smb_close *io) } /* - exit - closing files? + exit - closing files */ static NTSTATUS svfs_exit(struct smbsrv_request *req) { return NT_STATUS_NOT_SUPPORTED; } +/* + logoff - closing files +*/ +static NTSTATUS svfs_logoff(struct smbsrv_request *req) +{ + return NT_STATUS_NOT_SUPPORTED; +} + /* lock a byte range */ @@ -962,6 +970,7 @@ NTSTATUS ntvfs_simple_init(void) ops.search_next = svfs_search_next; ops.search_close = svfs_search_close; ops.trans = svfs_trans; + ops.logoff = svfs_logoff; /* register ourselves with the NTVFS subsystem. We register under names 'simple' diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index 17e629d81e..46029ce8dc 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -350,10 +350,6 @@ void dcesrv_endpoint_disconnect(struct dcesrv_connection *p) gensec_end(&p->auth_state.gensec_security); } - if (p->auth_state.session_info) { - free_session_info(&p->auth_state.session_info); - } - talloc_free(p); } diff --git a/source4/smb_server/reply.c b/source4/smb_server/reply.c index 72c7c20a11..94317bfc39 100644 --- a/source4/smb_server/reply.c +++ b/source4/smb_server/reply.c @@ -1149,23 +1149,26 @@ void reply_flush(struct smbsrv_request *req) /**************************************************************************** - Reply to a exit. + Reply to a exit. This closes all files open by a smbpid ****************************************************************************/ void reply_exit(struct smbsrv_request *req) { + NTSTATUS status; + struct smbsrv_tcon *tcon; REQ_CHECK_WCT(req, 0); - req->async.send_fn = reply_simple_send; - - if (!req->tcon) { - req_reply_error(req, NT_STATUS_INVALID_HANDLE); - return; + for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) { + req->tcon = tcon; + status = tcon->ntvfs_ops->exit(req); + req->tcon = NULL; + if (!NT_STATUS_IS_OK(status)) { + req_reply_error(req, status); + return; + } } - /* call backend */ - req->async.status = req->tcon->ntvfs_ops->exit(req); - - REQ_ASYNC_TAIL; + req_setup_reply(req, 0, 0); + req_send_reply(req); } @@ -2097,20 +2100,29 @@ void reply_sesssetup(struct smbsrv_request *req) req_reply_error(req, NT_STATUS_FOOBAR); } - /**************************************************************************** Reply to a SMBulogoffX. ****************************************************************************/ void reply_ulogoffX(struct smbsrv_request *req) { + struct smbsrv_tcon *tcon; uint16_t vuid; + NTSTATUS status; vuid = SVAL(req->in.hdr, HDR_UID); - + /* in user level security we are supposed to close any files - open by this user */ + open by this user on all open tree connects */ if ((vuid != 0) && (lp_security() != SEC_SHARE)) { - DEBUG(0,("REWRITE: not closing user files\n")); + for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) { + req->tcon = tcon; + status = tcon->ntvfs_ops->logoff(req); + req->tcon = NULL; + if (!NT_STATUS_IS_OK(status)) { + req_reply_error(req, status); + return; + } + } } smbsrv_invalidate_vuid(req->smb_conn, vuid); diff --git a/source4/torture/basic/secleak.c b/source4/torture/basic/secleak.c index 80bc799df0..54fa3ecee6 100644 --- a/source4/torture/basic/secleak.c +++ b/source4/torture/basic/secleak.c @@ -43,7 +43,7 @@ static BOOL try_failed_login(struct smbcli_state *cli) return False; } - smbcli_session_close(session); + talloc_free(session); talloc_free(mem_ctx); return True; diff --git a/source4/torture/raw/context.c b/source4/torture/raw/context.c index 7bc75a6627..194d2de93b 100644 --- a/source4/torture/raw/context.c +++ b/source4/torture/raw/context.c @@ -81,6 +81,8 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) printf("create a second security context on the same transport\n"); session = smbcli_session_init(cli->transport); + talloc_increase_ref_count(cli->transport); + setup.generic.level = RAW_SESSSETUP_GENERIC; setup.generic.in.sesskey = cli->transport->negotiate.sesskey; setup.generic.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */ @@ -95,6 +97,8 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) printf("create a third security context on the same transport, with vuid set\n"); session2 = smbcli_session_init(cli->transport); + talloc_increase_ref_count(cli->transport); + session2->vuid = session->vuid; setup.generic.level = RAW_SESSSETUP_GENERIC; setup.generic.in.sesskey = cli->transport->negotiate.sesskey; @@ -110,10 +114,13 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid); CHECK_NOT_VALUE(session->vuid, session2->vuid); + talloc_free(session2); if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) { printf("create a fourth security context on the same transport, without extended security\n"); session3 = smbcli_session_init(cli->transport); + talloc_increase_ref_count(cli->transport); + session3->vuid = session->vuid; setup.generic.level = RAW_SESSSETUP_GENERIC; setup.generic.in.sesskey = cli->transport->negotiate.sesskey; @@ -124,12 +131,14 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) status = smb_raw_session_setup(session3, mem_ctx, &setup); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); + + talloc_free(session3); } printf("use the same tree as the existing connection\n"); tree = smbcli_tree_init(session); + talloc_increase_ref_count(session); tree->tid = cli->tree->tid; - cli->tree->reference_count++; printf("create a file using the new vuid\n"); io.generic.level = RAW_OPEN_NTCREATEX; @@ -168,6 +177,7 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) printf("logoff the new vuid\n"); status = smb_raw_ulogoff(session); CHECK_STATUS(status, NT_STATUS_OK); + talloc_free(session); printf("the new vuid should not now be accessible\n"); status = smb_raw_write(tree, &wr); @@ -182,7 +192,7 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) /* close down the new tree, which will also close the session as the reference count will be 0 */ - smbcli_tree_close(tree); + talloc_free(tree); done: return ret; @@ -215,9 +225,10 @@ static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) } share = lp_parm_string(-1, "torture", "share"); - + printf("create a second tree context on the same session\n"); tree = smbcli_tree_init(cli->session); + talloc_increase_ref_count(cli->session); tcon.generic.level = RAW_TCON_TCONX; tcon.tconx.in.flags = 0; @@ -286,7 +297,7 @@ static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); /* close down the new tree */ - smbcli_tree_close(tree); + talloc_free(tree); done: return ret; @@ -425,5 +436,6 @@ BOOL torture_raw_context(int dummy) torture_close_connection(cli); talloc_destroy(mem_ctx); + return ret; } -- cgit