diff options
Diffstat (limited to 'source4/librpc/ndr')
-rw-r--r-- | source4/librpc/ndr/libndr.h | 16 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr.c | 10 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_basic.c | 54 |
3 files changed, 75 insertions, 5 deletions
diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index 3c77646239..5c51113874 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -99,9 +99,16 @@ struct ndr_print { #define LIBNDR_FLAG_STR_SIZE4 (1<<4) #define LIBNDR_FLAG_STR_NOTERM (1<<5) #define LIBNDR_FLAG_STR_NULLTERM (1<<6) -#define LIBNDR_STRING_FLAGS (0x7C) +#define LIBNDR_FLAG_STR_SIZE2 (1<<7) +#define LIBNDR_STRING_FLAGS (0xFC) #define LIBNDR_FLAG_REF_ALLOC (1<<10) +#define LIBNDR_FLAG_REMAINING (1<<11) +#define LIBNDR_FLAG_ALIGN2 (1<<12) +#define LIBNDR_FLAG_ALIGN4 (1<<13) +#define LIBNDR_FLAG_ALIGN8 (1<<14) + +#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8) /* useful macro for debugging */ #define NDR_PRINT_DEBUG(type, p) ndr_print_debug((ndr_print_fn_t)ndr_print_ ##type, #p, p) @@ -146,6 +153,8 @@ enum ndr_err_code { } \ } while(0) +#define NDR_ALIGN(ndr, n) ndr_align_size(ndr->offset, n) + #define NDR_PULL_ALIGN(ndr, n) do { \ if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \ ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \ @@ -176,7 +185,7 @@ enum ndr_err_code { #define NDR_ALLOC_SIZE(ndr, s, size) do { \ (s) = talloc(ndr->mem_ctx, size); \ - if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, \ + if ((size) && !(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, \ "Alloc %u failed\n", \ size); \ } while (0) @@ -201,7 +210,7 @@ enum ndr_err_code { #define NDR_PUSH_ALLOC_SIZE(ndr, s, size) do { \ (s) = talloc(ndr->mem_ctx, size); \ - if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, \ + if ((size) && !(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, \ "push alloc %u failed\n",\ size); \ } while (0) @@ -225,6 +234,7 @@ typedef void (*ndr_print_union_fn_t)(struct ndr_print *, const char *, uint32, v /* now pull in the individual parsers */ #include "librpc/ndr/ndr_basic.h" #include "librpc/ndr/ndr_sec.h" +#include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/gen_ndr/ndr_misc.h" #include "librpc/gen_ndr/ndr_echo.h" #include "librpc/gen_ndr/ndr_lsa.h" diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c index 44472147fd..bce4759d8a 100644 --- a/source4/librpc/ndr/ndr.c +++ b/source4/librpc/ndr/ndr.c @@ -31,6 +31,16 @@ #define NDR_BASE_MARSHALL_SIZE 1024 + +/* + work out the number of bytes needed to align on a n byte boundary +*/ +size_t ndr_align_size(uint32 offset, size_t n) +{ + if ((offset & (n-1)) == 0) return 0; + return n - (offset & (n-1)); +} + /* initialise a ndr parse structure from a data blob */ diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c index 4d0be44a89..081d9ff87a 100644 --- a/source4/librpc/ndr/ndr_basic.c +++ b/source4/librpc/ndr/ndr_basic.c @@ -343,6 +343,7 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) { char *as=NULL; uint32 len1, ofs, len2; + uint16 len3; int ret; if (!(ndr_flags & NDR_SCALARS)) { @@ -437,6 +438,14 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) (*s) = as; break; + case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2: + NDR_CHECK(ndr_pull_uint16(ndr, &len3)); + NDR_ALLOC_N(ndr, as, (len3+1)); + NDR_CHECK(ndr_pull_bytes(ndr, as, len3)); + as[len3] = 0; + (*s) = as; + break; + default: return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", ndr->flags & LIBNDR_STRING_FLAGS); @@ -546,6 +555,19 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) ndr->offset += c_len + 1; break; + case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2: + NDR_CHECK(ndr_push_uint16(ndr, c_len+1)); + NDR_PUSH_NEED_BYTES(ndr, c_len + 1); + ret = convert_string(CH_UNIX, CH_DOS, + s, s_len + 1, + ndr->data+ndr->offset, c_len + 1); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + ndr->offset += c_len + 1; + break; + default: return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", ndr->flags & LIBNDR_STRING_FLAGS); @@ -729,7 +751,19 @@ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r) */ NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, DATA_BLOB blob) { - NDR_CHECK(ndr_push_uint32(ndr, blob.length)); + if (ndr->flags & LIBNDR_ALIGN_FLAGS) { + if (ndr->flags & LIBNDR_FLAG_ALIGN2) { + blob.length = NDR_ALIGN(ndr, 2); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) { + blob.length = NDR_ALIGN(ndr, 4); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) { + blob.length = NDR_ALIGN(ndr, 8); + } + NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length); + data_blob_clear(&blob); + } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) { + NDR_CHECK(ndr_push_uint32(ndr, blob.length)); + } NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length)); return NT_STATUS_OK; } @@ -740,7 +774,23 @@ NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, DATA_BLOB blob) NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, DATA_BLOB *blob) { uint32 length; - NDR_CHECK(ndr_pull_uint32(ndr, &length)); + + if (ndr->flags & LIBNDR_ALIGN_FLAGS) { + if (ndr->flags & LIBNDR_FLAG_ALIGN2) { + length = NDR_ALIGN(ndr, 2); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) { + length = NDR_ALIGN(ndr, 4); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) { + length = NDR_ALIGN(ndr, 8); + } + if (ndr->data_size - ndr->offset < length) { + length = ndr->data_size - ndr->offset; + } + } else if (ndr->flags & LIBNDR_FLAG_REMAINING) { + length = ndr->data_size - ndr->offset; + } else { + NDR_CHECK(ndr_pull_uint32(ndr, &length)); + } NDR_PULL_NEED_BYTES(ndr, length); *blob = data_blob_talloc(ndr->mem_ctx, ndr->data+ndr->offset, length); ndr->offset += length; |