summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/librpc/ndr/ndr_string.c127
1 files changed, 105 insertions, 22 deletions
diff --git a/source4/librpc/ndr/ndr_string.c b/source4/librpc/ndr/ndr_string.c
index 6c4332bd01..e6da55a33b 100644
--- a/source4/librpc/ndr/ndr_string.c
+++ b/source4/librpc/ndr/ndr_string.c
@@ -275,7 +275,8 @@ _PUBLIC_ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const cha
case LIBNDR_FLAG_STR_NOTERM:
if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
- break;
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
}
len1 = ndr->data_size - ndr->offset;
@@ -482,32 +483,85 @@ _PUBLIC_ NTSTATUS ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, con
{
const char **a = *_a;
uint32_t count;
+ unsigned flags = ndr->flags;
+ unsigned saved_flags = ndr->flags;
if (!(ndr_flags & NDR_SCALARS)) {
return NT_STATUS_OK;
}
- for (count = 0;; count++) {
- TALLOC_CTX *tmp_ctx;
- const char *s = NULL;
- a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
- NT_STATUS_HAVE_NO_MEMORY(a);
- a[count] = NULL;
- a[count+1] = NULL;
-
- tmp_ctx = ndr->current_mem_ctx;
- ndr->current_mem_ctx = a;
- NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
- ndr->current_mem_ctx = tmp_ctx;
- if (strcmp("", s)==0) {
- a[count] = NULL;
- break;
- } else {
+ switch (flags & LIBNDR_STRING_FLAGS) {
+ case LIBNDR_FLAG_STR_NULLTERM:
+ /*
+ * here the strings are null terminated
+ * but also the array is null terminated
+ */
+ for (count = 0;; count++) {
+ TALLOC_CTX *tmp_ctx;
+ const char *s = NULL;
+ a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
+ NT_STATUS_HAVE_NO_MEMORY(a);
+ a[count] = NULL;
+ a[count+1] = NULL;
+
+ tmp_ctx = ndr->current_mem_ctx;
+ ndr->current_mem_ctx = a;
+ NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
+ ndr->current_mem_ctx = tmp_ctx;
+ if (strcmp("", s)==0) {
+ a[count] = NULL;
+ break;
+ } else {
+ a[count] = s;
+ }
+ }
+
+ *_a =a;
+ break;
+
+ case LIBNDR_FLAG_STR_NOTERM:
+ if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+ /*
+ * here the strings are not null terminated
+ * but serarated by a null terminator
+ *
+ * which means the same as:
+ * very string is null terminated exept the last
+ * string is terminated by the end of the buffer
+ *
+ * as LIBNDR_FLAG_STR_NULLTERM also end at the end
+ * of the buffer, we can pull each string with this flag
+ */
+ ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
+ ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
+
+ for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
+ TALLOC_CTX *tmp_ctx;
+ const char *s = NULL;
+ a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
+ NT_STATUS_HAVE_NO_MEMORY(a);
+ a[count] = NULL;
+ a[count+1] = NULL;
+
+ tmp_ctx = ndr->current_mem_ctx;
+ ndr->current_mem_ctx = a;
+ NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
+ ndr->current_mem_ctx = tmp_ctx;
a[count] = s;
}
+
+ *_a =a;
+ break;
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
}
- *_a =a;
+ ndr->flags = saved_flags;
return NT_STATUS_OK;
}
@@ -517,17 +571,46 @@ _PUBLIC_ NTSTATUS ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, con
_PUBLIC_ NTSTATUS ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
{
uint32_t count;
+ unsigned flags = ndr->flags;
+ unsigned saved_flags = ndr->flags;
if (!(ndr_flags & NDR_SCALARS)) {
return NT_STATUS_OK;
}
- for (count = 0; a && a[count]; count++) {
- NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
- }
+ switch (flags & LIBNDR_STRING_FLAGS) {
+ case LIBNDR_FLAG_STR_NULLTERM:
+ for (count = 0; a && a[count]; count++) {
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
+ }
+
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
+ break;
+
+ case LIBNDR_FLAG_STR_NOTERM:
+ if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
+ return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
- NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
+ for (count = 0; a && a[count]; count++) {
+ if (count > 0) {
+ ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
+ ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
+ ndr->flags = saved_flags;
+ }
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
+ }
+
+ break;
+ default:
+ return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+
+ ndr->flags = saved_flags;
return NT_STATUS_OK;
}