From ccc27e681cbd6283513b929d58f2ebce35e6658b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Feb 2008 12:54:44 +1100 Subject: fixed up the .in side of SMB2 negprot fixed the input side of the SMB2 negprot structure and parsers according to the documentation (This used to be commit 55af8acc7b32c24e4b1187e9d8d1c8f060e914b0) --- source4/libcli/smb2/connect.c | 8 +++++++- source4/libcli/smb2/negprot.c | 31 +++++++++++++++++++++++------- source4/libcli/smb2/smb2_calls.h | 13 ++++++++----- source4/smb_server/smb/negprot.c | 1 + source4/smb_server/smb2/negprot.c | 40 ++++++++++++++++++++++++++++++++++----- source4/smb_server/smb_server.h | 2 +- 6 files changed, 76 insertions(+), 19 deletions(-) (limited to 'source4') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 4518203183..a2ae828fa5 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/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/source4/libcli/smb2/negprot.c b/source4/libcli/smb2/negprot.c index 38fe0e7e53..a678ebe229 100644 --- a/source4/libcli/smb2/negprot.c +++ b/source4/libcli/smb2/negprot.c @@ -31,16 +31,33 @@ 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; + DATA_BLOB guid_blob; + 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); + ndr_err = ndr_push_struct_blob(&guid_blob, req, NULL, + &io->in.client_guid, + (ndr_push_flags_fn_t)ndr_push_GUID); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || guid_blob.length != 16) { + talloc_free(req); + return NULL; + } + + 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); + memcpy(req->out.body+0x0C, guid_blob.data, guid_blob.length); + smbcli_push_nttime(req->out.body, 0x1C, io->in.start_time); + for (i=0;iin.dialect_count;i++) { + SSVAL(req->out.body, 0x24 + i*2, io->in.dialects[i]); + } smb2_transport_send(req); diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index 6a551da4ae..41fb35b8f3 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -23,11 +23,14 @@ 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 */ diff --git a/source4/smb_server/smb/negprot.c b/source4/smb_server/smb/negprot.c index 6d9ff838cb..b57e5e1d64 100644 --- a/source4/smb_server/smb/negprot.c +++ b/source4/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/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c index 8e3cfd3547..68509d71c6 100644 --- a/source4/smb_server/smb2/negprot.c +++ b/source4/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,6 +93,12 @@ 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) { + return NT_STATUS_NOT_SUPPORTED; + } + req->smb_conn->negotiate.protocol = PROTOCOL_SMB2; current_time = timeval_current(); /* TODO: handle timezone?! */ @@ -155,6 +162,9 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro void smb2srv_negprot_recv(struct smb2srv_request *req) { struct smb2_negprot *io; + int i; + DATA_BLOB guid_blob; + enum ndr_err_code ndr_err; if (req->in.body_size < 0x26) { smb2srv_send_error(req, NT_STATUS_FOOBAR); @@ -168,9 +178,30 @@ 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); + guid_blob.data = req->in.body + 0xC; + guid_blob.length = 16; + ndr_err = ndr_pull_struct_blob(&guid_blob, req, NULL, &io->in.client_guid, + (ndr_pull_flags_fn_t)ndr_pull_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;iin.dialect_count;i++) { + io->in.dialects[i] = SVAL(req->in.body, 0x24+i*2); + } req->status = smb2srv_negprot_backend(req, io); @@ -182,14 +213,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/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index 5644dfe6fb..bb0673b7d0 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/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; -- cgit