diff options
-rw-r--r-- | libcli/smb/config.mk | 11 | ||||
-rw-r--r-- | libcli/smb/smb2_create_blob.c | 186 | ||||
-rw-r--r-- | libcli/smb/smb2_create_blob.h | 51 | ||||
-rw-r--r-- | libcli/smb/smb_common.h | 1 | ||||
-rw-r--r-- | source4/libcli/config.mk | 2 | ||||
-rw-r--r-- | source4/libcli/raw/interfaces.h | 8 | ||||
-rw-r--r-- | source4/libcli/smb2/create.c | 157 | ||||
-rw-r--r-- | source4/main.mk | 1 |
8 files changed, 252 insertions, 165 deletions
diff --git a/libcli/smb/config.mk b/libcli/smb/config.mk new file mode 100644 index 0000000000..57c25c3844 --- /dev/null +++ b/libcli/smb/config.mk @@ -0,0 +1,11 @@ +# common SMB and SMB2 stuff +[SUBSYSTEM::LIBCLI_SMB_COMMON] +PUBLIC_DEPENDENCIES = LIBTALLOC + +LIBCLI_SMB_COMMON_OBJ_FILES = $(addprefix ../libcli/smb/, \ + smb2_create_blob.o) + +$(eval $(call proto_header_template, \ + ../libcli/smb/smb_common_proto.h, \ + $(LIBCLI_SMB_COMMON_OBJ_FILES:.o=.c))) + diff --git a/libcli/smb/smb2_create_blob.c b/libcli/smb/smb2_create_blob.c new file mode 100644 index 0000000000..0dad2240d0 --- /dev/null +++ b/libcli/smb/smb2_create_blob.c @@ -0,0 +1,186 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 Create Context Blob handling + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Stefan Metzmacher 2008-2009 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "../libcli/smb/smb_common.h" + +static size_t smb2_create_blob_padding(uint32_t offset, size_t n) +{ + if ((offset & (n-1)) == 0) return 0; + return n - (offset & (n-1)); +} + +/* + parse a set of SMB2 create blobs +*/ +NTSTATUS smb2_create_blob_parse(TALLOC_CTX *mem_ctx, const DATA_BLOB buffer, + struct smb2_create_blobs *blobs) +{ + const uint8_t *data = buffer.data; + uint32_t remaining = buffer.length; + + while (remaining > 0) { + uint32_t next; + uint32_t name_offset, name_length; + uint32_t reserved, data_offset; + uint32_t data_length; + char *tag; + DATA_BLOB b; + NTSTATUS status; + + if (remaining < 16) { + return NT_STATUS_INVALID_PARAMETER; + } + next = IVAL(data, 0); + name_offset = SVAL(data, 4); + name_length = SVAL(data, 6); + reserved = SVAL(data, 8); + data_offset = SVAL(data, 10); + data_length = IVAL(data, 12); + + if ((next & 0x7) != 0 || + next > remaining || + name_offset < 16 || + name_offset > remaining || + name_length != 4 || /* windows enforces this */ + name_offset + name_length > remaining || + data_offset < name_offset + name_length || + data_offset > remaining || + data_offset + (uint64_t)data_length > remaining) { + return NT_STATUS_INVALID_PARAMETER; + } + + tag = talloc_strndup(mem_ctx, (const char *)data + name_offset, name_length); + if (tag == NULL) { + return NT_STATUS_NO_MEMORY; + } + + b = data_blob_const(data+data_offset, data_length); + status = smb2_create_blob_add(mem_ctx, blobs, tag, b); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + talloc_free(tag); + + if (next == 0) break; + + remaining -= next; + data += next; + + if (remaining < 16) { + return NT_STATUS_INVALID_PARAMETER; + } + } + + return NT_STATUS_OK; +} + + +/* + add a blob to a smb2_create attribute blob +*/ +static NTSTATUS smb2_create_blob_push_one(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer, + const struct smb2_create_blob *blob, + bool last) +{ + uint32_t ofs = buffer->length; + size_t tag_length = strlen(blob->tag); + uint8_t pad = smb2_create_blob_padding(blob->data.length+tag_length, 4); + + if (!data_blob_realloc(mem_ctx, buffer, + buffer->length + 0x14 + tag_length + blob->data.length + pad)) + return NT_STATUS_NO_MEMORY; + + if (last) { + SIVAL(buffer->data, ofs+0x00, 0); + } else { + SIVAL(buffer->data, ofs+0x00, 0x14 + tag_length + blob->data.length + pad); + } + SSVAL(buffer->data, ofs+0x04, 0x10); /* offset of tag */ + SIVAL(buffer->data, ofs+0x06, tag_length); /* tag length */ + SSVAL(buffer->data, ofs+0x0A, 0x14 + tag_length); /* offset of data */ + SIVAL(buffer->data, ofs+0x0C, blob->data.length); + memcpy(buffer->data+ofs+0x10, blob->tag, tag_length); + SIVAL(buffer->data, ofs+0x10+tag_length, 0); /* pad? */ + memcpy(buffer->data+ofs+0x14+tag_length, blob->data.data, blob->data.length); + memset(buffer->data+ofs+0x14+tag_length+blob->data.length, 0, pad); + + return NT_STATUS_OK; +} + + +/* + create a buffer of a set of create blobs +*/ +NTSTATUS smb2_create_blob_push(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer, + const struct smb2_create_blobs blobs) +{ + int i; + NTSTATUS status; + + *buffer = data_blob(NULL, 0); + for (i=0; i < blobs.num_blobs; i++) { + bool last = false; + const struct smb2_create_blob *c; + + if ((i + 1) == blobs.num_blobs) { + last = true; + } + + c = &blobs.blobs[i]; + status = smb2_create_blob_push_one(mem_ctx, buffer, c, last); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + return NT_STATUS_OK; +} + + +NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b, + const char *tag, DATA_BLOB data) +{ + struct smb2_create_blob *array; + + array = talloc_realloc(mem_ctx, b->blobs, + struct smb2_create_blob, + b->num_blobs + 1); + NT_STATUS_HAVE_NO_MEMORY(array); + b->blobs = array; + + b->blobs[b->num_blobs].tag = talloc_strdup(b->blobs, tag); + NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].tag); + + if (data.data) { + b->blobs[b->num_blobs].data = data_blob_talloc(b->blobs, + data.data, + data.length); + NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].data.data); + } else { + b->blobs[b->num_blobs].data = data_blob(NULL, 0); + } + + b->num_blobs += 1; + + return NT_STATUS_OK; +} diff --git a/libcli/smb/smb2_create_blob.h b/libcli/smb/smb2_create_blob.h new file mode 100644 index 0000000000..e8b8f12fe3 --- /dev/null +++ b/libcli/smb/smb2_create_blob.h @@ -0,0 +1,51 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 Create Context Blob handling + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Stefan Metzmacher 2008-2009 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _LIBCLI_SMB_SMB2_CREATE_BLOB_H_ +#define _LIBCLI_SMB_SMB2_CREATE_BLOB_H_ + +struct smb2_create_blob { + const char *tag; + DATA_BLOB data; +}; + +struct smb2_create_blobs { + uint32_t num_blobs; + struct smb2_create_blob *blobs; +}; + +/* + parse a set of SMB2 create blobs +*/ +NTSTATUS smb2_create_blob_parse(TALLOC_CTX *mem_ctx, const DATA_BLOB buffer, + struct smb2_create_blobs *blobs); + +/* + create a buffer of a set of create blobs +*/ +NTSTATUS smb2_create_blob_push(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer, + const struct smb2_create_blobs blobs); + +NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b, + const char *tag, DATA_BLOB data); + +#endif /* _LIBCLI_SMB_SMB2_CREATE_BLOB_H_ */ diff --git a/libcli/smb/smb_common.h b/libcli/smb/smb_common.h index f5994d4105..d6186ab526 100644 --- a/libcli/smb/smb_common.h +++ b/libcli/smb/smb_common.h @@ -23,5 +23,6 @@ #define __LIBCLI_SMB_SMB_COMMON_H__ #include "../libcli/smb/smb2_constants.h" +#include "../libcli/smb/smb2_create_blob.h" #endif diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index ad7bc311c2..b6a9f112a0 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -147,7 +147,7 @@ $(eval $(call proto_header_template,$(libclisrcdir)/libcli_proto.h,$(LIBCLI_SMB_ [SUBSYSTEM::LIBCLI_RAW] PRIVATE_DEPENDENCIES = LIBCLI_COMPOSITE LP_RESOLVE gensec LIBCLI_RESOLVE LIBSECURITY LIBNDR #LDFLAGS = $(LIBCLI_SMB_COMPOSITE_OUTPUT) -PUBLIC_DEPENDENCIES = samba_socket LIBPACKET gensec LIBCRYPTO CREDENTIALS +PUBLIC_DEPENDENCIES = samba_socket LIBPACKET gensec LIBCRYPTO CREDENTIALS LIBCLI_SMB_COMMON LIBCLI_RAW_OBJ_FILES = $(addprefix $(libclisrcdir)/raw/, rawfile.o smb_signing.o clisocket.o \ clitransport.o clisession.o clitree.o clierror.o rawrequest.o \ diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index ad5f5bf223..13217158cb 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -1660,13 +1660,7 @@ union smb_open { struct smb2_lease *lease_request; /* and any additional blobs the caller wants */ - struct smb2_create_blobs { - uint32_t num_blobs; - struct smb2_create_blob { - const char *tag; - DATA_BLOB data; - } *blobs; - } blobs; + struct smb2_create_blobs blobs; } in; struct { union smb_handle file; diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c index 363210bd03..c9fb4ea4e0 100644 --- a/source4/libcli/smb2/create.c +++ b/source4/libcli/smb2/create.c @@ -26,163 +26,6 @@ #include "libcli/smb2/smb2_calls.h" #include "librpc/gen_ndr/ndr_security.h" - -/* - parse a set of SMB2 create blobs -*/ -NTSTATUS smb2_create_blob_parse(TALLOC_CTX *mem_ctx, const DATA_BLOB buffer, - struct smb2_create_blobs *blobs) -{ - const uint8_t *data = buffer.data; - uint32_t remaining = buffer.length; - - while (remaining > 0) { - uint32_t next; - uint32_t name_offset, name_length; - uint32_t reserved, data_offset; - uint32_t data_length; - char *tag; - DATA_BLOB b; - NTSTATUS status; - - if (remaining < 16) { - return NT_STATUS_INVALID_PARAMETER; - } - next = IVAL(data, 0); - name_offset = SVAL(data, 4); - name_length = SVAL(data, 6); - reserved = SVAL(data, 8); - data_offset = SVAL(data, 10); - data_length = IVAL(data, 12); - - if ((next & 0x7) != 0 || - next > remaining || - name_offset < 16 || - name_offset > remaining || - name_length != 4 || /* windows enforces this */ - name_offset + name_length > remaining || - data_offset < name_offset + name_length || - data_offset > remaining || - data_offset + (uint64_t)data_length > remaining) { - return NT_STATUS_INVALID_PARAMETER; - } - - tag = talloc_strndup(mem_ctx, (const char *)data + name_offset, name_length); - if (tag == NULL) { - return NT_STATUS_NO_MEMORY; - } - - b = data_blob_const(data+data_offset, data_length); - status = smb2_create_blob_add(mem_ctx, blobs, tag, b); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - talloc_free(tag); - - if (next == 0) break; - - remaining -= next; - data += next; - - if (remaining < 16) { - return NT_STATUS_INVALID_PARAMETER; - } - } - - return NT_STATUS_OK; -} - - -/* - add a blob to a smb2_create attribute blob -*/ -static NTSTATUS smb2_create_blob_push_one(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer, - const struct smb2_create_blob *blob, - bool last) -{ - uint32_t ofs = buffer->length; - size_t tag_length = strlen(blob->tag); - uint8_t pad = smb2_padding_size(blob->data.length+tag_length, 4); - - if (!data_blob_realloc(mem_ctx, buffer, - buffer->length + 0x14 + tag_length + blob->data.length + pad)) - return NT_STATUS_NO_MEMORY; - - if (last) { - SIVAL(buffer->data, ofs+0x00, 0); - } else { - SIVAL(buffer->data, ofs+0x00, 0x14 + tag_length + blob->data.length + pad); - } - SSVAL(buffer->data, ofs+0x04, 0x10); /* offset of tag */ - SIVAL(buffer->data, ofs+0x06, tag_length); /* tag length */ - SSVAL(buffer->data, ofs+0x0A, 0x14 + tag_length); /* offset of data */ - SIVAL(buffer->data, ofs+0x0C, blob->data.length); - memcpy(buffer->data+ofs+0x10, blob->tag, tag_length); - SIVAL(buffer->data, ofs+0x10+tag_length, 0); /* pad? */ - memcpy(buffer->data+ofs+0x14+tag_length, blob->data.data, blob->data.length); - memset(buffer->data+ofs+0x14+tag_length+blob->data.length, 0, pad); - - return NT_STATUS_OK; -} - - -/* - create a buffer of a set of create blobs -*/ -NTSTATUS smb2_create_blob_push(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer, - const struct smb2_create_blobs blobs) -{ - int i; - NTSTATUS status; - - *buffer = data_blob(NULL, 0); - for (i=0; i < blobs.num_blobs; i++) { - bool last = false; - const struct smb2_create_blob *c; - - if ((i + 1) == blobs.num_blobs) { - last = true; - } - - c = &blobs.blobs[i]; - status = smb2_create_blob_push_one(mem_ctx, buffer, c, last); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } - return NT_STATUS_OK; -} - - -NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b, - const char *tag, DATA_BLOB data) -{ - struct smb2_create_blob *array; - - array = talloc_realloc(mem_ctx, b->blobs, - struct smb2_create_blob, - b->num_blobs + 1); - NT_STATUS_HAVE_NO_MEMORY(array); - b->blobs = array; - - b->blobs[b->num_blobs].tag = talloc_strdup(b->blobs, tag); - NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].tag); - - if (data.data) { - b->blobs[b->num_blobs].data = data_blob_talloc(b->blobs, - data.data, - data.length); - NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].data.data); - } else { - b->blobs[b->num_blobs].data = data_blob(NULL, 0); - } - - b->num_blobs += 1; - - return NT_STATUS_OK; -} - /* send a create request */ diff --git a/source4/main.mk b/source4/main.mk index 4d7fd584f8..63eea36cdf 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -48,6 +48,7 @@ mkinclude torture/config.mk mkinclude librpc/config.mk mkinclude client/config.mk mkinclude libcli/config.mk +mkinclude ../libcli/smb/config.mk mkinclude ../libcli/cldap/config.mk mkinclude scripting/python/config.mk mkinclude kdc/config.mk |