summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/smb_server/management.c4
-rw-r--r--source4/smb_server/smb/receive.c4
-rw-r--r--source4/smb_server/smb/reply.c4
-rw-r--r--source4/smb_server/smb/service.c2
-rw-r--r--source4/smb_server/smb2/receive.c5
-rw-r--r--source4/smb_server/smb2/sesssetup.c5
-rw-r--r--source4/smb_server/smb2/tcon.c2
-rw-r--r--source4/smb_server/smb_server.h58
-rw-r--r--source4/smb_server/tcon.c85
9 files changed, 116 insertions, 53 deletions
diff --git a/source4/smb_server/management.c b/source4/smb_server/management.c
index d158947ba4..19e2090682 100644
--- a/source4/smb_server/management.c
+++ b/source4/smb_server/management.c
@@ -71,7 +71,7 @@ static NTSTATUS smbsrv_tcon_information(struct irpc_message *msg,
struct smbsrv_tcon *tcon;
/* count the number of tcons */
- for (tcon=smb_conn->tcons.list; tcon; tcon=tcon->next) {
+ for (tcon=smb_conn->smb_tcons.list; tcon; tcon=tcon->next) {
count++;
}
@@ -79,7 +79,7 @@ static NTSTATUS smbsrv_tcon_information(struct irpc_message *msg,
r->out.info.tcons.tcons = talloc_array(r, struct smbsrv_tcon_info, count);
NT_STATUS_HAVE_NO_MEMORY(r->out.info.tcons.tcons);
- for (tcon=smb_conn->tcons.list; tcon; tcon=tcon->next) {
+ for (tcon=smb_conn->smb_tcons.list; tcon; tcon=tcon->next) {
struct smbsrv_tcon_info *info = &r->out.info.tcons.tcons[i];
info->tid = tcon->tid;
info->share_name = lp_servicename(tcon->service);
diff --git a/source4/smb_server/smb/receive.c b/source4/smb_server/smb/receive.c
index b77a166b9d..806244ee12 100644
--- a/source4/smb_server/smb/receive.c
+++ b/source4/smb_server/smb/receive.c
@@ -470,7 +470,7 @@ static void switch_message(int type, struct smbsrv_request *req)
flags = smb_messages[type].flags;
- req->tcon = smbsrv_tcon_find(smb_conn, SVAL(req->in.hdr,HDR_TID));
+ req->tcon = smbsrv_smb_tcon_find(smb_conn, SVAL(req->in.hdr,HDR_TID));
if (!req->session) {
/* setup the user context for this request if it
@@ -645,7 +645,7 @@ NTSTATUS smbsrv_init_smb_connection(struct smbsrv_connection *smb_conn)
status = smbsrv_init_sessions(smb_conn, UINT16_MAX);
NT_STATUS_NOT_OK_RETURN(status);
- status = smbsrv_init_tcons(smb_conn, UINT16_MAX);
+ status = smbsrv_smb_init_tcons(smb_conn);
NT_STATUS_NOT_OK_RETURN(status);
srv_init_signing(smb_conn);
diff --git a/source4/smb_server/smb/reply.c b/source4/smb_server/smb/reply.c
index eb7b5a1082..d780cb1a75 100644
--- a/source4/smb_server/smb/reply.c
+++ b/source4/smb_server/smb/reply.c
@@ -1200,7 +1200,7 @@ void reply_exit(struct smbsrv_request *req)
struct smbsrv_tcon *tcon;
REQ_CHECK_WCT(req, 0);
- for (tcon=req->smb_conn->tcons.list;tcon;tcon=tcon->next) {
+ for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
req->tcon = tcon;
status = ntvfs_exit(req);
req->tcon = NULL;
@@ -2181,7 +2181,7 @@ void reply_ulogoffX(struct smbsrv_request *req)
/* in user level security we are supposed to close any files
open by this user on all open tree connects */
- for (tcon=req->smb_conn->tcons.list;tcon;tcon=tcon->next) {
+ for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
req->tcon = tcon;
status = ntvfs_logoff(req);
req->tcon = NULL;
diff --git a/source4/smb_server/smb/service.c b/source4/smb_server/smb/service.c
index 213cf6726b..6032e5a20d 100644
--- a/source4/smb_server/smb/service.c
+++ b/source4/smb_server/smb/service.c
@@ -66,7 +66,7 @@ static NTSTATUS make_connection_snum(struct smbsrv_request *req,
return NT_STATUS_ACCESS_DENIED;
}
- tcon = smbsrv_tcon_new(req->smb_conn);
+ tcon = smbsrv_smb_tcon_new(req->smb_conn);
if (!tcon) {
DEBUG(0,("Couldn't find free connection.\n"));
return NT_STATUS_INSUFFICIENT_RESOURCES;
diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c
index 66ebe162cf..310ded5355 100644
--- a/source4/smb_server/smb2/receive.c
+++ b/source4/smb_server/smb2/receive.c
@@ -129,7 +129,7 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req)
uid = BVAL(req->in.hdr, SMB2_HDR_UID);
req->session = smbsrv_session_find(req->smb_conn, uid);
- req->tcon = smbsrv_tcon_find(req->smb_conn, tid);
+ req->tcon = smbsrv_smb2_tcon_find(req->session, tid);
errno = 0;
@@ -322,9 +322,6 @@ NTSTATUS smbsrv_init_smb2_connection(struct smbsrv_connection *smb_conn)
status = smbsrv_init_sessions(smb_conn, UINT64_MAX);
NT_STATUS_NOT_OK_RETURN(status);
- status = smbsrv_init_tcons(smb_conn, UINT32_MAX);
- NT_STATUS_NOT_OK_RETURN(status);
-
return NT_STATUS_OK;
}
diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c
index 7915590464..288671ddd3 100644
--- a/source4/smb_server/smb2/sesssetup.c
+++ b/source4/smb_server/smb2/sesssetup.c
@@ -67,6 +67,11 @@ static NTSTATUS smb2srv_sesssetup_backend(struct smb2srv_request *req, struct sm
/* allocate a new session */
smb_sess = smbsrv_session_new(req->smb_conn, gensec_ctx);
+ status = smbsrv_smb2_init_tcons(smb_sess);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(smb_sess);
+ smb_sess = NULL;
+ }
} else {
/* lookup an existing session */
smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
diff --git a/source4/smb_server/smb2/tcon.c b/source4/smb_server/smb2/tcon.c
index fb84aa6fdc..9fb2a03ce3 100644
--- a/source4/smb_server/smb2/tcon.c
+++ b/source4/smb_server/smb2/tcon.c
@@ -28,7 +28,7 @@ static NTSTATUS smb2srv_tcon_backend(struct smb2srv_request *req, struct smb2_tr
{
struct smbsrv_tcon *tcon;
- tcon = smbsrv_tcon_new(req->smb_conn);
+ tcon = smbsrv_smb2_tcon_new(req->session);
NT_STATUS_HAVE_NO_MEMORY(tcon);
/* TODO: do real tree connect */
diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h
index f879845134..6a73383480 100644
--- a/source4/smb_server/smb_server.h
+++ b/source4/smb_server/smb_server.h
@@ -32,12 +32,39 @@
these basic elements
*/
+struct smbsrv_tcons_context {
+ /* an id tree used to allocate tids */
+ struct idr_context *idtree_tid;
+
+ /* this is the limit of vuid values for this connection */
+ uint32_t idtree_limit;
+
+ /* list of open tree connects */
+ struct smbsrv_tcon *list;
+};
+
+struct smbsrv_sessions_context {
+ /* an id tree used to allocate vuids */
+ /* this holds info on session vuids that are already
+ * validated for this VC */
+ struct idr_context *idtree_vuid;
+
+ /* this is the limit of vuid values for this connection */
+ uint64_t idtree_limit;
+
+ /* also kept as a link list so it can be enumerated by
+ the management code */
+ struct smbsrv_session *list;
+} sessions;
+
/* the current user context for a request */
struct smbsrv_session {
struct smbsrv_session *prev, *next;
struct smbsrv_connection *smb_conn;
+ struct smbsrv_tcons_context smb2_tcons;
+
/*
* an index passed over the wire:
* - 16 bit for smb
@@ -94,6 +121,12 @@ struct smbsrv_tcon {
struct smbsrv_session *session;
} sec_share;
+ /* some stuff to support share level security */
+ struct {
+ /* in SMB2 a tcon always belongs to one session */
+ struct smbsrv_session *session;
+ } smb2;
+
/* some statictics for the management tools */
struct {
struct timeval connect_time;
@@ -232,31 +265,10 @@ struct smbsrv_connection {
} negotiate;
/* the context associated with open tree connects on a smb socket */
- struct {
- /* an id tree used to allocate tids */
- struct idr_context *idtree_tid;
-
- /* this is the limit of vuid values for this connection */
- uint32_t idtree_limit;
-
- /* list of open tree connects */
- struct smbsrv_tcon *list;
- } tcons;
+ struct smbsrv_tcons_context smb_tcons;
/* context associated with currently valid session setups */
- struct {
- /* an id tree used to allocate vuids */
- /* this holds info on session vuids that are already
- * validated for this VC */
- struct idr_context *idtree_vuid;
-
- /* this is the limit of vuid values for this connection */
- uint64_t idtree_limit;
-
- /* also kept as a link list so it can be enumerated by
- the management code */
- struct smbsrv_session *list;
- } sessions;
+ struct smbsrv_sessions_context sessions;
/* the server_context holds a linked list of pending requests,
* this is used for blocking locks and requests blocked due to oplock
diff --git a/source4/smb_server/tcon.c b/source4/smb_server/tcon.c
index 6714b61e90..0cb6738d31 100644
--- a/source4/smb_server/tcon.c
+++ b/source4/smb_server/tcon.c
@@ -29,7 +29,7 @@
/****************************************************************************
init the tcon structures
****************************************************************************/
-NTSTATUS smbsrv_init_tcons(struct smbsrv_connection *smb_conn, uint32_t limit)
+static NTSTATUS smbsrv_init_tcons(struct smbsrv_tcons_context *tcons_ctx, TALLOC_CTX *mem_ctx, uint32_t limit)
{
/*
* the idr_* functions take 'int' as limit,
@@ -37,27 +37,37 @@ NTSTATUS smbsrv_init_tcons(struct smbsrv_connection *smb_conn, uint32_t limit)
*/
limit &= 0x00FFFFFF;
- smb_conn->tcons.idtree_tid = idr_init(smb_conn);
- NT_STATUS_HAVE_NO_MEMORY(smb_conn->tcons.idtree_tid);
- smb_conn->tcons.idtree_limit = limit;
- smb_conn->tcons.list = NULL;
+ tcons_ctx->idtree_tid = idr_init(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tcons_ctx->idtree_tid);
+ tcons_ctx->idtree_limit = limit;
+ tcons_ctx->list = NULL;
return NT_STATUS_OK;
}
+NTSTATUS smbsrv_smb_init_tcons(struct smbsrv_connection *smb_conn)
+{
+ return smbsrv_init_tcons(&smb_conn->smb_tcons, smb_conn, UINT16_MAX);
+}
+
+NTSTATUS smbsrv_smb2_init_tcons(struct smbsrv_session *smb_sess)
+{
+ return smbsrv_init_tcons(&smb_sess->smb2_tcons, smb_sess, UINT32_MAX);
+}
+
/****************************************************************************
-find a tcon given a cnum
+find a tcon given a tid for SMB
****************************************************************************/
-struct smbsrv_tcon *smbsrv_tcon_find(struct smbsrv_connection *smb_conn, uint32_t tid)
+static struct smbsrv_tcon *smbsrv_tcon_find(struct smbsrv_tcons_context *tcons_ctx, uint32_t tid)
{
void *p;
struct smbsrv_tcon *tcon;
if (tid == 0) return NULL;
- if (tid > smb_conn->tcons.idtree_limit) return NULL;
+ if (tid > tcons_ctx->idtree_limit) return NULL;
- p = idr_find(smb_conn->tcons.idtree_tid, tid);
+ p = idr_find(tcons_ctx->idtree_tid, tid);
if (!p) return NULL;
tcon = talloc_get_type(p, struct smbsrv_tcon);
@@ -65,12 +75,24 @@ struct smbsrv_tcon *smbsrv_tcon_find(struct smbsrv_connection *smb_conn, uint32_
return tcon;
}
+struct smbsrv_tcon *smbsrv_smb_tcon_find(struct smbsrv_connection *smb_conn, uint32_t tid)
+{
+ return smbsrv_tcon_find(&smb_conn->smb_tcons, tid);
+}
+
+struct smbsrv_tcon *smbsrv_smb2_tcon_find(struct smbsrv_session *smb_sess, uint32_t tid)
+{
+ if (!smb_sess) return NULL;
+ return smbsrv_tcon_find(&smb_sess->smb2_tcons, tid);
+}
+
/*
destroy a connection structure
*/
static int smbsrv_tcon_destructor(void *ptr)
{
- struct smbsrv_tcon *tcon = ptr;
+ struct smbsrv_tcon *tcon = talloc_get_type(ptr, struct smbsrv_tcon);
+ struct smbsrv_tcons_context *tcons_ctx;
DEBUG(3,("%s closed connection to service %s\n",
socket_get_peer_addr(tcon->smb_conn->connection->socket, tcon),
@@ -81,31 +103,48 @@ static int smbsrv_tcon_destructor(void *ptr)
ntvfs_disconnect(tcon);
}
- idr_remove(tcon->smb_conn->tcons.idtree_tid, tcon->tid);
- DLIST_REMOVE(tcon->smb_conn->tcons.list, tcon);
+ if (tcon->smb2.session) {
+ tcons_ctx = &tcon->smb2.session->smb2_tcons;
+ } else {
+ tcons_ctx = &tcon->smb_conn->smb_tcons;
+ }
+
+ idr_remove(tcons_ctx->idtree_tid, tcon->tid);
+ DLIST_REMOVE(tcons_ctx->list, tcon);
return 0;
}
/*
find first available connection slot
*/
-struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn)
+static struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn, struct smbsrv_session *smb_sess)
{
+ TALLOC_CTX *mem_ctx;
+ struct smbsrv_tcons_context *tcons_ctx;
struct smbsrv_tcon *tcon;
int i;
- tcon = talloc_zero(smb_conn, struct smbsrv_tcon);
+ if (smb_sess) {
+ mem_ctx = smb_sess;
+ tcons_ctx = &smb_sess->smb2_tcons;
+ } else {
+ mem_ctx = smb_conn;
+ tcons_ctx = &smb_conn->smb_tcons;
+ }
+
+ tcon = talloc_zero(mem_ctx, struct smbsrv_tcon);
if (!tcon) return NULL;
- tcon->smb_conn = smb_conn;
+ tcon->smb_conn = smb_conn;
+ tcon->smb2.session = smb_sess;
- i = idr_get_new_random(smb_conn->tcons.idtree_tid, tcon, smb_conn->tcons.idtree_limit);
+ i = idr_get_new_random(tcons_ctx->idtree_tid, tcon, tcons_ctx->idtree_limit);
if (i == -1) {
- DEBUG(1,("ERROR! Out of connection structures\n"));
+ DEBUG(1,("ERROR! Out of connection structures\n"));
return NULL;
}
tcon->tid = i;
- DLIST_ADD(smb_conn->tcons.list, tcon);
+ DLIST_ADD(tcons_ctx->list, tcon);
talloc_set_destructor(tcon, smbsrv_tcon_destructor);
/* now fill in some statistics */
@@ -113,3 +152,13 @@ struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn)
return tcon;
}
+
+struct smbsrv_tcon *smbsrv_smb_tcon_new(struct smbsrv_connection *smb_conn)
+{
+ return smbsrv_tcon_new(smb_conn, NULL);
+}
+
+struct smbsrv_tcon *smbsrv_smb2_tcon_new(struct smbsrv_session *smb_sess)
+{
+ return smbsrv_tcon_new(smb_sess->smb_conn, smb_sess);
+}