mirror of
https://github.com/samba-team/samba.git
synced 2025-02-08 05:57:51 +03:00
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 (This used to be commit 9dc284770df9393a1a619735dc7a148713936fa7)
This commit is contained in:
parent
7b96c53bcb
commit
8fdb9504dc
@ -40,6 +40,10 @@ static const struct {
|
|||||||
{PROTOCOL_LANMAN2,"Samba"},
|
{PROTOCOL_LANMAN2,"Samba"},
|
||||||
{PROTOCOL_NT1,"NT LANMAN 1.0"},
|
{PROTOCOL_NT1,"NT LANMAN 1.0"},
|
||||||
{PROTOCOL_NT1,"NT LM 0.12"},
|
{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
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -32,7 +32,6 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport,
|
|||||||
{
|
{
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
uint16_t size = 0x24 + io->in.dialect_count*2;
|
uint16_t size = 0x24 + io->in.dialect_count*2;
|
||||||
DATA_BLOB guid_blob;
|
|
||||||
enum ndr_err_code ndr_err;
|
enum ndr_err_code ndr_err;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -40,20 +39,16 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport,
|
|||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
|
|
||||||
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, 0x00, 0x24);
|
||||||
SSVAL(req->out.body, 0x02, io->in.dialect_count);
|
SSVAL(req->out.body, 0x02, io->in.dialect_count);
|
||||||
SSVAL(req->out.body, 0x04, io->in.security_mode);
|
SSVAL(req->out.body, 0x04, io->in.security_mode);
|
||||||
SSVAL(req->out.body, 0x06, io->in.reserved);
|
SSVAL(req->out.body, 0x06, io->in.reserved);
|
||||||
SIVAL(req->out.body, 0x08, io->in.capabilities);
|
SIVAL(req->out.body, 0x08, io->in.capabilities);
|
||||||
memcpy(req->out.body+0x0C, guid_blob.data, guid_blob.length);
|
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);
|
smbcli_push_nttime(req->out.body, 0x1C, io->in.start_time);
|
||||||
for (i=0;i<io->in.dialect_count;i++) {
|
for (i=0;i<io->in.dialect_count;i++) {
|
||||||
SSVAL(req->out.body, 0x24 + i*2, io->in.dialects[i]);
|
SSVAL(req->out.body, 0x24 + i*2, io->in.dialects[i]);
|
||||||
@ -71,6 +66,7 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
|||||||
struct smb2_negprot *io)
|
struct smb2_negprot *io)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
enum ndr_err_code ndr_err;
|
||||||
|
|
||||||
if (!smb2_request_receive(req) ||
|
if (!smb2_request_receive(req) ||
|
||||||
smb2_request_is_error(req)) {
|
smb2_request_is_error(req)) {
|
||||||
@ -79,24 +75,27 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
|||||||
|
|
||||||
SMB2_CHECK_PACKET_RECV(req, 0x40, true);
|
SMB2_CHECK_PACKET_RECV(req, 0x40, true);
|
||||||
|
|
||||||
io->out._pad = SVAL(req->in.body, 0x02);
|
io->out.security_mode = SVAL(req->in.body, 0x02);
|
||||||
io->out.unknown2 = IVAL(req->in.body, 0x04);
|
io->out.dialect_revision = SVAL(req->in.body, 0x04);
|
||||||
memcpy(io->out.sessid, req->in.body + 0x08, 16);
|
io->out.reserved = SVAL(req->in.body, 0x06);
|
||||||
io->out.unknown3 = IVAL(req->in.body, 0x18);
|
ndr_err = smbcli_pull_guid(req->in.body, 0x08, &io->in.client_guid);
|
||||||
io->out.unknown4 = SVAL(req->in.body, 0x1C);
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||||
io->out.unknown5 = IVAL(req->in.body, 0x1E);
|
smb2_request_destroy(req);
|
||||||
io->out.unknown6 = IVAL(req->in.body, 0x22);
|
return NT_STATUS_INTERNAL_ERROR;
|
||||||
io->out.unknown7 = SVAL(req->in.body, 0x26);
|
}
|
||||||
io->out.current_time = smbcli_pull_nttime(req->in.body, 0x28);
|
io->out.capabilities = IVAL(req->in.body, 0x18);
|
||||||
io->out.boot_time = smbcli_pull_nttime(req->in.body, 0x30);
|
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);
|
status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x38, &io->out.secblob);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
smb2_request_destroy(req);
|
smb2_request_destroy(req);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
io->out.unknown9 = IVAL(req->in.body, 0x3C);
|
|
||||||
|
|
||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
@ -35,21 +35,19 @@ struct smb2_negprot {
|
|||||||
struct {
|
struct {
|
||||||
/* static body buffer 64 (0x40) bytes */
|
/* static body buffer 64 (0x40) bytes */
|
||||||
/* uint16_t buffer_code; 0x41 = 0x40 + 1 */
|
/* uint16_t buffer_code; 0x41 = 0x40 + 1 */
|
||||||
uint16_t _pad;
|
uint16_t security_mode;
|
||||||
uint32_t unknown2; /* 0x06 */
|
uint16_t dialect_revision;
|
||||||
uint8_t sessid[16];
|
uint16_t reserved;
|
||||||
uint32_t unknown3; /* 0x0d */
|
struct GUID server_guid;
|
||||||
uint16_t unknown4; /* 0x00 */
|
uint32_t capabilities;
|
||||||
uint32_t unknown5; /* 0x01 */
|
uint32_t max_transact_size;
|
||||||
uint32_t unknown6; /* 0x01 */
|
uint32_t max_read_size;
|
||||||
uint16_t unknown7; /* 0x01 */
|
uint32_t max_write_size;
|
||||||
NTTIME current_time;
|
NTTIME system_time;
|
||||||
NTTIME boot_time;
|
NTTIME server_start_time;
|
||||||
/* uint16_t secblob_ofs */
|
/* uint16_t secblob_ofs */
|
||||||
/* uint16_t secblob_size */
|
/* uint16_t secblob_size */
|
||||||
uint32_t unknown9; /* 0x204d4c20 */
|
uint32_t reserved2;
|
||||||
|
|
||||||
/* dynamic body buffer */
|
|
||||||
DATA_BLOB secblob;
|
DATA_BLOB secblob;
|
||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
|
@ -96,7 +96,7 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
|
|||||||
/* we only do dialect 0 for now */
|
/* we only do dialect 0 for now */
|
||||||
if (io->in.dialect_count < 1 ||
|
if (io->in.dialect_count < 1 ||
|
||||||
io->in.dialects[0] != 0) {
|
io->in.dialects[0] != 0) {
|
||||||
return NT_STATUS_NOT_SUPPORTED;
|
DEBUG(0,("Got unexpected SMB2 dialect %u\n", io->in.dialects[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
req->smb_conn->negotiate.protocol = PROTOCOL_SMB2;
|
req->smb_conn->negotiate.protocol = PROTOCOL_SMB2;
|
||||||
@ -104,19 +104,19 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
|
|||||||
current_time = timeval_current(); /* TODO: handle timezone?! */
|
current_time = timeval_current(); /* TODO: handle timezone?! */
|
||||||
boot_time = timeval_current(); /* TODO: fix me */
|
boot_time = timeval_current(); /* TODO: fix me */
|
||||||
|
|
||||||
io->out._pad = 0;
|
ZERO_STRUCT(io->out);
|
||||||
io->out.unknown2 = 0x06;
|
io->out.security_mode = 0; /* no signing yet */
|
||||||
ZERO_STRUCT(io->out.sessid);
|
/* choose the first dialect offered for now */
|
||||||
io->out.unknown3 = 0x0d;
|
io->out.dialect_revision = io->in.dialects[0];
|
||||||
io->out.unknown4 = 0x00;
|
io->out.capabilities = 0;
|
||||||
io->out.unknown5 = 0x01;
|
io->out.max_transact_size = 0x10000;
|
||||||
io->out.unknown6 = 0x01;
|
io->out.max_read_size = 0x10000;
|
||||||
io->out.unknown7 = 0x01;
|
io->out.max_write_size = 0x10000;
|
||||||
io->out.current_time = timeval_to_nttime(¤t_time);
|
io->out.system_time = timeval_to_nttime(¤t_time);
|
||||||
io->out.boot_time = timeval_to_nttime(&boot_time);
|
io->out.server_start_time = timeval_to_nttime(&boot_time);
|
||||||
|
io->out.reserved2 = 0;
|
||||||
status = smb2srv_negprot_secblob(req, &io->out.secblob);
|
status = smb2srv_negprot_secblob(req, &io->out.secblob);
|
||||||
NT_STATUS_NOT_OK_RETURN(status);
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
io->out.unknown9 = 0x204d4c20;
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -124,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)
|
static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negprot *io)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
enum ndr_err_code ndr_err;
|
||||||
|
|
||||||
if (NT_STATUS_IS_ERR(req->status)) {
|
if (NT_STATUS_IS_ERR(req->status)) {
|
||||||
smb2srv_send_error(req, req->status); /* TODO: is this correct? */
|
smb2srv_send_error(req, req->status); /* TODO: is this correct? */
|
||||||
@ -137,16 +138,22 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSVAL(req->out.body, 0x02, io->out._pad);
|
SSVAL(req->out.body, 0x02, io->out.security_mode);
|
||||||
SIVAL(req->out.body, 0x04, io->out.unknown2);
|
SIVAL(req->out.body, 0x04, io->out.dialect_revision);
|
||||||
memcpy(req->out.body+0x08, io->out.sessid, 16);
|
SIVAL(req->out.body, 0x06, io->out.reserved);
|
||||||
SIVAL(req->out.body, 0x18, io->out.unknown3);
|
ndr_err = smbcli_push_guid(req->out.body, 0x08, &io->out.server_guid);
|
||||||
SSVAL(req->out.body, 0x1C, io->out.unknown4);
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||||
SIVAL(req->out.body, 0x1E, io->out.unknown5);
|
smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
|
||||||
SIVAL(req->out.body, 0x22, io->out.unknown6);
|
talloc_free(req);
|
||||||
SSVAL(req->out.body, 0x26, io->out.unknown7);
|
return;
|
||||||
push_nttime(req->out.body, 0x28, io->out.current_time);
|
}
|
||||||
push_nttime(req->out.body, 0x30, io->out.boot_time);
|
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);
|
status = smb2_push_o16s16_blob(&req->out, 0x38, io->out.secblob);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
|
smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
|
||||||
@ -154,8 +161,6 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SIVAL(req->out.body, 0x3C, io->out.unknown9);
|
|
||||||
|
|
||||||
smb2srv_send_reply(req);
|
smb2srv_send_reply(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +168,6 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
|
|||||||
{
|
{
|
||||||
struct smb2_negprot *io;
|
struct smb2_negprot *io;
|
||||||
int i;
|
int i;
|
||||||
DATA_BLOB guid_blob;
|
|
||||||
enum ndr_err_code ndr_err;
|
enum ndr_err_code ndr_err;
|
||||||
|
|
||||||
if (req->in.body_size < 0x26) {
|
if (req->in.body_size < 0x26) {
|
||||||
@ -182,10 +186,7 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
|
|||||||
io->in.security_mode = SVAL(req->in.body, 0x04);
|
io->in.security_mode = SVAL(req->in.body, 0x04);
|
||||||
io->in.reserved = SVAL(req->in.body, 0x06);
|
io->in.reserved = SVAL(req->in.body, 0x06);
|
||||||
io->in.capabilities = IVAL(req->in.body, 0x08);
|
io->in.capabilities = IVAL(req->in.body, 0x08);
|
||||||
guid_blob.data = req->in.body + 0xC;
|
ndr_err = smbcli_pull_guid(req->in.body, 0xC, &io->in.client_guid);
|
||||||
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)) {
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||||
smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_FOOBAR));
|
smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_FOOBAR));
|
||||||
talloc_free(req);
|
talloc_free(req);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user