mirror of
https://github.com/samba-team/samba.git
synced 2025-11-09 20:23:51 +03:00
r11741: - the buffer code (first 2 bytes in the SMB2 body) seem to be the length
of the fixed body part, and +1 if there's a dynamic part - there're 3 types of dynamic blobs with uint16_t offset/uint16_t size with uint16_t offset/uint32_t size with uint32_t offset/uint32_t size /* aligned to 8 bytes */ - strings are transmitted in UTF-16 with no termination and packet into a uint16/uint16 blob metze
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
b1afcced39
commit
79103c51e5
@@ -32,13 +32,12 @@ struct smb2_request *smb2_close_send(struct smb2_tree *tree, struct smb2_close *
|
|||||||
{
|
{
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
|
|
||||||
req = smb2_request_init_tree(tree, SMB2_OP_CLOSE, 0x18);
|
req = smb2_request_init_tree(tree, SMB2_OP_CLOSE, 0x18, 0);
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SSVAL(req->out.body, 0x00, io->in.buffer_code);
|
|
||||||
SSVAL(req->out.body, 0x02, io->in.flags);
|
SSVAL(req->out.body, 0x02, io->in.flags);
|
||||||
SIVAL(req->out.body, 0x04, io->in._pad);
|
SIVAL(req->out.body, 0x04, io->in._pad);
|
||||||
smb2_put_handle(req->out.body+0x08, &io->in.handle);
|
smb2_push_handle(req->out.body+0x08, &io->in.handle);
|
||||||
|
|
||||||
smb2_transport_send(req);
|
smb2_transport_send(req);
|
||||||
|
|
||||||
@@ -56,11 +55,7 @@ NTSTATUS smb2_close_recv(struct smb2_request *req, struct smb2_close *io)
|
|||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->in.body_size < 0x3C) {
|
SMB2_CHECK_PACKET_RECV(req, 0x3C, False);
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMB2_CHECK_BUFFER_CODE(req, 0x3C);
|
|
||||||
|
|
||||||
io->out.flags = SVAL(req->in.body, 0x02);
|
io->out.flags = SVAL(req->in.body, 0x02);
|
||||||
io->out._pad = IVAL(req->in.body, 0x04);
|
io->out._pad = IVAL(req->in.body, 0x04);
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ static void continue_socket(struct composite_context *creq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZERO_STRUCT(state->negprot);
|
ZERO_STRUCT(state->negprot);
|
||||||
state->negprot.in.unknown1 = 0x010024;
|
state->negprot.in.unknown1 = 0x0001;
|
||||||
|
|
||||||
state->req = smb2_negprot_send(transport, &state->negprot);
|
state->req = smb2_negprot_send(transport, &state->negprot);
|
||||||
if (state->req == NULL) {
|
if (state->req == NULL) {
|
||||||
|
|||||||
@@ -32,18 +32,10 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
|
|||||||
{
|
{
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
DATA_BLOB path;
|
|
||||||
uint8_t *ptr;
|
|
||||||
|
|
||||||
status = smb2_string_blob(tree, io->in.fname, &path);
|
req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, 1);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x50 + path.length);
|
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SSVAL(req->out.body, 0x00, io->in.buffer_code);
|
|
||||||
SSVAL(req->out.body, 0x02, io->in.oplock_flags);
|
SSVAL(req->out.body, 0x02, io->in.oplock_flags);
|
||||||
SIVAL(req->out.body, 0x04, io->in.unknown2);
|
SIVAL(req->out.body, 0x04, io->in.unknown2);
|
||||||
SIVAL(req->out.body, 0x08, io->in.unknown3[0]);
|
SIVAL(req->out.body, 0x08, io->in.unknown3[0]);
|
||||||
@@ -56,23 +48,17 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
|
|||||||
SIVAL(req->out.body, 0x24, io->in.open_disposition);
|
SIVAL(req->out.body, 0x24, io->in.open_disposition);
|
||||||
SIVAL(req->out.body, 0x28, io->in.create_options);
|
SIVAL(req->out.body, 0x28, io->in.create_options);
|
||||||
|
|
||||||
SSVAL(req->out.body, 0x2C, 0x40+0x38); /* offset to fname */
|
status = smb2_push_o16s16_string(&req->out, req->out.body+0x2C, io->in.fname);
|
||||||
SSVAL(req->out.body, 0x2E, path.length);
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
SIVAL(req->out.body, 0x30, 0x40+0x38+path.length); /* offset to 2nd buffer? */
|
talloc_free(req);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SIVAL(req->out.body, 0x34, io->in.unknown6);
|
status = smb2_push_o32s32_blob(&req->out, req->out.body+0x30, io->in.blob);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
memcpy(req->out.body+0x38, path.data, path.length);
|
talloc_free(req);
|
||||||
|
return NULL;
|
||||||
ptr = req->out.body+0x38+path.length;
|
}
|
||||||
|
|
||||||
SIVAL(ptr, 0x00, io->in.unknown7);
|
|
||||||
SIVAL(ptr, 0x04, io->in.unknown8);
|
|
||||||
SIVAL(ptr, 0x08, io->in.unknown9);
|
|
||||||
SIVAL(ptr, 0x0C, io->in.unknown10);
|
|
||||||
SBVAL(ptr, 0x10, io->in.unknown11);
|
|
||||||
|
|
||||||
data_blob_free(&path);
|
|
||||||
|
|
||||||
smb2_transport_send(req);
|
smb2_transport_send(req);
|
||||||
|
|
||||||
@@ -83,18 +69,16 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
|
|||||||
/*
|
/*
|
||||||
recv a create reply
|
recv a create reply
|
||||||
*/
|
*/
|
||||||
NTSTATUS smb2_create_recv(struct smb2_request *req, struct smb2_create *io)
|
NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_create *io)
|
||||||
{
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
if (!smb2_request_receive(req) ||
|
if (!smb2_request_receive(req) ||
|
||||||
smb2_request_is_error(req)) {
|
smb2_request_is_error(req)) {
|
||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->in.body_size < 0x54) {
|
SMB2_CHECK_PACKET_RECV(req, 0x58, True);
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMB2_CHECK_BUFFER_CODE(req, 0x59);
|
|
||||||
|
|
||||||
io->out.oplock_flags = SVAL(req->in.body, 0x02);
|
io->out.oplock_flags = SVAL(req->in.body, 0x02);
|
||||||
io->out.create_action = IVAL(req->in.body, 0x04);
|
io->out.create_action = IVAL(req->in.body, 0x04);
|
||||||
@@ -106,9 +90,12 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, struct smb2_create *io)
|
|||||||
io->out.size = BVAL(req->in.body, 0x30);
|
io->out.size = BVAL(req->in.body, 0x30);
|
||||||
io->out.file_attr = IVAL(req->in.body, 0x38);
|
io->out.file_attr = IVAL(req->in.body, 0x38);
|
||||||
io->out._pad = IVAL(req->in.body, 0x3C);
|
io->out._pad = IVAL(req->in.body, 0x3C);
|
||||||
io->out.handle.data[0] = BVAL(req->in.body, 0x40);
|
smb2_pull_handle(req->in.body+0x40, &io->out.handle);
|
||||||
io->out.handle.data[1] = BVAL(req->in.body, 0x48);
|
status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x50, &io->out.blob);
|
||||||
io->out.unknown4 = IVAL(req->in.body, 0x50);
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
smb2_request_destroy(req);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
@@ -116,8 +103,8 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, struct smb2_create *io)
|
|||||||
/*
|
/*
|
||||||
sync create request
|
sync create request
|
||||||
*/
|
*/
|
||||||
NTSTATUS smb2_create(struct smb2_tree *tree, struct smb2_create *io)
|
NTSTATUS smb2_create(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, struct smb2_create *io)
|
||||||
{
|
{
|
||||||
struct smb2_request *req = smb2_create_send(tree, io);
|
struct smb2_request *req = smb2_create_send(tree, io);
|
||||||
return smb2_create_recv(req, io);
|
return smb2_create_recv(req, mem_ctx, io);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,17 +32,19 @@ struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getin
|
|||||||
{
|
{
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
|
|
||||||
req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28);
|
req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, 0);
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SSVAL(req->out.body, 0x00, io->in.buffer_code);
|
/* 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);
|
SSVAL(req->out.body, 0x02, io->in.level);
|
||||||
SIVAL(req->out.body, 0x04, io->in.max_response_size);
|
SIVAL(req->out.body, 0x04, io->in.max_response_size);
|
||||||
SIVAL(req->out.body, 0x08, io->in.unknown1);
|
SIVAL(req->out.body, 0x08, io->in.unknown1);
|
||||||
SIVAL(req->out.body, 0x0C, io->in.flags);
|
SIVAL(req->out.body, 0x0C, io->in.flags);
|
||||||
SIVAL(req->out.body, 0x10, io->in.unknown3);
|
SIVAL(req->out.body, 0x10, io->in.unknown3);
|
||||||
SIVAL(req->out.body, 0x14, io->in.unknown4);
|
SIVAL(req->out.body, 0x14, io->in.unknown4);
|
||||||
smb2_put_handle(req->out.body+0x18, &io->in.handle);
|
smb2_push_handle(req->out.body+0x18, &io->in.handle);
|
||||||
|
|
||||||
smb2_transport_send(req);
|
smb2_transport_send(req);
|
||||||
|
|
||||||
@@ -63,13 +65,9 @@ NTSTATUS smb2_getinfo_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
|||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->in.body_size < 0x08) {
|
SMB2_CHECK_PACKET_RECV(req, 0x08, True);
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMB2_CHECK_BUFFER_CODE(req, 0x09);
|
status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x02, &io->out.blob);
|
||||||
|
|
||||||
status = smb2_pull_ofs_blob(&req->in, mem_ctx, req->in.body+0x02, &io->out.blob);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -309,7 +307,6 @@ NTSTATUS smb2_getinfo_level(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
|
|||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
|
|
||||||
ZERO_STRUCT(b);
|
ZERO_STRUCT(b);
|
||||||
b.in.buffer_code = 0x29;
|
|
||||||
b.in.max_response_size = 0x10000;
|
b.in.max_response_size = 0x10000;
|
||||||
b.in.handle = handle;
|
b.in.handle = handle;
|
||||||
b.in.level = level;
|
b.in.level = level;
|
||||||
|
|||||||
@@ -33,12 +33,15 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport,
|
|||||||
{
|
{
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
|
|
||||||
req = smb2_request_init(transport, SMB2_OP_NEGPROT, 0x26);
|
req = smb2_request_init(transport, SMB2_OP_NEGPROT, 0x26, 0);
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SIVAL(req->out.body, 0x00, io->in.unknown1);
|
/* this seems to be a bug, they use 0x24 but the length is 0x26 */
|
||||||
SSVAL(req->out.body, 0x04, io->in.unknown2);
|
SSVAL(req->out.body, 0x00, 0x24);
|
||||||
memcpy(req->out.body+0x06, io->in.unknown3, 32);
|
|
||||||
|
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);
|
||||||
|
|
||||||
smb2_transport_send(req);
|
smb2_transport_send(req);
|
||||||
|
|
||||||
@@ -51,18 +54,14 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport,
|
|||||||
NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
||||||
struct smb2_negprot *io)
|
struct smb2_negprot *io)
|
||||||
{
|
{
|
||||||
uint16_t blobsize;
|
NTSTATUS status;
|
||||||
|
|
||||||
if (!smb2_request_receive(req) ||
|
if (!smb2_request_receive(req) ||
|
||||||
smb2_request_is_error(req)) {
|
smb2_request_is_error(req)) {
|
||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->in.body_size < 0x40) {
|
SMB2_CHECK_PACKET_RECV(req, 0x40, True);
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMB2_CHECK_BUFFER_CODE(req, 0x41);
|
|
||||||
|
|
||||||
io->out._pad = SVAL(req->in.body, 0x02);
|
io->out._pad = SVAL(req->in.body, 0x02);
|
||||||
io->out.unknown2 = IVAL(req->in.body, 0x04);
|
io->out.unknown2 = IVAL(req->in.body, 0x04);
|
||||||
@@ -74,10 +73,14 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
|||||||
io->out.unknown7 = SVAL(req->in.body, 0x26);
|
io->out.unknown7 = SVAL(req->in.body, 0x26);
|
||||||
io->out.current_time = smbcli_pull_nttime(req->in.body, 0x28);
|
io->out.current_time = smbcli_pull_nttime(req->in.body, 0x28);
|
||||||
io->out.boot_time = smbcli_pull_nttime(req->in.body, 0x30);
|
io->out.boot_time = smbcli_pull_nttime(req->in.body, 0x30);
|
||||||
io->out.unknown8 = SVAL(req->in.body, 0x38);
|
|
||||||
blobsize = SVAL(req->in.body, 0x3A);
|
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);
|
io->out.unknown9 = IVAL(req->in.body, 0x3C);
|
||||||
io->out.secblob = smb2_pull_blob(&req->in, mem_ctx, req->in.body+0x40, blobsize);
|
|
||||||
|
|
||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,15 +32,16 @@ struct smb2_request *smb2_read_send(struct smb2_tree *tree, struct smb2_read *io
|
|||||||
{
|
{
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
|
|
||||||
req = smb2_request_init_tree(tree, SMB2_OP_READ, 0x31);
|
req = smb2_request_init_tree(tree, SMB2_OP_READ, 0x31, 0);
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SSVAL(req->out.body, 0x00, io->in.buffer_code);
|
SSVAL(req->out.body, 0x02, io->in._pad);
|
||||||
SSVAL(req->out.body, 0x02, 0);
|
|
||||||
SIVAL(req->out.body, 0x04, io->in.length);
|
SIVAL(req->out.body, 0x04, io->in.length);
|
||||||
SBVAL(req->out.body, 0x08, io->in.offset);
|
SBVAL(req->out.body, 0x08, io->in.offset);
|
||||||
smb2_put_handle(req->out.body+0x10, &io->in.handle);
|
smb2_push_handle(req->out.body+0x10, &io->in.handle);
|
||||||
memcpy(req->out.body+0x20, io->in._pad, 17);
|
SBVAL(req->out.body, 0x20, io->in.unknown1);
|
||||||
|
SBVAL(req->out.body, 0x28, io->in.unknown2);
|
||||||
|
SCVAL(req->out.body, 0x30, io->in._bug);
|
||||||
|
|
||||||
smb2_transport_send(req);
|
smb2_transport_send(req);
|
||||||
|
|
||||||
@@ -54,29 +55,22 @@ struct smb2_request *smb2_read_send(struct smb2_tree *tree, struct smb2_read *io
|
|||||||
NTSTATUS smb2_read_recv(struct smb2_request *req,
|
NTSTATUS smb2_read_recv(struct smb2_request *req,
|
||||||
TALLOC_CTX *mem_ctx, struct smb2_read *io)
|
TALLOC_CTX *mem_ctx, struct smb2_read *io)
|
||||||
{
|
{
|
||||||
uint16_t ofs;
|
NTSTATUS status;
|
||||||
uint32_t nread;
|
|
||||||
|
|
||||||
if (!smb2_request_receive(req) ||
|
if (!smb2_request_receive(req) ||
|
||||||
smb2_request_is_error(req)) {
|
smb2_request_is_error(req)) {
|
||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->in.body_size < 16) {
|
SMB2_CHECK_PACKET_RECV(req, 0x10, True);
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
||||||
|
status = smb2_pull_o16s32_blob(&req->in, mem_ctx, req->in.body+0x02, &io->out.data);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
smb2_request_destroy(req);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMB2_CHECK_BUFFER_CODE(req, 0x11);
|
io->out.unknown1 = BVAL(req->in.body, 0x08);
|
||||||
|
|
||||||
ofs = SVAL(req->in.body, 0x02);
|
|
||||||
|
|
||||||
nread = IVAL(req->in.body, 0x04);
|
|
||||||
memcpy(io->out.unknown, req->in.body+0x08, 8);
|
|
||||||
|
|
||||||
io->out.data = smb2_pull_blob(&req->in, mem_ctx, req->in.hdr+ofs, nread);
|
|
||||||
if (io->out.data.data == NULL) {
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
SMB2 client request handling
|
SMB2 client request handling
|
||||||
|
|
||||||
Copyright (C) Andrew Tridgell 2005
|
Copyright (C) Andrew Tridgell 2005
|
||||||
|
Copyright (C) Stefan Metzmacher 2005
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -30,8 +31,8 @@
|
|||||||
/*
|
/*
|
||||||
initialise a smb2 request
|
initialise a smb2 request
|
||||||
*/
|
*/
|
||||||
struct smb2_request *smb2_request_init(struct smb2_transport *transport,
|
struct smb2_request *smb2_request_init(struct smb2_transport *transport, uint16_t opcode,
|
||||||
uint16_t opcode, uint32_t body_size)
|
uint16_t body_fixed_size, uint32_t body_dynamic_size)
|
||||||
{
|
{
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
|
|
||||||
@@ -49,18 +50,18 @@ struct smb2_request *smb2_request_init(struct smb2_transport *transport,
|
|||||||
|
|
||||||
ZERO_STRUCT(req->in);
|
ZERO_STRUCT(req->in);
|
||||||
|
|
||||||
req->out.allocated = SMB2_HDR_BODY+NBT_HDR_SIZE+body_size;
|
req->out.allocated = SMB2_HDR_BODY+NBT_HDR_SIZE+body_fixed_size+body_dynamic_size;
|
||||||
req->out.buffer = talloc_size(req, req->out.allocated);
|
req->out.buffer = talloc_size(req, req->out.allocated);
|
||||||
if (req->out.buffer == NULL) {
|
if (req->out.buffer == NULL) {
|
||||||
talloc_free(req);
|
talloc_free(req);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->out.size = SMB2_HDR_BODY+NBT_HDR_SIZE + body_size;
|
req->out.size = SMB2_HDR_BODY+NBT_HDR_SIZE+body_fixed_size+(body_dynamic_size?1:0);
|
||||||
req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
|
req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
|
||||||
req->out.body = req->out.hdr + SMB2_HDR_BODY;
|
req->out.body = req->out.hdr + SMB2_HDR_BODY;
|
||||||
req->out.body_size = body_size;
|
req->out.body_size = body_fixed_size;
|
||||||
req->out.ptr = req->out.body;
|
req->out.dynamic = (body_dynamic_size ? req->out.body + body_fixed_size : NULL);
|
||||||
|
|
||||||
SIVAL(req->out.hdr, 0, SMB2_MAGIC);
|
SIVAL(req->out.hdr, 0, SMB2_MAGIC);
|
||||||
SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
|
SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
|
||||||
@@ -76,17 +77,28 @@ struct smb2_request *smb2_request_init(struct smb2_transport *transport,
|
|||||||
SBVAL(req->out.hdr, SMB2_HDR_UID, 0);
|
SBVAL(req->out.hdr, SMB2_HDR_UID, 0);
|
||||||
memset(req->out.hdr+SMB2_HDR_SIG, 0, 16);
|
memset(req->out.hdr+SMB2_HDR_SIG, 0, 16);
|
||||||
|
|
||||||
|
/* set the length of the fixed body part and +1 if there's a dynamic part also */
|
||||||
|
SSVAL(req->out.body, 0, body_fixed_size + (body_dynamic_size?1:0));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we have a dynamic part, make sure the first byte
|
||||||
|
* which is always be part of the packet is initialized
|
||||||
|
*/
|
||||||
|
if (body_dynamic_size) {
|
||||||
|
SCVAL(req->out.dynamic, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
initialise a smb2 request for tree operations
|
initialise a smb2 request for tree operations
|
||||||
*/
|
*/
|
||||||
struct smb2_request *smb2_request_init_tree(struct smb2_tree *tree,
|
struct smb2_request *smb2_request_init_tree(struct smb2_tree *tree, uint16_t opcode,
|
||||||
uint16_t opcode, uint32_t body_size)
|
uint16_t body_fixed_size, uint32_t body_dynamic_size)
|
||||||
{
|
{
|
||||||
struct smb2_request *req = smb2_request_init(tree->session->transport, opcode,
|
struct smb2_request *req = smb2_request_init(tree->session->transport, opcode,
|
||||||
body_size);
|
body_fixed_size, body_dynamic_size);
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid);
|
SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid);
|
||||||
@@ -162,34 +174,41 @@ BOOL smb2_oob(struct smb2_request_buffer *buf, const uint8_t *ptr, uint_t size)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static size_t smb2_padding_size(uint32_t offset, size_t n)
|
||||||
pull a data blob from the body of a reply
|
|
||||||
*/
|
|
||||||
DATA_BLOB smb2_pull_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, uint_t size)
|
|
||||||
{
|
{
|
||||||
if (smb2_oob(buf, ptr, size)) {
|
if ((offset & (n-1)) == 0) return 0;
|
||||||
return data_blob(NULL, 0);
|
return n - (offset & (n-1));
|
||||||
}
|
|
||||||
return data_blob_talloc(mem_ctx, ptr, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static NTSTATUS smb2_grow_buffer(struct smb2_request_buffer *buf, size_t n)
|
||||||
push a data blob from the body of a reply
|
|
||||||
*/
|
|
||||||
NTSTATUS smb2_push_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DATA_BLOB blob)
|
|
||||||
{
|
{
|
||||||
if (smb2_oob(buf, ptr, blob.length)) {
|
size_t dynamic_ofs;
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
uint8_t *buffer_ptr;
|
||||||
}
|
|
||||||
memcpy(ptr, blob.data, blob.length);
|
/* a packet size should be limited a bit */
|
||||||
|
if (n >= 0x00FFFFFF) return NT_STATUS_MARSHALL_OVERFLOW;
|
||||||
|
|
||||||
|
if (n <= buf->allocated) return NT_STATUS_OK;
|
||||||
|
|
||||||
|
dynamic_ofs = buf->dynamic - buf->buffer;
|
||||||
|
|
||||||
|
buffer_ptr = talloc_realloc_size(buf, buf->buffer, n);
|
||||||
|
NT_STATUS_HAVE_NO_MEMORY(buffer_ptr);
|
||||||
|
|
||||||
|
buf->buffer = buffer_ptr;
|
||||||
|
buf->hdr = buf->buffer + NBT_HDR_SIZE;
|
||||||
|
buf->body = buf->hdr + SMB2_HDR_BODY;
|
||||||
|
buf->dynamic = buf->buffer + dynamic_ofs;
|
||||||
|
buf->allocated = n;
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pull a ofs/length/blob triple from a data blob
|
pull a uint16_t ofs/ uint16_t length/blob triple from a data blob
|
||||||
the ptr points to the start of the offset/length pair
|
the ptr points to the start of the offset/length pair
|
||||||
*/
|
*/
|
||||||
NTSTATUS smb2_pull_ofs_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
|
NTSTATUS smb2_pull_o16s16_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
|
||||||
{
|
{
|
||||||
uint16_t ofs, size;
|
uint16_t ofs, size;
|
||||||
if (smb2_oob(buf, ptr, 4)) {
|
if (smb2_oob(buf, ptr, 4)) {
|
||||||
@@ -197,6 +216,10 @@ NTSTATUS smb2_pull_ofs_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx
|
|||||||
}
|
}
|
||||||
ofs = SVAL(ptr, 0);
|
ofs = SVAL(ptr, 0);
|
||||||
size = SVAL(ptr, 2);
|
size = SVAL(ptr, 2);
|
||||||
|
if (ofs == 0 || size == 0) {
|
||||||
|
*blob = data_blob(NULL, 0);
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
if (smb2_oob(buf, buf->hdr + ofs, size)) {
|
if (smb2_oob(buf, buf->hdr + ofs, size)) {
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
@@ -206,35 +229,195 @@ NTSTATUS smb2_pull_ofs_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
push a ofs/length/blob triple into a data blob
|
push a uint16_t ofs/ uint16_t length/blob triple into a data blob
|
||||||
the ptr points to the start of the offset/length pair
|
the ptr points to the start of the offset/length pair
|
||||||
|
|
||||||
NOTE: assumes blob goes immediately after the offset/length pair. Needs
|
|
||||||
to be generalised
|
|
||||||
*/
|
*/
|
||||||
NTSTATUS smb2_push_ofs_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DATA_BLOB blob)
|
NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DATA_BLOB blob)
|
||||||
{
|
{
|
||||||
if (smb2_oob(buf, ptr, 4+blob.length)) {
|
NTSTATUS status;
|
||||||
|
size_t offset;
|
||||||
|
size_t padding_length;
|
||||||
|
|
||||||
|
if (!buf->dynamic) {
|
||||||
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have only 16 bit for the size */
|
||||||
|
if (blob.length > 0xFFFF) {
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
SSVAL(ptr, 0, 4 + (ptr - buf->hdr));
|
|
||||||
|
/* check if there're enough room for ofs and size */
|
||||||
|
if (smb2_oob(buf, ptr, 4)) {
|
||||||
|
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = buf->dynamic - buf->hdr;
|
||||||
|
padding_length = smb2_padding_size(offset, 2);
|
||||||
|
offset += padding_length;
|
||||||
|
|
||||||
|
SSVAL(ptr, 0, offset);
|
||||||
SSVAL(ptr, 2, blob.length);
|
SSVAL(ptr, 2, blob.length);
|
||||||
memcpy(ptr+4, blob.data, blob.length);
|
|
||||||
|
status = smb2_grow_buffer(buf, NBT_HDR_SIZE + offset + blob.length);
|
||||||
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
|
|
||||||
|
memset(buf->dynamic, 0, padding_length);
|
||||||
|
buf->dynamic += padding_length;
|
||||||
|
|
||||||
|
memcpy(buf->dynamic, blob.data, blob.length);
|
||||||
|
buf->dynamic += blob.length;
|
||||||
|
|
||||||
|
buf->size = buf->dynamic - buf->buffer;
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pull a string in a ofs/length/blob format
|
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
|
||||||
*/
|
*/
|
||||||
NTSTATUS smb2_pull_ofs_string(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx,
|
NTSTATUS smb2_pull_o16s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
|
||||||
|
{
|
||||||
|
uint16_t ofs;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
if (smb2_oob(buf, ptr, 6)) {
|
||||||
|
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
ofs = SVAL(ptr, 0);
|
||||||
|
size = IVAL(ptr, 2);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
push a uint16_t ofs/ uint32_t length/blob triple into a data blob
|
||||||
|
the ptr points to the start of the offset/length pair
|
||||||
|
*/
|
||||||
|
NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DATA_BLOB blob)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
size_t offset;
|
||||||
|
size_t padding_length;
|
||||||
|
|
||||||
|
if (!buf->dynamic) {
|
||||||
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if there're enough room for ofs and size */
|
||||||
|
if (smb2_oob(buf, ptr, 6)) {
|
||||||
|
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = buf->dynamic - buf->hdr;
|
||||||
|
padding_length = smb2_padding_size(offset, 2);
|
||||||
|
offset += padding_length;
|
||||||
|
|
||||||
|
SSVAL(ptr, 0, offset);
|
||||||
|
SIVAL(ptr, 2, blob.length);
|
||||||
|
|
||||||
|
status = smb2_grow_buffer(buf, NBT_HDR_SIZE + offset + blob.length);
|
||||||
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
|
|
||||||
|
memset(buf->dynamic, 0, padding_length);
|
||||||
|
buf->dynamic += padding_length;
|
||||||
|
|
||||||
|
memcpy(buf->dynamic, blob.data, blob.length);
|
||||||
|
buf->dynamic += blob.length;
|
||||||
|
|
||||||
|
buf->size = buf->dynamic - buf->buffer;
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pull a uint32_t ofs/ uint32_t length/blob triple from a data blob
|
||||||
|
the ptr points to the start of the offset/length pair
|
||||||
|
*/
|
||||||
|
NTSTATUS smb2_pull_o32s32_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 = IVAL(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
push a uint32_t ofs/ uint32_t length/blob triple into a data blob
|
||||||
|
the ptr points to the start of the offset/length pair
|
||||||
|
*/
|
||||||
|
NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DATA_BLOB blob)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
size_t offset;
|
||||||
|
size_t padding_length;
|
||||||
|
|
||||||
|
if (!buf->dynamic) {
|
||||||
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if there're enough room for ofs and size */
|
||||||
|
if (smb2_oob(buf, ptr, 8)) {
|
||||||
|
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = buf->dynamic - buf->hdr;
|
||||||
|
padding_length = smb2_padding_size(offset, 8);
|
||||||
|
offset += padding_length;
|
||||||
|
|
||||||
|
SIVAL(ptr, 0, offset);
|
||||||
|
SIVAL(ptr, 4, blob.length);
|
||||||
|
|
||||||
|
status = smb2_grow_buffer(buf, NBT_HDR_SIZE + offset + blob.length);
|
||||||
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
|
|
||||||
|
memset(buf->dynamic, 0, padding_length);
|
||||||
|
buf->dynamic += padding_length;
|
||||||
|
|
||||||
|
memcpy(buf->dynamic, blob.data, blob.length);
|
||||||
|
buf->dynamic += blob.length;
|
||||||
|
|
||||||
|
buf->size = buf->dynamic - buf->buffer;
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pull a string in a uint16_t ofs/ uint16_t length/blob format
|
||||||
|
UTF-16 without termination
|
||||||
|
*/
|
||||||
|
NTSTATUS smb2_pull_o16s16_string(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx,
|
||||||
uint8_t *ptr, const char **str)
|
uint8_t *ptr, const char **str)
|
||||||
{
|
{
|
||||||
DATA_BLOB blob;
|
DATA_BLOB blob;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
void *vstr;
|
void *vstr;
|
||||||
status = smb2_pull_ofs_blob(buf, mem_ctx, ptr, &blob);
|
|
||||||
|
status = smb2_pull_o16s16_blob(buf, mem_ctx, ptr, &blob);
|
||||||
NT_STATUS_NOT_OK_RETURN(status);
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
|
|
||||||
size = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
|
size = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
|
||||||
blob.data, blob.length, &vstr);
|
blob.data, blob.length, &vstr);
|
||||||
data_blob_free(&blob);
|
data_blob_free(&blob);
|
||||||
@@ -246,25 +429,44 @@ NTSTATUS smb2_pull_ofs_string(struct smb2_request_buffer *buf, TALLOC_CTX *mem_c
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
create a UTF16 string in a blob from a char*
|
push a string in a uint16_t ofs/ uint16_t length/blob format
|
||||||
|
UTF-16 without termination
|
||||||
*/
|
*/
|
||||||
NTSTATUS smb2_string_blob(TALLOC_CTX *mem_ctx, const char *str, DATA_BLOB *blob)
|
NTSTATUS smb2_push_o16s16_string(struct smb2_request_buffer *buf,
|
||||||
|
uint8_t *ptr, const char *str)
|
||||||
{
|
{
|
||||||
|
DATA_BLOB blob;
|
||||||
|
NTSTATUS status;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
size = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16,
|
|
||||||
str, strlen(str), (void **)&blob->data);
|
size = convert_string_talloc(buf->buffer, CH_UNIX, CH_UTF16,
|
||||||
|
str, strlen(str), (void **)&blob.data);
|
||||||
if (size == -1) {
|
if (size == -1) {
|
||||||
return NT_STATUS_ILLEGAL_CHARACTER;
|
return NT_STATUS_ILLEGAL_CHARACTER;
|
||||||
}
|
}
|
||||||
blob->length = size;
|
blob.length = size;
|
||||||
|
|
||||||
|
status = smb2_push_o16s16_blob(buf, ptr, blob);
|
||||||
|
data_blob_free(&blob);
|
||||||
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
put a file handle into a buffer
|
push a file handle into a buffer
|
||||||
*/
|
*/
|
||||||
void smb2_put_handle(uint8_t *data, struct smb2_handle *h)
|
void smb2_push_handle(uint8_t *data, struct smb2_handle *h)
|
||||||
{
|
{
|
||||||
SBVAL(data, 0, h->data[0]);
|
SBVAL(data, 0, h->data[0]);
|
||||||
SBVAL(data, 8, h->data[1]);
|
SBVAL(data, 8, h->data[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pull a file handle from a buffer
|
||||||
|
*/
|
||||||
|
void smb2_pull_handle(uint8_t *ptr, struct smb2_handle *h)
|
||||||
|
{
|
||||||
|
h->data[0] = BVAL(ptr, 0);
|
||||||
|
h->data[1] = BVAL(ptr, 8);
|
||||||
|
}
|
||||||
|
|||||||
@@ -67,17 +67,17 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session,
|
|||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
req = smb2_request_init(session->transport, SMB2_OP_SESSSETUP,
|
req = smb2_request_init(session->transport, SMB2_OP_SESSSETUP,
|
||||||
0x10 + io->in.secblob.length);
|
0x10, io->in.secblob.length);
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SBVAL(req->out.hdr, SMB2_HDR_UID, session->uid);
|
SBVAL(req->out.hdr, SMB2_HDR_UID, session->uid);
|
||||||
SIVAL(req->out.body, 0x00, io->in.unknown1);
|
SSVAL(req->out.body, 0x02, io->in._pad);
|
||||||
SIVAL(req->out.body, 0x04, io->in.unknown2);
|
SIVAL(req->out.body, 0x04, io->in.unknown2);
|
||||||
SIVAL(req->out.body, 0x08, io->in.unknown3);
|
SIVAL(req->out.body, 0x08, io->in.unknown3);
|
||||||
|
|
||||||
req->session = session;
|
req->session = session;
|
||||||
|
|
||||||
status = smb2_push_ofs_blob(&req->out, req->out.body+0x0C, io->in.secblob);
|
status = smb2_push_o16s16_blob(&req->out, req->out.body+0x0C, io->in.secblob);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
talloc_free(req);
|
talloc_free(req);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -103,16 +103,12 @@ NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
|||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->in.body_size < 0x08) {
|
SMB2_CHECK_PACKET_RECV(req, 0x08, True);
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMB2_CHECK_BUFFER_CODE(req, 0x09);
|
|
||||||
|
|
||||||
io->out._pad = SVAL(req->in.body, 0x02);
|
io->out._pad = SVAL(req->in.body, 0x02);
|
||||||
io->out.uid = BVAL(req->in.hdr, SMB2_HDR_UID);
|
io->out.uid = BVAL(req->in.hdr, SMB2_HDR_UID);
|
||||||
|
|
||||||
status = smb2_pull_ofs_blob(&req->in, mem_ctx, req->in.body+0x04, &io->out.secblob);
|
status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x04, &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;
|
||||||
@@ -203,7 +199,7 @@ struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *se
|
|||||||
c->event_ctx = session->transport->socket->event.ctx;
|
c->event_ctx = session->transport->socket->event.ctx;
|
||||||
|
|
||||||
ZERO_STRUCT(state->io);
|
ZERO_STRUCT(state->io);
|
||||||
state->io.in.unknown1 = 0x11;
|
state->io.in._pad = 0x0;
|
||||||
state->io.in.unknown2 = 0xF;
|
state->io.in.unknown2 = 0xF;
|
||||||
state->io.in.unknown3 = 0x00;
|
state->io.in.unknown3 = 0x00;
|
||||||
|
|
||||||
|
|||||||
@@ -88,12 +88,10 @@ struct smb2_request_buffer {
|
|||||||
uint8_t *body;
|
uint8_t *body;
|
||||||
uint_t body_size;
|
uint_t body_size;
|
||||||
|
|
||||||
/* ptr is used as a moving pointer into the data area
|
/* this point to the next dynamic byte that can be used
|
||||||
* of the packet. The reason its here and not a local
|
* this will be moved when some dynamic data is pushed
|
||||||
* variable in each function is that when a realloc of
|
*/
|
||||||
* a send packet is done we need to move this
|
uint8_t *dynamic;
|
||||||
* pointer */
|
|
||||||
uint8_t *ptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -176,13 +174,20 @@ struct smb2_request {
|
|||||||
#define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */
|
#define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
check that a buffer code matches the expected value
|
check that a body has the expected size
|
||||||
*/
|
*/
|
||||||
#define SMB2_CHECK_BUFFER_CODE(req, code) do { \
|
#define SMB2_CHECK_PACKET_RECV(req, size, dynamic) do { \
|
||||||
io->out.buffer_code = SVAL(req->in.body, 0); \
|
uint_t is_size = req->in.body_size; \
|
||||||
if (io->out.buffer_code != (code)) { \
|
uint16_t field_size = SVAL(req->in.body, 0); \
|
||||||
DEBUG(0,("Unexpected buffer code 0x%x. Expected 0x%x\n", \
|
uint16_t want_size = ((dynamic)?(size)+1:(size)); \
|
||||||
io->out.buffer_code, code)); \
|
if (is_size < (size)) { \
|
||||||
|
DEBUG(0,("%s: buffer too small 0x%x. Expected 0x%x\n", \
|
||||||
|
__location__, is_size, want_size)); \
|
||||||
|
return NT_STATUS_BUFFER_TOO_SMALL; \
|
||||||
|
}\
|
||||||
|
if (field_size != want_size) { \
|
||||||
|
DEBUG(0,("%s: unexpected fixed body size 0x%x. Expected 0x%x\n", \
|
||||||
|
__location__, field_size, want_size)); \
|
||||||
return NT_STATUS_INVALID_PARAMETER; \
|
return NT_STATUS_INVALID_PARAMETER; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|||||||
@@ -23,12 +23,15 @@
|
|||||||
|
|
||||||
struct smb2_negprot {
|
struct smb2_negprot {
|
||||||
struct {
|
struct {
|
||||||
uint32_t unknown1; /* 0x00010024 */
|
/* static body buffer 38 (0x26) bytes */
|
||||||
uint16_t unknown2; /* 0x00 */
|
/* uint16_t buffer_code; 0x24 (why?) */
|
||||||
uint8_t unknown3[32]; /* all zero */
|
uint16_t unknown1; /* 0x0001 */
|
||||||
|
uint8_t unknown2[32]; /* all zero */
|
||||||
|
uint16_t unknown3; /* 0x00000 */
|
||||||
} in;
|
} in;
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 64 (0x40) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x41 = 0x40 + 1 */
|
||||||
uint16_t _pad;
|
uint16_t _pad;
|
||||||
uint32_t unknown2; /* 0x06 */
|
uint32_t unknown2; /* 0x06 */
|
||||||
uint8_t sessid[16];
|
uint8_t sessid[16];
|
||||||
@@ -39,41 +42,63 @@ struct smb2_negprot {
|
|||||||
uint16_t unknown7; /* 0x01 */
|
uint16_t unknown7; /* 0x01 */
|
||||||
NTTIME current_time;
|
NTTIME current_time;
|
||||||
NTTIME boot_time;
|
NTTIME boot_time;
|
||||||
uint16_t unknown8; /* 0x80 */
|
/* uint16_t secblob_ofs */
|
||||||
/* uint16_t secblob size here */
|
/* uint16_t secblob_size */
|
||||||
uint32_t unknown9; /* 0x204d4c20 */
|
uint32_t unknown9; /* 0x204d4c20 */
|
||||||
|
|
||||||
|
/* dynamic body buffer */
|
||||||
DATA_BLOB secblob;
|
DATA_BLOB secblob;
|
||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb2_session_setup {
|
struct smb2_session_setup {
|
||||||
struct {
|
struct {
|
||||||
uint32_t unknown1; /* 0x11 */
|
/* static body buffer 16 (0x10) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x11 = 0x10 + 1 */
|
||||||
|
uint16_t _pad;
|
||||||
uint32_t unknown2; /* 0xF */
|
uint32_t unknown2; /* 0xF */
|
||||||
uint32_t unknown3; /* 0x00 */
|
uint32_t unknown3; /* 0x00 */
|
||||||
/* uint16_t secblob ofs/size here */
|
/* uint16_t secblob_ofs */
|
||||||
|
/* uint16_t secblob_size */
|
||||||
|
|
||||||
|
/* dynamic body */
|
||||||
DATA_BLOB secblob;
|
DATA_BLOB secblob;
|
||||||
} in;
|
} in;
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 8 (0x08) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x09 = 0x08 +1 */
|
||||||
uint16_t _pad;
|
uint16_t _pad;
|
||||||
/* uint16_t secblob ofs/size here */
|
/* uint16_t secblob_ofs */
|
||||||
|
/* uint16_t secblob_size */
|
||||||
|
|
||||||
|
/* dynamic body */
|
||||||
DATA_BLOB secblob;
|
DATA_BLOB secblob;
|
||||||
uint64_t uid; /* returned in header */
|
|
||||||
|
/* extracted from the SMB2 header */
|
||||||
|
uint64_t uid;
|
||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb2_tree_connect {
|
struct smb2_tree_connect {
|
||||||
struct {
|
struct {
|
||||||
uint32_t unknown1; /* 0x09 */
|
/* static body buffer 8 (0x08) bytes */
|
||||||
const char *path;
|
/* uint16_t buffer_code; 0x09 = 0x08 + 1 */
|
||||||
|
uint16_t unknown1; /* 0x0000 */
|
||||||
|
/* uint16_t path_ofs */
|
||||||
|
/* uint16_t path_size */
|
||||||
|
|
||||||
|
/* dynamic body */
|
||||||
|
const char *path; /* as non-terminated UTF-16 on the wire */
|
||||||
} in;
|
} in;
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 16 (0x10) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x10 */
|
||||||
uint16_t unknown1; /* 0x02 */
|
uint16_t unknown1; /* 0x02 */
|
||||||
uint32_t unknown2; /* 0x00 */
|
uint32_t unknown2; /* 0x00 */
|
||||||
uint32_t unknown3; /* 0x00 */
|
uint32_t unknown3; /* 0x00 */
|
||||||
uint32_t access_mask;
|
uint32_t access_mask;
|
||||||
|
|
||||||
|
/* extracted from the SMB2 header */
|
||||||
uint32_t tid;
|
uint32_t tid;
|
||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
@@ -93,27 +118,32 @@ struct smb2_handle {
|
|||||||
|
|
||||||
struct smb2_create {
|
struct smb2_create {
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code; /* 0x39 */
|
/* static body buffer 56 (0x38) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x39 = 0x38 + 1 */
|
||||||
uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */
|
uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */
|
||||||
uint32_t unknown2;
|
uint32_t unknown2;
|
||||||
uint32_t unknown3[4];
|
uint32_t unknown3[4];
|
||||||
uint32_t access_mask;
|
uint32_t access_mask;
|
||||||
|
|
||||||
uint32_t file_attr;
|
uint32_t file_attr;
|
||||||
uint32_t share_access;
|
uint32_t share_access;
|
||||||
uint32_t open_disposition;
|
uint32_t open_disposition;
|
||||||
uint32_t create_options;
|
uint32_t create_options;
|
||||||
/* ofs/len of name here, 16 bits */
|
|
||||||
uint32_t unknown6;
|
/* uint16_t fname_ofs */
|
||||||
|
/* uint16_t fname_size */
|
||||||
|
/* uint32_t blob_ofs; */
|
||||||
|
/* uint32_t blob_size; */
|
||||||
|
|
||||||
|
/* dynamic body */
|
||||||
const char *fname;
|
const char *fname;
|
||||||
uint32_t unknown7;
|
|
||||||
uint32_t unknown8;
|
DATA_BLOB blob;
|
||||||
uint32_t unknown9;
|
|
||||||
uint32_t unknown10;
|
|
||||||
uint64_t unknown11;
|
|
||||||
} in;
|
} in;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code; /* 0x59 */
|
/* static body buffer 88 (0x58) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x59 = 0x58 + 1 */
|
||||||
uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */
|
uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */
|
||||||
uint32_t create_action;
|
uint32_t create_action;
|
||||||
NTTIME create_time;
|
NTTIME create_time;
|
||||||
@@ -125,8 +155,11 @@ struct smb2_create {
|
|||||||
uint32_t file_attr;
|
uint32_t file_attr;
|
||||||
uint32_t _pad;
|
uint32_t _pad;
|
||||||
struct smb2_handle handle;
|
struct smb2_handle handle;
|
||||||
uint32_t unknown4;
|
/* uint32_t blob_ofs; */
|
||||||
uint32_t unknown5;
|
/* uint32_t blob_size; */
|
||||||
|
|
||||||
|
/* dynamic body */
|
||||||
|
DATA_BLOB blob;
|
||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,14 +168,16 @@ struct smb2_create {
|
|||||||
|
|
||||||
struct smb2_close {
|
struct smb2_close {
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 24 (0x18) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x18 */
|
||||||
uint16_t flags; /* SMB2_CLOSE_FLAGS_* */
|
uint16_t flags; /* SMB2_CLOSE_FLAGS_* */
|
||||||
uint32_t _pad;
|
uint32_t _pad;
|
||||||
struct smb2_handle handle;
|
struct smb2_handle handle;
|
||||||
} in;
|
} in;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 60 (0x3C) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x3C */
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint32_t _pad;
|
uint32_t _pad;
|
||||||
NTTIME create_time;
|
NTTIME create_time;
|
||||||
@@ -187,7 +222,8 @@ struct smb2_close {
|
|||||||
|
|
||||||
struct smb2_getinfo {
|
struct smb2_getinfo {
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 40 (0x28) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x29 = 0x28 + 1 (why???) */
|
||||||
uint16_t level;
|
uint16_t level;
|
||||||
uint32_t max_response_size;
|
uint32_t max_response_size;
|
||||||
uint32_t unknown1;
|
uint32_t unknown1;
|
||||||
@@ -198,7 +234,12 @@ struct smb2_getinfo {
|
|||||||
} in;
|
} in;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 8 (0x08) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x09 = 0x08 + 1 */
|
||||||
|
/* uint16_t blob_ofs; */
|
||||||
|
/* uint16_t blob_size; */
|
||||||
|
|
||||||
|
/* dynamic body */
|
||||||
DATA_BLOB blob;
|
DATA_BLOB blob;
|
||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
@@ -304,33 +345,50 @@ union smb2_fileinfo {
|
|||||||
|
|
||||||
struct smb2_write {
|
struct smb2_write {
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 48 (0x30) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x31 = 0x30 + 1 */
|
||||||
|
/* uint16_t data_ofs; */
|
||||||
|
/* uint32_t data_size; */
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
struct smb2_handle handle;
|
struct smb2_handle handle;
|
||||||
uint8_t _pad[16];
|
uint64_t unknown1; /* 0xFFFFFFFFFFFFFFFF */
|
||||||
|
uint64_t unknown2; /* 0xFFFFFFFFFFFFFFFF */
|
||||||
|
|
||||||
|
/* dynamic body */
|
||||||
DATA_BLOB data;
|
DATA_BLOB data;
|
||||||
} in;
|
} in;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 17 (0x11) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x11 */
|
||||||
uint16_t _pad;
|
uint16_t _pad;
|
||||||
uint32_t nwritten;
|
uint32_t nwritten;
|
||||||
uint8_t unknown[9];
|
uint64_t unknown1; /* 0x0000000000000000 */
|
||||||
|
uint8_t _bug;
|
||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb2_read {
|
struct smb2_read {
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 48 (0x30) bytes */
|
||||||
|
/* uint16_t buffer_code; 0x31 = 0x30 + 1 */
|
||||||
|
uint16_t _pad;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
struct smb2_handle handle;
|
struct smb2_handle handle;
|
||||||
uint8_t _pad[17];
|
uint64_t unknown1; /* 0x0000000000000000 */
|
||||||
|
uint64_t unknown2; /* 0x0000000000000000 */
|
||||||
|
uint8_t _bug;
|
||||||
} in;
|
} in;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16_t buffer_code;
|
/* static body buffer 16 (0x10) bytes */
|
||||||
uint8_t unknown[8];
|
/* uint16_t buffer_code; 0x11 = 0x10 + 1 */
|
||||||
|
/* uint16_t data_ofs; */
|
||||||
|
/* uint32_t data_size; */
|
||||||
|
uint64_t unknown1; /* 0x0000000000000000 */
|
||||||
|
|
||||||
|
/* dynamic body */
|
||||||
DATA_BLOB data;
|
DATA_BLOB data;
|
||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,21 +53,15 @@ struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree,
|
|||||||
{
|
{
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
DATA_BLOB path;
|
|
||||||
|
|
||||||
status = smb2_string_blob(tree, io->in.path, &path);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
req = smb2_request_init(tree->session->transport, SMB2_OP_TCON,
|
req = smb2_request_init(tree->session->transport, SMB2_OP_TCON,
|
||||||
0x8 + path.length);
|
0x08, 1);
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid);
|
SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid);
|
||||||
|
|
||||||
SIVAL(req->out.body, 0x00, io->in.unknown1);
|
SIVAL(req->out.body, 0x00, io->in.unknown1);
|
||||||
status = smb2_push_ofs_blob(&req->out, req->out.body+0x04, path);
|
status = smb2_push_o16s16_string(&req->out, req->out.body+0x04, io->in.path);
|
||||||
data_blob_free(&path);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
talloc_free(req);
|
talloc_free(req);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -89,11 +83,7 @@ NTSTATUS smb2_tree_connect_recv(struct smb2_request *req, struct smb2_tree_conne
|
|||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->in.body_size < 0x10) {
|
SMB2_CHECK_PACKET_RECV(req, 0x10, False);
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMB2_CHECK_BUFFER_CODE(req, 0x10);
|
|
||||||
|
|
||||||
io->out.tid = IVAL(req->in.hdr, SMB2_HDR_TID);
|
io->out.tid = IVAL(req->in.hdr, SMB2_HDR_TID);
|
||||||
|
|
||||||
|
|||||||
@@ -181,7 +181,6 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
|
|||||||
req->in.hdr = hdr;
|
req->in.hdr = hdr;
|
||||||
req->in.body = hdr+SMB2_HDR_BODY;
|
req->in.body = hdr+SMB2_HDR_BODY;
|
||||||
req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE);
|
req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE);
|
||||||
req->in.ptr = req->in.body;
|
|
||||||
req->status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
|
req->status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
|
||||||
|
|
||||||
DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", req->seqnum));
|
DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", req->seqnum));
|
||||||
|
|||||||
@@ -33,21 +33,21 @@ struct smb2_request *smb2_write_send(struct smb2_tree *tree, struct smb2_write *
|
|||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
|
|
||||||
req = smb2_request_init_tree(tree, SMB2_OP_WRITE, io->in.data.length + 0x30);
|
req = smb2_request_init_tree(tree, SMB2_OP_WRITE, 0x30, io->in.data.length);
|
||||||
if (req == NULL) return NULL;
|
if (req == NULL) return NULL;
|
||||||
|
|
||||||
SSVAL(req->out.body, 0x00, io->in.buffer_code);
|
status = smb2_push_o16s32_blob(&req->out, req->out.body+0x02, io->in.data);
|
||||||
SSVAL(req->out.body, 0x02, req->out.body+0x30 - req->out.hdr);
|
|
||||||
SIVAL(req->out.body, 0x04, io->in.data.length);
|
|
||||||
SBVAL(req->out.body, 0x08, io->in.offset);
|
|
||||||
smb2_put_handle(req->out.body+0x10, &io->in.handle);
|
|
||||||
memcpy(req->out.body+0x20, io->in._pad, 0x10);
|
|
||||||
|
|
||||||
status = smb2_push_blob(&req->out, req->out.body+0x30, io->in.data);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
talloc_free(req);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SBVAL(req->out.body, 0x08, io->in.offset);
|
||||||
|
smb2_push_handle(req->out.body+0x10, &io->in.handle);
|
||||||
|
|
||||||
|
SBVAL(req->out.body, 0x20, io->in.unknown1);
|
||||||
|
SBVAL(req->out.body, 0x28, io->in.unknown2);
|
||||||
|
|
||||||
smb2_transport_send(req);
|
smb2_transport_send(req);
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
@@ -64,15 +64,12 @@ NTSTATUS smb2_write_recv(struct smb2_request *req, struct smb2_write *io)
|
|||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->in.body_size < 17) {
|
SMB2_CHECK_PACKET_RECV(req, 0x11, False);
|
||||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMB2_CHECK_BUFFER_CODE(req, 0x11);
|
|
||||||
|
|
||||||
io->out._pad = SVAL(req->in.body, 0x02);
|
io->out._pad = SVAL(req->in.body, 0x02);
|
||||||
io->out.nwritten = IVAL(req->in.body, 0x04);
|
io->out.nwritten = IVAL(req->in.body, 0x04);
|
||||||
memcpy(io->out.unknown, req->in.body+0x08, 9);
|
io->out.unknown1 = BVAL(req->in.body, 0x08);
|
||||||
|
io->out._bug = CVAL(req->in.body, 0x10);
|
||||||
|
|
||||||
return smb2_request_destroy(req);
|
return smb2_request_destroy(req);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ static NTSTATUS torture_smb2_close(struct smb2_tree *tree, struct smb2_handle ha
|
|||||||
TALLOC_CTX *tmp_ctx = talloc_new(tree);
|
TALLOC_CTX *tmp_ctx = talloc_new(tree);
|
||||||
|
|
||||||
ZERO_STRUCT(io);
|
ZERO_STRUCT(io);
|
||||||
io.in.buffer_code = 0x18;
|
|
||||||
io.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
|
io.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
|
||||||
io.in.handle = handle;
|
io.in.handle = handle;
|
||||||
status = smb2_close(tree, &io);
|
status = smb2_close(tree, &io);
|
||||||
@@ -84,13 +83,10 @@ static NTSTATUS torture_smb2_write(struct smb2_tree *tree, struct smb2_handle ha
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZERO_STRUCT(w);
|
ZERO_STRUCT(w);
|
||||||
w.in.buffer_code = 0x31;
|
|
||||||
w.in.offset = 0;
|
w.in.offset = 0;
|
||||||
w.in.handle = handle;
|
w.in.handle = handle;
|
||||||
w.in.data = data;
|
w.in.data = data;
|
||||||
|
|
||||||
memset(w.in._pad, 0xff, 16);
|
|
||||||
|
|
||||||
status = smb2_write(tree, &w);
|
status = smb2_write(tree, &w);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
printf("write failed - %s\n", nt_errstr(status));
|
printf("write failed - %s\n", nt_errstr(status));
|
||||||
@@ -99,8 +95,6 @@ static NTSTATUS torture_smb2_write(struct smb2_tree *tree, struct smb2_handle ha
|
|||||||
|
|
||||||
torture_smb2_all_info(tree, handle);
|
torture_smb2_all_info(tree, handle);
|
||||||
|
|
||||||
memset(w.in._pad, 0xff, 16);
|
|
||||||
|
|
||||||
status = smb2_write(tree, &w);
|
status = smb2_write(tree, &w);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
printf("write failed - %s\n", nt_errstr(status));
|
printf("write failed - %s\n", nt_errstr(status));
|
||||||
@@ -110,7 +104,6 @@ static NTSTATUS torture_smb2_write(struct smb2_tree *tree, struct smb2_handle ha
|
|||||||
torture_smb2_all_info(tree, handle);
|
torture_smb2_all_info(tree, handle);
|
||||||
|
|
||||||
ZERO_STRUCT(r);
|
ZERO_STRUCT(r);
|
||||||
r.in.buffer_code = 0x31;
|
|
||||||
r.in.length = data.length;
|
r.in.length = data.length;
|
||||||
r.in.offset = 0;
|
r.in.offset = 0;
|
||||||
r.in.handle = handle;
|
r.in.handle = handle;
|
||||||
@@ -140,9 +133,21 @@ static struct smb2_handle torture_smb2_create(struct smb2_tree *tree,
|
|||||||
struct smb2_create io;
|
struct smb2_create io;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
TALLOC_CTX *tmp_ctx = talloc_new(tree);
|
TALLOC_CTX *tmp_ctx = talloc_new(tree);
|
||||||
|
DATA_BLOB blob = data_blob(NULL, 0);
|
||||||
|
|
||||||
|
#if 0 /* TODO: find out what this blob mean */
|
||||||
|
uint8_t buf[0x18];
|
||||||
|
|
||||||
|
SIVAL(buf, 0x00, 0x00000000);
|
||||||
|
SIVAL(buf, 0x04, 0x00040010);
|
||||||
|
SIVAL(buf, 0x08, 0x00180000);
|
||||||
|
SIVAL(buf, 0x0C, 0x00000000);
|
||||||
|
SBVAL(buf, 0x10, 0x006C00466341784DLLU);
|
||||||
|
|
||||||
|
blob = data_blob_const(buf, 0x18)
|
||||||
|
#endif
|
||||||
|
|
||||||
ZERO_STRUCT(io);
|
ZERO_STRUCT(io);
|
||||||
io.in.buffer_code = 0x39;
|
|
||||||
io.in.oplock_flags = 0;
|
io.in.oplock_flags = 0;
|
||||||
io.in.access_mask = SEC_RIGHTS_FILE_ALL;
|
io.in.access_mask = SEC_RIGHTS_FILE_ALL;
|
||||||
io.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
io.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
||||||
@@ -153,8 +158,9 @@ static struct smb2_handle torture_smb2_create(struct smb2_tree *tree,
|
|||||||
NTCREATEX_SHARE_ACCESS_WRITE;
|
NTCREATEX_SHARE_ACCESS_WRITE;
|
||||||
io.in.create_options = NTCREATEX_OPTIONS_WRITE_THROUGH;
|
io.in.create_options = NTCREATEX_OPTIONS_WRITE_THROUGH;
|
||||||
io.in.fname = fname;
|
io.in.fname = fname;
|
||||||
|
io.in.blob = blob;
|
||||||
|
|
||||||
status = smb2_create(tree, &io);
|
status = smb2_create(tree, tmp_ctx, &io);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
printf("create1 failed - %s\n", nt_errstr(status));
|
printf("create1 failed - %s\n", nt_errstr(status));
|
||||||
return io.out.handle;
|
return io.out.handle;
|
||||||
@@ -197,6 +203,7 @@ BOOL torture_smb2_connect(void)
|
|||||||
|
|
||||||
h1 = torture_smb2_create(tree, "test9.dat");
|
h1 = torture_smb2_create(tree, "test9.dat");
|
||||||
h2 = torture_smb2_create(tree, "test9.dat");
|
h2 = torture_smb2_create(tree, "test9.dat");
|
||||||
|
// h2 = torture_smb2_create(tree, "test9test9test9t9.dat");
|
||||||
torture_smb2_write(tree, h1);
|
torture_smb2_write(tree, h1);
|
||||||
torture_smb2_close(tree, h1);
|
torture_smb2_close(tree, h1);
|
||||||
torture_smb2_close(tree, h2);
|
torture_smb2_close(tree, h2);
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ BOOL torture_smb2_getinfo_scan(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZERO_STRUCT(cr);
|
ZERO_STRUCT(cr);
|
||||||
cr.in.buffer_code = 0x39;
|
|
||||||
cr.in.oplock_flags = 0;
|
cr.in.oplock_flags = 0;
|
||||||
cr.in.access_mask = SEC_RIGHTS_FILE_ALL;
|
cr.in.access_mask = SEC_RIGHTS_FILE_ALL;
|
||||||
cr.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
cr.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
||||||
@@ -62,8 +61,9 @@ BOOL torture_smb2_getinfo_scan(void)
|
|||||||
NTCREATEX_SHARE_ACCESS_WRITE;
|
NTCREATEX_SHARE_ACCESS_WRITE;
|
||||||
cr.in.create_options = NTCREATEX_OPTIONS_WRITE_THROUGH;
|
cr.in.create_options = NTCREATEX_OPTIONS_WRITE_THROUGH;
|
||||||
cr.in.fname = fname;
|
cr.in.fname = fname;
|
||||||
|
cr.in.blob = data_blob(NULL, 0);
|
||||||
|
|
||||||
status = smb2_create(tree, &cr);
|
status = smb2_create(tree, mem_ctx, &cr);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
printf("create of '%s' failed - %s\n", fname, nt_errstr(status));
|
printf("create of '%s' failed - %s\n", fname, nt_errstr(status));
|
||||||
return False;
|
return False;
|
||||||
@@ -73,7 +73,6 @@ BOOL torture_smb2_getinfo_scan(void)
|
|||||||
|
|
||||||
|
|
||||||
ZERO_STRUCT(io);
|
ZERO_STRUCT(io);
|
||||||
io.in.buffer_code = 0x29;
|
|
||||||
io.in.max_response_size = 0xFFFF;
|
io.in.max_response_size = 0xFFFF;
|
||||||
io.in.handle = handle;
|
io.in.handle = handle;
|
||||||
|
|
||||||
@@ -142,7 +141,7 @@ BOOL torture_smb2_scan(void)
|
|||||||
tree->session->transport->options.timeout = 3;
|
tree->session->transport->options.timeout = 3;
|
||||||
|
|
||||||
for (opcode=0;opcode<1000;opcode++) {
|
for (opcode=0;opcode<1000;opcode++) {
|
||||||
req = smb2_request_init_tree(tree, opcode, 2);
|
req = smb2_request_init_tree(tree, opcode, 2, 0);
|
||||||
SSVAL(req->out.body, 0, 0);
|
SSVAL(req->out.body, 0, 0);
|
||||||
smb2_transport_send(req);
|
smb2_transport_send(req);
|
||||||
if (!smb2_request_receive(req)) {
|
if (!smb2_request_receive(req)) {
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname,
|
|||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
ZERO_STRUCT(io);
|
ZERO_STRUCT(io);
|
||||||
io.in.buffer_code = 0x39;
|
|
||||||
io.in.oplock_flags = 0;
|
io.in.oplock_flags = 0;
|
||||||
io.in.access_mask = SEC_RIGHTS_FILE_ALL;
|
io.in.access_mask = SEC_RIGHTS_FILE_ALL;
|
||||||
io.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
io.in.file_attr = FILE_ATTRIBUTE_NORMAL;
|
||||||
@@ -135,14 +134,14 @@ NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname,
|
|||||||
NTCREATEX_SHARE_ACCESS_WRITE;
|
NTCREATEX_SHARE_ACCESS_WRITE;
|
||||||
io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
|
io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
|
||||||
io.in.fname = fname;
|
io.in.fname = fname;
|
||||||
|
io.in.blob = data_blob(NULL, 0);
|
||||||
|
|
||||||
status = smb2_create(tree, &io);
|
status = smb2_create(tree, tree, &io);
|
||||||
NT_STATUS_NOT_OK_RETURN(status);
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
|
|
||||||
*handle = io.out.handle;
|
*handle = io.out.handle;
|
||||||
|
|
||||||
ZERO_STRUCT(r);
|
ZERO_STRUCT(r);
|
||||||
r.in.buffer_code = 0x31;
|
|
||||||
r.in.length = 5;
|
r.in.length = 5;
|
||||||
r.in.offset = 0;
|
r.in.offset = 0;
|
||||||
r.in.handle = *handle;
|
r.in.handle = *handle;
|
||||||
@@ -162,7 +161,6 @@ NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
|
|||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
ZERO_STRUCT(io);
|
ZERO_STRUCT(io);
|
||||||
io.in.buffer_code = 0x39;
|
|
||||||
io.in.oplock_flags = 0;
|
io.in.oplock_flags = 0;
|
||||||
io.in.access_mask = SEC_RIGHTS_DIR_ALL;
|
io.in.access_mask = SEC_RIGHTS_DIR_ALL;
|
||||||
io.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
|
io.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
@@ -170,8 +168,9 @@ NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
|
|||||||
io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE;
|
io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE;
|
||||||
io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
||||||
io.in.fname = fname;
|
io.in.fname = fname;
|
||||||
|
io.in.blob = data_blob(NULL, 0);
|
||||||
|
|
||||||
status = smb2_create(tree, &io);
|
status = smb2_create(tree, tree, &io);
|
||||||
NT_STATUS_NOT_OK_RETURN(status);
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
|
|
||||||
*handle = io.out.handle;
|
*handle = io.out.handle;
|
||||||
|
|||||||
Reference in New Issue
Block a user