summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/smb2/connect.c8
-rw-r--r--source4/libcli/smb2/negprot.c31
-rw-r--r--source4/libcli/smb2/smb2_calls.h13
-rw-r--r--source4/smb_server/smb/negprot.c1
-rw-r--r--source4/smb_server/smb2/negprot.c40
-rw-r--r--source4/smb_server/smb_server.h2
6 files changed, 76 insertions, 19 deletions
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;i<io->in.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;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 +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;