diff options
-rw-r--r-- | source4/libcli/smb2/create.c | 4 | ||||
-rw-r--r-- | source4/libcli/smb2/request.c | 172 | ||||
-rw-r--r-- | source4/libcli/smb2/session.c | 2 | ||||
-rw-r--r-- | source4/libcli/smb2/tcon.c | 2 | ||||
-rw-r--r-- | source4/libcli/smb2/write.c | 2 |
5 files changed, 97 insertions, 85 deletions
diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c index 79d3341bd0..47fd208643 100644 --- a/source4/libcli/smb2/create.c +++ b/source4/libcli/smb2/create.c @@ -48,13 +48,13 @@ 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, 0x28, io->in.create_options); - status = smb2_push_o16s16_string(&req->out, req->out.body+0x2C, io->in.fname); + status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } - status = smb2_push_o32s32_blob(&req->out, req->out.body+0x30, io->in.blob); + status = smb2_push_o32s32_blob(&req->out, 0x30, io->in.blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 3e80115e47..1a98ba9987 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -50,10 +50,9 @@ struct smb2_request *smb2_request_init(struct smb2_transport *transport, uint16_ ZERO_STRUCT(req->in); - req->out.size = SMB2_HDR_BODY+NBT_HDR_SIZE+ - body_fixed_size+body_dynamic_size; + req->out.size = SMB2_HDR_BODY+NBT_HDR_SIZE+body_fixed_size; - req->out.allocated = req->out.size; + req->out.allocated = req->out.size + body_dynamic_size; req->out.buffer = talloc_size(req, req->out.allocated); if (req->out.buffer == NULL) { talloc_free(req); @@ -182,26 +181,30 @@ static size_t smb2_padding_size(uint32_t offset, size_t n) return n - (offset & (n-1)); } -static NTSTATUS smb2_grow_buffer(struct smb2_request_buffer *buf, size_t n) +/* + grow a SMB2 buffer by the specified amount +*/ +static NTSTATUS smb2_grow_buffer(struct smb2_request_buffer *buf, size_t increase) { size_t dynamic_ofs; uint8_t *buffer_ptr; + uint32_t newsize = buf->size + increase; /* a packet size should be limited a bit */ - if (n >= 0x00FFFFFF) return NT_STATUS_MARSHALL_OVERFLOW; + if (newsize >= 0x00FFFFFF) return NT_STATUS_MARSHALL_OVERFLOW; - if (n <= buf->allocated) return NT_STATUS_OK; + if (newsize <= buf->allocated) return NT_STATUS_OK; dynamic_ofs = buf->dynamic - buf->buffer; - buffer_ptr = talloc_realloc_size(buf, buf->buffer, n); + buffer_ptr = talloc_realloc_size(buf, buf->buffer, newsize); 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; + buf->allocated = newsize; return NT_STATUS_OK; } @@ -232,15 +235,18 @@ NTSTATUS smb2_pull_o16s16_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ /* 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 ofs points to the start of the offset/length pair, and is relative + to the body start */ -NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DATA_BLOB blob) +NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf, + uint16_t ofs, DATA_BLOB blob) { NTSTATUS status; size_t offset; size_t padding_length; + uint8_t *ptr = buf->body+ofs; - if (!buf->dynamic) { + if (buf->dynamic == NULL) { return NT_STATUS_INVALID_PARAMETER; } @@ -267,7 +273,7 @@ NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DA SSVAL(ptr, 0, offset); SSVAL(ptr, 2, blob.length); - status = smb2_grow_buffer(buf, NBT_HDR_SIZE + offset + blob.length); + status = smb2_grow_buffer(buf, padding_length + blob.length); NT_STATUS_NOT_OK_RETURN(status); memset(buf->dynamic, 0, padding_length); @@ -276,48 +282,27 @@ NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DA memcpy(buf->dynamic, blob.data, blob.length); buf->dynamic += blob.length; - buf->size = buf->dynamic - buf->buffer; + buf->size += blob.length + padding_length; + buf->body_size += blob.length + padding_length; return NT_STATUS_OK; } -/* - 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_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 + the ofs points to the start of the offset/length pair, and is relative + to the body start */ -NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DATA_BLOB blob) +NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf, + uint16_t ofs, DATA_BLOB blob) { NTSTATUS status; size_t offset; size_t padding_length; + uint8_t *ptr = buf->body+ofs; - if (!buf->dynamic) { + if (buf->dynamic == NULL) { return NT_STATUS_INVALID_PARAMETER; } @@ -339,7 +324,7 @@ NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DA SSVAL(ptr, 0, offset); SIVAL(ptr, 2, blob.length); - status = smb2_grow_buffer(buf, NBT_HDR_SIZE + offset + blob.length); + status = smb2_grow_buffer(buf, padding_length + blob.length); NT_STATUS_NOT_OK_RETURN(status); memset(buf->dynamic, 0, padding_length); @@ -348,46 +333,27 @@ NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DA memcpy(buf->dynamic, blob.data, blob.length); buf->dynamic += blob.length; - buf->size = buf->dynamic - buf->buffer; + buf->size += blob.length + padding_length; + buf->body_size += blob.length + padding_length; 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 + the ofs points to the start of the offset/length pair, and is relative + to the body start */ -NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DATA_BLOB blob) +NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf, + uint32_t ofs, DATA_BLOB blob) { NTSTATUS status; size_t offset; size_t padding_length; + uint8_t *ptr = buf->body+ofs; - if (!buf->dynamic) { + if (buf->dynamic == NULL) { return NT_STATUS_INVALID_PARAMETER; } @@ -409,7 +375,7 @@ NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DA SIVAL(ptr, 0, offset); SIVAL(ptr, 4, blob.length); - status = smb2_grow_buffer(buf, NBT_HDR_SIZE + offset + blob.length); + status = smb2_grow_buffer(buf, padding_length + blob.length); NT_STATUS_NOT_OK_RETURN(status); memset(buf->dynamic, 0, padding_length); @@ -418,8 +384,59 @@ NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf, uint8_t *ptr, DA memcpy(buf->dynamic, blob.data, blob.length); buf->dynamic += blob.length; - buf->size = buf->dynamic - buf->buffer; + buf->size += blob.length + padding_length; + buf->body_size += blob.length + padding_length; + + return NT_STATUS_OK; +} + +/* + 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_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; +} +/* + 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; } @@ -453,17 +470,14 @@ NTSTATUS smb2_pull_o16s16_string(struct smb2_request_buffer *buf, TALLOC_CTX *me UTF-16 without termination */ NTSTATUS smb2_push_o16s16_string(struct smb2_request_buffer *buf, - uint8_t *ptr, const char *str) + uint16_t ofs, const char *str) { DATA_BLOB blob; NTSTATUS status; ssize_t size; if (strcmp("", str) == 0) { - blob = data_blob(NULL, 0); - status = smb2_push_o16s16_blob(buf, ptr, blob); - NT_STATUS_NOT_OK_RETURN(status); - return NT_STATUS_OK; + return smb2_push_o16s16_blob(buf, ofs, data_blob(NULL, 0)); } size = convert_string_talloc(buf->buffer, CH_UNIX, CH_UTF16, @@ -473,11 +487,9 @@ NTSTATUS smb2_push_o16s16_string(struct smb2_request_buffer *buf, } blob.length = size; - status = smb2_push_o16s16_blob(buf, ptr, blob); + status = smb2_push_o16s16_blob(buf, ofs, blob); data_blob_free(&blob); - NT_STATUS_NOT_OK_RETURN(status); - - return NT_STATUS_OK; + return status; } /* diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index e572227a48..0a13a288fc 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -77,7 +77,7 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session, req->session = session; - status = smb2_push_o16s16_blob(&req->out, req->out.body+0x0C, io->in.secblob); + status = smb2_push_o16s16_blob(&req->out, 0x0C, io->in.secblob); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; diff --git a/source4/libcli/smb2/tcon.c b/source4/libcli/smb2/tcon.c index 32ad05733e..886ed9828b 100644 --- a/source4/libcli/smb2/tcon.c +++ b/source4/libcli/smb2/tcon.c @@ -61,7 +61,7 @@ struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree, SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid); SIVAL(req->out.body, 0x00, io->in.unknown1); - status = smb2_push_o16s16_string(&req->out, req->out.body+0x04, io->in.path); + status = smb2_push_o16s16_string(&req->out, 0x04, io->in.path); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; diff --git a/source4/libcli/smb2/write.c b/source4/libcli/smb2/write.c index 0b28b820ec..591cf2c891 100644 --- a/source4/libcli/smb2/write.c +++ b/source4/libcli/smb2/write.c @@ -36,7 +36,7 @@ struct smb2_request *smb2_write_send(struct smb2_tree *tree, struct smb2_write * req = smb2_request_init_tree(tree, SMB2_OP_WRITE, 0x30, io->in.data.length); if (req == NULL) return NULL; - status = smb2_push_o16s32_blob(&req->out, req->out.body+0x02, io->in.data); + status = smb2_push_o16s32_blob(&req->out, 0x02, io->in.data); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; |