summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--librpc/idl/idl_types.h6
-rw-r--r--librpc/ndr/libndr.h1
-rw-r--r--librpc/ndr/ndr_string.c46
-rw-r--r--source4/torture/ndr/ndr.c1
-rw-r--r--source4/torture/ndr/string.c199
-rw-r--r--source4/torture/wscript_build2
6 files changed, 246 insertions, 9 deletions
diff --git a/librpc/idl/idl_types.h b/librpc/idl/idl_types.h
index 023c04020e..c50eface0d 100644
--- a/librpc/idl/idl_types.h
+++ b/librpc/idl/idl_types.h
@@ -8,6 +8,7 @@
#define STR_CONFORMANT LIBNDR_FLAG_STR_CONFORMANT
#define STR_CHARLEN LIBNDR_FLAG_STR_CHARLEN
#define STR_UTF8 LIBNDR_FLAG_STR_UTF8
+#define STR_RAW8 LIBNDR_FLAG_STR_RAW8
/*
a null terminated UCS2 string
@@ -25,6 +26,11 @@
#define utf8string [flag(STR_UTF8|STR_NULLTERM)] string
/*
+ a null terminated "raw" string (null terminated byte sequence)
+*/
+#define raw8string [flag(STR_RAW8|STR_NULLTERM)] string
+
+/*
a null terminated UCS2 string
*/
#define nstring_array [flag(STR_NULLTERM|NDR_ALIGN2)] string_array
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index cbe9b40440..ca3710bc98 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -122,6 +122,7 @@ struct ndr_print {
#define LIBNDR_FLAG_STR_CONFORMANT (1<<10)
#define LIBNDR_FLAG_STR_CHARLEN (1<<11)
#define LIBNDR_FLAG_STR_UTF8 (1<<12)
+#define LIBNDR_FLAG_STR_RAW8 (1<<13)
#define LIBNDR_STRING_FLAGS (0x7FFC)
/* set if relative pointers should *not* be marshalled in reverse order */
diff --git a/librpc/ndr/ndr_string.c b/librpc/ndr/ndr_string.c
index d0d8303240..207d55bb1b 100644
--- a/librpc/ndr/ndr_string.c
+++ b/librpc/ndr/ndr_string.c
@@ -31,7 +31,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags,
uint32_t len1, ofs, len2;
uint16_t len3;
size_t conv_src_len = 0, converted_size;
- int chset = CH_UTF16;
+ int do_convert = 1, chset = CH_UTF16;
unsigned byte_mul = 2;
unsigned flags = ndr->flags;
unsigned c_len_term = 0;
@@ -56,6 +56,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags,
flags &= ~LIBNDR_FLAG_STR_UTF8;
}
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ do_convert = 0;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
+
flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
if (flags & LIBNDR_FLAG_STR_CHARLEN) {
c_len_term = 1;
@@ -138,7 +144,11 @@ _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags,
if (conv_src_len == 0) {
as = talloc_strdup(ndr->current_mem_ctx, "");
} else {
- if (!convert_string_talloc(ndr->current_mem_ctx, chset,
+ if (!do_convert) {
+ as = talloc_strndup(ndr->current_mem_ctx,
+ ndr->data + ndr->offset,
+ conv_src_len);
+ } else if (!convert_string_talloc(ndr->current_mem_ctx, chset,
CH_UNIX, ndr->data + ndr->offset,
conv_src_len * byte_mul,
(void **)(void *)&as,
@@ -174,7 +184,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags,
{
ssize_t s_len, c_len;
size_t d_len;
- int chset = CH_UTF16;
+ int do_convert = 1, chset = CH_UTF16;
unsigned flags = ndr->flags;
unsigned byte_mul = 2;
uint8_t *dest = NULL;
@@ -201,12 +211,22 @@ _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags,
flags &= ~LIBNDR_FLAG_STR_UTF8;
}
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ do_convert = 0;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
+
flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
s_len++;
}
- if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
+
+ if (!do_convert) {
+ d_len = s_len;
+ dest = talloc_strndup(ndr, s, s_len);
+ } else if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
(void **)(void *)&dest, &d_len))
{
return ndr_push_error(ndr, NDR_ERR_CHARCNV,
@@ -276,9 +296,13 @@ _PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
unsigned byte_mul = 2;
unsigned c_len_term = 1;
- c_len = s?strlen_m(s):0;
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ c_len = s?strlen(s):0;
+ } else {
+ c_len = s?strlen_m(s):0;
+ }
- if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
+ if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_RAW8|LIBNDR_FLAG_STR_UTF8)) {
byte_mul = 1;
}
@@ -484,16 +508,22 @@ _PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, int flags)
{
uint32_t i;
size_t size = 0;
+ int rawbytes = 0;
+
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ rawbytes = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
switch (flags & LIBNDR_STRING_FLAGS) {
case LIBNDR_FLAG_STR_NULLTERM:
for (i = 0; i < count; i++) {
- size += strlen_m_term(a[i]);
+ size += rawbytes?strlen(a[i]) + 1:strlen_m_term(a[i]);
}
break;
case LIBNDR_FLAG_STR_NOTERM:
for (i = 0; i < count; i++) {
- size += strlen_m(a[i]);
+ size += rawbytes?strlen(a[i]):strlen_m(a[i]);
}
break;
default:
diff --git a/source4/torture/ndr/ndr.c b/source4/torture/ndr/ndr.c
index 36b2b5540c..6c564d3310 100644
--- a/source4/torture/ndr/ndr.c
+++ b/source4/torture/ndr/ndr.c
@@ -355,6 +355,7 @@ struct torture_suite *torture_local_ndr(TALLOC_CTX *mem_ctx)
torture_suite_add_suite(suite, ndr_nbt_suite(suite));
torture_suite_add_suite(suite, ndr_ntlmssp_suite(suite));
torture_suite_add_suite(suite, ndr_backupkey_suite(suite));
+ torture_suite_add_suite(suite, ndr_string_suite(suite));
torture_suite_add_simple_test(suite, "string terminator",
test_check_string_terminator);
diff --git a/source4/torture/ndr/string.c b/source4/torture/ndr/string.c
new file mode 100644
index 0000000000..9214b59295
--- /dev/null
+++ b/source4/torture/ndr/string.c
@@ -0,0 +1,199 @@
+#include "includes.h"
+#include "torture/ndr/ndr.h"
+#include "torture/ndr/proto.h"
+#include "../lib/util/dlinklist.h"
+#include "param/param.h"
+
+static const char const *ascii = "ascii";
+/* the following is equivalent to "kamelåså öäüÿéèóò" in latin1 */
+static const char const latin1[] = { 0x6b, 0x61, 0x6d, 0x65, 0x6c, 0xe5, 0x73,
+ 0xe5, 0x20, 0xF6, 0xE4, 0xFC, 0xFF, 0xE9,
+ 0xE8, 0xF3, 0xF2, 0x00 };
+/* the following is equivalent to "kamelåså ☺☺☺ öäüÿéèóò" in utf8 */
+static const char const utf8[] = { 0x6b, 0x61, 0x6d, 0x65, 0x6c, 0xc3, 0xa5,
+ 0x73, 0xc3, 0xa5, 0x20, 0xE2, 0x98, 0xBA,
+ 0xE2, 0x98, 0xBA, 0xE2, 0x98, 0xBA, 0x20,
+ 0xc3, 0xb6, 0xc3, 0xa4, 0xc3, 0xbc, 0xc3,
+ 0xbf, 0xc3, 0xa9, 0xc3, 0xa8, 0xc3, 0xb3,
+ 0xc3, 0xb2, 0x00 };
+
+/* purely for convenience */
+static int fl_ascii_null = LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM;
+static int fl_utf8_null = LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM;
+static int fl_raw8_null = LIBNDR_FLAG_STR_RAW8|LIBNDR_FLAG_STR_NULLTERM;
+
+static bool
+test_ndr_push_string (struct torture_context *tctx, const char *string,
+ int flags, enum ndr_err_code exp_ndr_err,
+ bool strcmp_pass)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ndr_push *ndr;
+ enum ndr_err_code err;
+
+ torture_comment(tctx,
+ "test_ndr_push_string %s flags 0x%x expecting "
+ "err 0x%x and strcmp %s\n", string, flags, exp_ndr_err,
+ strcmp_pass?"pass":"fail");
+ if (exp_ndr_err != NDR_ERR_SUCCESS) {
+ torture_comment(tctx, "(ignore any Conversion error) ");
+ }
+
+ mem_ctx = talloc_named (NULL, 0, "test_ndr_push_string");
+ ndr = talloc_zero (mem_ctx, struct ndr_push);
+ ndr_set_flags (&ndr->flags, flags);
+
+ err = ndr_push_string (ndr, NDR_SCALARS, string);
+ torture_assert(tctx, err == exp_ndr_err,
+ "ndr_push_string: unexpected return code");
+
+ if (exp_ndr_err == NDR_ERR_SUCCESS) {
+ torture_assert(tctx, ndr->data != NULL,
+ "ndr_push_string: succeeded but NULL data");
+
+ torture_assert(tctx, strcmp_pass == !strcmp(string, ndr->data),
+ "ndr_push_string: post-push strcmp");
+ }
+
+ talloc_free(mem_ctx);
+ return true;
+}
+
+static bool
+test_ndr_pull_string (struct torture_context *tctx, const char *string,
+ int flags, enum ndr_err_code exp_ndr_err,
+ bool strcmp_pass)
+{
+ TALLOC_CTX *mem_ctx;
+ DATA_BLOB blob;
+ struct ndr_pull *ndr;
+ enum ndr_err_code err;
+ const char *result = NULL;
+
+ torture_comment(tctx,
+ "test_ndr_pull_string '%s' flags 0x%x expecting "
+ "err 0x%x and strcmp %s\n", string, flags, exp_ndr_err,
+ strcmp_pass?"pass":"fail");
+ if (exp_ndr_err != NDR_ERR_SUCCESS) {
+ torture_comment(tctx, "(ignore any Conversion error) ");
+ }
+
+ mem_ctx = talloc_named (NULL, 0, "test_ndr_pull_string");
+
+ blob = data_blob_string_const(string);
+ ndr = ndr_pull_init_blob(&blob, mem_ctx);
+ ndr_set_flags (&ndr->flags, flags);
+
+ err = ndr_pull_string (ndr, NDR_SCALARS, &result);
+ torture_assert(tctx, err == exp_ndr_err,
+ "ndr_pull_string: unexpected return code");
+
+ if (exp_ndr_err == NDR_ERR_SUCCESS) {
+ torture_assert(tctx, result != NULL,
+ "ndr_pull_string: NULL data");
+ torture_assert(tctx, strcmp_pass == !strcmp(string, result),
+ "ndr_pull_string: post-pull strcmp");
+ torture_assert(tctx, result != NULL,
+ "ndr_pull_string succeeded but result NULL");
+ }
+
+ talloc_free(mem_ctx);
+ return true;
+}
+
+static bool
+torture_ndr_string(struct torture_context *torture)
+{
+ bool ok;
+ int i;
+ const char *saved_dos_cp = lpcfg_dos_charset(torture->lp_ctx);
+
+ torture_assert(torture,
+ test_ndr_push_string (torture, ascii, fl_ascii_null,
+ NDR_ERR_SUCCESS, true),
+ "test_ndr_push_string(ASCII, STR_ASCII|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_push_string (torture, utf8, fl_utf8_null,
+ NDR_ERR_SUCCESS, true),
+ "test_ndr_push_string(UTF8, STR_UTF8|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_push_string (torture, utf8, fl_raw8_null,
+ NDR_ERR_SUCCESS, true),
+ "test_ndr_push_string(UTF8, STR_RAW8|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_push_string (torture, latin1, fl_raw8_null,
+ NDR_ERR_SUCCESS, true),
+ "test_ndr_push_string(LATIN1, STR_RAW8|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_push_string (torture, utf8, fl_ascii_null,
+ NDR_ERR_CHARCNV, false),
+ "test_ndr_push_string(UTF8, STR_ASCII|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_push_string (torture, latin1, fl_ascii_null,
+ NDR_ERR_CHARCNV, false),
+ "test_ndr_push_string(LATIN1, STR_ASCII|STR_NULL)");
+
+
+ torture_assert(torture,
+ test_ndr_pull_string (torture, ascii, fl_ascii_null,
+ NDR_ERR_SUCCESS, true),
+ "test_ndr_pull_string(ASCII, STR_ASCII|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_pull_string (torture, utf8, fl_utf8_null,
+ NDR_ERR_SUCCESS, true),
+ "test_ndr_pull_string(UTF8, STR_UTF8|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_pull_string (torture, utf8, fl_raw8_null,
+ NDR_ERR_SUCCESS, true),
+ "test_ndr_pull_string(UTF8, STR_RAW8|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_pull_string (torture, latin1, fl_raw8_null,
+ NDR_ERR_SUCCESS, true),
+ "test_ndr_pull_string(LATIN1, STR_RAW8|STR_NULL)");
+
+ /* Depending on runtime config, the behavior of ndr_pull_string on
+ * incorrect combinations of strings and flags (latin1 with ASCII
+ * flags, for example) may differ; it may return NDR_ERR_CHARCNV, or
+ * it may return NDR_ERR_SUCCESS but with a string that has been
+ * mutilated, depending on the value of "dos charset". We test for
+ * both cases here. */
+
+ lpcfg_do_global_parameter(torture->lp_ctx, "dos charset", "ASCII");
+ reload_charcnv(torture->lp_ctx);
+
+ torture_assert(torture,
+ test_ndr_pull_string (torture, latin1, fl_ascii_null,
+ NDR_ERR_CHARCNV, false),
+ "test_ndr_pull_string(LATIN1, STR_ASCII|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_pull_string (torture, utf8, fl_ascii_null,
+ NDR_ERR_CHARCNV, false),
+ "test_ndr_pull_string(UTF8, STR_ASCII|STR_NULL)");
+
+ lpcfg_do_global_parameter(torture->lp_ctx, "dos charset", "CP850");
+ reload_charcnv(torture->lp_ctx);
+
+ torture_assert(torture,
+ test_ndr_pull_string (torture, latin1, fl_ascii_null,
+ NDR_ERR_SUCCESS, false),
+ "test_ndr_pull_string(LATIN1, STR_ASCII|STR_NULL)");
+ torture_assert(torture,
+ test_ndr_pull_string (torture, utf8, fl_ascii_null,
+ NDR_ERR_SUCCESS, false),
+ "test_ndr_pull_string(UTF8, STR_ASCII|STR_NULL)");
+
+ lpcfg_do_global_parameter(torture->lp_ctx, "dos charset", saved_dos_cp);
+ reload_charcnv(torture->lp_ctx);
+
+ return true;
+}
+
+struct torture_suite *ndr_string_suite(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(ctx, "ndr_string");
+
+ torture_suite_add_simple_test(suite, "ndr_string", torture_ndr_string);
+ suite->description = talloc_strdup(suite, "NDR - string-conversion focused push/pull tests");
+
+ return suite;
+}
diff --git a/source4/torture/wscript_build b/source4/torture/wscript_build
index 68ec4e6220..106cc64280 100644
--- a/source4/torture/wscript_build
+++ b/source4/torture/wscript_build
@@ -33,7 +33,7 @@ bld.RECURSE('libnetapi')
bld.RECURSE('libsmbclient')
bld.SAMBA_SUBSYSTEM('TORTURE_NDR',
- source='ndr/ndr.c ndr/winreg.c ndr/atsvc.c ndr/lsa.c ndr/epmap.c ndr/dfs.c ndr/netlogon.c ndr/drsuapi.c ndr/spoolss.c ndr/samr.c ndr/dfsblob.c ndr/drsblobs.c ndr/nbt.c ndr/ntlmssp.c ndr/backupkey.c',
+ source='ndr/ndr.c ndr/winreg.c ndr/atsvc.c ndr/lsa.c ndr/epmap.c ndr/dfs.c ndr/netlogon.c ndr/drsuapi.c ndr/spoolss.c ndr/samr.c ndr/dfsblob.c ndr/drsblobs.c ndr/nbt.c ndr/ntlmssp.c ndr/backupkey.c ndr/string.c',
autoproto='ndr/proto.h',
deps='torture'
)