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.
26 pull a general string from the wire
28 NTSTATUS
ndr_pull_string(struct ndr_pull
*ndr
, int ndr_flags
, const char **s
)
31 uint32_t len1
, ofs
, len2
;
34 charset_t chset
= CH_UTF16LE
;
35 unsigned byte_mul
= 2;
36 unsigned flags
= ndr
->flags
;
37 unsigned c_len_term
= 0;
39 if (!(ndr_flags
& NDR_SCALARS
)) {
47 if (flags
& LIBNDR_FLAG_STR_ASCII
) {
50 flags
&= ~LIBNDR_FLAG_STR_ASCII
;
53 if (flags
& LIBNDR_FLAG_STR_UTF8
) {
56 flags
&= ~LIBNDR_FLAG_STR_UTF8
;
59 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
60 if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
62 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
65 switch (flags
& LIBNDR_STRING_FLAGS
) {
66 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
67 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
68 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
69 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
71 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
72 ndr
->flags
& LIBNDR_STRING_FLAGS
);
74 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len2
));
76 return ndr_pull_error(ndr
, NDR_ERR_STRING
,
77 "Bad string lengths len1=%u ofs=%u len2=%u\n",
80 NDR_PULL_NEED_BYTES(ndr
, (len2
+ c_len_term
)*byte_mul
);
82 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
84 ret
= convert_string_talloc(ndr
->current_mem_ctx
,
86 ndr
->data
+ndr
->offset
,
87 (len2
+ c_len_term
)*byte_mul
,
90 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
91 "Bad character conversion");
94 NDR_CHECK(ndr_pull_advance(ndr
, (len2
+ c_len_term
)*byte_mul
));
97 DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1
, len2
, as
));
100 /* this is a way of detecting if a string is sent with the wrong
102 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
103 if (strlen(as
) < (len2
+ c_len_term
)) {
104 DEBUG(6,("short string '%s'\n", as
));
107 if (strlen(as
) == (len2
+ c_len_term
)) {
108 DEBUG(6,("long string '%s'\n", as
));
114 case LIBNDR_FLAG_STR_SIZE4
:
115 case LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
116 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
117 NDR_PULL_NEED_BYTES(ndr
, (len1
+ c_len_term
)*byte_mul
);
119 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
121 ret
= convert_string_talloc(ndr
->current_mem_ctx
,
123 ndr
->data
+ndr
->offset
,
124 (len1
+ c_len_term
)*byte_mul
,
127 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
128 "Bad character conversion");
131 NDR_CHECK(ndr_pull_advance(ndr
, (len1
+ c_len_term
)*byte_mul
));
133 /* this is a way of detecting if a string is sent with the wrong
135 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
136 if (strlen(as
) < (len1
+ c_len_term
)) {
137 DEBUG(6,("short string '%s'\n", as
));
140 if (strlen(as
) == (len1
+ c_len_term
)) {
141 DEBUG(6,("long string '%s'\n", as
));
147 case LIBNDR_FLAG_STR_LEN4
:
148 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_NOTERM
:
149 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
151 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
152 ndr
->flags
& LIBNDR_STRING_FLAGS
);
154 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
155 NDR_PULL_NEED_BYTES(ndr
, (len1
+ c_len_term
)*byte_mul
);
157 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
159 ret
= convert_string_talloc(ndr
->current_mem_ctx
,
161 ndr
->data
+ndr
->offset
,
162 (len1
+ c_len_term
)*byte_mul
,
165 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
166 "Bad character conversion");
169 NDR_CHECK(ndr_pull_advance(ndr
, (len1
+ c_len_term
)*byte_mul
));
171 /* this is a way of detecting if a string is sent with the wrong
173 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
174 if (strlen(as
) < (len1
+ c_len_term
)) {
175 DEBUG(6,("short string '%s'\n", as
));
178 if (strlen(as
) == (len1
+ c_len_term
)) {
179 DEBUG(6,("long string '%s'\n", as
));
186 case LIBNDR_FLAG_STR_SIZE2
:
187 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
:
188 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
189 NDR_PULL_NEED_BYTES(ndr
, (len3
+ c_len_term
)*byte_mul
);
191 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
193 ret
= convert_string_talloc(ndr
->current_mem_ctx
,
195 ndr
->data
+ndr
->offset
,
196 (len3
+ c_len_term
)*byte_mul
,
199 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
200 "Bad character conversion");
203 NDR_CHECK(ndr_pull_advance(ndr
, (len3
+ c_len_term
)*byte_mul
));
205 /* this is a way of detecting if a string is sent with the wrong
207 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
208 if (strlen(as
) < (len3
+ c_len_term
)) {
209 DEBUG(6,("short string '%s'\n", as
));
212 if (strlen(as
) == (len3
+ c_len_term
)) {
213 DEBUG(6,("long string '%s'\n", as
));
219 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_BYTESIZE
:
220 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
221 NDR_PULL_NEED_BYTES(ndr
, len3
);
223 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
225 ret
= convert_string_talloc(ndr
->current_mem_ctx
,
227 ndr
->data
+ndr
->offset
,
230 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
231 "Bad character conversion");
234 NDR_CHECK(ndr_pull_advance(ndr
, len3
));
238 case LIBNDR_FLAG_STR_NULLTERM
:
240 len1
= ascii_len_n((const char *)(ndr
->data
+ndr
->offset
), ndr
->data_size
- ndr
->offset
);
242 len1
= utf16_len_n(ndr
->data
+ndr
->offset
, ndr
->data_size
- ndr
->offset
);
244 ret
= convert_string_talloc(ndr
->current_mem_ctx
,
246 ndr
->data
+ndr
->offset
,
249 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
250 "Bad character conversion");
252 NDR_CHECK(ndr_pull_advance(ndr
, len1
));
256 case LIBNDR_FLAG_STR_FIXLEN15
:
257 case LIBNDR_FLAG_STR_FIXLEN32
:
258 len1
= (flags
& LIBNDR_FLAG_STR_FIXLEN32
)?32:15;
259 NDR_PULL_NEED_BYTES(ndr
, len1
*byte_mul
);
260 ret
= convert_string_talloc(ndr
->current_mem_ctx
,
262 ndr
->data
+ndr
->offset
,
263 len1
*byte_mul
, &as
, False
);
265 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
266 "Bad character conversion");
268 NDR_CHECK(ndr_pull_advance(ndr
, len1
*byte_mul
));
273 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
274 ndr
->flags
& LIBNDR_STRING_FLAGS
);
282 push a general string onto the wire
284 NTSTATUS
ndr_push_string(struct ndr_push
*ndr
, int ndr_flags
, const char *s
)
286 ssize_t s_len
, c_len
, d_len
;
287 charset_t chset
= CH_UTF16LE
;
288 unsigned flags
= ndr
->flags
;
289 unsigned byte_mul
= 2;
290 uint8_t *dest
= NULL
;
292 if (!(ndr_flags
& NDR_SCALARS
)) {
300 s_len
= s
?strlen(s
):0;
302 if (flags
& LIBNDR_FLAG_STR_ASCII
) {
305 flags
&= ~LIBNDR_FLAG_STR_ASCII
;
308 if (flags
& LIBNDR_FLAG_STR_UTF8
) {
311 flags
&= ~LIBNDR_FLAG_STR_UTF8
;
314 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
317 (LIBNDR_FLAG_STR_NOTERM
|
318 LIBNDR_FLAG_STR_FIXLEN15
|
319 LIBNDR_FLAG_STR_FIXLEN32
))) {
322 d_len
= convert_string_talloc(ndr
, CH_UNIX
, chset
, s
, s_len
, &dest
,
325 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
326 "Bad character conversion");
329 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
331 flags
&= ~LIBNDR_FLAG_STR_BYTESIZE
;
332 } else if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
333 c_len
= (d_len
/ byte_mul
)-1;
334 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
336 c_len
= d_len
/ byte_mul
;
339 switch ((flags
& LIBNDR_STRING_FLAGS
) & ~LIBNDR_FLAG_STR_NOTERM
) {
340 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
341 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
342 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
343 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
344 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
347 case LIBNDR_FLAG_STR_LEN4
:
348 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
349 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
350 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
353 case LIBNDR_FLAG_STR_SIZE4
:
354 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
355 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
358 case LIBNDR_FLAG_STR_SIZE2
:
359 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, c_len
));
360 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
363 case LIBNDR_FLAG_STR_NULLTERM
:
364 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
367 case LIBNDR_FLAG_STR_FIXLEN15
:
368 case LIBNDR_FLAG_STR_FIXLEN32
: {
369 ssize_t fix_len
= (flags
& LIBNDR_FLAG_STR_FIXLEN32
)?32:15;
370 uint32_t pad_len
= fix_len
- d_len
;
371 if (d_len
> fix_len
) {
372 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
373 "Bad character conversion");
375 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
377 NDR_CHECK(ndr_push_zero(ndr
, pad_len
));
383 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
384 ndr
->flags
& LIBNDR_STRING_FLAGS
);
393 push a general string onto the wire
395 size_t ndr_string_array_size(struct ndr_push
*ndr
, const char *s
)
398 unsigned flags
= ndr
->flags
;
399 unsigned byte_mul
= 2;
400 unsigned c_len_term
= 1;
402 if (flags
& LIBNDR_FLAG_STR_FIXLEN32
) {
405 if (flags
& LIBNDR_FLAG_STR_FIXLEN15
) {
409 c_len
= s
?strlen(s
):0;
411 if (flags
& (LIBNDR_FLAG_STR_ASCII
|LIBNDR_FLAG_STR_UTF8
)) {
415 if (flags
& LIBNDR_FLAG_STR_NOTERM
) {
419 c_len
= c_len
+ c_len_term
;
421 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
422 c_len
= c_len
* byte_mul
;
428 void ndr_print_string(struct ndr_print
*ndr
, const char *name
, const char *s
)
431 ndr
->print(ndr
, "%-25s: '%s'", name
, s
);
433 ndr
->print(ndr
, "%-25s: NULL", name
);
437 uint32_t ndr_size_string(int ret
, const char * const* string
, int flags
)
439 /* FIXME: Is this correct for all strings ? */
440 if(!(*string
)) return ret
;
441 return ret
+strlen(*string
)+1;
445 pull a general string array from the wire
447 NTSTATUS
ndr_pull_string_array(struct ndr_pull
*ndr
, int ndr_flags
, const char ***_a
)
449 const char **a
= *_a
;
452 if (!(ndr_flags
& NDR_SCALARS
)) {
456 for (count
= 0;; count
++) {
458 const char *s
= NULL
;
459 a
= talloc_realloc(ndr
->current_mem_ctx
, a
, const char *, count
+ 2);
460 NT_STATUS_HAVE_NO_MEMORY(a
);
464 tmp_ctx
= ndr
->current_mem_ctx
;
465 ndr
->current_mem_ctx
= a
;
466 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
467 ndr
->current_mem_ctx
= tmp_ctx
;
468 if (strcmp("", s
)==0) {
481 push a general string array onto the wire
483 NTSTATUS
ndr_push_string_array(struct ndr_push
*ndr
, int ndr_flags
, const char **a
)
487 if (!(ndr_flags
& NDR_SCALARS
)) {
491 for (count
= 0; a
&& a
[count
]; count
++) {
492 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
495 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
500 void ndr_print_string_array(struct ndr_print
*ndr
, const char *name
, const char **a
)
505 for (count
= 0; a
&& a
[count
]; count
++) {}
507 ndr
->print(ndr
, "%s: ARRAY(%d)", name
, count
);
509 for (i
=0;i
<count
;i
++) {
511 asprintf(&idx
, "[%d]", i
);
513 ndr_print_string(ndr
, idx
, a
[i
]);
521 * Return number of elements in a string including the last (zeroed) element
523 uint32_t ndr_string_length(const void *_var
, uint32_t element_size
)
526 uint8_t zero
[4] = {0,0,0,0};
527 const char *var
= (const char *)_var
;
529 for (i
= 0; memcmp(var
+i
*element_size
,zero
,element_size
) != 0; i
++);
534 NTSTATUS
ndr_check_string_terminator(struct ndr_pull
*ndr
, uint32_t count
, uint32_t element_size
)
537 struct ndr_pull_save save_offset
;
539 ndr_pull_save(ndr
, &save_offset
);
540 ndr_pull_advance(ndr
, (count
- 1) * element_size
);
541 NDR_PULL_NEED_BYTES(ndr
, element_size
);
543 for (i
= 0; i
< element_size
; i
++) {
544 if (ndr
->data
[ndr
->offset
+i
] != 0) {
545 ndr_pull_restore(ndr
, &save_offset
);
547 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
, "String terminator not present or outside string boundaries");
551 ndr_pull_restore(ndr
, &save_offset
);
556 NTSTATUS
ndr_pull_charset(struct ndr_pull
*ndr
, int ndr_flags
, const char **var
, uint32_t length
, uint8_t byte_mul
, charset_t chset
)
560 *var
= talloc_strdup(ndr
->current_mem_ctx
, "");
564 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
568 NDR_PULL_NEED_BYTES(ndr
, length
*byte_mul
);
570 ret
= convert_string_talloc(ndr
->current_mem_ctx
,
572 ndr
->data
+ndr
->offset
,
576 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
577 "Bad character conversion");
579 NDR_CHECK(ndr_pull_advance(ndr
, length
*byte_mul
));
584 NTSTATUS
ndr_push_charset(struct ndr_push
*ndr
, int ndr_flags
, const char *var
,
585 uint32_t length
, uint8_t byte_mul
, charset_t chset
)
587 ssize_t ret
, required
;
589 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
593 required
= byte_mul
* length
;
595 NDR_PUSH_NEED_BYTES(ndr
, required
);
596 ret
= convert_string(CH_UNIX
, chset
,
598 ndr
->data
+ndr
->offset
, required
, False
);
600 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
601 "Bad character conversion");
604 /* Make sure the remaining part of the string is filled with zeroes */
605 if (ret
< required
) {
606 memset(ndr
->data
+ndr
->offset
+ret
, 0, required
-ret
);
609 ndr
->offset
+= required
;
614 /* Return number of elements in a string in the specified charset */
615 uint32_t ndr_charset_length(const void *var
, int chset
)
617 /* FIXME: Treat special chars special here, taking chset into account */
618 /* Also include 0 byte */
619 return strlen((const char *)var
)+1;