{
struct ndr_print *ndr;
- ndr = talloc(NULL, struct ndr_print);
+ ndr = talloc_zero(NULL, struct ndr_print);
if (!ndr) return;
ndr->print = ndr_print_debug_helper;
ndr->depth = 1;
talloc_free(ndr);
}
-
-/*
- a useful helper function for printing idl unions via DEBUG()
-*/
-void ndr_print_union_debug(ndr_print_union_fn_t fn, const char *name, uint32_t level, void *ptr)
-{
- struct ndr_print *ndr;
-
- ndr = talloc(NULL, struct ndr_print);
- if (!ndr) return;
- ndr->print = ndr_print_debug_helper;
- ndr->depth = 1;
- ndr->flags = 0;
- fn(ndr, name, level, ptr);
- talloc_free(ndr);
-}
-
/*
a useful helper function for printing idl function calls via DEBUG()
*/
{
struct ndr_print *ndr;
- ndr = talloc(NULL, struct ndr_print);
+ ndr = talloc_zero(NULL, struct ndr_print);
if (!ndr) return;
ndr->print = ndr_print_debug_helper;
ndr->depth = 1;
we use magic in pidl to make them easier to cope with
*/
NTSTATUS ndr_pull_subcontext_header(struct ndr_pull *ndr,
- size_t sub_size,
+ size_t header_size,
+ ssize_t size_is,
struct ndr_pull *ndr2)
{
ndr2->flags = ndr->flags;
- switch (sub_size) {
+ switch (header_size) {
case 0: {
- uint32_t size = ndr->data_size - ndr->offset;
- NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, size));
+ uint32_t content_size = ndr->data_size - ndr->offset;
+ if (size_is >= 0) {
+ content_size = size_is;
+ }
+ NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, content_size));
break;
}
case 2: {
- uint16_t size;
- NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &size));
- NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, size));
+ uint16_t content_size;
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
+ if (size_is >= 0 && size_is != content_size) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
+ size_is, content_size);
+ }
+ NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, content_size));
break;
}
case 4: {
- uint32_t size;
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &size));
- NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, size));
+ uint32_t content_size;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
+ if (size_is >= 0 && size_is != content_size) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
+ size_is, content_size);
+ }
+ NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, content_size));
break;
}
default:
- return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext size %d",
- sub_size);
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d",
+ header_size);
}
return NT_STATUS_OK;
}
push a subcontext header
*/
NTSTATUS ndr_push_subcontext_header(struct ndr_push *ndr,
- size_t sub_size,
+ size_t header_size,
+ ssize_t size_is,
struct ndr_push *ndr2)
{
- switch (sub_size) {
+ if (size_is >= 0) {
+ ssize_t padding_len = size_is - ndr2->offset;
+ if (padding_len > 0) {
+ NDR_CHECK(ndr_push_zero(ndr2, padding_len));
+ } else if (padding_len < 0) {
+ return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
+ ndr2->offset, size_is);
+ }
+ }
+
+ switch (header_size) {
case 0:
break;
break;
default:
- return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext size %d",
- sub_size);
+ return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d",
+ header_size);
}
return NT_STATUS_OK;
}
/*
store a switch value
*/
-NTSTATUS ndr_push_set_switch_value(struct ndr_push *ndr, void *p, uint32_t val)
+NTSTATUS ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
+{
+ return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+NTSTATUS ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
{
return ndr_token_store(ndr, &ndr->switch_list, p, val);
}
-NTSTATUS ndr_pull_set_switch_value(struct ndr_pull *ndr, void *p, uint32_t val)
+NTSTATUS ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
{
return ndr_token_store(ndr, &ndr->switch_list, p, val);
}
/*
retrieve a switch value
*/
-uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, void *p)
+uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p)
+{
+ return ndr_token_peek(&ndr->switch_list, p);
+}
+
+uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p)
{
return ndr_token_peek(&ndr->switch_list, p);
}
-uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, void *p)
+uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p)
{
return ndr_token_peek(&ndr->switch_list, p);
}
return NT_STATUS_OK;
}
-
/*
- pull a union from a blob using NDR
+ pull a struct from a blob using NDR
*/
-NTSTATUS ndr_pull_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, uint32_t level, void *p,
- ndr_pull_union_fn_t fn)
+NTSTATUS ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+ ndr_pull_flags_fn_t fn)
{
struct ndr_pull *ndr;
ndr = ndr_pull_init_blob(blob, mem_ctx);
if (!ndr) {
return NT_STATUS_NO_MEMORY;
}
- return fn(ndr, NDR_SCALARS|NDR_BUFFERS, level, p);
+ return fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
}
/*
- pull a struct from a blob using NDR
+ pull a struct from a blob using NDR - failing if all bytes are not consumed
*/
-NTSTATUS ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
- ndr_pull_flags_fn_t fn)
+NTSTATUS ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+ ndr_pull_flags_fn_t fn)
{
struct ndr_pull *ndr;
+ NTSTATUS status;
+
ndr = ndr_pull_init_blob(blob, mem_ctx);
if (!ndr) {
return NT_STATUS_NO_MEMORY;
}
- return fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ if (!NT_STATUS_IS_OK(status)) return status;
+ if (ndr->offset != ndr->data_size) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+ return status;
}
/*
NTSTATUS status;
size_t ret;
+ /* avoid recursion */
+ if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
+
ndr = ndr_push_init_ctx(NULL);
if (!ndr) return 0;
- ndr->flags |= flags;
+ ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
status = push(ndr, NDR_SCALARS|NDR_BUFFERS, discard_const(p));
if (!NT_STATUS_IS_OK(status)) {
return 0;
/*
generic ndr_size_*() handler for unions
*/
-size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_union_fn_t push)
+size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push)
{
struct ndr_push *ndr;
NTSTATUS status;
size_t ret;
+ /* avoid recursion */
+ if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
+
ndr = ndr_push_init_ctx(NULL);
if (!ndr) return 0;
- ndr->flags |= flags;
- status = push(ndr, NDR_SCALARS|NDR_BUFFERS, level, discard_const(p));
+ ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
+ ndr_push_set_switch_value(ndr, p, level);
+ status = push(ndr, NDR_SCALARS|NDR_BUFFERS, discard_const(p));
if (!NT_STATUS_IS_OK(status)) {
return 0;
}