2 Unix SMB/CIFS implementation.
4 routines for marshalling/unmarshalling string types
6 Copyright (C) Andrew Tridgell 2003
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "system/network.h"
27 pull a general string from the wire
29 NTSTATUS
ndr_pull_string(struct ndr_pull
*ndr
, int ndr_flags
, const char **s
)
32 uint32_t len1
, ofs
, len2
;
36 unsigned byte_mul
= 2;
37 unsigned flags
= ndr
->flags
;
38 unsigned c_len_term
= 0;
40 if (!(ndr_flags
& NDR_SCALARS
)) {
48 if (flags
& LIBNDR_FLAG_STR_ASCII
) {
51 flags
&= ~LIBNDR_FLAG_STR_ASCII
;
54 if (flags
& LIBNDR_FLAG_STR_UTF8
) {
57 flags
&= ~LIBNDR_FLAG_STR_UTF8
;
60 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
61 if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
63 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
66 switch (flags
& LIBNDR_STRING_FLAGS
) {
67 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
68 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
69 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_LARGE_SIZE
:
70 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
71 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
73 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
74 ndr
->flags
& LIBNDR_STRING_FLAGS
);
76 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len2
));
78 return ndr_pull_error(ndr
, NDR_ERR_STRING
,
79 "Bad string lengths len1=%u ofs=%u len2=%u\n",
82 NDR_PULL_NEED_BYTES(ndr
, (len2
+ c_len_term
)*byte_mul
);
84 as
= talloc_strdup(ndr
, "");
86 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
87 ndr
->data
+ndr
->offset
,
88 (len2
+ c_len_term
)*byte_mul
,
91 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
92 "Bad character conversion");
95 NDR_CHECK(ndr_pull_advance(ndr
, (len2
+ c_len_term
)*byte_mul
));
97 if (ndr
->flags
& LIBNDR_FLAG_STR_LARGE_SIZE
) {
98 if (len1
!= 0 && len2
== 0) {
99 DEBUG(6,("len1[%u] != (len2[%u]) '%s'\n", len1
, len2
, as
));
100 } else if (len1
!= (len2
+ 1)) {
101 DEBUG(6,("len1[%u] != (len2[%u]+1) '%s'\n", len1
, len2
, as
));
105 DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1
, len2
, as
));
109 /* this is a way of detecting if a string is sent with the wrong
111 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
112 if (strlen(as
) < (len2
+ c_len_term
)) {
113 DEBUG(6,("short string '%s'\n", as
));
116 if (strlen(as
) == (len2
+ c_len_term
)) {
117 DEBUG(6,("long string '%s'\n", as
));
123 case LIBNDR_FLAG_STR_SIZE4
:
124 case LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
125 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
126 NDR_PULL_NEED_BYTES(ndr
, (len1
+ c_len_term
)*byte_mul
);
128 as
= talloc_strdup(ndr
, "");
130 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
131 ndr
->data
+ndr
->offset
,
132 (len1
+ c_len_term
)*byte_mul
,
135 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
136 "Bad character conversion");
139 NDR_CHECK(ndr_pull_advance(ndr
, (len1
+ c_len_term
)*byte_mul
));
141 /* this is a way of detecting if a string is sent with the wrong
143 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
144 if (strlen(as
) < (len1
+ c_len_term
)) {
145 DEBUG(6,("short string '%s'\n", as
));
148 if (strlen(as
) == (len1
+ c_len_term
)) {
149 DEBUG(6,("long string '%s'\n", as
));
155 case LIBNDR_FLAG_STR_LEN4
:
156 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_NOTERM
:
157 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
159 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
160 ndr
->flags
& LIBNDR_STRING_FLAGS
);
162 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
163 NDR_PULL_NEED_BYTES(ndr
, (len1
+ c_len_term
)*byte_mul
);
165 as
= talloc_strdup(ndr
, "");
167 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
168 ndr
->data
+ndr
->offset
,
169 (len1
+ c_len_term
)*byte_mul
,
172 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
173 "Bad character conversion");
176 NDR_CHECK(ndr_pull_advance(ndr
, (len1
+ c_len_term
)*byte_mul
));
178 /* this is a way of detecting if a string is sent with the wrong
180 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
181 if (strlen(as
) < (len1
+ c_len_term
)) {
182 DEBUG(6,("short string '%s'\n", as
));
185 if (strlen(as
) == (len1
+ c_len_term
)) {
186 DEBUG(6,("long string '%s'\n", as
));
193 case LIBNDR_FLAG_STR_SIZE2
:
194 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
:
195 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
196 NDR_PULL_NEED_BYTES(ndr
, (len3
+ c_len_term
)*byte_mul
);
198 as
= talloc_strdup(ndr
, "");
200 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
201 ndr
->data
+ndr
->offset
,
202 (len3
+ c_len_term
)*byte_mul
,
205 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
206 "Bad character conversion");
209 NDR_CHECK(ndr_pull_advance(ndr
, (len3
+ c_len_term
)*byte_mul
));
211 /* this is a way of detecting if a string is sent with the wrong
213 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
214 if (strlen(as
) < (len3
+ c_len_term
)) {
215 DEBUG(6,("short string '%s'\n", as
));
218 if (strlen(as
) == (len3
+ c_len_term
)) {
219 DEBUG(6,("long string '%s'\n", as
));
225 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_BYTESIZE
:
226 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
227 NDR_PULL_NEED_BYTES(ndr
, len3
);
229 as
= talloc_strdup(ndr
, "");
231 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
232 ndr
->data
+ndr
->offset
,
236 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
237 "Bad character conversion");
240 NDR_CHECK(ndr_pull_advance(ndr
, len3
));
244 case LIBNDR_FLAG_STR_NULLTERM
:
246 len1
= ascii_len_n((const char *)(ndr
->data
+ndr
->offset
), ndr
->data_size
- ndr
->offset
);
248 len1
= utf16_len_n(ndr
->data
+ndr
->offset
, ndr
->data_size
- ndr
->offset
);
250 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
251 ndr
->data
+ndr
->offset
,
255 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
256 "Bad character conversion");
258 NDR_CHECK(ndr_pull_advance(ndr
, len1
));
262 case LIBNDR_FLAG_STR_FIXLEN15
:
263 case LIBNDR_FLAG_STR_FIXLEN32
:
264 len1
= (flags
& LIBNDR_FLAG_STR_FIXLEN32
)?32:15;
265 NDR_PULL_NEED_BYTES(ndr
, len1
*byte_mul
);
266 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
267 ndr
->data
+ndr
->offset
,
271 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
272 "Bad character conversion");
274 NDR_CHECK(ndr_pull_advance(ndr
, len1
*byte_mul
));
279 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
280 ndr
->flags
& LIBNDR_STRING_FLAGS
);
288 push a general string onto the wire
290 NTSTATUS
ndr_push_string(struct ndr_push
*ndr
, int ndr_flags
, const char *s
)
292 ssize_t s_len
, c_len
, d_len
;
294 int chset
= CH_UTF16
;
295 unsigned flags
= ndr
->flags
;
296 unsigned byte_mul
= 2;
297 unsigned c_len_term
= 1;
299 if (!(ndr_flags
& NDR_SCALARS
)) {
307 s_len
= s
?strlen(s
):0;
308 c_len
= s
?strlen_m(s
):0;
310 if (flags
& LIBNDR_FLAG_STR_ASCII
) {
313 flags
&= ~LIBNDR_FLAG_STR_ASCII
;
316 if (flags
& LIBNDR_FLAG_STR_UTF8
) {
319 flags
&= ~LIBNDR_FLAG_STR_UTF8
;
322 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
324 if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
326 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
329 switch (flags
& LIBNDR_STRING_FLAGS
) {
330 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
331 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+c_len_term
));
332 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
333 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+c_len_term
));
334 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
335 ret
= convert_string(CH_UNIX
, chset
,
337 ndr
->data
+ndr
->offset
,
340 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
341 "Bad character conversion");
343 ndr
->offset
+= byte_mul
*(c_len
+1);
346 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
348 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_LARGE_SIZE
:
349 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+c_len_term
));
350 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
351 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
352 NDR_PUSH_NEED_BYTES(ndr
, c_len
*byte_mul
);
353 ret
= convert_string(CH_UNIX
, chset
,
355 ndr
->data
+ndr
->offset
, c_len
*byte_mul
);
357 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
358 "Bad character conversion");
360 ndr
->offset
+= c_len
*byte_mul
;
363 case LIBNDR_FLAG_STR_LEN4
:
364 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
365 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+ c_len_term
));
366 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
367 ret
= convert_string(CH_UNIX
, chset
,
369 ndr
->data
+ndr
->offset
, byte_mul
*(c_len
+1));
371 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
372 "Bad character conversion");
374 ndr
->offset
+= byte_mul
*(c_len
+1);
377 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_NOTERM
:
378 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
379 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
380 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*c_len
);
381 ret
= convert_string(CH_UNIX
, chset
,
383 ndr
->data
+ndr
->offset
, byte_mul
*c_len
);
385 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
386 "Bad character conversion");
388 ndr
->offset
+= byte_mul
*c_len
;
391 case LIBNDR_FLAG_STR_SIZE4
:
392 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+ c_len_term
));
393 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
394 ret
= convert_string(CH_UNIX
, chset
,
396 ndr
->data
+ndr
->offset
, byte_mul
*(c_len
+1));
398 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
399 "Bad character conversion");
401 ndr
->offset
+= byte_mul
*(c_len
+1);
404 case LIBNDR_FLAG_STR_SIZE2
:
405 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, c_len
+ c_len_term
));
406 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
407 ret
= convert_string(CH_UNIX
, chset
,
409 ndr
->data
+ndr
->offset
, byte_mul
*(c_len
+1));
411 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
412 "Bad character conversion");
414 ndr
->offset
+= byte_mul
*(c_len
+1);
417 case LIBNDR_FLAG_STR_NULLTERM
:
418 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
419 ret
= convert_string(CH_UNIX
, chset
,
421 ndr
->data
+ndr
->offset
, byte_mul
*(c_len
+1));
423 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
424 "Bad character conversion");
426 ndr
->offset
+= byte_mul
*(c_len
+1);
429 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_BYTESIZE
:
430 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, c_len
*byte_mul
));
431 NDR_PUSH_NEED_BYTES(ndr
, c_len
*byte_mul
);
432 ret
= convert_string(CH_UNIX
, chset
,
434 ndr
->data
+ndr
->offset
, c_len
*byte_mul
);
436 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
437 "Bad character conversion");
439 ndr
->offset
+= c_len
*byte_mul
;
442 case LIBNDR_FLAG_STR_FIXLEN15
:
443 case LIBNDR_FLAG_STR_FIXLEN32
:
444 d_len
= (flags
& LIBNDR_FLAG_STR_FIXLEN32
)?32:15;
445 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*d_len
);
446 ret
= convert_string(CH_UNIX
, chset
,
448 ndr
->data
+ndr
->offset
, byte_mul
*d_len
);
450 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
451 "Bad character conversion");
454 if ((byte_mul
*d_len
) > ret
) {
455 uint32_t _padding_len
= (byte_mul
*d_len
) - ret
;
456 NDR_CHECK(ndr_push_zero(ndr
, _padding_len
));
461 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
462 ndr
->flags
& LIBNDR_STRING_FLAGS
);
469 push a general string onto the wire
471 size_t ndr_string_array_size(struct ndr_push
*ndr
, const char *s
)
474 unsigned flags
= ndr
->flags
;
475 unsigned byte_mul
= 2;
476 unsigned c_len_term
= 1;
478 if (flags
& LIBNDR_FLAG_STR_FIXLEN32
) {
481 if (flags
& LIBNDR_FLAG_STR_FIXLEN15
) {
485 c_len
= s
?strlen_m(s
):0;
487 if (flags
& (LIBNDR_FLAG_STR_ASCII
|LIBNDR_FLAG_STR_UTF8
)) {
491 if (flags
& LIBNDR_FLAG_STR_NOTERM
) {
495 c_len
= c_len
+ c_len_term
;
497 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
498 c_len
= c_len
* byte_mul
;
504 void ndr_print_string(struct ndr_print
*ndr
, const char *name
, const char *s
)
507 ndr
->print(ndr
, "%-25s: '%s'", name
, s
);
509 ndr
->print(ndr
, "%-25s: NULL", name
);
513 uint32_t ndr_size_string(int ret
, const char * const* string
, int flags
)
515 /* FIXME: Is this correct for all strings ? */
516 if(!(*string
)) return ret
;
517 return ret
+strlen(*string
)+1;
521 pull a general string array from the wire
523 NTSTATUS
ndr_pull_string_array(struct ndr_pull
*ndr
, int ndr_flags
, const char ***_a
)
525 const char **a
= *_a
;
528 if (!(ndr_flags
& NDR_SCALARS
)) {
532 for (count
= 0;; count
++) {
533 const char *s
= NULL
;
534 a
= talloc_realloc(ndr
, a
, const char *, count
+ 2);
535 NT_STATUS_HAVE_NO_MEMORY(a
);
539 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
540 if (strcmp("", s
)==0) {
553 push a general string array onto the wire
555 NTSTATUS
ndr_push_string_array(struct ndr_push
*ndr
, int ndr_flags
, const char **a
)
559 if (!(ndr_flags
& NDR_SCALARS
)) {
563 for (count
= 0; a
&& a
[count
]; count
++) {
564 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
567 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
572 void ndr_print_string_array(struct ndr_print
*ndr
, const char *name
, const char **a
)
577 for (count
= 0; a
&& a
[count
]; count
++) {}
579 ndr
->print(ndr
, "%s: ARRAY(%d)", name
, count
);
581 for (i
=0;i
<count
;i
++) {
583 asprintf(&idx
, "[%d]", i
);
585 ndr_print_string(ndr
, idx
, a
[i
]);
592 /* Return number of elements in a string including the last (zeroed) element */
593 uint32_t ndr_string_length(const void *_var
, uint32_t element_size
)
596 uint8_t zero
[4] = {0,0,0,0};
597 const char *var
= _var
;
599 for (i
= 0; memcmp(var
+i
*element_size
,zero
,element_size
) != 0; i
++);
604 NTSTATUS
ndr_check_string_terminator(struct ndr_pull
*ndr
, const void *_var
, uint32_t count
, uint32_t element_size
)
606 const char *var
= _var
;
609 var
+= element_size
*(count
-1);
611 for (i
= 0; i
< element_size
; i
++) {
613 return NT_STATUS_UNSUCCESSFUL
;
621 NTSTATUS
ndr_pull_charset(struct ndr_pull
*ndr
, int ndr_flags
, const char **var
, uint32_t length
, uint8_t byte_mul
, int chset
)
625 *var
= talloc_strdup(ndr
, "");
628 NDR_PULL_NEED_BYTES(ndr
, length
*byte_mul
);
629 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
630 ndr
->data
+ndr
->offset
,
632 discard_const_p(void *, var
));
634 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
635 "Bad character conversion");
637 NDR_CHECK(ndr_pull_advance(ndr
, length
*byte_mul
));
642 NTSTATUS
ndr_push_charset(struct ndr_push
*ndr
, int ndr_flags
, const char *var
, uint32_t length
, uint8_t byte_mul
, int chset
)
644 ssize_t ret
, required
;
646 required
= byte_mul
* length
;
648 NDR_PUSH_NEED_BYTES(ndr
, required
);
649 ret
= convert_string(CH_UNIX
, chset
,
651 ndr
->data
+ndr
->offset
, required
);
653 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
654 "Bad character conversion");
657 /* Make sure the remaining part of the string is filled with zeroes */
658 if (ret
< required
) {
659 memset(ndr
->data
+ndr
->offset
+ret
, 0, required
-ret
);
662 ndr
->offset
+= required
;