2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Jelmer Vernooij 2005-2008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 this provides the core routines for NDR parsing functions
26 see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
31 #include "librpc/ndr/libndr.h"
32 #include "librpc/ndr/ndr_private.h"
33 #include "../lib/util/dlinklist.h"
36 #define DBGC_CLASS DBGC_RPC_PARSE
38 #define NDR_BASE_MARSHALL_SIZE 1024
41 * This value is arbitrary, but designed to reduce the memory a client
42 * can allocate and the work the client can force in processing a
45 * In an ideal world this would be controlled by range() restrictions
46 * on array sizes and careful IDL construction to avoid arbitrary
47 * linked lists, but this is a backstop for now.
49 #define NDR_TOKEN_MAX_LIST_SIZE 65535
51 size_t ndr_token_max_list_size(void) {
52 return NDR_TOKEN_MAX_LIST_SIZE
;
55 /* this guid indicates NDR encoding in a protocol tower */
56 const struct ndr_syntax_id ndr_transfer_syntax_ndr
= {
57 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
61 const struct ndr_syntax_id ndr_transfer_syntax_ndr64
= {
62 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
66 const struct ndr_syntax_id ndr_syntax_id_null
= {
67 { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
72 work out the number of bytes needed to align on a n byte boundary
74 _PUBLIC_
size_t ndr_align_size(uint32_t offset
, size_t n
)
76 if ((offset
& (n
-1)) == 0) return 0;
77 return n
- (offset
& (n
-1));
81 initialise a ndr parse structure from a data blob
83 _PUBLIC_
struct ndr_pull
*ndr_pull_init_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
87 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
88 if (!ndr
) return NULL
;
89 ndr
->current_mem_ctx
= mem_ctx
;
91 ndr
->data
= blob
->data
;
92 ndr
->data_size
= blob
->length
;
97 _PUBLIC_
enum ndr_err_code
ndr_pull_append(struct ndr_pull
*ndr
, DATA_BLOB
*blob
)
99 enum ndr_err_code ndr_err
;
104 if (blob
->length
== 0) {
105 return NDR_ERR_SUCCESS
;
108 ndr_err
= ndr_token_retrieve(&ndr
->array_size_list
, ndr
, &append
);
109 if (ndr_err
== NDR_ERR_TOKEN
) {
111 ndr_err
= NDR_ERR_SUCCESS
;
115 if (ndr
->data_size
== 0) {
120 if (append
== UINT32_MAX
) {
122 * append == UINT32_MAX means that
123 * ndr->data is either NULL or a valid
124 * talloc child of ndr, which means
125 * we can use data_blob_append() without
126 * data_blob_talloc() of the existing callers data
128 b
= data_blob_const(ndr
->data
, ndr
->data_size
);
130 b
= data_blob_talloc(ndr
, ndr
->data
, ndr
->data_size
);
131 if (b
.data
== NULL
) {
132 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
136 ok
= data_blob_append(ndr
, &b
, blob
->data
, blob
->length
);
138 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
142 ndr
->data_size
= b
.length
;
144 return ndr_token_store(ndr
, &ndr
->array_size_list
, ndr
, UINT32_MAX
);
147 _PUBLIC_
enum ndr_err_code
ndr_pull_pop(struct ndr_pull
*ndr
)
151 enum ndr_err_code ndr_err
;
153 if (ndr
->relative_base_offset
!= 0) {
154 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
157 if (ndr
->relative_highest_offset
!= 0) {
158 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
161 if (ndr
->relative_list
.count
!= 0) {
162 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
165 if (ndr
->relative_base_list
.count
!= 0) {
166 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
171 * we need to keep up to 7 bytes
172 * in order to get the alignment right.
174 skip
= ndr
->offset
& 0xFFFFFFF8;
177 return NDR_ERR_SUCCESS
;
181 ndr
->data_size
-= skip
;
183 ndr_err
= ndr_token_peek(&ndr
->array_size_list
, ndr
, &append
);
184 if (ndr_err
== NDR_ERR_TOKEN
) {
186 * here we assume, that ndr->data is not a
187 * talloc child of ndr.
190 return NDR_ERR_SUCCESS
;
193 memmove(ndr
->data
, ndr
->data
+ skip
, ndr
->data_size
);
195 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->data_size
);
196 if (ndr
->data_size
!= 0 && ndr
->data
== NULL
) {
197 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
200 return NDR_ERR_SUCCESS
;
204 advance by 'size' bytes
206 _PUBLIC_
enum ndr_err_code
ndr_pull_advance(struct ndr_pull
*ndr
, uint32_t size
)
208 NDR_PULL_NEED_BYTES(ndr
, size
);
210 return NDR_ERR_SUCCESS
;
214 set the parse offset to 'ofs'
216 static enum ndr_err_code
ndr_pull_set_offset(struct ndr_pull
*ndr
, uint32_t ofs
)
219 if (ndr
->offset
> ndr
->data_size
) {
220 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
221 "ndr_pull_set_offset %"PRIu32
" failed",
224 return NDR_ERR_SUCCESS
;
227 /* create a ndr_push structure, ready for some marshalling */
228 _PUBLIC_
struct ndr_push
*ndr_push_init_ctx(TALLOC_CTX
*mem_ctx
)
230 struct ndr_push
*ndr
;
232 ndr
= talloc_zero(mem_ctx
, struct ndr_push
);
238 ndr
->alloc_size
= NDR_BASE_MARSHALL_SIZE
;
239 ndr
->data
= talloc_array(ndr
, uint8_t, ndr
->alloc_size
);
248 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
249 _PUBLIC_ DATA_BLOB
ndr_push_blob(struct ndr_push
*ndr
)
252 blob
= data_blob_const(ndr
->data
, ndr
->offset
);
253 if (ndr
->alloc_size
> ndr
->offset
) {
254 ndr
->data
[ndr
->offset
] = 0;
261 expand the available space in the buffer to ndr->offset + extra_size
263 _PUBLIC_
enum ndr_err_code
ndr_push_expand(struct ndr_push
*ndr
, uint32_t extra_size
)
265 uint32_t size
= extra_size
+ ndr
->offset
;
267 if (size
< ndr
->offset
) {
268 /* extra_size overflowed the offset */
269 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
, "Overflow in push_expand to %"PRIu32
,
273 if (ndr
->fixed_buf_size
) {
274 if (ndr
->alloc_size
>= size
) {
275 return NDR_ERR_SUCCESS
;
277 return ndr_push_error(ndr
,
279 "Overflow of fixed buffer in "
280 "push_expand to %"PRIu32
,
284 if (ndr
->alloc_size
> size
) {
285 return NDR_ERR_SUCCESS
;
288 ndr
->alloc_size
+= NDR_BASE_MARSHALL_SIZE
;
289 if (size
== UINT32_MAX
) {
290 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
, "Overflow in push_expand");
292 if (size
+1 > ndr
->alloc_size
) {
293 ndr
->alloc_size
= size
+1;
295 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->alloc_size
);
297 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %"PRIu32
,
301 return NDR_ERR_SUCCESS
;
304 _PUBLIC_
void ndr_print_debugc_helper(struct ndr_print
*ndr
, const char *format
, ...)
312 va_start(ap
, format
);
313 ret
= vasprintf(&s
, format
, ap
);
320 dbgc_class
= *(int *)ndr
->private_data
;
322 if (ndr
->no_newline
) {
323 DEBUGADDC(dbgc_class
, 1,("%s", s
));
328 for (i
=0;i
<ndr
->depth
;i
++) {
329 DEBUGADDC(dbgc_class
, 1,(" "));
332 DEBUGADDC(dbgc_class
, 1,("%s\n", s
));
336 _PUBLIC_
void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...)
343 va_start(ap
, format
);
344 ret
= vasprintf(&s
, format
, ap
);
351 if (ndr
->no_newline
) {
352 DEBUGADD(1,("%s", s
));
357 for (i
=0;i
<ndr
->depth
;i
++) {
361 DEBUGADD(1,("%s\n", s
));
365 _PUBLIC_
void ndr_print_printf_helper(struct ndr_print
*ndr
, const char *format
, ...)
370 if (!ndr
->no_newline
) {
371 for (i
=0;i
<ndr
->depth
;i
++) {
376 va_start(ap
, format
);
379 if (!ndr
->no_newline
) {
384 _PUBLIC_
void ndr_print_string_helper(struct ndr_print
*ndr
, const char *format
, ...)
389 if (!ndr
->no_newline
) {
390 for (i
=0;i
<ndr
->depth
;i
++) {
391 ndr
->private_data
= talloc_asprintf_append_buffer(
392 (char *)ndr
->private_data
, " ");
396 va_start(ap
, format
);
397 ndr
->private_data
= talloc_vasprintf_append_buffer((char *)ndr
->private_data
,
400 if (!ndr
->no_newline
) {
401 ndr
->private_data
= talloc_asprintf_append_buffer((char *)ndr
->private_data
,
407 a useful helper function for printing idl structures via DEBUGC()
409 _PUBLIC_
void ndr_print_debugc(int dbgc_class
,
414 struct ndr_print
*ndr
;
416 DEBUGC(dbgc_class
, 1,(" "));
418 ndr
= talloc_zero(NULL
, struct ndr_print
);
420 ndr
->private_data
= &dbgc_class
;
421 ndr
->print
= ndr_print_debugc_helper
;
424 #ifdef DEBUG_PASSWORD
425 if (CHECK_DEBUGLVL(100)) {
426 ndr
->print_secrets
= true;
435 a useful helper function for printing idl structures via DEBUG()
437 _PUBLIC_
bool ndr_print_debug(int level
,
441 const char *location
,
442 const char *function
)
444 struct ndr_print
*ndr
;
447 ndr
= talloc_zero(NULL
, struct ndr_print
);
448 if (!ndr
) return false;
449 ndr
->private_data
= talloc_strdup(ndr
, "");
450 if (ndr
->private_data
== NULL
) {
453 ndr
->print
= ndr_print_string_helper
;
456 #ifdef DEBUG_PASSWORD
457 if (CHECK_DEBUGLVL(100)) {
458 ndr
->print_secrets
= true;
463 DEBUGLF(level
, (" %s", (char *)ndr
->private_data
), location
, function
);
472 a useful helper function for printing idl unions via DEBUG()
474 _PUBLIC_
void ndr_print_union_debug(ndr_print_fn_t fn
,
479 struct ndr_print
*ndr
;
483 ndr
= talloc_zero(NULL
, struct ndr_print
);
485 ndr
->print
= ndr_print_debug_helper
;
488 #ifdef DEBUG_PASSWORD
489 if (CHECK_DEBUGLVL(100)) {
490 ndr
->print_secrets
= true;
494 ndr_print_set_switch_value(ndr
, ptr
, level
);
500 a useful helper function for printing idl function calls via DEBUG()
502 _PUBLIC_
void ndr_print_function_debug(ndr_print_function_t fn
,
504 ndr_flags_type flags
,
507 struct ndr_print
*ndr
;
511 ndr
= talloc_zero(NULL
, struct ndr_print
);
513 ndr
->print
= ndr_print_debug_helper
;
516 #ifdef DEBUG_PASSWORD
517 if (CHECK_DEBUGLVL(100)) {
518 ndr
->print_secrets
= true;
522 fn(ndr
, name
, flags
, ptr
);
526 static char *ndr_print_generic_string(TALLOC_CTX
*mem_ctx
,
527 ndr_print_function_t inout_fn
,
528 ndr_flags_type inout_flags
,
529 ndr_print_fn_t single_fn
,
532 const uint32_t *level
,
535 struct ndr_print
*ndr
;
538 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
539 if (!ndr
) return NULL
;
540 ndr
->private_data
= talloc_strdup(ndr
, "");
541 if (!ndr
->private_data
) {
544 ndr
->print
= ndr_print_string_helper
;
547 ndr
->print_secrets
= print_secrets
;
549 ndr_print_set_switch_value(ndr
, ptr
, *level
);
551 if (inout_fn
!= NULL
) {
552 inout_fn(ndr
, name
, inout_flags
, ptr
);
554 single_fn(ndr
, name
, ptr
);
556 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
558 talloc_keep_secret(ret
);
566 a useful helper function for printing idl structures to a string
568 _PUBLIC_
char *ndr_print_struct_string(TALLOC_CTX
*mem_ctx
,
573 return ndr_print_generic_string(mem_ctx
,
577 false, /* print_secrets */
584 a useful helper function for printing idl structures to a string
585 This includes values marked with NDR_SECRET
587 _PUBLIC_
char *ndr_print_struct_secret_string(TALLOC_CTX
*mem_ctx
,
592 return ndr_print_generic_string(mem_ctx
,
596 true, /* print_secrets */
603 a useful helper function for printing idl unions to a string
605 _PUBLIC_
char *ndr_print_union_string(TALLOC_CTX
*mem_ctx
,
611 return ndr_print_generic_string(mem_ctx
,
615 false, /* print_secrets */
622 a useful helper function for printing idl unions to a string
623 This includes values marked with NDR_SECRET
625 _PUBLIC_
char *ndr_print_union_secret_string(TALLOC_CTX
*mem_ctx
,
631 return ndr_print_generic_string(mem_ctx
,
635 true, /* print_secrets */
642 a useful helper function for printing idl function calls to a string
644 _PUBLIC_
char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
645 ndr_print_function_t fn
,
647 ndr_flags_type flags
,
650 return ndr_print_generic_string(mem_ctx
,
652 flags
, /* inout_flags */
653 NULL
, /* single_fn */
654 false, /* print_secrets */
661 a useful helper function for printing idl function calls to a string
662 This includes values marked with NDR_SECRET
664 _PUBLIC_
char *ndr_print_function_secret_string(TALLOC_CTX
*mem_ctx
,
665 ndr_print_function_t fn
,
667 ndr_flags_type flags
,
670 return ndr_print_generic_string(mem_ctx
,
672 flags
, /* inout_flags */
673 NULL
, /* single_fn */
674 true, /* print_secrets */
680 _PUBLIC_
void ndr_set_flags(libndr_flags
*pflags
, libndr_flags new_flags
)
682 /* the big/little endian flags are inter-dependent */
683 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
684 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
685 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
687 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
688 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
689 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
691 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
692 /* Ensure we only have the passed-in
693 align flag set in the new_flags,
694 remove any old align flag. */
695 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
697 if (new_flags
& LIBNDR_FLAG_NO_RELATIVE_REVERSE
) {
698 (*pflags
) &= ~LIBNDR_FLAG_RELATIVE_REVERSE
;
700 (*pflags
) |= new_flags
;
704 return and possibly log an NDR error
706 _PUBLIC_
enum ndr_err_code
_ndr_pull_error(struct ndr_pull
*ndr
,
707 enum ndr_err_code ndr_err
,
708 const char *function
,
709 const char *location
,
710 const char *format
, ...)
716 if (ndr
->flags
& LIBNDR_FLAG_INCOMPLETE_BUFFER
) {
718 case NDR_ERR_BUFSIZE
:
719 return NDR_ERR_INCOMPLETE_BUFFER
;
725 va_start(ap
, format
);
726 ret
= vasprintf(&s
, format
, ap
);
730 return NDR_ERR_ALLOC
;
733 D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
735 ndr_map_error2string(ndr_err
),
745 return and possibly log an NDR error
747 _PUBLIC_
enum ndr_err_code
_ndr_push_error(struct ndr_push
*ndr
,
748 enum ndr_err_code ndr_err
,
749 const char *function
,
750 const char *location
,
751 const char *format
, ...)
757 va_start(ap
, format
);
758 ret
= vasprintf(&s
, format
, ap
);
762 return NDR_ERR_ALLOC
;
765 D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
767 ndr_map_error2string(ndr_err
),
777 handle subcontext buffers, which in midl land are user-marshalled, but
778 we use magic in pidl to make them easier to cope with
780 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
781 struct ndr_pull
**_subndr
,
785 struct ndr_pull
*subndr
;
786 uint32_t r_content_size
;
787 bool force_le
= false;
788 bool force_be
= false;
790 switch (header_size
) {
792 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
794 content_size
= size_is
;
796 r_content_size
= content_size
;
801 uint16_t content_size
;
802 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
803 if (size_is
>= 0 && size_is
!= content_size
) {
804 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%zd) (0x%04zx) mismatch content_size %"PRIu16
" (0x%04"PRIx16
")",
809 r_content_size
= content_size
;
814 uint32_t content_size
;
815 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &content_size
));
816 if (size_is
>= 0 && size_is
!= content_size
) {
817 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%zd) (0x%08zx) mismatch content_size %"PRIu32
" (0x%08"PRIx32
")",
822 r_content_size
= content_size
;
827 * Common Type Header for the Serialization Stream
828 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
834 uint32_t content_size
;
838 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &version
));
841 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
842 "Bad subcontext (PULL) Common Type Header version %"PRIu8
" != 1",
850 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &drep
));
853 } else if (drep
== 0x00) {
856 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
857 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02"PRIX8
,
861 /* length of the "Private Header for Constructed Type" */
862 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &hdrlen
));
864 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
865 "Bad subcontext (PULL) Common Type Header length %"PRIu16
" != 8",
869 /* filler should be ignored */
870 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &filler
));
873 * Private Header for Constructed Type
875 /* length - will be updated later */
876 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
877 if (size_is
>= 0 && size_is
!= content_size
) {
878 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%zd) mismatch content_size %"PRIu32
,
879 size_is
, content_size
);
881 /* the content size must be a multiple of 8 */
882 if ((content_size
% 8) != 0) {
883 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
884 "Bad subcontext (PULL) size_is(%zd) not padded to 8 content_size %"PRIu32
,
885 size_is
, content_size
);
887 r_content_size
= content_size
;
890 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &reserved
));
895 * a shallow copy like subcontext
896 * useful for DCERPC pipe chunks.
898 subndr
= talloc_zero(ndr
, struct ndr_pull
);
899 NDR_ERR_HAVE_NO_MEMORY(subndr
);
901 subndr
->flags
= ndr
->flags
;
902 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
903 subndr
->data
= ndr
->data
;
904 subndr
->offset
= ndr
->offset
;
905 subndr
->data_size
= ndr
->data_size
;
908 return NDR_ERR_SUCCESS
;
911 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %zu",
915 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
917 subndr
= talloc_zero(ndr
, struct ndr_pull
);
918 NDR_ERR_HAVE_NO_MEMORY(subndr
);
919 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
920 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
922 subndr
->data
= ndr
->data
+ ndr
->offset
;
924 subndr
->data_size
= r_content_size
;
927 ndr_set_flags(&subndr
->flags
, LIBNDR_FLAG_LITTLE_ENDIAN
);
928 } else if (force_be
) {
929 ndr_set_flags(&subndr
->flags
, LIBNDR_FLAG_BIGENDIAN
);
933 return NDR_ERR_SUCCESS
;
936 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
937 struct ndr_pull
*subndr
,
942 uint32_t highest_ofs
;
944 if (header_size
== 0xFFFFFFFF) {
945 advance
= subndr
->offset
- ndr
->offset
;
946 } else if (size_is
>= 0) {
948 } else if (header_size
> 0) {
949 advance
= subndr
->data_size
;
951 advance
= subndr
->offset
;
954 if (subndr
->offset
> ndr
->relative_highest_offset
) {
955 highest_ofs
= subndr
->offset
;
957 highest_ofs
= subndr
->relative_highest_offset
;
959 if (!(subndr
->flags
& LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
)) {
961 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
963 highest_ofs
= advance
;
965 if (highest_ofs
< advance
) {
966 return ndr_pull_error(subndr
, NDR_ERR_UNREAD_BYTES
,
967 "not all bytes consumed ofs[%"PRIu32
"] advance[%"PRIu32
"]",
968 highest_ofs
, advance
);
971 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
972 return NDR_ERR_SUCCESS
;
975 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_start(struct ndr_push
*ndr
,
976 struct ndr_push
**_subndr
,
980 struct ndr_push
*subndr
;
982 subndr
= ndr_push_init_ctx(ndr
);
983 NDR_ERR_HAVE_NO_MEMORY(subndr
);
984 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
987 enum ndr_err_code status
;
989 status
= ndr_push_zero(subndr
, size_is
);
990 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
995 subndr
->relative_end_offset
= size_is
;
999 return NDR_ERR_SUCCESS
;
1003 push a subcontext header
1005 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_end(struct ndr_push
*ndr
,
1006 struct ndr_push
*subndr
,
1010 ssize_t padding_len
;
1013 padding_len
= size_is
- subndr
->offset
;
1014 if (padding_len
< 0) {
1015 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %"PRIu32
" is larger than size_is(%zd)",
1016 subndr
->offset
, size_is
);
1018 subndr
->offset
= size_is
;
1021 switch (header_size
) {
1026 if (subndr
->offset
> UINT16_MAX
) {
1027 return ndr_push_error(
1030 "Subcontext (PUSH) too large: %" PRIu32
1031 " does not fit into 16 bits",
1034 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
1038 NDR_CHECK(ndr_push_uint3264(ndr
, NDR_SCALARS
, subndr
->offset
));
1043 * Common Type Header for the Serialization Stream
1044 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
1046 padding_len
= NDR_ROUND(subndr
->offset
, 8) - subndr
->offset
;
1047 if (padding_len
> 0) {
1048 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
1052 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 1));
1055 * 0x10 little endian
1058 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, NDR_BE(ndr
)?0x00:0x10));
1060 /* length of the "Private Header for Constructed Type" */
1061 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 8));
1064 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0xCCCCCCCC));
1067 * Private Header for Constructed Type
1069 /* length - will be updated later */
1070 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
1073 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1077 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %zu",
1081 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
1082 return NDR_ERR_SUCCESS
;
1092 store a token in the ndr context, for later retrieval
1094 _PUBLIC_
enum ndr_err_code
ndr_token_store(TALLOC_CTX
*mem_ctx
,
1095 struct ndr_token_list
*list
,
1099 if (list
->tokens
== NULL
) {
1100 list
->tokens
= talloc_array(mem_ctx
, struct ndr_token
, 10);
1101 if (list
->tokens
== NULL
) {
1102 NDR_ERR_HAVE_NO_MEMORY(list
->tokens
);
1105 struct ndr_token
*new_tokens
= NULL
;
1106 uint32_t alloc_count
= talloc_array_length(list
->tokens
);
1109 * Check every time we have not allocated too many
1110 * tokens. This ensures developer sanity when
1111 * debugging the boundary condition
1113 if (list
->count
>= NDR_TOKEN_MAX_LIST_SIZE
) {
1114 return NDR_ERR_RANGE
;
1116 if (list
->count
== alloc_count
) {
1119 * Double the list, until we start in chunks
1122 uint32_t increment
= MIN(list
->count
, 1000);
1123 new_alloc
= alloc_count
+ increment
;
1124 if (new_alloc
< alloc_count
) {
1125 return NDR_ERR_RANGE
;
1127 new_tokens
= talloc_realloc(mem_ctx
, list
->tokens
,
1128 struct ndr_token
, new_alloc
);
1129 NDR_ERR_HAVE_NO_MEMORY(new_tokens
);
1130 list
->tokens
= new_tokens
;
1133 list
->tokens
[list
->count
].key
= key
;
1134 list
->tokens
[list
->count
].value
= value
;
1136 return NDR_ERR_SUCCESS
;
1140 retrieve a token from a ndr context, using cmp_fn to match the tokens
1142 static enum ndr_err_code
ndr_token_find(struct ndr_token_list
*list
,
1145 comparison_fn_t _cmp_fn
,
1148 struct ndr_token
*tokens
= list
->tokens
;
1150 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1151 if (_cmp_fn(tokens
[i
].key
, key
) == 0) {
1153 *v
= tokens
[i
].value
;
1154 return NDR_ERR_SUCCESS
;
1157 return NDR_ERR_TOKEN
;
1161 * retrieve a token from a ndr context, matching by key address.
1163 static enum ndr_err_code
ndr_token_find_by_key_address(struct ndr_token_list
*list
,
1168 struct ndr_token
*tokens
= list
->tokens
;
1170 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1171 if (tokens
[i
].key
== key
) {
1173 *v
= tokens
[i
].value
;
1174 return NDR_ERR_SUCCESS
;
1177 return NDR_ERR_TOKEN
;
1181 _PUBLIC_
enum ndr_err_code
ndr_token_peek_cmp_fn(struct ndr_token_list
*list
,
1184 comparison_fn_t _cmp_fn
)
1187 return ndr_token_find(list
, key
, v
, _cmp_fn
, &i
);
1191 retrieve a token from a ndr context
1193 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve(struct ndr_token_list
*list
,
1194 const void *key
, uint32_t *v
)
1196 enum ndr_err_code err
;
1200 err
= ndr_token_find_by_key_address(list
, key
, v
, &i
);
1201 if (!NDR_ERR_CODE_IS_SUCCESS(err
)) {
1205 last
= list
->count
- 1;
1207 list
->tokens
[i
] = list
->tokens
[last
];
1211 return NDR_ERR_SUCCESS
;
1215 peek at but don't removed a token from a ndr context
1217 _PUBLIC_
enum ndr_err_code
ndr_token_peek(struct ndr_token_list
*list
,
1218 const void *key
, uint32_t *v
)
1221 return ndr_token_find_by_key_address(list
, key
, v
, &i
);
1225 pull an array size field and add it to the array_size_list token list
1227 _PUBLIC_
enum ndr_err_code
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
1229 enum ndr_err_code ret
;
1231 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &size
));
1232 ret
= ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
1233 if (ret
== NDR_ERR_RANGE
) {
1234 return ndr_pull_error(ndr
, ret
,
1235 "More than %d NDR tokens stored for array_size",
1236 NDR_TOKEN_MAX_LIST_SIZE
);
1242 get the stored array size field
1244 _PUBLIC_
enum ndr_err_code
ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t *size
)
1246 return ndr_token_peek(&ndr
->array_size_list
, p
, size
);
1250 get and remove from the stored list the stored array size field
1252 _PUBLIC_
enum ndr_err_code
ndr_steal_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t *size
)
1254 return ndr_token_retrieve(&ndr
->array_size_list
, p
, size
);
1258 * check the stored array size field and remove from the stored list
1259 * (the array_size NDR token list). We try to remove when possible to
1260 * avoid the list growing towards the bounds check
1262 _PUBLIC_
enum ndr_err_code
ndr_check_steal_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t size
)
1265 NDR_CHECK(ndr_steal_array_size(ndr
, p
, &stored
));
1266 if (stored
!= size
) {
1267 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1268 "Bad array size - got %u expected %u\n",
1271 return NDR_ERR_SUCCESS
;
1275 * check the stored array size field (leaving it on the array_size
1278 _PUBLIC_
enum ndr_err_code
ndr_check_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t size
)
1281 NDR_CHECK(ndr_get_array_size(ndr
, p
, &stored
));
1282 if (stored
!= size
) {
1283 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1284 "Bad array size - got %"PRIu32
" expected %"PRIu32
"\n",
1287 return NDR_ERR_SUCCESS
;
1291 pull an array length field and add it to the array_length_list token list
1293 _PUBLIC_
enum ndr_err_code
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
1295 enum ndr_err_code ret
;
1296 uint32_t length
, offset
;
1297 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &offset
));
1299 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1300 "non-zero array offset %"PRIu32
"\n", offset
);
1302 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &length
));
1303 ret
= ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
1304 if (ret
== NDR_ERR_RANGE
) {
1305 return ndr_pull_error(ndr
, ret
,
1306 "More than %d NDR tokens stored for array_length_list",
1307 NDR_TOKEN_MAX_LIST_SIZE
);
1313 get the stored array length field
1315 _PUBLIC_
enum ndr_err_code
ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t *length
)
1317 return ndr_token_peek(&ndr
->array_length_list
, p
, length
);
1321 * check the stored array length field and remove from the stored list
1322 * (the array_size NDR token list). We try to remove when possible to
1323 * avoid the list growing towards the bounds check
1325 _PUBLIC_
enum ndr_err_code
ndr_steal_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t *length
)
1327 return ndr_token_retrieve(&ndr
->array_length_list
, p
, length
);
1330 check the stored array length field, removing it from the list
1332 _PUBLIC_
enum ndr_err_code
ndr_check_steal_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t length
)
1335 NDR_CHECK(ndr_steal_array_length(ndr
, p
, &stored
));
1336 if (stored
!= length
) {
1337 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1338 "Bad array length: got %"PRIu32
" expected %"PRIu32
"\n",
1341 return NDR_ERR_SUCCESS
;
1344 _PUBLIC_
enum ndr_err_code
ndr_push_pipe_chunk_trailer(struct ndr_push
*ndr
, ndr_flags_type ndr_flags
, uint32_t count
)
1346 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1347 int64_t tmp
= 0 - (int64_t)count
;
1348 uint64_t ncount
= tmp
;
1350 NDR_CHECK(ndr_push_hyper(ndr
, ndr_flags
, ncount
));
1353 return NDR_ERR_SUCCESS
;
1356 _PUBLIC_
enum ndr_err_code
ndr_check_pipe_chunk_trailer(struct ndr_pull
*ndr
, ndr_flags_type ndr_flags
, uint32_t count
)
1358 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1359 int64_t tmp
= 0 - (int64_t)count
;
1360 uint64_t ncount1
= tmp
;
1363 NDR_CHECK(ndr_pull_hyper(ndr
, ndr_flags
, &ncount2
));
1364 if (ncount1
== ncount2
) {
1365 return NDR_ERR_SUCCESS
;
1368 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1369 "Bad pipe trailer[%"PRIu64
" should be %"PRIu64
"] size was %"PRIu32
"\"",
1375 return NDR_ERR_SUCCESS
;
1379 store a switch value
1381 _PUBLIC_
enum ndr_err_code
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
1383 enum ndr_err_code ret
=
1384 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1385 if (ret
== NDR_ERR_RANGE
) {
1386 return ndr_push_error(ndr
, ret
,
1387 "More than %d NDR tokens stored for switch_list",
1388 NDR_TOKEN_MAX_LIST_SIZE
);
1393 _PUBLIC_
enum ndr_err_code
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
1396 enum ndr_err_code ret
=
1397 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1398 if (ret
== NDR_ERR_RANGE
) {
1399 return ndr_pull_error(ndr
, ret
,
1400 "More than %d NDR tokens stored for switch_list",
1401 NDR_TOKEN_MAX_LIST_SIZE
);
1406 _PUBLIC_
enum ndr_err_code
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
1408 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1411 /* retrieve a switch value (for push) and remove it from the list */
1412 _PUBLIC_
enum ndr_err_code
ndr_push_steal_switch_value(struct ndr_push
*ndr
,
1416 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1419 /* retrieve a switch value and remove it from the list */
1420 _PUBLIC_
uint32_t ndr_print_steal_switch_value(struct ndr_print
*ndr
, const void *p
)
1422 enum ndr_err_code status
;
1425 status
= ndr_token_retrieve(&ndr
->switch_list
, p
, &v
);
1426 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1433 /* retrieve a switch value and remove it from the list */
1434 _PUBLIC_
enum ndr_err_code
ndr_pull_steal_switch_value(struct ndr_pull
*ndr
,
1438 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1442 pull a struct from a blob using NDR
1444 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1445 ndr_pull_flags_fn_t fn
)
1447 struct ndr_pull
*ndr
;
1448 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1449 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1450 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1452 return NDR_ERR_SUCCESS
;
1456 pull a struct from a blob using NDR - failing if all bytes are not consumed
1458 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1459 void *p
, ndr_pull_flags_fn_t fn
)
1461 struct ndr_pull
*ndr
;
1462 uint32_t highest_ofs
;
1463 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1464 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1465 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1466 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1467 highest_ofs
= ndr
->offset
;
1469 highest_ofs
= ndr
->relative_highest_offset
;
1471 if (highest_ofs
< ndr
->data_size
) {
1472 enum ndr_err_code ret
;
1473 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1474 "not all bytes consumed ofs[%"PRIu32
"] size[%"PRIu32
"]",
1475 highest_ofs
, ndr
->data_size
);
1480 return NDR_ERR_SUCCESS
;
1483 _PUBLIC_
enum ndr_err_code
1484 _ndr_deepcopy_struct(ndr_push_flags_fn_t push_fn
,
1486 ndr_pull_flags_fn_t pull_fn
,
1487 TALLOC_CTX
*dst_mem
, void *dst
)
1489 TALLOC_CTX
*frame
= talloc_stackframe();
1490 DATA_BLOB blob
= { .length
= 0, };
1491 enum ndr_err_code ndr_err
;
1493 ndr_err
= ndr_push_struct_blob(&blob
, frame
, src
, push_fn
);
1494 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1499 ndr_err
= ndr_pull_struct_blob_all(&blob
, dst_mem
, dst
, pull_fn
);
1500 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1506 return NDR_ERR_SUCCESS
;
1510 * pull a struct from a blob using NDR
1512 * This only works for structures with NO allocated memory, like
1513 * objectSID and GUID. This helps because we parse these a lot.
1515 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_noalloc(const uint8_t *buf
,
1518 ndr_pull_flags_fn_t fn
,
1522 * We init this structure on the stack here, to avoid a
1523 * talloc() as otherwise this call to the fn() is assured not
1524 * to be doing any allocation, eg SIDs and GUIDs.
1526 * This allows us to keep the safety of the PIDL-generated
1527 * code without the talloc() overhead.
1529 struct ndr_pull ndr
= {
1530 .data
= discard_const_p(uint8_t, buf
),
1531 .data_size
= buflen
,
1532 .current_mem_ctx
= (void *)-1,
1535 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1536 *consumed
= MAX(ndr
.offset
, ndr
.relative_highest_offset
);
1538 return NDR_ERR_SUCCESS
;
1542 pull a struct from a blob using NDR - failing if all bytes are not consumed
1544 This only works for structures with NO allocated memory, like
1545 objectSID and GUID. This helps because we parse these a lot.
1547 _PUBLIC_
enum ndr_err_code
1548 ndr_pull_struct_blob_all_noalloc(const DATA_BLOB
*blob
,
1550 ndr_pull_flags_fn_t fn
)
1553 enum ndr_err_code ndr_err
;
1555 ndr_err
= ndr_pull_struct_blob_noalloc(blob
->data
,
1560 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1564 if (consumed
< blob
->length
) {
1565 D_WARNING("not all bytes consumed ofs[%zu] size[%zu]",
1568 return NDR_ERR_UNREAD_BYTES
;
1571 return NDR_ERR_SUCCESS
;
1575 pull a union from a blob using NDR, given the union discriminator
1577 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1579 uint32_t level
, ndr_pull_flags_fn_t fn
)
1581 struct ndr_pull
*ndr
;
1582 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1583 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1584 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1585 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1587 return NDR_ERR_SUCCESS
;
1591 pull a union from a blob using NDR, given the union discriminator,
1592 failing if all bytes are not consumed
1594 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1596 uint32_t level
, ndr_pull_flags_fn_t fn
)
1598 struct ndr_pull
*ndr
;
1599 uint32_t highest_ofs
;
1600 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1601 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1602 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1603 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1604 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1605 highest_ofs
= ndr
->offset
;
1607 highest_ofs
= ndr
->relative_highest_offset
;
1609 if (highest_ofs
< ndr
->data_size
) {
1610 enum ndr_err_code ret
;
1611 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1612 "not all bytes consumed ofs[%"PRIu32
"] size[%"PRIu32
"]",
1613 highest_ofs
, ndr
->data_size
);
1618 return NDR_ERR_SUCCESS
;
1622 push a struct to a blob using NDR
1624 _PUBLIC_
enum ndr_err_code
ndr_push_struct_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, const void *p
, ndr_push_flags_fn_t fn
)
1626 struct ndr_push
*ndr
;
1627 ndr
= ndr_push_init_ctx(mem_ctx
);
1628 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1630 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1632 *blob
= ndr_push_blob(ndr
);
1633 talloc_steal(mem_ctx
, blob
->data
);
1636 return NDR_ERR_SUCCESS
;
1640 push a struct into a provided blob using NDR.
1642 We error because we want to have the performance issue (extra
1643 talloc() calls) show up as an error, not just slower code. This is
1644 used for things like GUIDs, which we expect to be a fixed size, and
1645 SIDs that we can pre-calculate the size for.
1647 _PUBLIC_
enum ndr_err_code
ndr_push_struct_into_fixed_blob(
1648 DATA_BLOB
*blob
, const void *p
, ndr_push_flags_fn_t fn
)
1650 struct ndr_push ndr
= {
1652 .alloc_size
= blob
->length
,
1653 .fixed_buf_size
= true
1656 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1658 if (ndr
.offset
!= blob
->length
) {
1659 return ndr_push_error(&ndr
, NDR_ERR_BUFSIZE
,
1660 "buffer was either too large or small "
1661 "ofs[%"PRIu32
"] size[%zu]",
1662 ndr
.offset
, blob
->length
);
1665 return NDR_ERR_SUCCESS
;
1669 push a union to a blob using NDR
1671 _PUBLIC_
enum ndr_err_code
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1672 uint32_t level
, ndr_push_flags_fn_t fn
)
1674 struct ndr_push
*ndr
;
1675 ndr
= ndr_push_init_ctx(mem_ctx
);
1676 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1678 NDR_CHECK_FREE(ndr_push_set_switch_value(ndr
, p
, level
));
1679 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1681 *blob
= ndr_push_blob(ndr
);
1682 talloc_steal(mem_ctx
, blob
->data
);
1685 return NDR_ERR_SUCCESS
;
1689 generic ndr_size_*() handler for structures
1691 _PUBLIC_
size_t ndr_size_struct(const void *p
, libndr_flags flags
, ndr_push_flags_fn_t push
)
1693 struct ndr_push
*ndr
;
1694 enum ndr_err_code status
;
1697 /* avoid recursion */
1698 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1700 /* Avoid following a NULL pointer */
1705 ndr
= ndr_push_init_ctx(NULL
);
1707 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1708 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
1709 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1719 generic ndr_size_*() handler for unions
1721 _PUBLIC_
size_t ndr_size_union(const void *p
, libndr_flags flags
, uint32_t level
, ndr_push_flags_fn_t push
)
1723 struct ndr_push
*ndr
;
1724 enum ndr_err_code status
;
1727 /* avoid recursion */
1728 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1730 /* Avoid following a NULL pointer */
1735 ndr
= ndr_push_init_ctx(NULL
);
1737 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1739 status
= ndr_push_set_switch_value(ndr
, p
, level
);
1740 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1744 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
1745 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1755 get the current base for relative pointers for the push
1757 _PUBLIC_
uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
1759 return ndr
->relative_base_offset
;
1763 restore the old base for relative pointers for the push
1765 _PUBLIC_
void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
1767 ndr
->relative_base_offset
= offset
;
1771 setup the current base for relative pointers for the push
1772 called in the NDR_SCALAR stage
1774 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
1776 enum ndr_err_code ret
;
1777 ndr
->relative_base_offset
= offset
;
1778 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1779 if (ret
== NDR_ERR_RANGE
) {
1780 return ndr_push_error(ndr
, ret
,
1781 "More than %d NDR tokens stored for relative_base_list",
1782 NDR_TOKEN_MAX_LIST_SIZE
);
1788 setup the current base for relative pointers for the push
1789 called in the NDR_BUFFERS stage
1791 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
1793 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1797 push a relative object - stage1
1798 this is called during SCALARS processing
1800 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1802 enum ndr_err_code ret
;
1804 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1805 return NDR_ERR_SUCCESS
;
1807 NDR_CHECK(ndr_push_align(ndr
, 4));
1808 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1809 if (ret
== NDR_ERR_RANGE
) {
1810 return ndr_push_error(ndr
, ret
,
1811 "More than %d NDR tokens stored for relative_list",
1812 NDR_TOKEN_MAX_LIST_SIZE
);
1815 return ndr_push_uint32(ndr
, NDR_SCALARS
, UINT32_MAX
);
1819 push a short relative object - stage1
1820 this is called during SCALARS processing
1822 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1824 enum ndr_err_code ret
;
1826 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 0));
1827 return NDR_ERR_SUCCESS
;
1829 NDR_CHECK(ndr_push_align(ndr
, 2));
1830 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1831 if (ret
== NDR_ERR_RANGE
) {
1832 return ndr_push_error(ndr
, ret
,
1833 "More than %d NDR tokens stored for relative_list",
1834 NDR_TOKEN_MAX_LIST_SIZE
);
1837 return ndr_push_uint16(ndr
, NDR_SCALARS
, 0xFFFF);
1840 push a relative object - stage2
1841 this is called during buffers processing
1843 static enum ndr_err_code
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1845 uint32_t save_offset
;
1846 uint32_t ptr_offset
= 0xFFFFFFFF;
1848 return NDR_ERR_SUCCESS
;
1850 if (ndr
->offset
< ndr
->relative_base_offset
) {
1851 return ndr_push_error(
1854 "ndr_push_relative_ptr2 ndr->offset(%" PRIu32
") "
1855 "< ndr->relative_base_offset(%" PRIu32
")",
1857 ndr
->relative_base_offset
);
1859 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1860 if (ptr_offset
> ndr
->offset
) {
1861 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1862 "ndr_push_relative_ptr2 ptr_offset(%"PRIu32
") > ndr->offset(%"PRIu32
")",
1863 ptr_offset
, ndr
->offset
);
1865 save_offset
= ndr
->offset
;
1866 ndr
->offset
= ptr_offset
;
1867 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1868 ndr
->offset
= save_offset
;
1869 return NDR_ERR_SUCCESS
;
1872 push a short relative object - stage2
1873 this is called during buffers processing
1875 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1877 uint32_t save_offset
;
1878 uint32_t ptr_offset
= 0xFFFF;
1879 uint32_t relative_offset
;
1884 return NDR_ERR_SUCCESS
;
1887 if (ndr
->offset
< ndr
->relative_base_offset
) {
1888 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1889 "ndr_push_relative_ptr2 ndr->offset(%"PRIu32
") < ndr->relative_base_offset(%"PRIu32
")",
1890 ndr
->offset
, ndr
->relative_base_offset
);
1893 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1895 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1897 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1899 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1901 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1905 pad
= ndr_align_size(relative_offset
, align
);
1907 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1910 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1911 if (relative_offset
> UINT16_MAX
) {
1912 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1913 "ndr_push_relative_ptr2 relative_offset(%"PRIu32
") > UINT16_MAX",
1917 save_offset
= ndr
->offset
;
1918 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1919 if (ptr_offset
> ndr
->offset
) {
1920 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1921 "ndr_push_short_relative_ptr2 ptr_offset(%"PRIu32
") > ndr->offset(%"PRIu32
")",
1922 ptr_offset
, ndr
->offset
);
1924 ndr
->offset
= ptr_offset
;
1925 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, relative_offset
));
1926 ndr
->offset
= save_offset
;
1927 return NDR_ERR_SUCCESS
;
1931 push a relative object - stage2 start
1932 this is called during buffers processing
1934 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_start(struct ndr_push
*ndr
, const void *p
)
1936 enum ndr_err_code ret
;
1938 return NDR_ERR_SUCCESS
;
1940 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1941 uint32_t relative_offset
;
1945 if (ndr
->offset
< ndr
->relative_base_offset
) {
1946 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1947 "ndr_push_relative_ptr2_start ndr->offset(%"PRIu32
") < ndr->relative_base_offset(%"PRIu32
")",
1948 ndr
->offset
, ndr
->relative_base_offset
);
1951 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1953 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1955 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1957 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1959 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1963 pad
= ndr_align_size(relative_offset
, align
);
1965 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1968 return ndr_push_relative_ptr2(ndr
, p
);
1970 if (ndr
->relative_end_offset
== -1) {
1971 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1972 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %"PRIu32
,
1973 ndr
->relative_end_offset
);
1975 ret
= ndr_token_store(ndr
,
1976 &ndr
->relative_begin_list
,
1979 if (ret
== NDR_ERR_RANGE
) {
1980 return ndr_push_error(ndr
, ret
,
1981 "More than %d NDR tokens stored for array_size",
1982 NDR_TOKEN_MAX_LIST_SIZE
);
1988 push a relative object - stage2 end
1989 this is called during buffers processing
1991 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_end(struct ndr_push
*ndr
, const void *p
)
1993 uint32_t begin_offset
= 0xFFFFFFFF;
1995 uint32_t correct_offset
= 0;
2000 return NDR_ERR_SUCCESS
;
2003 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
2004 return NDR_ERR_SUCCESS
;
2007 if (ndr
->flags
& LIBNDR_FLAG_NO_NDR_SIZE
) {
2008 /* better say more than calculation a too small buffer */
2009 NDR_PUSH_ALIGN(ndr
, 8);
2010 return NDR_ERR_SUCCESS
;
2013 if (ndr
->relative_end_offset
< ndr
->offset
) {
2014 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
2015 "ndr_push_relative_ptr2_end:"
2016 "relative_end_offset %"PRIu32
" < offset %"PRIu32
,
2017 ndr
->relative_end_offset
, ndr
->offset
);
2020 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_begin_list
, p
, &begin_offset
));
2022 /* we have marshalled a buffer, see how long it was */
2023 len
= ndr
->offset
- begin_offset
;
2026 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
2027 "ndr_push_relative_ptr2_end:"
2028 "offset %"PRIu32
" - begin_offset %"PRIu32
" < 0",
2029 ndr
->offset
, begin_offset
);
2032 if (ndr
->relative_end_offset
< len
) {
2033 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
2034 "ndr_push_relative_ptr2_end:"
2035 "relative_end_offset %"PRIu32
" < len %zd",
2039 /* the reversed offset is at the end of the main buffer */
2040 correct_offset
= ndr
->relative_end_offset
- len
;
2042 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
2044 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
2046 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
2048 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
2052 pad
= ndr_align_size(correct_offset
, align
);
2054 correct_offset
+= pad
;
2055 correct_offset
-= align
;
2058 if (correct_offset
< begin_offset
) {
2059 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
2060 "ndr_push_relative_ptr2_end: "
2061 "correct_offset %"PRIu32
" < begin_offset %"PRIu32
,
2062 correct_offset
, begin_offset
);
2066 uint32_t clear_size
= correct_offset
- begin_offset
;
2068 clear_size
= MIN(clear_size
, len
);
2070 /* now move the marshalled buffer to the end of the main buffer */
2071 memmove(ndr
->data
+ correct_offset
, ndr
->data
+ begin_offset
, len
);
2074 /* and wipe out old buffer within the main buffer */
2075 memset(ndr
->data
+ begin_offset
, '\0', clear_size
);
2079 /* and set the end offset for the next buffer */
2080 ndr
->relative_end_offset
= correct_offset
;
2082 /* finally write the offset to the main buffer */
2083 ndr
->offset
= correct_offset
;
2084 NDR_CHECK(ndr_push_relative_ptr2(ndr
, p
));
2086 /* restore to where we were in the main buffer */
2087 ndr
->offset
= begin_offset
;
2089 return NDR_ERR_SUCCESS
;
2093 get the current base for relative pointers for the pull
2095 _PUBLIC_
uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
2097 return ndr
->relative_base_offset
;
2101 restore the old base for relative pointers for the pull
2103 _PUBLIC_
void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
2105 ndr
->relative_base_offset
= offset
;
2109 setup the current base for relative pointers for the pull
2110 called in the NDR_SCALAR stage
2112 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
2114 enum ndr_err_code ret
;
2115 ndr
->relative_base_offset
= offset
;
2116 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
2117 if (ret
== NDR_ERR_RANGE
) {
2118 return ndr_pull_error(ndr
, ret
,
2119 "More than %d NDR tokens stored for relative_base_list",
2120 NDR_TOKEN_MAX_LIST_SIZE
);
2126 setup the current base for relative pointers for the pull
2127 called in the NDR_BUFFERS stage
2129 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
2131 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
2135 pull a relative object - stage1
2136 called during SCALARS processing
2138 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
2140 enum ndr_err_code ret
;
2141 rel_offset
+= ndr
->relative_base_offset
;
2142 if (rel_offset
< ndr
->relative_base_offset
) {
2143 return ndr_pull_error(ndr
,
2144 NDR_ERR_INVALID_POINTER
,
2145 "Overflow rel_offset=%" PRIu32
" + "
2146 "relative_base_offset=%" PRIu32
,
2148 ndr
->relative_base_offset
);
2150 if (rel_offset
> ndr
->data_size
) {
2151 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
2152 "ndr_pull_relative_ptr1 rel_offset(%"PRIu32
") > ndr->data_size(%"PRIu32
")",
2153 rel_offset
, ndr
->data_size
);
2155 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
2156 if (ret
== NDR_ERR_RANGE
) {
2157 return ndr_pull_error(ndr
, ret
,
2158 "More than %d NDR tokens stored for relative_list",
2159 NDR_TOKEN_MAX_LIST_SIZE
);
2165 pull a relative object - stage2
2166 called during BUFFERS processing
2168 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
2170 uint32_t rel_offset
;
2171 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
2172 return ndr_pull_set_offset(ndr
, rel_offset
);
2175 _PUBLIC_
const char *ndr_map_error2string(enum ndr_err_code ndr_err
)
2177 const char *ret
= "Unknown error";
2180 case NDR_ERR_SUCCESS
:
2183 case NDR_ERR_ARRAY_SIZE
:
2184 ret
= "Bad Array Size";
2186 case NDR_ERR_BAD_SWITCH
:
2189 case NDR_ERR_OFFSET
:
2190 ret
= "Offset Error";
2192 case NDR_ERR_RELATIVE
:
2193 ret
= "Relative Pointer Error";
2195 case NDR_ERR_CHARCNV
:
2196 ret
= "Character Conversion Error";
2198 case NDR_ERR_LENGTH
:
2199 ret
= "Length Error";
2201 case NDR_ERR_SUBCONTEXT
:
2202 ret
= "Subcontext Error";
2204 case NDR_ERR_COMPRESSION
:
2205 ret
= "Compression Error";
2207 case NDR_ERR_STRING
:
2208 ret
= "String Error";
2210 case NDR_ERR_VALIDATE
:
2211 ret
= "Validate Error";
2213 case NDR_ERR_BUFSIZE
:
2214 ret
= "Buffer Size Error";
2217 ret
= "Allocation Error";
2220 ret
= "Range Error";
2223 ret
= "Token Error";
2225 case NDR_ERR_IPV4ADDRESS
:
2226 ret
= "IPv4 Address Error";
2228 case NDR_ERR_INVALID_POINTER
:
2229 ret
= "Invalid Pointer";
2231 case NDR_ERR_UNREAD_BYTES
:
2232 ret
= "Unread Bytes";
2235 ret
= "NDR64 assertion error";
2237 case NDR_ERR_INCOMPLETE_BUFFER
:
2238 ret
= "Incomplete Buffer";
2240 case NDR_ERR_MAX_RECURSION_EXCEEDED
:
2241 ret
= "Maximum Recursion Exceeded";
2243 case NDR_ERR_UNDERFLOW
:
2246 case NDR_ERR_IPV6ADDRESS
:
2247 ret
= "Invalid IPv6 address";
2250 ret
= "Invalid NDR flags";