[SCM] Samba Shared Repository - branch v4-0-test updated - release-4-0-0alpha2-766-g9dc2847

Andrew Tridgell tridge at samba.org
Tue Feb 12 05:21:06 GMT 2008


The branch, v4-0-test has been updated
       via  9dc284770df9393a1a619735dc7a148713936fa7 (commit)
       via  7d3ffd4d2b59d7c87c0a81030f349db21c071967 (commit)
       via  3beaa04ef73ca21925d41745b30b6bbaadb7b939 (commit)
       via  55af8acc7b32c24e4b1187e9d8d1c8f060e914b0 (commit)
      from  ab19a8f62719eb0f347696a2e5f34f8847fd82cb (commit)

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


- Log -----------------------------------------------------------------
commit 9dc284770df9393a1a619735dc7a148713936fa7
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Feb 12 16:20:13 2008 +1100

    converted the out side of SMB2 negprot handling
    
    This follows the SMB2 PFIF docs. Current versions of Vista can now connect to Samba4 as a SMB2 server
    and do basic operations

commit 7d3ffd4d2b59d7c87c0a81030f349db21c071967
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Feb 12 16:18:51 2008 +1100

    added some helper functions for GUID handling

commit 3beaa04ef73ca21925d41745b30b6bbaadb7b939
Merge: 55af8acc7b32c24e4b1187e9d8d1c8f060e914b0 ab19a8f62719eb0f347696a2e5f34f8847fd82cb
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Feb 12 12:56:30 2008 +1100

    Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-test

commit 55af8acc7b32c24e4b1187e9d8d1c8f060e914b0
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Feb 12 12:54:44 2008 +1100

    fixed up the .in side of SMB2 negprot
    
    fixed the input side of the SMB2 negprot structure and parsers according to the documentation

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

Summary of changes:
 source/libcli/raw/rawnegotiate.c |    4 ++
 source/libcli/raw/rawrequest.c   |   41 ++++++++++++++++++
 source/libcli/smb2/connect.c     |    8 +++-
 source/libcli/smb2/negprot.c     |   54 +++++++++++++++--------
 source/libcli/smb2/smb2_calls.h  |   37 ++++++++--------
 source/smb_server/smb/negprot.c  |    1 +
 source/smb_server/smb2/negprot.c |   87 +++++++++++++++++++++++++------------
 source/smb_server/smb_server.h   |    2 +-
 8 files changed, 167 insertions(+), 67 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/libcli/raw/rawnegotiate.c b/source/libcli/raw/rawnegotiate.c
index fc7725c..1f5e347 100644
--- a/source/libcli/raw/rawnegotiate.c
+++ b/source/libcli/raw/rawnegotiate.c
@@ -40,6 +40,10 @@ static const struct {
 	{PROTOCOL_LANMAN2,"Samba"},
 	{PROTOCOL_NT1,"NT LANMAN 1.0"},
 	{PROTOCOL_NT1,"NT LM 0.12"},
+#if 0
+	/* we don't yet handle chaining a SMB transport onto SMB2 */
+	{PROTOCOL_SMB2,"SMB 2.002"},
+#endif
 };
 
 /*
diff --git a/source/libcli/raw/rawrequest.c b/source/libcli/raw/rawrequest.c
index e7dffaf..3551e5d 100644
--- a/source/libcli/raw/rawrequest.c
+++ b/source/libcli/raw/rawrequest.c
@@ -972,3 +972,44 @@ size_t smbcli_blob_append_string(struct smbcli_session *session,
 
 	return len;
 }
+
+/*
+  pull a GUID structure from the wire. The buffer must be at least 16
+  bytes long
+ */
+enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset, 
+				   struct GUID *guid)
+{
+	DATA_BLOB blob;
+	TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+	enum ndr_err_code ndr_err;
+
+	ZERO_STRUCTP(guid);
+
+	blob.data       = offset + (uint8_t *)base;
+	blob.length     = 16;
+	ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid, 
+				       (ndr_pull_flags_fn_t)ndr_pull_GUID);
+	talloc_free(tmp_ctx);
+	return ndr_err;
+}
+
+/*
+  push a guid onto the wire. The buffer must hold 16 bytes
+ */
+enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset, 
+				   const struct GUID *guid)
+{
+	TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+	enum ndr_err_code ndr_err;
+	DATA_BLOB blob;
+	ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
+				       guid, (ndr_push_flags_fn_t)ndr_push_GUID);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
+		talloc_free(tmp_ctx);
+		return ndr_err;
+	}
+	memcpy(offset + (uint8_t *)base, blob.data, blob.length);
+	talloc_free(tmp_ctx);
+	return ndr_err;
+}
diff --git a/source/libcli/smb2/connect.c b/source/libcli/smb2/connect.c
index 4518203..a2ae828 100644
--- a/source/libcli/smb2/connect.c
+++ b/source/libcli/smb2/connect.c
@@ -120,6 +120,7 @@ static void continue_socket(struct composite_context *creq)
 	struct smbcli_socket *sock;
 	struct smb2_transport *transport;
 	struct smb2_request *req;
+	uint16_t dialects[1];
 
 	c->status = smbcli_sock_connect_recv(creq, state, &sock);
 	if (!composite_is_ok(c)) return;
@@ -128,7 +129,12 @@ static void continue_socket(struct composite_context *creq)
 	if (composite_nomem(transport, c)) return;
 
 	ZERO_STRUCT(state->negprot);
-	state->negprot.in.unknown1 = 0x0001;
+	state->negprot.in.dialect_count = 1;
+	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;
+	state->negprot.in.dialects = dialects;
 
 	req = smb2_negprot_send(transport, &state->negprot);
 	if (composite_nomem(req, c)) return;
diff --git a/source/libcli/smb2/negprot.c b/source/libcli/smb2/negprot.c
index 38fe0e7..6b879e2 100644
--- a/source/libcli/smb2/negprot.c
+++ b/source/libcli/smb2/negprot.c
@@ -31,16 +31,28 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport,
 				       struct smb2_negprot *io)
 {
 	struct smb2_request *req;
-	
-	req = smb2_request_init(transport, SMB2_OP_NEGPROT, 0x26, false, 0);
+	uint16_t size = 0x24 + io->in.dialect_count*2;
+	enum ndr_err_code ndr_err;
+	int i;
+
+	req = smb2_request_init(transport, SMB2_OP_NEGPROT, size, false, 0);
 	if (req == NULL) return NULL;
 
-	/* this seems to be a bug, they use 0x24 but the length is 0x26 */
-	SSVAL(req->out.body, 0x00, 0x24);
 
-	SSVAL(req->out.body, 0x02, io->in.unknown1);
-	memcpy(req->out.body+0x04, io->in.unknown2, 32);
-	SSVAL(req->out.body, 0x24, io->in.unknown3);
+	SSVAL(req->out.body, 0x00, 0x24);
+	SSVAL(req->out.body, 0x02, io->in.dialect_count);
+	SSVAL(req->out.body, 0x04, io->in.security_mode);
+	SSVAL(req->out.body, 0x06, io->in.reserved);
+	SIVAL(req->out.body, 0x08, io->in.capabilities);
+	ndr_err = smbcli_push_guid(req->out.body, 0x0C, &io->in.client_guid);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		talloc_free(req);
+		return NULL;
+	}
+	smbcli_push_nttime(req->out.body, 0x1C, io->in.start_time);
+	for (i=0;i<io->in.dialect_count;i++) {
+		SSVAL(req->out.body, 0x24 + i*2, io->in.dialects[i]);		
+	}
 
 	smb2_transport_send(req);
 
@@ -54,6 +66,7 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
 			   struct smb2_negprot *io)
 {
 	NTSTATUS status;
+	enum ndr_err_code ndr_err;
 
 	if (!smb2_request_receive(req) ||
 	    smb2_request_is_error(req)) {
@@ -62,24 +75,27 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
 
 	SMB2_CHECK_PACKET_RECV(req, 0x40, true);
 
-	io->out._pad         = SVAL(req->in.body, 0x02);
-	io->out.unknown2     = IVAL(req->in.body, 0x04);
-	memcpy(io->out.sessid, req->in.body + 0x08, 16);
-	io->out.unknown3     = IVAL(req->in.body, 0x18);
-	io->out.unknown4     = SVAL(req->in.body, 0x1C);
-	io->out.unknown5     = IVAL(req->in.body, 0x1E);
-	io->out.unknown6     = IVAL(req->in.body, 0x22);
-	io->out.unknown7     = SVAL(req->in.body, 0x26);
-	io->out.current_time = smbcli_pull_nttime(req->in.body, 0x28);
-	io->out.boot_time    = smbcli_pull_nttime(req->in.body, 0x30);
+	io->out.security_mode      = SVAL(req->in.body, 0x02);
+	io->out.dialect_revision   = SVAL(req->in.body, 0x04);
+	io->out.reserved           = SVAL(req->in.body, 0x06);
+	ndr_err = smbcli_pull_guid(req->in.body, 0x08, &io->in.client_guid);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		smb2_request_destroy(req);
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+	io->out.capabilities       = IVAL(req->in.body, 0x18);
+	io->out.max_transact_size  = IVAL(req->in.body, 0x1C);
+	io->out.max_read_size      = IVAL(req->in.body, 0x20);
+	io->out.max_write_size     = IVAL(req->in.body, 0x24);
+	io->out.system_time        = smbcli_pull_nttime(req->in.body, 0x28);
+	io->out.server_start_time  = smbcli_pull_nttime(req->in.body, 0x30);
+	io->out.reserved2          = IVAL(req->in.body, 0x3C);
 
 	status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x38, &io->out.secblob);
 	if (!NT_STATUS_IS_OK(status)) {
 		smb2_request_destroy(req);
 		return status;
 	}
-	
-	io->out.unknown9     = IVAL(req->in.body, 0x3C);
 
 	return smb2_request_destroy(req);
 }
diff --git a/source/libcli/smb2/smb2_calls.h b/source/libcli/smb2/smb2_calls.h
index 6a551da..423d9d1 100644
--- a/source/libcli/smb2/smb2_calls.h
+++ b/source/libcli/smb2/smb2_calls.h
@@ -23,30 +23,31 @@
 
 struct smb2_negprot {
 	struct {
-		/* static body buffer 38 (0x26) bytes */
-		/* uint16_t buffer_code;  0x24 (why?) */
-		uint16_t unknown1;    /* 0x0001 */
-		uint8_t  unknown2[32]; /* all zero */
-		uint16_t unknown3; /* 0x00000 */
+		uint16_t dialect_count;    /* size of dialects array */
+		uint16_t security_mode;    /* 0==signing disabled   
+					      1==signing enabled */
+		uint16_t reserved;
+		uint32_t capabilities;
+		struct GUID client_guid;
+		NTTIME   start_time;
+		uint16_t *dialects;
 	} in;
 	struct {
 		/* static body buffer 64 (0x40) bytes */
 		/* uint16_t buffer_code;  0x41 = 0x40 + 1 */
-		uint16_t _pad;
-		uint32_t unknown2; /* 0x06 */
-		uint8_t  sessid[16];
-		uint32_t unknown3; /* 0x0d */
-		uint16_t unknown4; /* 0x00 */
-		uint32_t unknown5; /* 0x01 */
-		uint32_t unknown6; /* 0x01 */
-		uint16_t unknown7; /* 0x01 */
-		NTTIME   current_time;
-		NTTIME   boot_time;
+		uint16_t security_mode;
+		uint16_t dialect_revision;
+		uint16_t reserved;
+		struct GUID server_guid;
+		uint32_t capabilities;
+		uint32_t max_transact_size;
+		uint32_t max_read_size;
+		uint32_t max_write_size;
+		NTTIME   system_time;
+		NTTIME   server_start_time;
 		/* uint16_t secblob_ofs */
 		/* uint16_t secblob_size */
-		uint32_t unknown9; /* 0x204d4c20 */
-
-		/* dynamic body buffer */
+		uint32_t reserved2;
 		DATA_BLOB secblob;
 	} out;
 };
diff --git a/source/smb_server/smb/negprot.c b/source/smb_server/smb/negprot.c
index 6d9ff83..b57e5e1 100644
--- a/source/smb_server/smb/negprot.c
+++ b/source/smb_server/smb/negprot.c
@@ -466,6 +466,7 @@ static const struct {
 	void (*proto_reply_fn)(struct smbsrv_request *req, uint16_t choice);
 	int protocol_level;
 } supported_protocols[] = {
+	{"SMB 2.002",			"SMB2",		reply_smb2,	PROTOCOL_SMB2},
 	{"SMB 2.001",			"SMB2",		reply_smb2,	PROTOCOL_SMB2},
 	{"NT LANMAN 1.0",		"NT1",		reply_nt1,	PROTOCOL_NT1},
 	{"NT LM 0.12",			"NT1",		reply_nt1,	PROTOCOL_NT1},
diff --git a/source/smb_server/smb2/negprot.c b/source/smb_server/smb2/negprot.c
index 8e3cfd3..043534d 100644
--- a/source/smb_server/smb2/negprot.c
+++ b/source/smb_server/smb2/negprot.c
@@ -21,6 +21,7 @@
 #include "includes.h"
 #include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
+#include "libcli/raw/libcliraw.h"
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
 #include "smb_server/smb_server.h"
@@ -92,24 +93,30 @@ 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 */
+	if (io->in.dialect_count < 1 ||
+	    io->in.dialects[0] != 0) {
+		DEBUG(0,("Got unexpected SMB2 dialect %u\n", io->in.dialects[0]));
+	}
+
 	req->smb_conn->negotiate.protocol = PROTOCOL_SMB2;
 
 	current_time = timeval_current(); /* TODO: handle timezone?! */
 	boot_time = timeval_current(); /* TODO: fix me */
 
-	io->out._pad		= 0;
-	io->out.unknown2	= 0x06;
-	ZERO_STRUCT(io->out.sessid);
-	io->out.unknown3	= 0x0d;
-	io->out.unknown4	= 0x00;
-	io->out.unknown5	= 0x01;
-	io->out.unknown6	= 0x01;
-	io->out.unknown7	= 0x01;
-	io->out.current_time	= timeval_to_nttime(&current_time);
-	io->out.boot_time	= timeval_to_nttime(&boot_time);
+	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.capabilities       = 0;
+	io->out.max_transact_size  = 0x10000;
+	io->out.max_read_size      = 0x10000;
+	io->out.max_write_size     = 0x10000;
+	io->out.system_time	   = timeval_to_nttime(&current_time);
+	io->out.server_start_time  = timeval_to_nttime(&boot_time);
+	io->out.reserved2          = 0;
 	status = smb2srv_negprot_secblob(req, &io->out.secblob);
 	NT_STATUS_NOT_OK_RETURN(status);
-	io->out.unknown9	= 0x204d4c20;
 
 	return NT_STATUS_OK;
 }
@@ -117,6 +124,7 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
 static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negprot *io)
 {
 	NTSTATUS status;
+	enum ndr_err_code ndr_err;
 
 	if (NT_STATUS_IS_ERR(req->status)) {
 		smb2srv_send_error(req, req->status); /* TODO: is this correct? */
@@ -130,16 +138,22 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro
 		return;
 	}
 
-	SSVAL(req->out.body, 0x02, io->out._pad);
-	SIVAL(req->out.body, 0x04, io->out.unknown2);
-	memcpy(req->out.body+0x08, io->out.sessid, 16);
-	SIVAL(req->out.body, 0x18, io->out.unknown3);
-	SSVAL(req->out.body, 0x1C, io->out.unknown4);
-	SIVAL(req->out.body, 0x1E, io->out.unknown5);
-	SIVAL(req->out.body, 0x22, io->out.unknown6);
-	SSVAL(req->out.body, 0x26, io->out.unknown7);
-	push_nttime(req->out.body, 0x28, io->out.current_time);
-	push_nttime(req->out.body, 0x30, io->out.boot_time);
+	SSVAL(req->out.body, 0x02, io->out.security_mode);
+	SIVAL(req->out.body, 0x04, io->out.dialect_revision);
+	SIVAL(req->out.body, 0x06, io->out.reserved);
+	ndr_err = smbcli_push_guid(req->out.body, 0x08, &io->out.server_guid);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
+		talloc_free(req);
+		return;
+	}
+	SIVAL(req->out.body, 0x18, io->out.capabilities);
+	SIVAL(req->out.body, 0x1C, io->out.max_transact_size);
+	SIVAL(req->out.body, 0x20, io->out.max_read_size);
+	SIVAL(req->out.body, 0x24, io->out.max_write_size);
+	push_nttime(req->out.body, 0x28, io->out.system_time);
+	push_nttime(req->out.body, 0x30, io->out.server_start_time);
+	SIVAL(req->out.body, 0x3C, io->out.reserved2);
 	status = smb2_push_o16s16_blob(&req->out, 0x38, io->out.secblob);
 	if (!NT_STATUS_IS_OK(status)) {
 		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
@@ -147,14 +161,14 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro
 		return;
 	}
 
-	SIVAL(req->out.body, 0x3C, io->out.unknown9);
-
 	smb2srv_send_reply(req);
 }
 
 void smb2srv_negprot_recv(struct smb2srv_request *req)
 {
 	struct smb2_negprot *io;
+	int i;
+	enum ndr_err_code ndr_err;
 
 	if (req->in.body_size < 0x26) {
 		smb2srv_send_error(req,  NT_STATUS_FOOBAR);
@@ -168,9 +182,27 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
 		return;
 	}
 
-	io->in.unknown1	= SVAL(req->in.body, 0x02);
-	memcpy(io->in.unknown2, req->in.body + 0x04, 0x20);
-	io->in.unknown3 = SVAL(req->in.body, 0x24);
+	io->in.dialect_count = SVAL(req->in.body, 0x02);
+	io->in.security_mode = SVAL(req->in.body, 0x04);
+	io->in.reserved      = SVAL(req->in.body, 0x06);
+	io->in.capabilities  = IVAL(req->in.body, 0x08);
+	ndr_err = smbcli_pull_guid(req->in.body, 0xC, &io->in.client_guid);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_FOOBAR));
+		talloc_free(req);
+		return;
+	}
+	io->in.start_time = smbcli_pull_nttime(req->in.body, 0x1C);
+
+	io->in.dialects = talloc_array(req, uint16_t, io->in.dialect_count);
+	if (io->in.dialects == NULL) {
+		smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_NO_MEMORY));
+		talloc_free(req);
+		return;
+	}
+	for (i=0;i<io->in.dialect_count;i++) {
+		io->in.dialects[i] = SVAL(req->in.body, 0x24+i*2);
+	}
 
 	req->status = smb2srv_negprot_backend(req, io);
 
@@ -182,14 +214,13 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
 }
 
 /*
- * reply to a SMB negprot request with dialect "SMB 2.001"
+ * reply to a SMB negprot request with dialect "SMB 2.002"
  */
 void smb2srv_reply_smb_negprot(struct smbsrv_request *smb_req)
 {
 	struct smb2srv_request *req;
 	uint32_t body_fixed_size = 0x26;
 
-	/* create a fake SMB2 negprot request */
 	req = talloc_zero(smb_req->smb_conn, struct smb2srv_request);
 	if (!req) goto nomem;
 	req->smb_conn		= smb_req->smb_conn;
diff --git a/source/smb_server/smb_server.h b/source/smb_server/smb_server.h
index 5644dfe..bb0673b 100644
--- a/source/smb_server/smb_server.h
+++ b/source/smb_server/smb_server.h
@@ -291,7 +291,7 @@ struct smbsrv_connection {
 	
 		/* the negotiatiated protocol */
 		enum protocol_types protocol;
-	
+
 		/* authentication context for multi-part negprot */
 		struct auth_context *auth_context;
 	


-- 
Samba Shared Repository


More information about the samba-cvs mailing list