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 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
70 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
72 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
73 ndr
->flags
& LIBNDR_STRING_FLAGS
);
75 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len2
));
77 return ndr_pull_error(ndr
, NDR_ERR_STRING
,
78 "Bad string lengths len1=%u ofs=%u len2=%u\n",
82 *s
= talloc_strdup(ndr
, "");
85 NDR_PULL_NEED_BYTES(ndr
, (len2
+ c_len_term
)*byte_mul
);
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");
94 NDR_CHECK(ndr_pull_advance(ndr
, (len2
+ c_len_term
)*byte_mul
));
96 /* this is a way of detecting if a string is sent with the wrong
98 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
99 if (strlen(as
) < (len2
+ c_len_term
)) {
100 DEBUG(6,("short string '%s'\n", as
));
103 if (strlen(as
) == (len2
+ c_len_term
)) {
104 DEBUG(6,("long string '%s'\n", as
));
110 case LIBNDR_FLAG_STR_SIZE4
:
111 case LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
112 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
113 NDR_PULL_NEED_BYTES(ndr
, (len1
+ c_len_term
)*byte_mul
);
115 *s
= talloc_strdup(ndr
, "");
118 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
119 ndr
->data
+ndr
->offset
,
120 (len1
+ c_len_term
)*byte_mul
,
123 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
124 "Bad character conversion");
126 NDR_CHECK(ndr_pull_advance(ndr
, (len1
+ c_len_term
)*byte_mul
));
128 /* this is a way of detecting if a string is sent with the wrong
130 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
131 if (strlen(as
) < (len1
+ c_len_term
)) {
132 DEBUG(6,("short string '%s'\n", as
));
135 if (strlen(as
) == (len1
+ c_len_term
)) {
136 DEBUG(6,("long string '%s'\n", as
));
142 case LIBNDR_FLAG_STR_LEN4
:
143 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_NOTERM
:
144 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
146 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
147 ndr
->flags
& LIBNDR_STRING_FLAGS
);
149 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
150 NDR_PULL_NEED_BYTES(ndr
, (len1
+ c_len_term
)*byte_mul
);
152 *s
= talloc_strdup(ndr
, "");
155 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
156 ndr
->data
+ndr
->offset
,
157 (len1
+ c_len_term
)*byte_mul
,
160 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
161 "Bad character conversion");
163 NDR_CHECK(ndr_pull_advance(ndr
, (len1
+ c_len_term
)*byte_mul
));
165 /* this is a way of detecting if a string is sent with the wrong
167 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
168 if (strlen(as
) < (len1
+ c_len_term
)) {
169 DEBUG(6,("short string '%s'\n", as
));
172 if (strlen(as
) == (len1
+ c_len_term
)) {
173 DEBUG(6,("long string '%s'\n", as
));
180 case LIBNDR_FLAG_STR_SIZE2
:
181 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
:
182 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
183 NDR_PULL_NEED_BYTES(ndr
, (len3
+ c_len_term
)*byte_mul
);
185 *s
= talloc_strdup(ndr
, "");
188 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
189 ndr
->data
+ndr
->offset
,
190 (len3
+ c_len_term
)*byte_mul
,
193 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
194 "Bad character conversion");
196 NDR_CHECK(ndr_pull_advance(ndr
, (len3
+ c_len_term
)*byte_mul
));
198 /* this is a way of detecting if a string is sent with the wrong
200 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
201 if (strlen(as
) < (len3
+ c_len_term
)) {
202 DEBUG(6,("short string '%s'\n", as
));
205 if (strlen(as
) == (len3
+ c_len_term
)) {
206 DEBUG(6,("long string '%s'\n", as
));
212 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_BYTESIZE
:
213 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
214 NDR_PULL_NEED_BYTES(ndr
, len3
);
216 *s
= talloc_strdup(ndr
, "");
219 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
220 ndr
->data
+ndr
->offset
,
224 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
225 "Bad character conversion");
227 NDR_CHECK(ndr_pull_advance(ndr
, len3
));
231 case LIBNDR_FLAG_STR_NULLTERM
:
233 len1
= ascii_len_n((const char *)(ndr
->data
+ndr
->offset
), ndr
->data_size
- ndr
->offset
);
235 len1
= utf16_len_n(ndr
->data
+ndr
->offset
, ndr
->data_size
- ndr
->offset
);
237 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
238 ndr
->data
+ndr
->offset
,
242 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
243 "Bad character conversion");
245 NDR_CHECK(ndr_pull_advance(ndr
, len1
));
249 case LIBNDR_FLAG_STR_FIXLEN15
:
250 case LIBNDR_FLAG_STR_FIXLEN32
:
251 len1
= (flags
& LIBNDR_FLAG_STR_FIXLEN32
)?32:15;
252 NDR_PULL_NEED_BYTES(ndr
, len1
*byte_mul
);
253 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
254 ndr
->data
+ndr
->offset
,
258 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
259 "Bad character conversion");
261 NDR_CHECK(ndr_pull_advance(ndr
, len1
*byte_mul
));
266 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
267 ndr
->flags
& LIBNDR_STRING_FLAGS
);
275 push a general string onto the wire
277 NTSTATUS
ndr_push_string(struct ndr_push
*ndr
, int ndr_flags
, const char *s
)
279 ssize_t s_len
, c_len
, d_len
;
281 int chset
= CH_UTF16
;
282 unsigned flags
= ndr
->flags
;
283 unsigned byte_mul
= 2;
284 unsigned c_len_term
= 1;
286 if (!(ndr_flags
& NDR_SCALARS
)) {
294 s_len
= s
?strlen(s
):0;
295 c_len
= s
?strlen_m(s
):0;
297 if (flags
& LIBNDR_FLAG_STR_ASCII
) {
300 flags
&= ~LIBNDR_FLAG_STR_ASCII
;
303 if (flags
& LIBNDR_FLAG_STR_UTF8
) {
306 flags
&= ~LIBNDR_FLAG_STR_UTF8
;
309 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
311 if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
313 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
316 switch (flags
& LIBNDR_STRING_FLAGS
) {
317 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
318 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+c_len_term
));
319 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
320 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+c_len_term
));
321 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
322 ret
= convert_string(CH_UNIX
, chset
,
324 ndr
->data
+ndr
->offset
,
327 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
328 "Bad character conversion");
330 ndr
->offset
+= byte_mul
*(c_len
+1);
333 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
334 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
335 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
336 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
337 NDR_PUSH_NEED_BYTES(ndr
, c_len
*byte_mul
);
338 ret
= convert_string(CH_UNIX
, chset
,
340 ndr
->data
+ndr
->offset
, c_len
*byte_mul
);
342 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
343 "Bad character conversion");
345 ndr
->offset
+= c_len
*byte_mul
;
348 case LIBNDR_FLAG_STR_LEN4
:
349 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
350 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+ c_len_term
));
351 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
352 ret
= convert_string(CH_UNIX
, chset
,
354 ndr
->data
+ndr
->offset
, byte_mul
*(c_len
+1));
356 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
357 "Bad character conversion");
359 ndr
->offset
+= byte_mul
*(c_len
+1);
362 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_NOTERM
:
363 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
364 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
365 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*c_len
);
366 ret
= convert_string(CH_UNIX
, chset
,
368 ndr
->data
+ndr
->offset
, byte_mul
*c_len
);
370 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
371 "Bad character conversion");
373 ndr
->offset
+= byte_mul
*c_len
;
376 case LIBNDR_FLAG_STR_SIZE4
:
377 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
+ c_len_term
));
378 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
379 ret
= convert_string(CH_UNIX
, chset
,
381 ndr
->data
+ndr
->offset
, byte_mul
*(c_len
+1));
383 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
384 "Bad character conversion");
386 ndr
->offset
+= byte_mul
*(c_len
+1);
389 case LIBNDR_FLAG_STR_SIZE2
:
390 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, c_len
+ c_len_term
));
391 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
392 ret
= convert_string(CH_UNIX
, chset
,
394 ndr
->data
+ndr
->offset
, byte_mul
*(c_len
+1));
396 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
397 "Bad character conversion");
399 ndr
->offset
+= byte_mul
*(c_len
+1);
402 case LIBNDR_FLAG_STR_NULLTERM
:
403 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*(c_len
+1));
404 ret
= convert_string(CH_UNIX
, chset
,
406 ndr
->data
+ndr
->offset
, byte_mul
*(c_len
+1));
408 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
409 "Bad character conversion");
411 ndr
->offset
+= byte_mul
*(c_len
+1);
414 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_BYTESIZE
:
415 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, c_len
*byte_mul
));
416 NDR_PUSH_NEED_BYTES(ndr
, c_len
*byte_mul
);
417 ret
= convert_string(CH_UNIX
, chset
,
419 ndr
->data
+ndr
->offset
, c_len
*byte_mul
);
421 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
422 "Bad character conversion");
424 ndr
->offset
+= c_len
*byte_mul
;
427 case LIBNDR_FLAG_STR_FIXLEN15
:
428 case LIBNDR_FLAG_STR_FIXLEN32
:
429 d_len
= (flags
& LIBNDR_FLAG_STR_FIXLEN32
)?32:15;
430 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*d_len
);
431 ret
= convert_string(CH_UNIX
, chset
,
433 ndr
->data
+ndr
->offset
, byte_mul
*d_len
);
435 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
436 "Bad character conversion");
438 ndr
->offset
+= byte_mul
*d_len
;
442 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
443 ndr
->flags
& LIBNDR_STRING_FLAGS
);
450 push a general string onto the wire
452 size_t ndr_string_array_size(struct ndr_push
*ndr
, const char *s
)
455 unsigned flags
= ndr
->flags
;
456 unsigned byte_mul
= 2;
457 unsigned c_len_term
= 1;
459 if (flags
& LIBNDR_FLAG_STR_FIXLEN32
) {
462 if (flags
& LIBNDR_FLAG_STR_FIXLEN15
) {
466 c_len
= s
?strlen_m(s
):0;
468 if (flags
& (LIBNDR_FLAG_STR_ASCII
|LIBNDR_FLAG_STR_UTF8
)) {
472 if (flags
& LIBNDR_FLAG_STR_NOTERM
) {
476 c_len
= c_len
+ c_len_term
;
478 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
479 c_len
= c_len
* byte_mul
;
485 void ndr_print_string(struct ndr_print
*ndr
, const char *name
, const char *s
)
488 ndr
->print(ndr
, "%-25s: '%s'", name
, s
);
490 ndr
->print(ndr
, "%-25s: NULL", name
);
494 uint32_t ndr_size_string(int ret
, const char * const* string
, int flags
)
496 /* FIXME: Is this correct for all strings ? */
497 if(!(*string
)) return ret
;
498 return ret
+strlen(*string
)+1;
502 pull a general string array from the wire
504 NTSTATUS
ndr_pull_string_array(struct ndr_pull
*ndr
, int ndr_flags
, const char ***_a
)
506 const char **a
= *_a
;
509 if (!(ndr_flags
& NDR_SCALARS
)) {
513 for (count
= 0;; count
++) {
514 const char *s
= NULL
;
515 a
= talloc_realloc(ndr
, a
, const char *, count
+ 2);
516 NT_STATUS_HAVE_NO_MEMORY(a
);
520 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
521 if (strcmp("", s
)==0) {
534 push a general string array onto the wire
536 NTSTATUS
ndr_push_string_array(struct ndr_push
*ndr
, int ndr_flags
, const char **a
)
540 if (!(ndr_flags
& NDR_SCALARS
)) {
544 for (count
= 0; a
&& a
[count
]; count
++) {
545 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
548 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
553 void ndr_print_string_array(struct ndr_print
*ndr
, const char *name
, const char **a
)
558 for (count
= 0; a
&& a
[count
]; count
++) {}
560 ndr
->print(ndr
, "%s: ARRAY(%d)", name
, count
);
562 for (i
=0;i
<count
;i
++) {
564 asprintf(&idx
, "[%d]", i
);
566 ndr_print_string(ndr
, idx
, a
[i
]);
573 /* Return number of elements in a string including the last (zeroed) element */
574 uint32_t ndr_string_length(void *_var
, uint32_t element_size
)
577 uint8_t zero
[4] = {0,0,0,0};
580 for (i
= 0; memcmp(var
+i
*element_size
,zero
,element_size
) != 0; i
++);
585 NTSTATUS
ndr_check_string_terminator(struct ndr_pull
*ndr
, const void *_var
, uint32_t count
, uint32_t element_size
)
587 const char *var
= _var
;
590 var
+= element_size
*(count
-1);
592 for (i
= 0; i
< element_size
; i
++) {
594 return NT_STATUS_UNSUCCESSFUL
;
602 NTSTATUS
ndr_pull_charset(struct ndr_pull
*ndr
, int ndr_flags
, char **var
, uint32_t length
, uint8_t byte_mul
, int chset
)
605 NDR_PULL_NEED_BYTES(ndr
, length
*byte_mul
);
606 ret
= convert_string_talloc(ndr
, chset
, CH_UNIX
,
607 ndr
->data
+ndr
->offset
,
611 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
612 "Bad character conversion");
614 NDR_CHECK(ndr_pull_advance(ndr
, length
*byte_mul
));
619 NTSTATUS
ndr_push_charset(struct ndr_push
*ndr
, int ndr_flags
, const char *var
, uint32_t length
, uint8_t byte_mul
, int chset
)
622 NDR_PUSH_NEED_BYTES(ndr
, byte_mul
*length
);
623 ret
= convert_string(CH_UNIX
, chset
,
625 ndr
->data
+ndr
->offset
,
628 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
629 "Bad character conversion");
631 ndr
->offset
+= byte_mul
*length
;