summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-09-26 11:30:20 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:59:18 -0500
commite3880fa759cfa03222262327854fe7bbe585fe01 (patch)
tree7000172fad1b5cdcc0d071698ee3e203e61a8f4f /source4
parentad053090b817105a0974f4b8bf0b90e002297903 (diff)
downloadsamba-e3880fa759cfa03222262327854fe7bbe585fe01.tar.gz
samba-e3880fa759cfa03222262327854fe7bbe585fe01.tar.bz2
samba-e3880fa759cfa03222262327854fe7bbe585fe01.zip
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)
Diffstat (limited to 'source4')
-rw-r--r--source4/include/cli_context.h12
-rw-r--r--source4/libcli/cliconnect.c12
-rw-r--r--source4/libcli/raw/clisession.c50
-rw-r--r--source4/libcli/raw/clisocket.c28
-rw-r--r--source4/libcli/raw/clitransport.c34
-rw-r--r--source4/libcli/raw/clitree.c38
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c4
-rw-r--r--source4/librpc/rpc/dcerpc_util.c2
-rw-r--r--source4/ntvfs/cifs/vfs_cifs.c25
-rw-r--r--source4/ntvfs/ipc/vfs_ipc.c43
-rw-r--r--source4/ntvfs/nbench/vfs_nbench.c14
-rw-r--r--source4/ntvfs/ntvfs.h3
-rw-r--r--source4/ntvfs/posix/pvfs_open.c53
-rw-r--r--source4/ntvfs/posix/pvfs_qfileinfo.c2
-rw-r--r--source4/ntvfs/posix/pvfs_read.c3
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c2
-rw-r--r--source4/ntvfs/posix/pvfs_write.c4
-rw-r--r--source4/ntvfs/posix/vfs_posix.c10
-rw-r--r--source4/ntvfs/posix/vfs_posix.h8
-rw-r--r--source4/ntvfs/simple/vfs_simple.c11
-rw-r--r--source4/rpc_server/dcerpc_server.c4
-rw-r--r--source4/smb_server/reply.c40
-rw-r--r--source4/torture/basic/secleak.c2
-rw-r--r--source4/torture/raw/context.c20
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;
}
@@ -97,18 +111,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.
****************************************************************************/
void smbcli_sock_set_options(struct smbcli_socket *sock, const char *options)
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
@@ -42,6 +42,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
*/
struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock)
@@ -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,25 +50,12 @@ 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)
****************************************************************************/
struct smbcli_request *smb_tree_connect_send(struct smbcli_tree *tree, union smb_tcon *parms)
@@ -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
@@ -476,6 +476,19 @@ static NTSTATUS nbench_exit(struct smbsrv_request *req)
}
/*
+ 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
*/
static NTSTATUS nbench_lock(struct smbsrv_request *req, union smb_lock *lck)
@@ -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
@@ -161,15 +161,6 @@ static NTSTATUS pvfs_flush(struct smbsrv_request *req, struct smb_flush *io)
}
/*
- 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
*/
static NTSTATUS pvfs_lock(struct smbsrv_request *req, union smb_lock *lck)
@@ -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,7 +589,7 @@ 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)
{
@@ -597,6 +597,14 @@ static NTSTATUS svfs_exit(struct smbsrv_request *req)
}
/*
+ logoff - closing files
+*/
+static NTSTATUS svfs_logoff(struct smbsrv_request *req)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+/*
lock a byte range
*/
static NTSTATUS svfs_lock(struct smbsrv_request *req, union smb_lock *lck)
@@ -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;
}