summaryrefslogtreecommitdiffstats
path: root/source4/torture/ndr/string.c
blob: 30ed1e4d1a0295cd9d70cfe20cb5adc09be2e903 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#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, (char *)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)
{
	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;
}