Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : routines for marshalling/unmarshalling string types
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "librpc/ndr/libndr.h"
24 :
25 : /**
26 : pull a general string from the wire
27 : */
28 102224506 : _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **s)
29 : {
30 102224506 : char *as=NULL;
31 891203 : uint32_t len1, ofs, len2;
32 891203 : uint16_t len3;
33 102224506 : size_t conv_src_len = 0, converted_size;
34 102224506 : int do_convert = 1, chset = CH_UTF16;
35 102224506 : unsigned byte_mul = 2;
36 102224506 : libndr_flags flags = ndr->flags;
37 102224506 : unsigned c_len_term = 0;
38 :
39 102224506 : if (!(ndr_flags & NDR_SCALARS)) {
40 0 : return NDR_ERR_SUCCESS;
41 : }
42 :
43 102224506 : if (NDR_BE(ndr)) {
44 24614 : chset = CH_UTF16BE;
45 : }
46 :
47 102224506 : if (flags & LIBNDR_FLAG_STR_ASCII) {
48 1382884 : chset = CH_DOS;
49 1382884 : byte_mul = 1;
50 1382884 : flags &= ~LIBNDR_FLAG_STR_ASCII;
51 : }
52 :
53 102224506 : if (flags & LIBNDR_FLAG_STR_UTF8) {
54 98972452 : chset = CH_UTF8;
55 98972452 : byte_mul = 1;
56 98972452 : flags &= ~LIBNDR_FLAG_STR_UTF8;
57 : }
58 :
59 102224506 : if (flags & LIBNDR_FLAG_STR_RAW8) {
60 524292 : do_convert = 0;
61 524292 : byte_mul = 1;
62 524292 : flags &= ~LIBNDR_FLAG_STR_RAW8;
63 : }
64 :
65 102224506 : flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
66 102224506 : if (flags & LIBNDR_FLAG_STR_CHARLEN) {
67 403164 : c_len_term = 1;
68 403164 : flags &= ~LIBNDR_FLAG_STR_CHARLEN;
69 : }
70 :
71 102224506 : switch (flags & LIBNDR_STRING_FLAGS) {
72 0 : case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
73 : case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
74 0 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
75 0 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
76 0 : if (ofs != 0) {
77 0 : return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%"PRI_LIBNDR_FLAGS"\n",
78 : ndr->flags & LIBNDR_STRING_FLAGS);
79 : }
80 0 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
81 0 : if (len2 > len1) {
82 0 : return ndr_pull_error(ndr, NDR_ERR_STRING,
83 : "Bad string lengths len1=%"PRIu32" ofs=%"PRIu32" len2=%"PRIu32"\n",
84 : len1, ofs, len2);
85 0 : } else if (len1 != len2) {
86 0 : DEBUG(6,("len1[%"PRIu32"] != len2[%"PRIu32"] '%s'\n", len1, len2, as));
87 : }
88 0 : conv_src_len = len2 + c_len_term;
89 0 : break;
90 :
91 28 : case LIBNDR_FLAG_STR_SIZE4:
92 : case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
93 28 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
94 28 : conv_src_len = len1 + c_len_term;
95 28 : break;
96 :
97 1666 : case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
98 1666 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
99 1666 : conv_src_len = len1;
100 1666 : byte_mul = 1; /* the length is now absolute */
101 1666 : break;
102 :
103 0 : case LIBNDR_FLAG_STR_LEN4:
104 : case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
105 0 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
106 0 : if (ofs != 0) {
107 0 : return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%"PRI_LIBNDR_FLAGS"\n",
108 : ndr->flags & LIBNDR_STRING_FLAGS);
109 : }
110 0 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
111 0 : conv_src_len = len1 + c_len_term;
112 0 : break;
113 :
114 0 : case LIBNDR_FLAG_STR_SIZE2:
115 : case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
116 0 : NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
117 0 : conv_src_len = len3 + c_len_term;
118 0 : break;
119 :
120 0 : case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
121 0 : NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
122 0 : conv_src_len = len3;
123 0 : byte_mul = 1; /* the length is now absolute */
124 0 : break;
125 :
126 101117536 : case LIBNDR_FLAG_STR_NULLTERM:
127 : /*
128 : * We ensure that conv_str_len cannot return 0 by
129 : * requiring that there be enough bytes for at least
130 : * the NULL terminator
131 : */
132 101117536 : if (byte_mul == 1) {
133 100879594 : NDR_PULL_NEED_BYTES(ndr, 1);
134 100879593 : conv_src_len = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
135 : } else {
136 237942 : NDR_PULL_NEED_BYTES(ndr, 2);
137 237939 : conv_src_len = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
138 : }
139 100248074 : byte_mul = 1; /* the length is now absolute */
140 100248074 : break;
141 :
142 1105276 : case LIBNDR_FLAG_STR_NOTERM:
143 1105276 : if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
144 0 : return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
145 : ndr->flags & LIBNDR_STRING_FLAGS);
146 : }
147 1105276 : conv_src_len = ndr->data_size - ndr->offset;
148 1105276 : byte_mul = 1; /* the length is now absolute */
149 1105276 : break;
150 :
151 0 : default:
152 0 : return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
153 : ndr->flags & LIBNDR_STRING_FLAGS);
154 : }
155 :
156 102224502 : NDR_PULL_NEED_BYTES(ndr, conv_src_len * byte_mul);
157 102224502 : if (conv_src_len == 0) {
158 7 : as = talloc_strdup(ndr->current_mem_ctx, "");
159 7 : converted_size = 0;
160 : } else {
161 102224495 : if (!do_convert) {
162 1048584 : as = talloc_strndup(ndr->current_mem_ctx,
163 524292 : (char *)ndr->data + ndr->offset,
164 : conv_src_len);
165 524292 : if (!as) {
166 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC,
167 : "Failed to talloc_strndup() in RAW8 ndr_string_pull()");
168 : }
169 524292 : converted_size = MIN(strlen(as)+1, conv_src_len);
170 101700203 : } else if (!convert_string_talloc(ndr->current_mem_ctx, chset,
171 101700203 : CH_UNIX, ndr->data + ndr->offset,
172 : conv_src_len * byte_mul,
173 : &as,
174 : &converted_size)) {
175 4 : return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
176 : "Bad character conversion with flags 0x%"PRI_LIBNDR_FLAGS, flags);
177 : }
178 : }
179 :
180 : /* this is a way of detecting if a string is sent with the wrong
181 : termination */
182 102224498 : if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
183 1106970 : if (as && converted_size > 0 && as[converted_size-1] == '\0') {
184 0 : DEBUG(6,("short string '%s', sent with NULL termination despite NOTERM flag in IDL\n", as));
185 : }
186 : } else {
187 101117528 : if (as && converted_size > 0 && as[converted_size-1] != '\0') {
188 14 : DEBUG(6,("long string '%s', send without NULL termination (which was expected)\n", as));
189 : }
190 : }
191 :
192 102224498 : NDR_CHECK(ndr_pull_advance(ndr, conv_src_len * byte_mul));
193 102224498 : *s = as;
194 :
195 102224498 : return NDR_ERR_SUCCESS;
196 : }
197 :
198 :
199 : /**
200 : push a general string onto the wire
201 : */
202 5171971 : _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *s)
203 : {
204 27659 : ssize_t s_len, c_len;
205 27659 : size_t d_len;
206 5171971 : int do_convert = 1, chset = CH_UTF16;
207 5171971 : libndr_flags flags = ndr->flags;
208 5171971 : unsigned byte_mul = 2;
209 5171971 : uint8_t *dest = NULL;
210 :
211 5171971 : if (!(ndr_flags & NDR_SCALARS)) {
212 0 : return NDR_ERR_SUCCESS;
213 : }
214 :
215 5171971 : if (NDR_BE(ndr)) {
216 37187 : chset = CH_UTF16BE;
217 : }
218 :
219 5171971 : s_len = s?strlen(s):0;
220 :
221 5171971 : if (flags & LIBNDR_FLAG_STR_ASCII) {
222 217574 : chset = CH_DOS;
223 217574 : byte_mul = 1;
224 217574 : flags &= ~LIBNDR_FLAG_STR_ASCII;
225 : }
226 :
227 5171971 : if (flags & LIBNDR_FLAG_STR_UTF8) {
228 2814683 : chset = CH_UTF8;
229 2814683 : byte_mul = 1;
230 2814683 : flags &= ~LIBNDR_FLAG_STR_UTF8;
231 : }
232 :
233 5171971 : if (flags & LIBNDR_FLAG_STR_RAW8) {
234 4 : do_convert = 0;
235 4 : byte_mul = 1;
236 4 : flags &= ~LIBNDR_FLAG_STR_RAW8;
237 : }
238 :
239 5171971 : flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
240 :
241 5171971 : if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
242 3407722 : s_len++;
243 : }
244 :
245 5171971 : if (s_len == 0) {
246 133 : d_len = 0;
247 133 : dest = (uint8_t *)talloc_strdup(ndr, "");
248 5171838 : } else if (!do_convert) {
249 4 : d_len = s_len;
250 4 : dest = (uint8_t *)talloc_strndup(ndr, s, s_len);
251 5171834 : } else if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
252 : &dest, &d_len))
253 : {
254 4 : return ndr_push_error(ndr, NDR_ERR_CHARCNV,
255 : "Bad character push conversion with flags 0x%"PRI_LIBNDR_FLAGS, flags);
256 : }
257 :
258 5171967 : if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
259 2727 : c_len = d_len;
260 2727 : flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
261 5169240 : } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
262 1484483 : c_len = (d_len / byte_mul)-1;
263 1484483 : flags &= ~LIBNDR_FLAG_STR_CHARLEN;
264 : } else {
265 3684757 : c_len = d_len / byte_mul;
266 : }
267 :
268 5171967 : switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
269 0 : case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
270 0 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
271 0 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
272 0 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
273 0 : NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
274 0 : break;
275 :
276 0 : case LIBNDR_FLAG_STR_LEN4:
277 0 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
278 0 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
279 0 : NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
280 0 : break;
281 :
282 2972 : case LIBNDR_FLAG_STR_SIZE4:
283 2972 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
284 2972 : NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
285 1065 : break;
286 :
287 0 : case LIBNDR_FLAG_STR_SIZE2:
288 0 : NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
289 0 : NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
290 0 : break;
291 :
292 3407718 : case LIBNDR_FLAG_STR_NULLTERM:
293 3407718 : NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
294 3391934 : break;
295 :
296 1761277 : default:
297 1761277 : if (ndr->flags & LIBNDR_FLAG_REMAINING) {
298 1761277 : NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
299 1751313 : break;
300 : }
301 :
302 0 : return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
303 : ndr->flags & LIBNDR_STRING_FLAGS);
304 : }
305 :
306 5171967 : talloc_free(dest);
307 :
308 5171967 : return NDR_ERR_SUCCESS;
309 : }
310 :
311 : /**
312 : push a general string onto the wire
313 : */
314 0 : _PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
315 : {
316 0 : size_t c_len;
317 0 : libndr_flags flags = ndr->flags;
318 0 : unsigned byte_mul = 2;
319 0 : unsigned c_len_term = 1;
320 :
321 0 : if (flags & LIBNDR_FLAG_STR_RAW8) {
322 0 : c_len = s?strlen(s):0;
323 : } else {
324 0 : c_len = s?strlen_m(s):0;
325 : }
326 :
327 0 : if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_RAW8|LIBNDR_FLAG_STR_UTF8)) {
328 0 : byte_mul = 1;
329 : }
330 :
331 0 : if (flags & LIBNDR_FLAG_STR_NOTERM) {
332 0 : c_len_term = 0;
333 : }
334 :
335 0 : c_len = c_len + c_len_term;
336 :
337 0 : if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
338 0 : c_len = c_len * byte_mul;
339 : }
340 :
341 0 : return c_len;
342 : }
343 :
344 119618 : _PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
345 : {
346 119618 : if (NDR_HIDE_SECRET(ndr)) {
347 40 : ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
348 40 : return;
349 : }
350 119578 : if (s) {
351 118332 : ndr->print(ndr, "%-25s: '%s'", name, s);
352 : } else {
353 1246 : ndr->print(ndr, "%-25s: NULL", name);
354 : }
355 : }
356 :
357 0 : _PUBLIC_ uint32_t ndr_size_string(int ret, const char * const* string, ndr_flags_type flags)
358 : {
359 : /* FIXME: Is this correct for all strings ? */
360 0 : if(!(*string)) return ret;
361 0 : return ret+strlen(*string)+1;
362 : }
363 :
364 2744 : static uint32_t guess_string_array_size(struct ndr_pull *ndr, ndr_flags_type ndr_flags)
365 : {
366 : /*
367 : * Here we could do something clever like count the number of zeros in
368 : * the ndr data, but it is probably sufficient to pick a lowish number
369 : * (compared to the overhead of the talloc header) and let the
370 : * exponential resizing deal with longer arrays.
371 : */
372 2744 : return 5;
373 : }
374 :
375 52 : static enum ndr_err_code extend_string_array(struct ndr_pull *ndr,
376 : const char ***_a,
377 : uint32_t *count)
378 : {
379 52 : const char **a = *_a;
380 52 : uint32_t inc = *count / 4 + 3;
381 52 : uint32_t alloc_size = *count + inc;
382 :
383 52 : if (alloc_size < *count) {
384 : /* overflow ! */
385 0 : return NDR_ERR_ALLOC;
386 : }
387 : /*
388 : * We allocate and zero two more bytes than we report back, so that
389 : * the string array will always be NULL terminated.
390 : */
391 52 : a = talloc_realloc(ndr->current_mem_ctx, a,
392 : const char *,
393 : alloc_size);
394 52 : NDR_ERR_HAVE_NO_MEMORY(a);
395 :
396 52 : memset(a + *count, 0, inc * sizeof(a[0]));
397 52 : *_a = a;
398 52 : *count = alloc_size - 2;
399 52 : return NDR_ERR_SUCCESS;
400 : }
401 :
402 : /**
403 : pull a general string array from the wire
404 : */
405 2758 : _PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char ***_a)
406 : {
407 2758 : const char **a = NULL;
408 14 : uint32_t count;
409 2758 : libndr_flags flags = ndr->flags;
410 2758 : libndr_flags saved_flags = ndr->flags;
411 14 : uint32_t alloc_size;
412 :
413 2758 : if (!(ndr_flags & NDR_SCALARS)) {
414 0 : return NDR_ERR_SUCCESS;
415 : }
416 :
417 2758 : alloc_size = guess_string_array_size(ndr, ndr_flags);
418 2758 : a = talloc_zero_array(ndr->current_mem_ctx, const char *, alloc_size + 2);
419 2758 : NDR_ERR_HAVE_NO_MEMORY(a);
420 :
421 2758 : switch (flags & (LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_STR_NOTERM)) {
422 2744 : case LIBNDR_FLAG_STR_NULLTERM:
423 : /*
424 : * here the strings are null terminated
425 : * but also the array is null terminated if LIBNDR_FLAG_REMAINING
426 : * is specified
427 : */
428 527043 : for (count = 0;; count++) {
429 524312 : TALLOC_CTX *tmp_ctx;
430 529080 : const char *s = NULL;
431 529080 : if (count == alloc_size) {
432 52 : NDR_CHECK(extend_string_array(ndr,
433 : &a,
434 : &alloc_size));
435 : }
436 :
437 529080 : tmp_ctx = ndr->current_mem_ctx;
438 529080 : ndr->current_mem_ctx = a;
439 529080 : NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
440 529080 : ndr->current_mem_ctx = tmp_ctx;
441 529080 : if ((ndr->data_size - ndr->offset) == 0 && ndr->flags & LIBNDR_FLAG_REMAINING)
442 : {
443 21 : a[count] = s;
444 21 : break;
445 : }
446 529059 : if (strcmp("", s)==0) {
447 2736 : a[count] = NULL;
448 2736 : break;
449 : } else {
450 526323 : a[count] = s;
451 : }
452 : }
453 :
454 2757 : *_a =a;
455 2757 : break;
456 :
457 1 : case LIBNDR_FLAG_STR_NOTERM:
458 1 : if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
459 0 : return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
460 : ndr->flags & LIBNDR_STRING_FLAGS);
461 : }
462 : /*
463 : * here the strings are not null terminated
464 : * but separated by a null terminator
465 : *
466 : * which means the same as:
467 : * Every string is null terminated except the last
468 : * string is terminated by the end of the buffer
469 : *
470 : * as LIBNDR_FLAG_STR_NULLTERM also end at the end
471 : * of the buffer, we can pull each string with this flag
472 : *
473 : * The big difference with the case LIBNDR_FLAG_STR_NOTERM +
474 : * LIBNDR_FLAG_REMAINING is that the last string will not be null terminated
475 : */
476 1 : ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
477 1 : ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
478 :
479 1 : for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
480 1 : TALLOC_CTX *tmp_ctx;
481 1 : const char *s = NULL;
482 1 : if (count == alloc_size) {
483 1 : NDR_CHECK(extend_string_array(ndr,
484 : &a,
485 : &alloc_size));
486 : }
487 :
488 1 : tmp_ctx = ndr->current_mem_ctx;
489 1 : ndr->current_mem_ctx = a;
490 1 : NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
491 0 : ndr->current_mem_ctx = tmp_ctx;
492 0 : a[count] = s;
493 : }
494 :
495 0 : a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 1);
496 0 : NDR_ERR_HAVE_NO_MEMORY(a);
497 0 : *_a = a;
498 0 : break;
499 :
500 0 : default:
501 0 : return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
502 : ndr->flags & LIBNDR_STRING_FLAGS);
503 : }
504 :
505 2757 : ndr->flags = saved_flags;
506 2757 : return NDR_ERR_SUCCESS;
507 : }
508 :
509 : /**
510 : push a general string array onto the wire
511 : */
512 38598 : _PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char **a)
513 : {
514 201 : uint32_t count;
515 38598 : libndr_flags flags = ndr->flags;
516 38598 : libndr_flags saved_flags = ndr->flags;
517 :
518 38598 : if (!(ndr_flags & NDR_SCALARS)) {
519 0 : return NDR_ERR_SUCCESS;
520 : }
521 :
522 38598 : switch (flags & LIBNDR_STRING_FLAGS) {
523 6609 : case LIBNDR_FLAG_STR_NULLTERM:
524 14272 : for (count = 0; a && a[count]; count++) {
525 7661 : NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
526 : }
527 : /* If LIBNDR_FLAG_REMAINING then we do not add a null terminator to the array */
528 6611 : if (!(flags & LIBNDR_FLAG_REMAINING))
529 : {
530 6591 : NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
531 : }
532 6609 : break;
533 :
534 31987 : case LIBNDR_FLAG_STR_NOTERM:
535 31987 : if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
536 0 : return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
537 : ndr->flags & LIBNDR_STRING_FLAGS);
538 : }
539 :
540 131190 : for (count = 0; a && a[count]; count++) {
541 99203 : if (count > 0) {
542 67216 : ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
543 67216 : ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
544 67216 : NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
545 67216 : ndr->flags = saved_flags;
546 : }
547 99203 : NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
548 : }
549 :
550 31788 : break;
551 :
552 0 : default:
553 0 : return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
554 : ndr->flags & LIBNDR_STRING_FLAGS);
555 : }
556 :
557 38598 : ndr->flags = saved_flags;
558 38598 : return NDR_ERR_SUCCESS;
559 : }
560 :
561 12 : _PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
562 : {
563 12 : uint32_t count;
564 12 : uint32_t i;
565 :
566 26 : for (count = 0; a && a[count]; count++) {}
567 :
568 12 : ndr->print(ndr, "%s: ARRAY(%"PRIu32")", name, count);
569 12 : ndr->depth++;
570 26 : for (i=0;i<count;i++) {
571 14 : char *idx=NULL;
572 14 : if (asprintf(&idx, "[%"PRIu32"]", i) != -1) {
573 14 : ndr_print_string(ndr, idx, a[i]);
574 14 : free(idx);
575 : }
576 : }
577 12 : ndr->depth--;
578 12 : }
579 :
580 4 : _PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, libndr_flags flags)
581 : {
582 0 : uint32_t i;
583 4 : size_t size = 0;
584 4 : int rawbytes = 0;
585 :
586 4 : if (flags & LIBNDR_FLAG_STR_RAW8) {
587 0 : rawbytes = 1;
588 0 : flags &= ~LIBNDR_FLAG_STR_RAW8;
589 : }
590 :
591 4 : switch (flags & LIBNDR_STRING_FLAGS) {
592 4 : case LIBNDR_FLAG_STR_NULLTERM:
593 8 : for (i = 0; i < count; i++) {
594 4 : size += rawbytes?strlen(a[i]) + 1:strlen_m_term(a[i]);
595 : }
596 4 : break;
597 0 : case LIBNDR_FLAG_STR_NOTERM:
598 0 : for (i = 0; i < count; i++) {
599 0 : size += rawbytes?strlen(a[i]):strlen_m(a[i]);
600 : }
601 0 : break;
602 0 : default:
603 0 : return 0;
604 : }
605 :
606 4 : return size;
607 : }
608 :
609 : /**
610 : * Return number of elements in a string including the last (zeroed) element
611 : */
612 0 : _PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
613 : {
614 0 : uint32_t i;
615 0 : uint8_t zero[4] = {0,0,0,0};
616 0 : const char *var = (const char *)_var;
617 :
618 0 : for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
619 :
620 0 : return i+1;
621 : }
622 :
623 : /**
624 : * @brief Get the string length including the null terminator if available.
625 : *
626 : * This checks the string length based on the elements. The returned number
627 : * includes the terminating null byte(s) if found.
628 : *
629 : * @param[in] _var The string to calculate the length for.
630 : *
631 : * @param[in] length The length of the buffer passed by _var.
632 : *
633 : * @param[in] element_size The element_size of a string char in bytes.
634 : *
635 : * @return The length of the strings or 0.
636 : */
637 9374 : static uint32_t ndr_string_n_length(const void *_var,
638 : size_t length,
639 : uint32_t element_size)
640 : {
641 9374 : size_t i = 0;
642 9374 : uint8_t zero[4] = {0,0,0,0};
643 9374 : const char *var = (const char *)_var;
644 26 : int cmp;
645 :
646 9374 : if (element_size > 4) {
647 0 : return 0;
648 : }
649 :
650 162701 : for (i = 0; i < length; i++, var += element_size) {
651 162667 : cmp = memcmp(var, zero, element_size);
652 162667 : if (cmp == 0) {
653 9316 : break;
654 : }
655 : }
656 :
657 9374 : if (i == length) {
658 34 : return length;
659 : }
660 :
661 9340 : return i + 1;
662 : }
663 :
664 9510458 : _PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
665 : {
666 138972 : uint32_t i;
667 138972 : uint32_t save_offset;
668 :
669 9510458 : if (count == 0) {
670 0 : return NDR_ERR_RANGE;
671 : }
672 :
673 9510458 : if (element_size && count - 1 > UINT32_MAX / element_size) {
674 0 : return NDR_ERR_RANGE;
675 : }
676 :
677 9510458 : save_offset = ndr->offset;
678 9510458 : NDR_CHECK(ndr_pull_advance(ndr, (count - 1) * element_size));
679 9510458 : NDR_PULL_NEED_BYTES(ndr, element_size);
680 :
681 21301724 : for (i = 0; i < element_size; i++) {
682 11791270 : if (ndr->data[ndr->offset+i] != 0) {
683 2 : ndr->offset = save_offset;
684 :
685 2 : return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
686 : }
687 : }
688 :
689 9510454 : ndr->offset = save_offset;
690 :
691 9510454 : return NDR_ERR_SUCCESS;
692 : }
693 :
694 17500217 : _PUBLIC_ enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
695 : {
696 308087 : size_t converted_size;
697 :
698 17500217 : if (length == 0) {
699 1195452 : *var = talloc_strdup(ndr->current_mem_ctx, "");
700 1195452 : return NDR_ERR_SUCCESS;
701 : }
702 :
703 16304765 : if (NDR_BE(ndr) && chset == CH_UTF16) {
704 460596 : chset = CH_UTF16BE;
705 : }
706 :
707 16304765 : if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
708 0 : return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
709 : }
710 16304765 : NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
711 :
712 16304765 : if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
713 16304765 : ndr->data+ndr->offset, length*byte_mul,
714 : var,
715 : &converted_size))
716 : {
717 0 : return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
718 : "Bad character conversion");
719 : }
720 16304765 : NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
721 :
722 16018581 : return NDR_ERR_SUCCESS;
723 : }
724 :
725 9368 : _PUBLIC_ enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
726 : {
727 20 : size_t converted_size;
728 20 : uint32_t str_len;
729 :
730 9368 : if (length == 0) {
731 0 : *var = talloc_strdup(ndr->current_mem_ctx, "");
732 0 : return NDR_ERR_SUCCESS;
733 : }
734 :
735 9368 : if (NDR_BE(ndr) && chset == CH_UTF16) {
736 0 : chset = CH_UTF16BE;
737 : }
738 :
739 9368 : if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
740 0 : return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
741 : }
742 9368 : NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
743 :
744 9368 : str_len = ndr_string_n_length(ndr->data+ndr->offset, length, byte_mul);
745 9368 : if (str_len == 0) {
746 0 : return ndr_pull_error(ndr, NDR_ERR_LENGTH,
747 : "Invalid length");
748 : }
749 :
750 9368 : if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
751 9368 : ndr->data+ndr->offset, str_len*byte_mul,
752 : var,
753 : &converted_size))
754 : {
755 0 : return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
756 : "Bad character conversion");
757 : }
758 9368 : NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
759 :
760 9348 : return NDR_ERR_SUCCESS;
761 : }
762 :
763 27682426 : _PUBLIC_ enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
764 : {
765 251641 : size_t required;
766 :
767 27682426 : if (NDR_BE(ndr) && chset == CH_UTF16) {
768 38061 : chset = CH_UTF16BE;
769 : }
770 :
771 27682426 : if ((byte_mul != 0) && (length > SIZE_MAX/byte_mul)) {
772 0 : return ndr_push_error(ndr, NDR_ERR_LENGTH, "length overflow");
773 : }
774 27682426 : required = byte_mul * length;
775 :
776 27682426 : NDR_PUSH_NEED_BYTES(ndr, required);
777 :
778 27682426 : if (required) {
779 26689505 : size_t size = 0;
780 :
781 26689505 : if (var == NULL) {
782 2 : return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
783 : }
784 :
785 26689503 : if (!convert_string(CH_UNIX, chset,
786 : var, strlen(var),
787 26689503 : ndr->data+ndr->offset, required, &size)) {
788 0 : return ndr_push_error(ndr, NDR_ERR_CHARCNV,
789 : "Bad character conversion");
790 : }
791 :
792 : /* Make sure the remaining part of the string is filled with zeroes */
793 26689503 : if (size < required) {
794 24375132 : memset(ndr->data+ndr->offset+size, 0, required-size);
795 : }
796 : }
797 :
798 27682424 : ndr->offset += required;
799 :
800 27682424 : return NDR_ERR_SUCCESS;
801 : }
802 :
803 32342 : _PUBLIC_ enum ndr_err_code ndr_push_charset_to_null(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
804 : {
805 32342 : const char *str = var;
806 :
807 32342 : if (str == NULL) {
808 2 : str = "\0"; /* i.e. two zero bytes, for UTF16 null word. */
809 2 : length = 1;
810 : }
811 :
812 32342 : return ndr_push_charset(ndr, ndr_flags, str, length, byte_mul, chset);
813 : }
814 :
815 : /* Return number of elements in a string in the specified charset */
816 31538855 : _PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset)
817 : {
818 31538855 : switch (chset) {
819 : /* case CH_UTF16: this has the same value as CH_UTF16LE */
820 29177601 : case CH_UTF16LE:
821 : case CH_UTF16BE:
822 : case CH_UTF16MUNGED:
823 : case CH_UTF8:
824 29177601 : return strlen_m_ext_term((const char *)var, CH_UNIX, chset);
825 2361254 : case CH_DOS:
826 : case CH_UNIX:
827 2361254 : return strlen((const char *)var)+1;
828 0 : default:
829 : /* Fallback, this should never happen */
830 0 : return strlen((const char *)var)+1;
831 : }
832 : }
|