[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha7-1752-g202509a

Stefan Metzmacher metze at samba.org
Fri May 22 12:21:35 GMT 2009


The branch, master has been updated
       via  202509a3479b7bba9a5dfce58270fb8f46cc496a (commit)
       via  7dfbb2835f395105982c8e42529c468de3cffcb4 (commit)
       via  7749647740e945cf63e3df76545c04129d592429 (commit)
      from  edd9bd9b167cb04290b06eb9b209c21ad5a884a0 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 202509a3479b7bba9a5dfce58270fb8f46cc496a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 22 12:42:24 2009 +0200

    s3:smbd: implement SMB2 Tree Disconnect
    
    metze

commit 7dfbb2835f395105982c8e42529c468de3cffcb4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 15 11:50:20 2009 +0200

    s3:smbd: implement SMB2 Tree Connect
    
    For now this only checks if the share is present or not.
    
    metze

commit 7749647740e945cf63e3df76545c04129d592429
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 22 11:06:54 2009 +0200

    s3:smbd: SMB2 session ids are 64bit...
    
    We only grand ids up to 0x0000000000FFFFFF,
    because that's what our idtree implementation can handle.
    But also 16777215 sessions on one tcp connection should be enough:-)
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 source3/Makefile.in           |    2 +-
 source3/smbd/globals.h        |   24 ++++
 source3/smbd/smb2_server.c    |   58 ++++++++++-
 source3/smbd/smb2_sesssetup.c |   17 +++-
 source3/smbd/smb2_tcon.c      |  232 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 327 insertions(+), 6 deletions(-)
 create mode 100644 source3/smbd/smb2_tcon.c


Changeset truncated at 500 lines:

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 68d5488..1ad1f5a 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -749,7 +749,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
 	       smbd/file_access.o \
 	       smbd/dnsregister.o smbd/globals.o \
 	       smbd/smb2_server.o smbd/smb2_negprot.o \
-	       smbd/smb2_sesssetup.o \
+	       smbd/smb2_sesssetup.o smbd/smb2_tcon.o \
 	       smbd/smb2_keepalive.o \
 	       $(MANGLE_OBJ) @VFS_STATIC@
 
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index c03da19..9d5eead 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -202,6 +202,7 @@ extern int num_children;
 struct tstream_context;
 struct smbd_smb2_request;
 struct smbd_smb2_session;
+struct smbd_smb2_tcon;
 
 DATA_BLOB negprot_spnego(void);
 
@@ -222,10 +223,13 @@ NTSTATUS smbd_smb2_request_done(struct smbd_smb2_request *req,
 				DATA_BLOB body, DATA_BLOB *dyn);
 
 NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req);
+NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req);
 
 NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req);
 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req);
 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req);
+NTSTATUS smbd_smb2_request_process_tcon(struct smbd_smb2_request *req);
+NTSTATUS smbd_smb2_request_process_tdis(struct smbd_smb2_request *req);
 NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req);
 
 struct smbd_smb2_request {
@@ -236,6 +240,9 @@ struct smbd_smb2_request {
 	/* the session the request operates on, maybe NULL */
 	struct smbd_smb2_session *session;
 
+	/* the tcon the request operates on, maybe NULL */
+	struct smbd_smb2_tcon *tcon;
+
 	int current_idx;
 
 	struct {
@@ -292,6 +299,23 @@ struct smbd_smb2_session {
 	NTSTATUS status;
 	uint64_t vuid;
 	AUTH_NTLMSSP_STATE *auth_ntlmssp_state;
+
+	struct {
+		/* an id tree used to allocate tids */
+		struct idr_context *idtree;
+
+		/* this is the limit of tid values for this connection */
+		uint32_t limit;
+
+		struct smbd_smb2_tcon *list;
+	} tcons;
+};
+
+struct smbd_smb2_tcon {
+	struct smbd_smb2_tcon *prev, *next;
+	struct smbd_smb2_session *session;
+	uint32_t tid;
+	int snum;
 };
 
 struct smbd_server_connection {
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 83ce7c4..32bb554 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -59,7 +59,7 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *conn)
 	if (conn->smb2.sessions.idtree == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
-	conn->smb2.sessions.limit = 0x0000FFFF;
+	conn->smb2.sessions.limit = 0x00FFFFFF;
 	conn->smb2.sessions.list = NULL;
 
 	ret = tstream_bsd_existing_socket(conn, smbd_server_fd(),
@@ -315,20 +315,28 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
-		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+		return smbd_smb2_request_process_tcon(req);
 
 	case SMB2_OP_TDIS:
 		status = smbd_smb2_request_check_session(req);
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
-		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
+		return smbd_smb2_request_process_tdis(req);
 
 	case SMB2_OP_CREATE:
 		status = smbd_smb2_request_check_session(req);
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_CLOSE:
@@ -336,6 +344,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_FLUSH:
@@ -343,6 +355,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_READ:
@@ -350,6 +366,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_WRITE:
@@ -357,6 +377,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_LOCK:
@@ -364,6 +388,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_IOCTL:
@@ -371,6 +399,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_CANCEL:
@@ -384,6 +416,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_NOTIFY:
@@ -391,6 +427,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_GETINFO:
@@ -398,6 +438,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_SETINFO:
@@ -405,6 +449,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
 	case SMB2_OP_BREAK:
@@ -412,6 +460,10 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
+		status = smbd_smb2_request_check_tcon(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 	}
 
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 50476bf..fafda24 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -71,7 +71,7 @@ NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
-	in_session_id = SVAL(inhdr, SMB2_HDR_SESSION_ID);
+	in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
 	in_security_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
 	in_security_buffer.length = in_security_length;
 
@@ -115,6 +115,11 @@ static int smbd_smb2_session_destructor(struct smbd_smb2_session *session)
 		return 0;
 	}
 
+	/* first free all tcons */
+	while (session->tcons.list) {
+		talloc_free(session->tcons.list);
+	}
+
 	idr_remove(session->conn->smb2.sessions.idtree, session->vuid);
 	DLIST_REMOVE(session->conn->smb2.sessions.list, session);
 
@@ -150,6 +155,14 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req,
 			return NT_STATUS_INSUFFICIENT_RESOURCES;
 		}
 		session->vuid = id;
+
+		session->tcons.idtree = idr_init(session);
+		if (session->tcons.idtree == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		session->tcons.limit = 0x00FFFFFF;
+		session->tcons.list = NULL;
+
 		DLIST_ADD_END(req->conn->smb2.sessions.list, session,
 			      struct smbd_smb2_session *);
 		session->conn = req->conn;
@@ -207,7 +220,7 @@ NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
 
 	inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
 
-	in_session_id = SVAL(inhdr, SMB2_HDR_SESSION_ID);
+	in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
 
 	/* lookup an existing session */
 	p = idr_find(req->conn->smb2.sessions.idtree, in_session_id);
diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c
new file mode 100644
index 0000000..f74d1bc
--- /dev/null
+++ b/source3/smbd/smb2_tcon.c
@@ -0,0 +1,232 @@
+/*
+   Unix SMB/CIFS implementation.
+   Core SMB2 server
+
+   Copyright (C) Stefan Metzmacher 2009
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "smbd/globals.h"
+#include "../source4/libcli/smb2/smb2_constants.h"
+
+static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
+				       const char *share,
+				       uint32_t *out_tree_id);
+
+NTSTATUS smbd_smb2_request_process_tcon(struct smbd_smb2_request *req)
+{
+	const uint8_t *inbody;
+	int i = req->current_idx;
+	uint8_t *outhdr;
+	DATA_BLOB outbody;
+	size_t expected_body_size = 0x09;
+	size_t body_size;
+	uint16_t in_path_offset;
+	uint16_t in_path_length;
+	DATA_BLOB in_path_buffer;
+	char *in_path_string;
+	size_t in_path_string_size;
+	uint32_t out_tree_id;
+	NTSTATUS status;
+	bool ok;
+
+	if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+
+	inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
+
+	body_size = SVAL(inbody, 0x00);
+	if (body_size != expected_body_size) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+
+	in_path_offset = SVAL(inbody, 0x04);
+	in_path_length = SVAL(inbody, 0x06);
+
+	if (in_path_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+
+	if (in_path_length > req->in.vector[i+2].iov_len) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+
+	in_path_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
+	in_path_buffer.length = in_path_length;
+
+	ok = convert_string_talloc(req, CH_UTF16, CH_UNIX,
+				   in_path_buffer.data,
+				   in_path_buffer.length,
+				   &in_path_string,
+				   &in_path_string_size, false);
+	if (!ok) {
+		return smbd_smb2_request_error(req, NT_STATUS_ILLEGAL_CHARACTER);
+	}
+
+	status = smbd_smb2_tree_connect(req, in_path_string, &out_tree_id);
+	if (!NT_STATUS_IS_OK(status)) {
+		return smbd_smb2_request_error(req, status);
+	}
+
+	outhdr = (uint8_t *)req->out.vector[i].iov_base;
+
+	outbody = data_blob_talloc(req->out.vector, NULL, 0x10);
+	if (outbody.data == NULL) {
+		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+	}
+
+	SIVAL(outhdr, SMB2_HDR_TID, out_tree_id);
+
+	SSVAL(outbody.data, 0x00, 0x10);	/* struct size */
+	SCVAL(outbody.data, 0x02, 0);		/* share type */
+	SCVAL(outbody.data, 0x03, 0);		/* reserved */
+	SIVAL(outbody.data, 0x04, 0);		/* share flags */
+	SIVAL(outbody.data, 0x08, 0);		/* capabilities */
+	SIVAL(outbody.data, 0x0C, 0);		/* maximal access */
+
+	return smbd_smb2_request_done(req, outbody, NULL);
+}
+
+static int smbd_smb2_tcon_destructor(struct smbd_smb2_tcon *tcon)
+{
+	if (tcon->session == NULL) {
+		return 0;
+	}
+
+	idr_remove(tcon->session->tcons.idtree, tcon->tid);
+	DLIST_REMOVE(tcon->session->tcons.list, tcon);
+
+	tcon->tid = 0;
+	tcon->session = NULL;
+
+	return 0;
+}
+
+static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
+				       const char *in_path,
+				       uint32_t *out_tree_id)
+{
+	const char *share = in_path;
+	fstring service;
+	int snum = -1;
+	struct smbd_smb2_tcon *tcon;
+	int id;
+
+	if (strncmp(share, "\\\\", 2) == 0) {
+		const char *p = strchr(share+2, '\\');
+		if (p) {
+			share = p + 1;
+		}
+	}
+
+	DEBUG(10,("smbd_smb2_tree_connect: path[%s] share[%s]\n",
+		  in_path, share));
+
+	fstrcpy(service, share);
+
+	strlower_m(service);
+
+	snum = find_service(service);
+	if (snum < 0) {
+		DEBUG(1,("smbd_smb2_tree_connect: couldn't find service %s\n",
+			 service));
+		return NT_STATUS_BAD_NETWORK_NAME;
+	}
+
+	/* TODO: do more things... */
+
+	/* create a new tcon as child of the session */
+	tcon = talloc_zero(req->session, struct smbd_smb2_tcon);
+	if (tcon == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	id = idr_get_new_random(req->session->tcons.idtree,
+				tcon,
+				req->session->tcons.limit);
+	if (id == -1) {
+		return NT_STATUS_INSUFFICIENT_RESOURCES;
+	}
+	tcon->tid = id;
+	tcon->snum = snum;
+
+	DLIST_ADD_END(req->session->tcons.list, tcon,
+		      struct smbd_smb2_tcon *);
+	tcon->session = req->session;
+	talloc_set_destructor(tcon, smbd_smb2_tcon_destructor);
+
+	*out_tree_id = tcon->tid;
+	return NT_STATUS_OK;
+}
+
+NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
+{
+	const uint8_t *inhdr;
+	int i = req->current_idx;
+	uint32_t in_tid;
+	void *p;
+	struct smbd_smb2_tcon *tcon;
+
+	inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
+
+	in_tid = IVAL(inhdr, SMB2_HDR_TID);
+
+	/* lookup an existing session */
+	p = idr_find(req->session->tcons.idtree, in_tid);
+	if (p == NULL) {
+		return NT_STATUS_NETWORK_NAME_DELETED;
+	}
+	tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
+
+	req->tcon = tcon;
+	return NT_STATUS_OK;
+}
+
+NTSTATUS smbd_smb2_request_process_tdis(struct smbd_smb2_request *req)
+{
+	const uint8_t *inbody;
+	int i = req->current_idx;
+	DATA_BLOB outbody;
+	size_t expected_body_size = 0x04;
+	size_t body_size;
+
+	if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list