[SCM] Samba Shared Repository - branch v4-0-test updated - release-4-0-0alpha2-814-g3aaa2e8

Andrew Tridgell tridge at samba.org
Thu Feb 14 06:12:02 GMT 2008


The branch, v4-0-test has been updated
       via  3aaa2e86d94675c6c68d66d75292c3e34bfbc81b (commit)
      from  f6cdf3f1177f63d80be757f007eb15380839b4f5 (commit)

http://gitweb.samba.org/?samba.git;a=shortlog;h=v4-0-test


- Log -----------------------------------------------------------------
commit 3aaa2e86d94675c6c68d66d75292c3e34bfbc81b
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Feb 14 17:11:36 2008 +1100

    updated SMB2 code for getinfo according to WSPP docs
    
    - Updated getinfo structures and field names
    - also updated the protocol revision number handling to reflect
      new docs

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

Summary of changes:
 source/libcli/smb2/connect.c      |    2 +-
 source/libcli/smb2/getinfo.c      |   45 ++++++++++++++++++++++--------------
 source/libcli/smb2/request.c      |   27 ++++++++++++++++++++++
 source/libcli/smb2/smb2.h         |    3 ++
 source/libcli/smb2/smb2_calls.h   |   24 ++++++++++++++-----
 source/smb_server/smb2/fileinfo.c |   42 ++++++++++++++++------------------
 source/smb_server/smb2/negprot.c  |    9 ++++---
 source/torture/smb2/scan.c        |   15 +++++++-----
 8 files changed, 109 insertions(+), 58 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/libcli/smb2/connect.c b/source/libcli/smb2/connect.c
index 535df11..85ddafc 100644
--- a/source/libcli/smb2/connect.c
+++ b/source/libcli/smb2/connect.c
@@ -133,7 +133,7 @@ static void continue_socket(struct composite_context *creq)
 	state->negprot.in.security_mode = 0;
 	state->negprot.in.capabilities  = 0;
 	unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
-	dialects[0] = 0;
+	dialects[0] = SMB2_DIALECT_REVISION;
 	state->negprot.in.dialects = dialects;
 
 	req = smb2_negprot_send(transport, &state->negprot);
diff --git a/source/libcli/smb2/getinfo.c b/source/libcli/smb2/getinfo.c
index 0665dd4..e9f4714 100644
--- a/source/libcli/smb2/getinfo.c
+++ b/source/libcli/smb2/getinfo.c
@@ -30,21 +30,27 @@
 struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getinfo *io)
 {
 	struct smb2_request *req;
+	NTSTATUS status;
 
-	req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, false, 0);
+	req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, true, 
+				     io->in.blob.length);
 	if (req == NULL) return NULL;
 
-	/* this seems to be a bug, they use 0x29 but only send 0x28 bytes */
-	SSVAL(req->out.body, 0x00, 0x29);
-
-	SSVAL(req->out.body, 0x02, io->in.level);
-	SIVAL(req->out.body, 0x04, io->in.max_response_size);
-	SIVAL(req->out.body, 0x08, io->in.unknown1);
-	SIVAL(req->out.body, 0x0C, io->in.unknown2);
-	SIVAL(req->out.body, 0x10, io->in.flags);
-	SIVAL(req->out.body, 0x14, io->in.flags2);
+	SCVAL(req->out.body, 0x02, io->in.info_type);
+	SCVAL(req->out.body, 0x03, io->in.info_class);
+	SIVAL(req->out.body, 0x04, io->in.output_buffer_length);
+	SIVAL(req->out.body, 0x0C, io->in.reserved);
+	SIVAL(req->out.body, 0x08, io->in.input_buffer_length);
+	SIVAL(req->out.body, 0x10, io->in.additional_information);
+	SIVAL(req->out.body, 0x14, io->in.getinfo_flags);
 	smb2_push_handle(req->out.body+0x18, &io->in.file.handle);
 
+	/* this blob is used for quota queries */
+	status = smb2_push_o32s32_blob(&req->out, 0x08, io->in.blob);
+	if (!NT_STATUS_IS_OK(status)) {
+		talloc_free(req);
+		return NULL;
+	}
 	smb2_transport_send(req);
 
 	return req;
@@ -116,15 +122,17 @@ struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fi
 	}
 
 	ZERO_STRUCT(b);
-	b.in.max_response_size = 0x10000;
-	b.in.file.handle       = io->generic.in.file.handle;
-	b.in.level             = smb2_level;
+	b.in.info_type            = smb2_level & 0xFF;
+	b.in.info_class           = smb2_level >> 8;
+	b.in.output_buffer_length = 0x10000;
+	b.in.input_buffer_length  = 0;
+	b.in.file.handle          = io->generic.in.file.handle;
 
 	if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
-		b.in.flags = io->query_secdesc.in.secinfo_flags;
+		b.in.additional_information = io->query_secdesc.in.secinfo_flags;
 	}
 	if (io->generic.level == RAW_FILEINFO_SMB2_ALL_EAS) {
-		b.in.flags2 = io->all_eas.in.continue_flags;
+		b.in.getinfo_flags = io->all_eas.in.continue_flags;
 	}
 
 	return smb2_getinfo_send(tree, &b);
@@ -172,9 +180,10 @@ struct smb2_request *smb2_getinfo_fs_send(struct smb2_tree *tree, union smb_fsin
 	}
 	
 	ZERO_STRUCT(b);
-	b.in.max_response_size = 0x10000;
-	b.in.file.handle       = io->generic.handle;
-	b.in.level             = smb2_level;
+	b.in.output_buffer_length = 0x10000;
+	b.in.file.handle          = io->generic.handle;
+	b.in.info_type            = smb2_level & 0xFF;
+	b.in.info_class           = smb2_level >> 8;
 
 	return smb2_getinfo_send(tree, &b);
 }
diff --git a/source/libcli/smb2/request.c b/source/libcli/smb2/request.c
index 35229dc..7a0311f 100644
--- a/source/libcli/smb2/request.c
+++ b/source/libcli/smb2/request.c
@@ -549,6 +549,33 @@ NTSTATUS smb2_pull_o32s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_
 }
 
 /*
+  pull a uint16_t ofs/ uint32_t length/blob triple from a data blob
+  the ptr points to the start of the offset/length pair
+  
+  In this varient the uint16_t is padded by an extra 2 bytes, making
+  the size aligned on 4 byte boundary
+*/
+NTSTATUS smb2_pull_o16As32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
+{
+	uint32_t ofs, size;
+	if (smb2_oob(buf, ptr, 8)) {
+		return NT_STATUS_BUFFER_TOO_SMALL;
+	}
+	ofs  = SVAL(ptr, 0);
+	size = IVAL(ptr, 4);
+	if (ofs == 0 || size == 0) {
+		*blob = data_blob(NULL, 0);
+		return NT_STATUS_OK;
+	}
+	if (smb2_oob(buf, buf->hdr + ofs, size)) {
+		return NT_STATUS_BUFFER_TOO_SMALL;
+	}
+	*blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
+	NT_STATUS_HAVE_NO_MEMORY(blob->data);
+	return NT_STATUS_OK;
+}
+
+/*
   pull a uint32_t length/ uint32_t ofs/blob triple from a data blob
   the ptr points to the start of the offset/length pair
 */
diff --git a/source/libcli/smb2/smb2.h b/source/libcli/smb2/smb2.h
index af08b01..726df64 100644
--- a/source/libcli/smb2/smb2.h
+++ b/source/libcli/smb2/smb2.h
@@ -200,6 +200,9 @@ struct smb2_request {
 
 #define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */
 
+/* the dialect we support */
+#define SMB2_DIALECT_REVISION           0x202
+
 /* SMB2 negotiate security_mode */
 #define SMB2_NEGOTIATE_SIGNING_ENABLED   0x01
 #define SMB2_NEGOTIATE_SIGNING_REQUIRED  0x02
diff --git a/source/libcli/smb2/smb2_calls.h b/source/libcli/smb2/smb2_calls.h
index f2e3019..f66236a 100644
--- a/source/libcli/smb2/smb2_calls.h
+++ b/source/libcli/smb2/smb2_calls.h
@@ -56,6 +56,13 @@ struct smb2_negprot {
 #define SMB2_GETINFO_FILE               0x01
 #define SMB2_GETINFO_FS                 0x02
 #define SMB2_GETINFO_SECURITY           0x03
+#define SMB2_GETINFO_QUOTA              0x04
+
+#define SMB2_GETINFO_ADD_OWNER_SECURITY 0x01
+#define SMB2_GETINFO_ADD_GROUP_SECURITY 0x02
+#define SMB2_GETINFO_ADD_DACL_SECURITY  0x04
+#define SMB2_GETINFO_ADD_SACL_SECURITY  0x08
+#define SMB2_GETINFO_ADD_LABEL_SECURITY 0x10
 
 /* NOTE! the getinfo fs and file levels exactly match up with the
    'passthru' SMB levels, which are levels >= 1000. The SMB2 client
@@ -64,14 +71,17 @@ struct smb2_negprot {
 struct smb2_getinfo {
 	struct {
 		/* static body buffer 40 (0x28) bytes */
-		/* uint16_t buffer_code;  0x29 = 0x28 + 1 (why???) */
-		uint16_t level;
-		uint32_t max_response_size;
-		uint32_t unknown1;
-		uint32_t unknown2;
-		uint32_t flags; /* level specific */
-		uint32_t flags2; /* used by all_eas level */
+		/* uint16_t buffer_code;  0x29 = 0x28 + 1 */
+		uint8_t info_type;
+		uint8_t info_class;
+		uint32_t output_buffer_length;
+		/* uint32_t input_buffer_offset; */
+		uint32_t reserved;
+		uint32_t input_buffer_length;
+		uint32_t additional_information; /* SMB2_GETINFO_ADD_* */
+		uint32_t getinfo_flags; /* level specific */
 		union smb_handle file;
+		DATA_BLOB blob;
 	} in;
 
 	struct {
diff --git a/source/smb_server/smb2/fileinfo.c b/source/smb_server/smb2/fileinfo.c
index e652199..d6db61e 100644
--- a/source/smb_server/smb2/fileinfo.c
+++ b/source/smb_server/smb2/fileinfo.c
@@ -79,19 +79,21 @@ static NTSTATUS smb2srv_getinfo_file_send(struct smb2srv_getinfo_op *op)
 static NTSTATUS smb2srv_getinfo_file(struct smb2srv_getinfo_op *op, uint8_t smb2_level)
 {
 	union smb_fileinfo *io;
+	uint16_t level;
 
 	io = talloc(op, union smb_fileinfo);
 	NT_STATUS_HAVE_NO_MEMORY(io);
 
-	switch (op->info->in.level) {
+	level = op->info->in.info_type | (op->info->in.info_class << 8);
+	switch (level) {
 	case RAW_FILEINFO_SMB2_ALL_EAS:
-		io->all_eas.level		= op->info->in.level;
+		io->all_eas.level		= level;
 		io->all_eas.in.file.ntvfs	= op->info->in.file.ntvfs;
-		io->all_eas.in.continue_flags	= op->info->in.flags2;
+		io->all_eas.in.continue_flags	= op->info->in.getinfo_flags;
 		break;
 
 	case RAW_FILEINFO_SMB2_ALL_INFORMATION:
-		io->all_info2.level		= op->info->in.level;
+		io->all_info2.level		= level;
 		io->all_info2.in.file.ntvfs	= op->info->in.file.ntvfs;
 		break;
 
@@ -166,7 +168,7 @@ static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, uint8_t
 
 		io->query_secdesc.level			= RAW_FILEINFO_SEC_DESC;
 		io->query_secdesc.in.file.ntvfs		= op->info->in.file.ntvfs;
-		io->query_secdesc.in.secinfo_flags	= op->info->in.flags;
+		io->query_secdesc.in.secinfo_flags	= op->info->in.additional_information;
 
 		op->io_ptr	= io;
 		op->send_fn	= smb2srv_getinfo_security_send;
@@ -179,23 +181,17 @@ static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, uint8_t
 
 static NTSTATUS smb2srv_getinfo_backend(struct smb2srv_getinfo_op *op)
 {
-	uint8_t smb2_class;
-	uint8_t smb2_level;
-
-	smb2_class = 0xFF & op->info->in.level;
-	smb2_level = 0xFF & (op->info->in.level>>8);
-
-	switch (smb2_class) {
+	switch (op->info->in.info_type) {
 	case SMB2_GETINFO_FILE:
-		return smb2srv_getinfo_file(op, smb2_level);
+		return smb2srv_getinfo_file(op, op->info->in.info_class);
 
 	case SMB2_GETINFO_FS:
-		return smb2srv_getinfo_fs(op, smb2_level);
+		return smb2srv_getinfo_fs(op, op->info->in.info_class);
 
 	case SMB2_GETINFO_SECURITY:
-		return smb2srv_getinfo_security(op, smb2_level);
+		return smb2srv_getinfo_security(op, op->info->in.info_class);
 
-	case 0x04:
+	case SMB2_GETINFO_QUOTA:
 		return NT_STATUS_NOT_SUPPORTED;
 	}
 
@@ -217,13 +213,15 @@ void smb2srv_getinfo_recv(struct smb2srv_request *req)
 	op->send_fn	= NULL;
 	SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_getinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
 
-	info->in.level			= SVAL(req->in.body, 0x02);
-	info->in.max_response_size	= IVAL(req->in.body, 0x04);
-	info->in.unknown1		= IVAL(req->in.body, 0x08);
-	info->in.unknown2		= IVAL(req->in.body, 0x0C);
-	info->in.flags			= IVAL(req->in.body, 0x10);
-	info->in.flags2			= IVAL(req->in.body, 0x14);
+	info->in.info_type		= CVAL(req->in.body, 0x02);
+	info->in.info_class		= CVAL(req->in.body, 0x03);
+	info->in.output_buffer_length	= IVAL(req->in.body, 0x04);
+	info->in.reserved		= IVAL(req->in.body, 0x0C);
+	info->in.additional_information	= IVAL(req->in.body, 0x10);
+	info->in.getinfo_flags		= IVAL(req->in.body, 0x14);
 	info->in.file.ntvfs		= smb2srv_pull_handle(req, req->in.body, 0x18);
+	SMB2SRV_CHECK(smb2_pull_o16As32_blob(&req->in, op, 
+					    req->in.body+0x08, &info->in.blob));
 
 	SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
 	SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_getinfo_backend(op));
diff --git a/source/smb_server/smb2/negprot.c b/source/smb_server/smb2/negprot.c
index 578eadb..5bbd7f7 100644
--- a/source/smb_server/smb2/negprot.c
+++ b/source/smb_server/smb2/negprot.c
@@ -93,12 +93,14 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
 	struct timeval current_time;
 	struct timeval boot_time;
 
-	/* we only do dialect 0 for now */
+	/* we only do one dialect for now */
 	if (io->in.dialect_count < 1) {
 		return NT_STATUS_NOT_SUPPORTED;
 	}
-	if (io->in.dialects[0] != 0) {
+	if (io->in.dialects[0] != 0 &&
+	    io->in.dialects[0] != SMB2_DIALECT_REVISION) {
 		DEBUG(0,("Got unexpected SMB2 dialect %u\n", io->in.dialects[0]));
+		return NT_STATUS_NOT_SUPPORTED;
 	}
 
 	req->smb_conn->negotiate.protocol = PROTOCOL_SMB2;
@@ -108,8 +110,7 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
 
 	ZERO_STRUCT(io->out);
 	io->out.security_mode      = 0; /* no signing yet */
-	 /* choose the first dialect offered for now */
-	io->out.dialect_revision   = io->in.dialects[0];
+	io->out.dialect_revision   = SMB2_DIALECT_REVISION;
 	io->out.capabilities       = 0;
 	io->out.max_transact_size  = 0x10000;
 	io->out.max_read_size      = 0x10000;
diff --git a/source/torture/smb2/scan.c b/source/torture/smb2/scan.c
index 84be11c..0f4c9fe 100644
--- a/source/torture/smb2/scan.c
+++ b/source/torture/smb2/scan.c
@@ -68,19 +68,21 @@ bool torture_smb2_getinfo_scan(struct torture_context *torture)
 
 
 	ZERO_STRUCT(io);
-	io.in.max_response_size = 0xFFFF;
+	io.in.output_buffer_length = 0xFFFF;
 
 	for (c=1;c<5;c++) {
 		for (i=0;i<0x100;i++) {
-			io.in.level = (i<<8) | c;
+			io.in.info_type = c;
+			io.in.info_class = i;
 
 			io.in.file.handle = fhandle;
 			status = smb2_getinfo(tree, torture, &io);
 			if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) &&
 			    !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) &&
 			    !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
-				printf("file level 0x%04x is %ld bytes - %s\n", 
-				       io.in.level, (long)io.out.blob.length, nt_errstr(status));
+				printf("file level 0x%02x:%02x is %ld bytes - %s\n", 
+				       io.in.info_type, io.in.info_class, 
+				       (long)io.out.blob.length, nt_errstr(status));
 				dump_data(1, io.out.blob.data, io.out.blob.length);
 			}
 
@@ -89,8 +91,9 @@ bool torture_smb2_getinfo_scan(struct torture_context *torture)
 			if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) &&
 			    !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) &&
 			    !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
-				printf("dir  level 0x%04x is %ld bytes - %s\n", 
-				       io.in.level, (long)io.out.blob.length, nt_errstr(status));
+				printf("dir  level 0x%02x:%02x is %ld bytes - %s\n", 
+				       io.in.info_type, io.in.info_class,
+				       (long)io.out.blob.length, nt_errstr(status));
 				dump_data(1, io.out.blob.data, io.out.blob.length);
 			}
 		}


-- 
Samba Shared Repository


More information about the samba-cvs mailing list