LCOV - code coverage report
Current view: top level - librpc/ndr - ndr.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 557 817 68.2 %
Date: 2024-06-13 04:01:37 Functions: 67 76 88.2 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    libndr interface
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             :    Copyright (C) Jelmer Vernooij 2005-2008
       8             : 
       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.
      13             : 
      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.
      18             : 
      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/>.
      21             : */
      22             : 
      23             : /*
      24             :   this provides the core routines for NDR parsing functions
      25             : 
      26             :   see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
      27             :   of NDR encoding rules
      28             : */
      29             : 
      30             : #include "includes.h"
      31             : #include "librpc/ndr/libndr.h"
      32             : #include "librpc/ndr/ndr_private.h"
      33             : #include "../lib/util/dlinklist.h"
      34             : 
      35             : #undef DBGC_CLASS
      36             : #define DBGC_CLASS DBGC_RPC_PARSE
      37             : 
      38             : #define NDR_BASE_MARSHALL_SIZE 1024
      39             : 
      40             : /*
      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
      43             :  * malicious packet.
      44             :  *
      45             :  * In an ideal world this would be controlled by range() restrictions
      46             :  * on array sizes and careful IDL construction to avoid arbitary
      47             :  * linked lists, but this is a backstop for now.
      48             :  */
      49             : #define NDR_TOKEN_MAX_LIST_SIZE 65535
      50             : 
      51           0 : size_t ndr_token_max_list_size(void) {
      52           0 :         return NDR_TOKEN_MAX_LIST_SIZE;
      53             : };
      54             : 
      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} },
      58             :   2
      59             : };
      60             : 
      61             : const struct ndr_syntax_id ndr_transfer_syntax_ndr64 = {
      62             :   { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
      63             :   1
      64             : };
      65             : 
      66             : const struct ndr_syntax_id ndr_syntax_id_null = {
      67             :   { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
      68             :   0
      69             : };
      70             : 
      71             : /*
      72             :   work out the number of bytes needed to align on a n byte boundary
      73             : */
      74    14386554 : _PUBLIC_ size_t ndr_align_size(uint32_t offset, size_t n)
      75             : {
      76    14386554 :         if ((offset & (n-1)) == 0) return 0;
      77      295108 :         return n - (offset & (n-1));
      78             : }
      79             : 
      80             : /*
      81             :   initialise a ndr parse structure from a data blob
      82             : */
      83    30376730 : _PUBLIC_ struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
      84             : {
      85             :         struct ndr_pull *ndr;
      86             : 
      87    30376730 :         ndr = talloc_zero(mem_ctx, struct ndr_pull);
      88    30376730 :         if (!ndr) return NULL;
      89    30376730 :         ndr->current_mem_ctx = mem_ctx;
      90             : 
      91    30376730 :         ndr->data = blob->data;
      92    30376730 :         ndr->data_size = blob->length;
      93             : 
      94    30376730 :         return ndr;
      95             : }
      96             : 
      97           0 : _PUBLIC_ enum ndr_err_code ndr_pull_append(struct ndr_pull *ndr, DATA_BLOB *blob)
      98             : {
      99             :         enum ndr_err_code ndr_err;
     100             :         DATA_BLOB b;
     101           0 :         uint32_t append = 0;
     102             :         bool ok;
     103             : 
     104           0 :         if (blob->length == 0) {
     105           0 :                 return NDR_ERR_SUCCESS;
     106             :         }
     107             : 
     108           0 :         ndr_err = ndr_token_retrieve(&ndr->array_size_list, ndr, &append);
     109           0 :         if (ndr_err == NDR_ERR_TOKEN) {
     110           0 :                 append = 0;
     111           0 :                 ndr_err = NDR_ERR_SUCCESS;
     112             :         }
     113           0 :         NDR_CHECK(ndr_err);
     114             : 
     115           0 :         if (ndr->data_size == 0) {
     116           0 :                 ndr->data = NULL;
     117           0 :                 append = UINT32_MAX;
     118             :         }
     119             : 
     120           0 :         if (append == UINT32_MAX) {
     121             :                 /*
     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
     127             :                  */
     128           0 :                 b = data_blob_const(ndr->data, ndr->data_size);
     129             :         } else {
     130           0 :                 b = data_blob_talloc(ndr, ndr->data, ndr->data_size);
     131           0 :                 if (b.data == NULL) {
     132           0 :                         return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
     133             :                 }
     134             :         }
     135             : 
     136           0 :         ok = data_blob_append(ndr, &b, blob->data, blob->length);
     137           0 :         if (!ok) {
     138           0 :                 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
     139             :         }
     140             : 
     141           0 :         ndr->data = b.data;
     142           0 :         ndr->data_size = b.length;
     143             : 
     144           0 :         return ndr_token_store(ndr, &ndr->array_size_list, ndr, UINT32_MAX);
     145             : }
     146             : 
     147           0 : _PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr)
     148             : {
     149           0 :         uint32_t skip = 0;
     150           0 :         uint32_t append = 0;
     151             :         enum ndr_err_code ndr_err;
     152             : 
     153           0 :         if (ndr->relative_base_offset != 0) {
     154           0 :                 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
     155             :                                       "%s", __location__);
     156             :         }
     157           0 :         if (ndr->relative_highest_offset != 0) {
     158           0 :                 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
     159             :                                       "%s", __location__);
     160             :         }
     161           0 :         if (ndr->relative_list.count != 0) {
     162           0 :                 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
     163             :                                       "%s", __location__);
     164             :         }
     165           0 :         if (ndr->relative_base_list.count != 0) {
     166           0 :                 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
     167             :                                       "%s", __location__);
     168             :         }
     169             : 
     170             :         /*
     171             :          * we need to keep up to 7 bytes
     172             :          * in order to get the aligment right.
     173             :          */
     174           0 :         skip = ndr->offset & 0xFFFFFFF8;
     175             : 
     176           0 :         if (skip == 0) {
     177           0 :                 return NDR_ERR_SUCCESS;
     178             :         }
     179             : 
     180           0 :         ndr->offset -= skip;
     181           0 :         ndr->data_size -= skip;
     182             : 
     183           0 :         ndr_err = ndr_token_peek(&ndr->array_size_list, ndr, &append);
     184           0 :         if (ndr_err == NDR_ERR_TOKEN) {
     185             :                 /*
     186             :                  * here we assume, that ndr->data is not a
     187             :                  * talloc child of ndr.
     188             :                  */
     189           0 :                 ndr->data += skip;
     190           0 :                 return NDR_ERR_SUCCESS;
     191             :         }
     192             : 
     193           0 :         memmove(ndr->data, ndr->data + skip, ndr->data_size);
     194             : 
     195           0 :         ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->data_size);
     196           0 :         if (ndr->data_size != 0 && ndr->data == NULL) {
     197           0 :                 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
     198             :         }
     199             : 
     200           0 :         return NDR_ERR_SUCCESS;
     201             : }
     202             : 
     203             : /*
     204             :   advance by 'size' bytes
     205             : */
     206    21289498 : _PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
     207             : {
     208    21289498 :         NDR_PULL_NEED_BYTES(ndr, size);
     209    21289498 :         ndr->offset += size;
     210    21289498 :         return NDR_ERR_SUCCESS;
     211             : }
     212             : 
     213             : /*
     214             :   set the parse offset to 'ofs'
     215             : */
     216    31332173 : static enum ndr_err_code ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
     217             : {
     218    31332173 :         ndr->offset = ofs;
     219    31332173 :         if (ndr->offset > ndr->data_size) {
     220           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
     221             :                                       "ndr_pull_set_offset %u failed",
     222             :                                       ofs);
     223             :         }
     224    31332173 :         return NDR_ERR_SUCCESS;
     225             : }
     226             : 
     227             : /* create a ndr_push structure, ready for some marshalling */
     228    33092926 : _PUBLIC_ struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
     229             : {
     230             :         struct ndr_push *ndr;
     231             : 
     232    33092926 :         ndr = talloc_zero(mem_ctx, struct ndr_push);
     233    33092926 :         if (!ndr) {
     234           0 :                 return NULL;
     235             :         }
     236             : 
     237    33092926 :         ndr->flags = 0;
     238    33092926 :         ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
     239    33092926 :         ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
     240    33092926 :         if (!ndr->data) {
     241           0 :                 talloc_free(ndr);
     242           0 :                 return NULL;
     243             :         }
     244             : 
     245    33092926 :         return ndr;
     246             : }
     247             : 
     248             : /* return a DATA_BLOB structure for the current ndr_push marshalled data */
     249    25067959 : _PUBLIC_ DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
     250             : {
     251             :         DATA_BLOB blob;
     252    25067959 :         blob = data_blob_const(ndr->data, ndr->offset);
     253    25067959 :         if (ndr->alloc_size > ndr->offset) {
     254    25067959 :                 ndr->data[ndr->offset] = 0;
     255             :         }
     256    25067959 :         return blob;
     257             : }
     258             : 
     259             : 
     260             : /*
     261             :   expand the available space in the buffer to ndr->offset + extra_size
     262             : */
     263  3142642355 : _PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
     264             : {
     265  3142642355 :         uint32_t size = extra_size + ndr->offset;
     266             : 
     267  3142642355 :         if (size < ndr->offset) {
     268             :                 /* extra_size overflowed the offset */
     269           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %u",
     270             :                                       size);
     271             :         }
     272             : 
     273  3142642355 :         if (ndr->fixed_buf_size) {
     274   459566978 :                 if (ndr->alloc_size >= size) {
     275   459566978 :                         return NDR_ERR_SUCCESS;
     276             :                 }
     277           0 :                 return ndr_push_error(ndr,
     278             :                                       NDR_ERR_BUFSIZE,
     279             :                                       "Overflow of fixed buffer in "
     280             :                                       "push_expand to %u",
     281             :                                       size);
     282             :         }
     283             : 
     284  2683075377 :         if (ndr->alloc_size > size) {
     285  2668944841 :                 return NDR_ERR_SUCCESS;
     286             :         }
     287             : 
     288    14130536 :         ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
     289    14130536 :         if (size+1 > ndr->alloc_size) {
     290     1442353 :                 ndr->alloc_size = size+1;
     291             :         }
     292    14130536 :         ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
     293    14130536 :         if (!ndr->data) {
     294           0 :                 return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u",
     295             :                                       ndr->alloc_size);
     296             :         }
     297             : 
     298    14130536 :         return NDR_ERR_SUCCESS;
     299             : }
     300             : 
     301           0 : _PUBLIC_ void ndr_print_debugc_helper(struct ndr_print *ndr, const char *format, ...)
     302             : {
     303             :         va_list ap;
     304           0 :         char *s = NULL;
     305             :         uint32_t i;
     306             :         int ret;
     307             :         int dbgc_class;
     308             : 
     309           0 :         va_start(ap, format);
     310           0 :         ret = vasprintf(&s, format, ap);
     311           0 :         va_end(ap);
     312             : 
     313           0 :         if (ret == -1) {
     314           0 :                 return;
     315             :         }
     316             : 
     317           0 :         dbgc_class = *(int *)ndr->private_data;
     318             : 
     319           0 :         if (ndr->no_newline) {
     320           0 :                 DEBUGADDC(dbgc_class, 1,("%s", s));
     321           0 :                 free(s);
     322           0 :                 return;
     323             :         }
     324             : 
     325           0 :         for (i=0;i<ndr->depth;i++) {
     326           0 :                 DEBUGADDC(dbgc_class, 1,("    "));
     327             :         }
     328             : 
     329           0 :         DEBUGADDC(dbgc_class, 1,("%s\n", s));
     330           0 :         free(s);
     331             : }
     332             : 
     333       14790 : _PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...)
     334             : {
     335             :         va_list ap;
     336       14790 :         char *s = NULL;
     337             :         uint32_t i;
     338             :         int ret;
     339             : 
     340       14790 :         va_start(ap, format);
     341       14790 :         ret = vasprintf(&s, format, ap);
     342       14790 :         va_end(ap);
     343             : 
     344       14790 :         if (ret == -1) {
     345           0 :                 return;
     346             :         }
     347             : 
     348       14790 :         if (ndr->no_newline) {
     349           0 :                 DEBUGADD(1,("%s", s));
     350           0 :                 free(s);
     351           0 :                 return;
     352             :         }
     353             : 
     354       75826 :         for (i=0;i<ndr->depth;i++) {
     355       61036 :                 DEBUGADD(1,("    "));
     356             :         }
     357             : 
     358       14790 :         DEBUGADD(1,("%s\n", s));
     359       14790 :         free(s);
     360             : }
     361             : 
     362         440 : _PUBLIC_ void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...)
     363             : {
     364             :         va_list ap;
     365             :         uint32_t i;
     366             : 
     367         440 :         if (!ndr->no_newline) {
     368        2172 :                 for (i=0;i<ndr->depth;i++) {
     369        1732 :                         printf("    ");
     370             :                 }
     371             :         }
     372             : 
     373         440 :         va_start(ap, format);
     374         440 :         vprintf(format, ap);
     375         440 :         va_end(ap);
     376         440 :         if (!ndr->no_newline) {
     377         440 :                 printf("\n");
     378             :         }
     379         440 : }
     380             : 
     381    36922589 : _PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...)
     382             : {
     383             :         va_list ap;
     384             :         uint32_t i;
     385             : 
     386    36922589 :         if (!ndr->no_newline) {
     387    60211582 :                 for (i=0;i<ndr->depth;i++) {
     388    55143649 :                         ndr->private_data = talloc_asprintf_append_buffer(
     389    55143649 :                                 (char *)ndr->private_data, "    ");
     390             :                 }
     391             :         }
     392             : 
     393    36922589 :         va_start(ap, format);
     394    36922589 :         ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data,
     395             :                                                     format, ap);
     396    36922589 :         va_end(ap);
     397    36922589 :         if (!ndr->no_newline) {
     398     5067933 :                 ndr->private_data = talloc_asprintf_append_buffer((char *)ndr->private_data,
     399             :                                                                   "\n");
     400             :         }
     401    36922589 : }
     402             : 
     403             : /*
     404             :   a useful helper function for printing idl structures via DEBUGC()
     405             : */
     406           0 : _PUBLIC_ void ndr_print_debugc(int dbgc_class, ndr_print_fn_t fn, const char *name, void *ptr)
     407             : {
     408             :         struct ndr_print *ndr;
     409             : 
     410           0 :         DEBUGC(dbgc_class, 1,(" "));
     411             : 
     412           0 :         ndr = talloc_zero(NULL, struct ndr_print);
     413           0 :         if (!ndr) return;
     414           0 :         ndr->private_data = &dbgc_class;
     415           0 :         ndr->print = ndr_print_debugc_helper;
     416           0 :         ndr->depth = 1;
     417           0 :         ndr->flags = 0;
     418             : #ifdef DEBUG_PASSWORD
     419           0 :         if (CHECK_DEBUGLVL(100)) {
     420           0 :                 ndr->print_secrets = true;
     421             :         }
     422             : #endif
     423             : 
     424           0 :         fn(ndr, name, ptr);
     425           0 :         talloc_free(ndr);
     426             : }
     427             : 
     428             : /*
     429             :   a useful helper function for printing idl structures via DEBUG()
     430             : */
     431         321 : _PUBLIC_ bool ndr_print_debug(int level,
     432             :                               ndr_print_fn_t fn,
     433             :                               const char *name,
     434             :                               void *ptr,
     435             :                               const char *location,
     436             :                               const char *function)
     437             : {
     438             :         struct ndr_print *ndr;
     439             : 
     440         321 :         DEBUGLF(level, (" "), location, function);
     441             : 
     442         321 :         ndr = talloc_zero(NULL, struct ndr_print);
     443         321 :         if (!ndr) return false;
     444         321 :         ndr->print = ndr_print_debug_helper;
     445         321 :         ndr->depth = 1;
     446         321 :         ndr->flags = 0;
     447             : #ifdef DEBUG_PASSWORD
     448         321 :         if (CHECK_DEBUGLVL(100)) {
     449           0 :                 ndr->print_secrets = true;
     450             :         }
     451             : #endif
     452             : 
     453         321 :         fn(ndr, name, ptr);
     454         321 :         talloc_free(ndr);
     455         321 :         return true;
     456             : }
     457             : 
     458             : /*
     459             :   a useful helper function for printing idl unions via DEBUG()
     460             : */
     461           0 : _PUBLIC_ void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
     462             : {
     463             :         struct ndr_print *ndr;
     464             : 
     465           0 :         DEBUG(1,(" "));
     466             : 
     467           0 :         ndr = talloc_zero(NULL, struct ndr_print);
     468           0 :         if (!ndr) return;
     469           0 :         ndr->print = ndr_print_debug_helper;
     470           0 :         ndr->depth = 1;
     471           0 :         ndr->flags = 0;
     472             : #ifdef DEBUG_PASSWORD
     473           0 :         if (CHECK_DEBUGLVL(100)) {
     474           0 :                 ndr->print_secrets = true;
     475             :         }
     476             : #endif
     477             : 
     478           0 :         ndr_print_set_switch_value(ndr, ptr, level);
     479           0 :         fn(ndr, name, ptr);
     480           0 :         talloc_free(ndr);
     481             : }
     482             : 
     483             : /*
     484             :   a useful helper function for printing idl function calls via DEBUG()
     485             : */
     486          24 : _PUBLIC_ void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
     487             : {
     488             :         struct ndr_print *ndr;
     489             : 
     490          24 :         DEBUG(1,(" "));
     491             : 
     492          24 :         ndr = talloc_zero(NULL, struct ndr_print);
     493          24 :         if (!ndr) return;
     494          24 :         ndr->print = ndr_print_debug_helper;
     495          24 :         ndr->depth = 1;
     496          24 :         ndr->flags = 0;
     497             : #ifdef DEBUG_PASSWORD
     498          24 :         if (CHECK_DEBUGLVL(100)) {
     499           0 :                 ndr->print_secrets = true;
     500             :         }
     501             : #endif
     502             : 
     503          24 :         fn(ndr, name, flags, ptr);
     504          24 :         talloc_free(ndr);
     505             : }
     506             : 
     507             : /*
     508             :   a useful helper function for printing idl structures to a string
     509             : */
     510         415 : _PUBLIC_ char *ndr_print_struct_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, void *ptr)
     511             : {
     512             :         struct ndr_print *ndr;
     513         415 :         char *ret = NULL;
     514             : 
     515         415 :         ndr = talloc_zero(mem_ctx, struct ndr_print);
     516         415 :         if (!ndr) return NULL;
     517         415 :         ndr->private_data = talloc_strdup(ndr, "");
     518         415 :         if (!ndr->private_data) {
     519           0 :                 goto failed;
     520             :         }
     521         415 :         ndr->print = ndr_print_string_helper;
     522         415 :         ndr->depth = 1;
     523         415 :         ndr->flags = 0;
     524             : 
     525         415 :         fn(ndr, name, ptr);
     526         415 :         ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
     527         415 : failed:
     528         415 :         talloc_free(ndr);
     529         415 :         return ret;
     530             : }
     531             : 
     532             : /*
     533             :   a useful helper function for printing idl unions to a string
     534             : */
     535           0 : _PUBLIC_ char *ndr_print_union_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
     536             : {
     537             :         struct ndr_print *ndr;
     538           0 :         char *ret = NULL;
     539             : 
     540           0 :         ndr = talloc_zero(mem_ctx, struct ndr_print);
     541           0 :         if (!ndr) return NULL;
     542           0 :         ndr->private_data = talloc_strdup(ndr, "");
     543           0 :         if (!ndr->private_data) {
     544           0 :                 goto failed;
     545             :         }
     546           0 :         ndr->print = ndr_print_string_helper;
     547           0 :         ndr->depth = 1;
     548           0 :         ndr->flags = 0;
     549           0 :         ndr_print_set_switch_value(ndr, ptr, level);
     550           0 :         fn(ndr, name, ptr);
     551           0 :         ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
     552           0 : failed:
     553           0 :         talloc_free(ndr);
     554           0 :         return ret;
     555             : }
     556             : 
     557             : /*
     558             :   a useful helper function for printing idl function calls to a string
     559             : */
     560       27710 : _PUBLIC_ char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
     561             :                                 ndr_print_function_t fn, const char *name,
     562             :                                 int flags, void *ptr)
     563             : {
     564             :         struct ndr_print *ndr;
     565       27710 :         char *ret = NULL;
     566             : 
     567       27710 :         ndr = talloc_zero(mem_ctx, struct ndr_print);
     568       27710 :         if (!ndr) return NULL;
     569       27710 :         ndr->private_data = talloc_strdup(ndr, "");
     570       27710 :         if (!ndr->private_data) {
     571           0 :                 goto failed;
     572             :         }
     573       27710 :         ndr->print = ndr_print_string_helper;
     574       27710 :         ndr->depth = 1;
     575       27710 :         ndr->flags = 0;
     576       27710 :         fn(ndr, name, flags, ptr);
     577       27710 :         ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
     578       27710 : failed:
     579       27710 :         talloc_free(ndr);
     580       27710 :         return ret;
     581             : }
     582             : 
     583   213572458 : _PUBLIC_ void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
     584             : {
     585             :         /* the big/little endian flags are inter-dependent */
     586   213572458 :         if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
     587    12067475 :                 (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
     588    12067475 :                 (*pflags) &= ~LIBNDR_FLAG_NDR64;
     589             :         }
     590   213572458 :         if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
     591     1893995 :                 (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
     592     1893995 :                 (*pflags) &= ~LIBNDR_FLAG_NDR64;
     593             :         }
     594   213572458 :         if (new_flags & LIBNDR_ALIGN_FLAGS) {
     595             :                 /* Ensure we only have the passed-in
     596             :                    align flag set in the new_flags,
     597             :                    remove any old align flag. */
     598    22159139 :                 (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
     599             :         }
     600   213572458 :         if (new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE) {
     601           0 :                 (*pflags) &= ~LIBNDR_FLAG_RELATIVE_REVERSE;
     602             :         }
     603   213572458 :         (*pflags) |= new_flags;
     604   213572458 : }
     605             : 
     606             : /*
     607             :   return and possibly log an NDR error
     608             : */
     609         452 : _PUBLIC_ enum ndr_err_code _ndr_pull_error(struct ndr_pull *ndr,
     610             :                                            enum ndr_err_code ndr_err,
     611             :                                            const char *function,
     612             :                                            const char *location,
     613             :                                            const char *format, ...)
     614             : {
     615         452 :         char *s=NULL;
     616             :         va_list ap;
     617             :         int ret;
     618             : 
     619         452 :         if (ndr->flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
     620           0 :                 switch (ndr_err) {
     621           0 :                 case NDR_ERR_BUFSIZE:
     622           0 :                         return NDR_ERR_INCOMPLETE_BUFFER;
     623           0 :                 default:
     624           0 :                         break;
     625             :                 }
     626         370 :         }
     627             : 
     628         452 :         va_start(ap, format);
     629         452 :         ret = vasprintf(&s, format, ap);
     630         452 :         va_end(ap);
     631             : 
     632         452 :         if (ret == -1) {
     633           0 :                 return NDR_ERR_ALLOC;
     634             :         }
     635             : 
     636         452 :         D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
     637             :                   function,
     638             :                   ndr_map_error2string(ndr_err),
     639             :                   s,
     640             :                   location);
     641             : 
     642         452 :         free(s);
     643             : 
     644         452 :         return ndr_err;
     645             : }
     646             : 
     647             : /*
     648             :   return and possibly log an NDR error
     649             : */
     650         162 : _PUBLIC_ enum ndr_err_code _ndr_push_error(struct ndr_push *ndr,
     651             :                                            enum ndr_err_code ndr_err,
     652             :                                            const char *function,
     653             :                                            const char *location,
     654             :                                            const char *format, ...)
     655             : {
     656         162 :         char *s=NULL;
     657             :         va_list ap;
     658             :         int ret;
     659             : 
     660         162 :         va_start(ap, format);
     661         162 :         ret = vasprintf(&s, format, ap);
     662         162 :         va_end(ap);
     663             : 
     664         162 :         if (ret == -1) {
     665           0 :                 return NDR_ERR_ALLOC;
     666             :         }
     667             : 
     668         162 :         D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
     669             :                   function,
     670             :                   ndr_map_error2string(ndr_err),
     671             :                   s,
     672             :                   location);
     673             : 
     674         162 :         free(s);
     675             : 
     676         162 :         return ndr_err;
     677             : }
     678             : 
     679             : /*
     680             :   handle subcontext buffers, which in midl land are user-marshalled, but
     681             :   we use magic in pidl to make them easier to cope with
     682             : */
     683     3264780 : _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
     684             :                                    struct ndr_pull **_subndr,
     685             :                                    size_t header_size,
     686             :                                    ssize_t size_is)
     687             : {
     688             :         struct ndr_pull *subndr;
     689             :         uint32_t r_content_size;
     690     3264780 :         bool force_le = false;
     691     3264780 :         bool force_be = false;
     692             : 
     693     3264780 :         switch (header_size) {
     694     2412233 :         case 0: {
     695     2412233 :                 uint32_t content_size = ndr->data_size - ndr->offset;
     696     2412233 :                 if (size_is >= 0) {
     697     2374284 :                         content_size = size_is;
     698             :                 }
     699     2412233 :                 r_content_size = content_size;
     700     2412233 :                 break;
     701             :         }
     702             : 
     703      676028 :         case 2: {
     704             :                 uint16_t content_size;
     705      676028 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
     706      676028 :                 if (size_is >= 0 && size_is != content_size) {
     707           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x)",
     708             :                                                 (int)size_is, (int)size_is,
     709             :                                                 (int)content_size,
     710             :                                                 (int)content_size);
     711             :                 }
     712      676028 :                 r_content_size = content_size;
     713      676028 :                 break;
     714             :         }
     715             : 
     716       80791 :         case 4: {
     717             :                 uint32_t content_size;
     718       80791 :                 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &content_size));
     719       80791 :                 if (size_is >= 0 && size_is != content_size) {
     720           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x)",
     721             :                                                 (int)size_is, (int)size_is,
     722             :                                                 (int)content_size,
     723             :                                                 (int)content_size);
     724             :                 }
     725       80791 :                 r_content_size = content_size;
     726       80791 :                 break;
     727             :         }
     728       95728 :         case 0xFFFFFC01: {
     729             :                 /*
     730             :                  * Common Type Header for the Serialization Stream
     731             :                  * See [MS-RPCE] 2.2.6 Type Serialization Version 1
     732             :                  */
     733             :                 uint8_t version;
     734             :                 uint8_t drep;
     735             :                 uint16_t hdrlen;
     736             :                 uint32_t filler;
     737             :                 uint32_t content_size;
     738             :                 uint32_t reserved;
     739             : 
     740             :                 /* version */
     741       95728 :                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version));
     742             : 
     743       95728 :                 if (version != 1) {
     744           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
     745             :                                               "Bad subcontext (PULL) Common Type Header version %d != 1",
     746             :                                               (int)version);
     747             :                 }
     748             : 
     749             :                 /*
     750             :                  * 0x10 little endian
     751             :                  * 0x00 big endian
     752             :                  */
     753       95728 :                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep));
     754       95728 :                 if (drep == 0x10) {
     755       95728 :                         force_le = true;
     756           0 :                 } else if (drep == 0x00) {
     757           0 :                         force_be = true;
     758             :                 } else {
     759           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
     760             :                                               "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
     761             :                                               (unsigned int)drep);
     762             :                 }
     763             : 
     764             :                 /* length of the "Private Header for Constructed Type" */
     765       95728 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen));
     766       95728 :                 if (hdrlen != 8) {
     767           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
     768             :                                               "Bad subcontext (PULL) Common Type Header length %d != 8",
     769             :                                               (int)hdrlen);
     770             :                 }
     771             : 
     772             :                 /* filler should be ignored */
     773       95728 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler));
     774             : 
     775             :                 /*
     776             :                  * Private Header for Constructed Type
     777             :                  */
     778             :                 /* length - will be updated latter */
     779       95728 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
     780       95728 :                 if (size_is >= 0 && size_is != content_size) {
     781           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
     782             :                                               (int)size_is, (int)content_size);
     783             :                 }
     784             :                 /* the content size must be a multiple of 8 */
     785       95728 :                 if ((content_size % 8) != 0) {
     786           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
     787             :                                               "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
     788             :                                               (int)size_is, (int)content_size);
     789             :                 }
     790       95728 :                 r_content_size = content_size;
     791             : 
     792             :                 /* reserved */
     793       95728 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved));
     794       95728 :                 break;
     795             :         }
     796           0 :         case 0xFFFFFFFF:
     797             :                 /*
     798             :                  * a shallow copy like subcontext
     799             :                  * useful for DCERPC pipe chunks.
     800             :                  */
     801           0 :                 subndr = talloc_zero(ndr, struct ndr_pull);
     802           0 :                 NDR_ERR_HAVE_NO_MEMORY(subndr);
     803             : 
     804           0 :                 subndr->flags                = ndr->flags;
     805           0 :                 subndr->current_mem_ctx      = ndr->current_mem_ctx;
     806           0 :                 subndr->data         = ndr->data;
     807           0 :                 subndr->offset               = ndr->offset;
     808           0 :                 subndr->data_size    = ndr->data_size;
     809             : 
     810           0 :                 *_subndr = subndr;
     811           0 :                 return NDR_ERR_SUCCESS;
     812             : 
     813           0 :         default:
     814           0 :                 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d",
     815             :                                       (int)header_size);
     816             :         }
     817             : 
     818     3264780 :         NDR_PULL_NEED_BYTES(ndr, r_content_size);
     819             : 
     820     3264778 :         subndr = talloc_zero(ndr, struct ndr_pull);
     821     3264778 :         NDR_ERR_HAVE_NO_MEMORY(subndr);
     822     3264778 :         subndr->flags                = ndr->flags & ~LIBNDR_FLAG_NDR64;
     823     3264778 :         subndr->current_mem_ctx      = ndr->current_mem_ctx;
     824             : 
     825     3264778 :         subndr->data = ndr->data + ndr->offset;
     826     3264778 :         subndr->offset = 0;
     827     3264778 :         subndr->data_size = r_content_size;
     828             : 
     829     3264778 :         if (force_le) {
     830       95728 :                 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
     831     3169050 :         } else if (force_be) {
     832           0 :                 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN);
     833             :         }
     834             : 
     835     3264778 :         *_subndr = subndr;
     836     3264778 :         return NDR_ERR_SUCCESS;
     837             : }
     838             : 
     839     3264776 : _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr,
     840             :                                  struct ndr_pull *subndr,
     841             :                                  size_t header_size,
     842             :                                  ssize_t size_is)
     843             : {
     844             :         uint32_t advance;
     845             :         uint32_t highest_ofs;
     846             : 
     847     3264776 :         if (header_size == 0xFFFFFFFF) {
     848           0 :                 advance = subndr->offset - ndr->offset;
     849     3264776 :         } else if (size_is >= 0) {
     850     2374808 :                 advance = size_is;
     851      889968 :         } else if (header_size > 0) {
     852      852021 :                 advance = subndr->data_size;
     853             :         } else {
     854       37947 :                 advance = subndr->offset;
     855             :         }
     856             : 
     857     3264776 :         if (subndr->offset > ndr->relative_highest_offset) {
     858     1823159 :                 highest_ofs = subndr->offset;
     859             :         } else {
     860     1441617 :                 highest_ofs = subndr->relative_highest_offset;
     861             :         }
     862     3264776 :         if (!(subndr->flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES)) {
     863             :                 /*
     864             :                  * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
     865             :                  */
     866     3101818 :                 highest_ofs = advance;
     867             :         }
     868     3264776 :         if (highest_ofs < advance) {
     869           0 :                 return ndr_pull_error(subndr, NDR_ERR_UNREAD_BYTES,
     870             :                                       "not all bytes consumed ofs[%u] advance[%u]",
     871             :                                       highest_ofs, advance);
     872             :         }
     873             : 
     874     3264776 :         NDR_CHECK(ndr_pull_advance(ndr, advance));
     875     3264776 :         return NDR_ERR_SUCCESS;
     876             : }
     877             : 
     878     1901809 : _PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
     879             :                                    struct ndr_push **_subndr,
     880             :                                    size_t header_size,
     881             :                                    ssize_t size_is)
     882             : {
     883             :         struct ndr_push *subndr;
     884             : 
     885     1901809 :         subndr = ndr_push_init_ctx(ndr);
     886     1901809 :         NDR_ERR_HAVE_NO_MEMORY(subndr);
     887     1901809 :         subndr->flags        = ndr->flags & ~LIBNDR_FLAG_NDR64;
     888             : 
     889     1901809 :         if (size_is > 0) {
     890      685930 :                 NDR_CHECK(ndr_push_zero(subndr, size_is));
     891      685930 :                 subndr->offset = 0;
     892      685930 :                 subndr->relative_end_offset = size_is;
     893             :         }
     894             : 
     895     1901809 :         *_subndr = subndr;
     896     1901809 :         return NDR_ERR_SUCCESS;
     897             : }
     898             : 
     899             : /*
     900             :   push a subcontext header
     901             : */
     902     1901769 : _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
     903             :                                  struct ndr_push *subndr,
     904             :                                  size_t header_size,
     905             :                                  ssize_t size_is)
     906             : {
     907             :         ssize_t padding_len;
     908             : 
     909     1901769 :         if (size_is >= 0) {
     910      723180 :                 padding_len = size_is - subndr->offset;
     911      723180 :                 if (padding_len < 0) {
     912           0 :                         return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
     913             :                                               (int)subndr->offset, (int)size_is);
     914             :                 }
     915      723180 :                 subndr->offset = size_is;
     916             :         }
     917             : 
     918     1901769 :         switch (header_size) {
     919      706930 :         case 0:
     920      706930 :                 break;
     921             : 
     922     1027912 :         case 2:
     923     1027912 :                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
     924     1027912 :                 break;
     925             : 
     926      110890 :         case 4:
     927      110890 :                 NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset));
     928      110890 :                 break;
     929             : 
     930       56037 :         case 0xFFFFFC01:
     931             :                 /*
     932             :                  * Common Type Header for the Serialization Stream
     933             :                  * See [MS-RPCE] 2.2.6 Type Serialization Version 1
     934             :                  */
     935       56037 :                 padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset;
     936       56037 :                 if (padding_len > 0) {
     937       41022 :                         NDR_CHECK(ndr_push_zero(subndr, padding_len));
     938             :                 }
     939             : 
     940             :                 /* version */
     941       56037 :                 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1));
     942             : 
     943             :                 /*
     944             :                  * 0x10 little endian
     945             :                  * 0x00 big endian
     946             :                  */
     947       56037 :                 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10));
     948             : 
     949             :                 /* length of the "Private Header for Constructed Type" */
     950       56037 :                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8));
     951             : 
     952             :                 /* filler */
     953       56037 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC));
     954             : 
     955             :                 /*
     956             :                  * Private Header for Constructed Type
     957             :                  */
     958             :                 /* length - will be updated latter */
     959       56037 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
     960             : 
     961             :                 /* reserved */
     962       56037 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
     963       56037 :                 break;
     964             : 
     965           0 :         default:
     966           0 :                 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d",
     967             :                                       (int)header_size);
     968             :         }
     969             : 
     970     1901769 :         NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
     971     1901769 :         return NDR_ERR_SUCCESS;
     972             : }
     973             : 
     974             : 
     975             : struct ndr_token {
     976             :         const void *key;
     977             :         uint32_t value;
     978             : };
     979             : 
     980             : /*
     981             :   store a token in the ndr context, for later retrieval
     982             : */
     983   813444372 : _PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
     984             :                          struct ndr_token_list *list,
     985             :                          const void *key,
     986             :                          uint32_t value)
     987             : {
     988   813444372 :         if (list->tokens == NULL) {
     989    46458737 :                 list->tokens = talloc_array(mem_ctx, struct ndr_token, 10);
     990    46458737 :                 if (list->tokens == NULL) {
     991           0 :                         NDR_ERR_HAVE_NO_MEMORY(list->tokens);
     992             :                 }
     993             :         } else {
     994   766985635 :                 struct ndr_token *new_tokens = NULL;
     995   766985635 :                 uint32_t alloc_count = talloc_array_length(list->tokens);
     996             : 
     997             :                 /*
     998             :                  * Check every time we have not allocated too many
     999             :                  * tokens.  This ensures developer sanity when
    1000             :                  * debugging the boundary condition
    1001             :                  */
    1002   766985635 :                 if (list->count >= NDR_TOKEN_MAX_LIST_SIZE) {
    1003           0 :                         return NDR_ERR_RANGE;
    1004             :                 }
    1005   766985635 :                 if (list->count == alloc_count) {
    1006             :                         unsigned new_alloc;
    1007             :                         /*
    1008             :                          * Double the list, until we start in chunks
    1009             :                          * of 1000
    1010             :                          */
    1011    10350592 :                         unsigned increment = MIN(list->count, 1000);
    1012    10350592 :                         new_alloc = alloc_count + increment;
    1013    10350592 :                         if (new_alloc < alloc_count) {
    1014           0 :                                 return NDR_ERR_RANGE;
    1015             :                         }
    1016    10350592 :                         new_tokens = talloc_realloc(mem_ctx, list->tokens,
    1017             :                                                     struct ndr_token, new_alloc);
    1018    10350592 :                         NDR_ERR_HAVE_NO_MEMORY(new_tokens);
    1019    10350592 :                         list->tokens = new_tokens;
    1020             :                 }
    1021             :         }
    1022   813444372 :         list->tokens[list->count].key = key;
    1023   813444372 :         list->tokens[list->count].value = value;
    1024   813444372 :         list->count++;
    1025   813444372 :         return NDR_ERR_SUCCESS;
    1026             : }
    1027             : 
    1028             : /*
    1029             :   retrieve a token from a ndr context, using cmp_fn to match the tokens
    1030             : */
    1031   633027058 : _PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list *list,
    1032             :                                                      const void *key, uint32_t *v,
    1033             :                                                      comparison_fn_t _cmp_fn,
    1034             :                                                      bool erase)
    1035             : {
    1036   633027058 :         struct ndr_token *tokens = list->tokens;
    1037             :         unsigned i;
    1038   633027058 :         if (_cmp_fn) {
    1039     3631037 :                 for (i = list->count - 1; i < list->count; i--) {
    1040     2986067 :                         if (_cmp_fn(tokens[i].key, key) == 0) {
    1041      236246 :                                 goto found;
    1042             :                         }
    1043             :                 }
    1044             :         } else {
    1045   680645059 :                 for (i = list->count - 1; i < list->count; i--) {
    1046   680586243 :                         if (tokens[i].key == key) {
    1047   632087026 :                                 goto found;
    1048             :                         }
    1049             :                 }
    1050             :         }
    1051      703786 :         return NDR_ERR_TOKEN;
    1052   632323272 : found:
    1053   632323272 :         *v = tokens[i].value;
    1054   632323272 :         if (erase) {
    1055   612425694 :                 if (i != list->count - 1) {
    1056    20527444 :                         tokens[i] = tokens[list->count - 1];
    1057             :                 }
    1058   612425694 :                 list->count--;
    1059             :         }
    1060   632323272 :         return NDR_ERR_SUCCESS;
    1061             : }
    1062             : 
    1063             : /*
    1064             :   retrieve a token from a ndr context
    1065             : */
    1066   612425694 : _PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list,
    1067             :                                               const void *key, uint32_t *v)
    1068             : {
    1069   612425694 :         return ndr_token_retrieve_cmp_fn(list, key, v, NULL, true);
    1070             : }
    1071             : 
    1072             : /*
    1073             :   peek at but don't removed a token from a ndr context
    1074             : */
    1075    19720148 : _PUBLIC_ enum ndr_err_code ndr_token_peek(struct ndr_token_list *list,
    1076             :                                           const void *key, uint32_t *v)
    1077             : {
    1078    19720148 :         return ndr_token_retrieve_cmp_fn(list, key, v, NULL, false);
    1079             : }
    1080             : 
    1081             : /*
    1082             :   pull an array size field and add it to the array_size_list token list
    1083             : */
    1084    16468865 : _PUBLIC_ enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
    1085             : {
    1086             :         enum ndr_err_code ret;
    1087             :         uint32_t size;
    1088    16468865 :         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &size));
    1089    16468865 :         ret = ndr_token_store(ndr, &ndr->array_size_list, p, size);
    1090    16468865 :         if (ret == NDR_ERR_RANGE) {
    1091           0 :                 return ndr_pull_error(ndr, ret,
    1092             :                                       "More than %d NDR tokens stored for array_size",
    1093             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1094             :         }
    1095    16468865 :         return ret;
    1096             : }
    1097             : 
    1098             : /*
    1099             :   get the stored array size field
    1100             : */
    1101    18434270 : _PUBLIC_ enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
    1102             : {
    1103    18434270 :         return ndr_token_peek(&ndr->array_size_list, p, size);
    1104             : }
    1105             : 
    1106             : /*
    1107             :   get and remove from the stored list the stored array size field
    1108             : */
    1109     9728168 : _PUBLIC_ enum ndr_err_code ndr_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
    1110             : {
    1111     9728168 :         return ndr_token_retrieve(&ndr->array_size_list, p, size);
    1112             : }
    1113             : 
    1114             : /*
    1115             :  * check the stored array size field and remove from the stored list
    1116             :  * (the array_size NDR token list).  We try to remove when possible to
    1117             :  * avoid the list growing towards the bounds check
    1118             :  */
    1119     4933888 : _PUBLIC_ enum ndr_err_code ndr_check_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
    1120             : {
    1121             :         uint32_t stored;
    1122     4933888 :         NDR_CHECK(ndr_steal_array_size(ndr, p, &stored));
    1123     4933888 :         if (stored != size) {
    1124           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1125             :                                       "Bad array size - got %u expected %u\n",
    1126             :                                       stored, size);
    1127             :         }
    1128     4933888 :         return NDR_ERR_SUCCESS;
    1129             : }
    1130             : 
    1131             : /*
    1132             :  * check the stored array size field (leaving it on the array_size
    1133             :  * token list)
    1134             :  */
    1135     6740697 : _PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
    1136             : {
    1137             :         uint32_t stored;
    1138     6740697 :         NDR_CHECK(ndr_get_array_size(ndr, p, &stored));
    1139     6740697 :         if (stored != size) {
    1140           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1141             :                                       "Bad array size - got %u expected %u\n",
    1142             :                                       stored, size);
    1143             :         }
    1144     6740697 :         return NDR_ERR_SUCCESS;
    1145             : }
    1146             : 
    1147             : /*
    1148             :   pull an array length field and add it to the array_length_list token list
    1149             : */
    1150     6021342 : _PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
    1151             : {
    1152             :         enum ndr_err_code ret;
    1153             :         uint32_t length, offset;
    1154     6021342 :         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &offset));
    1155     6021342 :         if (offset != 0) {
    1156           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1157             :                                       "non-zero array offset %u\n", offset);
    1158             :         }
    1159     6021342 :         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
    1160     6021342 :         ret = ndr_token_store(ndr, &ndr->array_length_list, p, length);
    1161     6021342 :         if (ret == NDR_ERR_RANGE) {
    1162           0 :                 return ndr_pull_error(ndr, ret,
    1163             :                                       "More than %d NDR tokens stored for array_length_list",
    1164             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1165             :         }
    1166     6021342 :         return ret;
    1167             : }
    1168             : 
    1169             : /*
    1170             :   get the stored array length field
    1171             : */
    1172     1227062 : _PUBLIC_ enum ndr_err_code ndr_get_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
    1173             : {
    1174     1227062 :         return ndr_token_peek(&ndr->array_length_list, p, length);
    1175             : }
    1176             : 
    1177             : /*
    1178             :  * check the stored array length field and remove from the stored list
    1179             :  * (the array_size NDR token list).  We try to remove when possible to
    1180             :  * avoid the list growing towards the bounds check
    1181             :  */
    1182     6021342 : _PUBLIC_ enum ndr_err_code ndr_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
    1183             : {
    1184     6021342 :         return ndr_token_retrieve(&ndr->array_length_list, p, length);
    1185             : }
    1186             : /*
    1187             :   check the stored array length field, removing it from the list
    1188             : */
    1189     1227062 : _PUBLIC_ enum ndr_err_code ndr_check_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t length)
    1190             : {
    1191             :         uint32_t stored;
    1192     1227062 :         NDR_CHECK(ndr_steal_array_length(ndr, p, &stored));
    1193     1227062 :         if (stored != length) {
    1194           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1195             :                                       "Bad array length - got %u expected %u\n",
    1196             :                                       stored, length);
    1197             :         }
    1198     1227062 :         return NDR_ERR_SUCCESS;
    1199             : }
    1200             : 
    1201           0 : _PUBLIC_ enum ndr_err_code ndr_push_pipe_chunk_trailer(struct ndr_push *ndr, int ndr_flags, uint32_t count)
    1202             : {
    1203           0 :         if (ndr->flags & LIBNDR_FLAG_NDR64) {
    1204           0 :                 int64_t tmp = 0 - (int64_t)count;
    1205           0 :                 uint64_t ncount = tmp;
    1206             : 
    1207           0 :                 NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, ncount));
    1208             :         }
    1209             : 
    1210           0 :         return NDR_ERR_SUCCESS;
    1211             : }
    1212             : 
    1213           0 : _PUBLIC_ enum ndr_err_code ndr_check_pipe_chunk_trailer(struct ndr_pull *ndr, int ndr_flags, uint32_t count)
    1214             : {
    1215           0 :         if (ndr->flags & LIBNDR_FLAG_NDR64) {
    1216           0 :                 int64_t tmp = 0 - (int64_t)count;
    1217           0 :                 uint64_t ncount1 = tmp;
    1218             :                 uint64_t ncount2;
    1219             : 
    1220           0 :                 NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &ncount2));
    1221           0 :                 if (ncount1 == ncount2) {
    1222           0 :                         return NDR_ERR_SUCCESS;
    1223             :                 }
    1224             : 
    1225           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1226             :                         "Bad pipe trailer[%lld should be %lld] size was %lu\"",
    1227             :                         (unsigned long long)ncount2,
    1228             :                         (unsigned long long)ncount1,
    1229             :                         (unsigned long)count);
    1230             :         }
    1231             : 
    1232           0 :         return NDR_ERR_SUCCESS;
    1233             : }
    1234             : 
    1235             : /*
    1236             :   store a switch value
    1237             :  */
    1238   138015735 : _PUBLIC_ enum ndr_err_code ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
    1239             : {
    1240   129527483 :         enum ndr_err_code ret =
    1241   138015735 :                 ndr_token_store(ndr, &ndr->switch_list, p, val);
    1242   138015735 :         if (ret == NDR_ERR_RANGE) {
    1243           0 :                 return ndr_push_error(ndr, ret,
    1244             :                                       "More than %d NDR tokens stored for switch_list",
    1245             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1246             :         }
    1247   138015735 :         return ret;
    1248             : }
    1249             : 
    1250   606858583 : _PUBLIC_ enum ndr_err_code ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
    1251             : {
    1252             : 
    1253   555947458 :         enum ndr_err_code ret =
    1254   606858583 :                 ndr_token_store(ndr, &ndr->switch_list, p, val);
    1255   606858583 :         if (ret == NDR_ERR_RANGE) {
    1256           0 :                 return ndr_pull_error(ndr, ret,
    1257             :                                       "More than %d NDR tokens stored for switch_list",
    1258             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1259             :         }
    1260   606858583 :         return ret;
    1261             : }
    1262             : 
    1263       12002 : _PUBLIC_ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
    1264             : {
    1265       12002 :         return ndr_token_store(ndr, &ndr->switch_list, p, val);
    1266             : }
    1267             : 
    1268             : /* retrieve a switch value (for push) and remove it from the list */
    1269   108245798 : _PUBLIC_ enum ndr_err_code ndr_push_steal_switch_value(struct ndr_push *ndr,
    1270             :                                                        const void *p,
    1271             :                                                        uint32_t *v)
    1272             : {
    1273   108245798 :         return ndr_token_retrieve(&ndr->switch_list, p, v);
    1274             : }
    1275             : 
    1276             : /* retrieve a switch value and remove it from the list */
    1277       12002 : _PUBLIC_ uint32_t ndr_print_steal_switch_value(struct ndr_print *ndr, const void *p)
    1278             : {
    1279             :         enum ndr_err_code status;
    1280             :         uint32_t v;
    1281             : 
    1282       12002 :         status = ndr_token_retrieve(&ndr->switch_list, p, &v);
    1283       12002 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
    1284           0 :                 return 0;
    1285             :         }
    1286             : 
    1287       12002 :         return v;
    1288             : }
    1289             : 
    1290             : /* retrieve a switch value and remove it from the list */
    1291   443102688 : _PUBLIC_ enum ndr_err_code ndr_pull_steal_switch_value(struct ndr_pull *ndr,
    1292             :                                                        const void *p,
    1293             :                                                        uint32_t *v)
    1294             : {
    1295   443102688 :         return ndr_token_retrieve(&ndr->switch_list, p, v);
    1296             : }
    1297             : 
    1298             : /*
    1299             :   pull a struct from a blob using NDR
    1300             : */
    1301    15662806 : _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
    1302             :                               ndr_pull_flags_fn_t fn)
    1303             : {
    1304             :         struct ndr_pull *ndr;
    1305    15662806 :         ndr = ndr_pull_init_blob(blob, mem_ctx);
    1306    15662806 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1307    15662806 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1308    15662528 :         talloc_free(ndr);
    1309    15662528 :         return NDR_ERR_SUCCESS;
    1310             : }
    1311             : 
    1312             : /*
    1313             :   pull a struct from a blob using NDR - failing if all bytes are not consumed
    1314             : */
    1315     7087823 : _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
    1316             :                                                     void *p, ndr_pull_flags_fn_t fn)
    1317             : {
    1318             :         struct ndr_pull *ndr;
    1319             :         uint32_t highest_ofs;
    1320     7087823 :         ndr = ndr_pull_init_blob(blob, mem_ctx);
    1321     7087823 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1322     7087823 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1323     7087804 :         if (ndr->offset > ndr->relative_highest_offset) {
    1324     6709605 :                 highest_ofs = ndr->offset;
    1325             :         } else {
    1326      378199 :                 highest_ofs = ndr->relative_highest_offset;
    1327             :         }
    1328     7087804 :         if (highest_ofs < ndr->data_size) {
    1329             :                 enum ndr_err_code ret;
    1330         155 :                 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
    1331             :                                      "not all bytes consumed ofs[%u] size[%u]",
    1332             :                                      highest_ofs, ndr->data_size);
    1333         155 :                 talloc_free(ndr);
    1334         155 :                 return ret;
    1335             :         }
    1336     7087649 :         talloc_free(ndr);
    1337     7087649 :         return NDR_ERR_SUCCESS;
    1338             : }
    1339             : 
    1340             : /*
    1341             :   pull a struct from a blob using NDR - failing if all bytes are not consumed
    1342             : 
    1343             :   This only works for structures with NO allocated memory, like
    1344             :   objectSID and GUID.  This helps because we parse these a lot.
    1345             : */
    1346   166799238 : _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blob,
    1347             :                                                             void *p, ndr_pull_flags_fn_t fn)
    1348             : {
    1349             :         /*
    1350             :          * We init this structure on the stack here, to avoid a
    1351             :          * talloc() as otherwise this call to the fn() is assured not
    1352             :          * to be doing any allocation, eg SIDs and GUIDs.
    1353             :          *
    1354             :          * This allows us to keep the safety of the PIDL-generated
    1355             :          * code without the talloc() overhead.
    1356             :          */
    1357   420153878 :         struct ndr_pull ndr = {
    1358   166799238 :                 .data = blob->data,
    1359   166799238 :                 .data_size = blob->length,
    1360             :                 .current_mem_ctx = (void *)-1
    1361             :         };
    1362             :         uint32_t highest_ofs;
    1363   166799238 :         NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1364   166799238 :         highest_ofs = MAX(ndr.offset, ndr.relative_highest_offset);
    1365   166799238 :         if (highest_ofs < ndr.data_size) {
    1366             :                 enum ndr_err_code ret;
    1367           0 :                 ret = ndr_pull_error(
    1368             :                         &ndr,
    1369             :                         NDR_ERR_UNREAD_BYTES,
    1370             :                         "not all bytes consumed ofs[%"PRIu32"] "
    1371             :                         "size[%"PRIu32"]",
    1372             :                         highest_ofs,
    1373             :                         ndr.data_size);
    1374           0 :                 return ret;
    1375             :         }
    1376   166799238 :         return NDR_ERR_SUCCESS;
    1377             : }
    1378             : 
    1379             : /*
    1380             :   pull a union from a blob using NDR, given the union discriminator
    1381             : */
    1382      224250 : _PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
    1383             :                                                void *p,
    1384             :                              uint32_t level, ndr_pull_flags_fn_t fn)
    1385             : {
    1386             :         struct ndr_pull *ndr;
    1387      224250 :         ndr = ndr_pull_init_blob(blob, mem_ctx);
    1388      224250 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1389      224250 :         NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
    1390      224250 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1391      224250 :         talloc_free(ndr);
    1392      224250 :         return NDR_ERR_SUCCESS;
    1393             : }
    1394             : 
    1395             : /*
    1396             :   pull a union from a blob using NDR, given the union discriminator,
    1397             :   failing if all bytes are not consumed
    1398             : */
    1399           1 : _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
    1400             :                                                    void *p,
    1401             :                              uint32_t level, ndr_pull_flags_fn_t fn)
    1402             : {
    1403             :         struct ndr_pull *ndr;
    1404             :         uint32_t highest_ofs;
    1405           1 :         ndr = ndr_pull_init_blob(blob, mem_ctx);
    1406           1 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1407           1 :         NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
    1408           1 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1409           1 :         if (ndr->offset > ndr->relative_highest_offset) {
    1410           1 :                 highest_ofs = ndr->offset;
    1411             :         } else {
    1412           0 :                 highest_ofs = ndr->relative_highest_offset;
    1413             :         }
    1414           1 :         if (highest_ofs < ndr->data_size) {
    1415             :                 enum ndr_err_code ret;
    1416           0 :                 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
    1417             :                                      "not all bytes consumed ofs[%u] size[%u]",
    1418             :                                      highest_ofs, ndr->data_size);
    1419           0 :                 talloc_free(ndr);
    1420           0 :                 return ret;
    1421             :         }
    1422           1 :         talloc_free(ndr);
    1423           1 :         return NDR_ERR_SUCCESS;
    1424             : }
    1425             : 
    1426             : /*
    1427             :   push a struct to a blob using NDR
    1428             : */
    1429    10229469 : _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)
    1430             : {
    1431             :         struct ndr_push *ndr;
    1432    10229469 :         ndr = ndr_push_init_ctx(mem_ctx);
    1433    10229469 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1434             : 
    1435    10229469 :         NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1436             : 
    1437    10229469 :         *blob = ndr_push_blob(ndr);
    1438    10229469 :         talloc_steal(mem_ctx, blob->data);
    1439    10229469 :         talloc_free(ndr);
    1440             : 
    1441    10229469 :         return NDR_ERR_SUCCESS;
    1442             : }
    1443             : 
    1444             : /*
    1445             :   push a struct into a provided blob using NDR.
    1446             : 
    1447             :   We error because we want to have the performance issue (extra
    1448             :   talloc() calls) show up as an error, not just slower code.  This is
    1449             :   used for things like GUIDs, which we expect to be a fixed size, and
    1450             :   SIDs that we can pre-calculate the size for.
    1451             : */
    1452    88875663 : _PUBLIC_ enum ndr_err_code ndr_push_struct_into_fixed_blob(
    1453             :         DATA_BLOB *blob, const void *p, ndr_push_flags_fn_t fn)
    1454             : {
    1455   243970077 :         struct ndr_push ndr = {
    1456    88875663 :                 .data = blob->data,
    1457    88875663 :                 .alloc_size = blob->length,
    1458             :                 .fixed_buf_size = true
    1459             :         };
    1460             : 
    1461    88875663 :         NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1462             : 
    1463    88875663 :         if (ndr.offset != blob->length) {
    1464           0 :                 return ndr_push_error(&ndr, NDR_ERR_BUFSIZE,
    1465             :                                       "buffer was either to large or small "
    1466             :                                       "ofs[%u] size[%zu]",
    1467             :                                       ndr.offset, blob->length);
    1468             :         }
    1469             : 
    1470    88875663 :         return NDR_ERR_SUCCESS;
    1471             : }
    1472             : 
    1473             : /*
    1474             :   push a union to a blob using NDR
    1475             : */
    1476      124544 : _PUBLIC_ enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
    1477             :                              uint32_t level, ndr_push_flags_fn_t fn)
    1478             : {
    1479             :         struct ndr_push *ndr;
    1480      124544 :         ndr = ndr_push_init_ctx(mem_ctx);
    1481      124544 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1482             : 
    1483      124544 :         NDR_CHECK(ndr_push_set_switch_value(ndr, p, level));
    1484      124544 :         NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1485             : 
    1486      124544 :         *blob = ndr_push_blob(ndr);
    1487      124544 :         talloc_steal(mem_ctx, blob->data);
    1488      124544 :         talloc_free(ndr);
    1489             : 
    1490      124544 :         return NDR_ERR_SUCCESS;
    1491             : }
    1492             : 
    1493             : /*
    1494             :   generic ndr_size_*() handler for structures
    1495             : */
    1496    12300588 : _PUBLIC_ size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push)
    1497             : {
    1498             :         struct ndr_push *ndr;
    1499             :         enum ndr_err_code status;
    1500             :         size_t ret;
    1501             : 
    1502             :         /* avoid recursion */
    1503    12300588 :         if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
    1504             : 
    1505             :         /* Avoid following a NULL pointer */
    1506     5124506 :         if (p == NULL) {
    1507           0 :                 return 0;
    1508             :         }
    1509             : 
    1510     5124506 :         ndr = ndr_push_init_ctx(NULL);
    1511     5124506 :         if (!ndr) return 0;
    1512     5124506 :         ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
    1513     5124506 :         status = push(ndr, NDR_SCALARS|NDR_BUFFERS, discard_const(p));
    1514     5124506 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
    1515           0 :                 talloc_free(ndr);
    1516           0 :                 return 0;
    1517             :         }
    1518     5124506 :         ret = ndr->offset;
    1519     5124506 :         talloc_free(ndr);
    1520     5124506 :         return ret;
    1521             : }
    1522             : 
    1523             : /*
    1524             :   generic ndr_size_*() handler for unions
    1525             : */
    1526      998609 : _PUBLIC_ size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push)
    1527             : {
    1528             :         struct ndr_push *ndr;
    1529             :         enum ndr_err_code status;
    1530             :         size_t ret;
    1531             : 
    1532             :         /* avoid recursion */
    1533      998609 :         if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
    1534             : 
    1535             :         /* Avoid following a NULL pointer */
    1536      998609 :         if (p == NULL) {
    1537           0 :                 return 0;
    1538             :         }
    1539             : 
    1540      998609 :         ndr = ndr_push_init_ctx(NULL);
    1541      998609 :         if (!ndr) return 0;
    1542      998609 :         ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
    1543             : 
    1544      998609 :         status = ndr_push_set_switch_value(ndr, p, level);
    1545      998609 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
    1546           0 :                 talloc_free(ndr);
    1547           0 :                 return 0;
    1548             :         }
    1549      998609 :         status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
    1550      998609 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
    1551         120 :                 talloc_free(ndr);
    1552         120 :                 return 0;
    1553             :         }
    1554      998489 :         ret = ndr->offset;
    1555      998489 :         talloc_free(ndr);
    1556      998489 :         return ret;
    1557             : }
    1558             : 
    1559             : /*
    1560             :   get the current base for relative pointers for the push
    1561             : */
    1562        3807 : _PUBLIC_ uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
    1563             : {
    1564        3807 :         return ndr->relative_base_offset;
    1565             : }
    1566             : 
    1567             : /*
    1568             :   restore the old base for relative pointers for the push
    1569             : */
    1570        3807 : _PUBLIC_ void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
    1571             : {
    1572        3807 :         ndr->relative_base_offset = offset;
    1573        3807 : }
    1574             : 
    1575             : /*
    1576             :   setup the current base for relative pointers for the push
    1577             :   called in the NDR_SCALAR stage
    1578             : */
    1579        2111 : _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
    1580             : {
    1581             :         enum ndr_err_code ret;
    1582        2111 :         ndr->relative_base_offset = offset;
    1583        2111 :         ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
    1584        2111 :         if (ret == NDR_ERR_RANGE) {
    1585           0 :                 return ndr_push_error(ndr, ret,
    1586             :                                       "More than %d NDR tokens stored for relative_base_list",
    1587             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1588             :         }
    1589        2111 :         return ret;
    1590             : }
    1591             : 
    1592             : /*
    1593             :   setup the current base for relative pointers for the push
    1594             :   called in the NDR_BUFFERS stage
    1595             : */
    1596        2111 : _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
    1597             : {
    1598        2111 :         return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
    1599             : }
    1600             : 
    1601             : /*
    1602             :   push a relative object - stage1
    1603             :   this is called during SCALARS processing
    1604             : */
    1605    15485485 : _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
    1606             : {
    1607             :         enum ndr_err_code ret;
    1608    15485485 :         if (p == NULL) {
    1609     1590997 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
    1610     1590997 :                 return NDR_ERR_SUCCESS;
    1611             :         }
    1612    13894488 :         NDR_CHECK(ndr_push_align(ndr, 4));
    1613    13894488 :         ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
    1614    13894488 :         if (ret == NDR_ERR_RANGE) {
    1615           0 :                 return ndr_push_error(ndr, ret,
    1616             :                                       "More than %d NDR tokens stored for relative_list",
    1617             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1618             :         }
    1619    13894488 :         NDR_CHECK(ret);
    1620    13894488 :         return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF);
    1621             : }
    1622             : 
    1623             : /*
    1624             :   push a short relative object - stage1
    1625             :   this is called during SCALARS processing
    1626             : */
    1627       85010 : _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1(struct ndr_push *ndr, const void *p)
    1628             : {
    1629             :         enum ndr_err_code ret;
    1630       85010 :         if (p == NULL) {
    1631          12 :                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
    1632          12 :                 return NDR_ERR_SUCCESS;
    1633             :         }
    1634       84998 :         NDR_CHECK(ndr_push_align(ndr, 2));
    1635       84998 :         ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
    1636       84998 :         if (ret == NDR_ERR_RANGE) {
    1637           0 :                 return ndr_push_error(ndr, ret,
    1638             :                                       "More than %d NDR tokens stored for relative_list",
    1639             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1640             :         }
    1641       84998 :         NDR_CHECK(ret);
    1642       84998 :         return ndr_push_uint16(ndr, NDR_SCALARS, 0xFFFF);
    1643             : }
    1644             : /*
    1645             :   push a relative object - stage2
    1646             :   this is called during buffers processing
    1647             : */
    1648    13894488 : static enum ndr_err_code ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
    1649             : {
    1650             :         uint32_t save_offset;
    1651    13894488 :         uint32_t ptr_offset = 0xFFFFFFFF;
    1652    13894488 :         if (p == NULL) {
    1653           0 :                 return NDR_ERR_SUCCESS;
    1654             :         }
    1655    13894488 :         save_offset = ndr->offset;
    1656    13894488 :         NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
    1657    13894488 :         if (ptr_offset > ndr->offset) {
    1658           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1659             :                                       "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
    1660             :                                       ptr_offset, ndr->offset);
    1661             :         }
    1662    13894488 :         ndr->offset = ptr_offset;
    1663    13894488 :         if (save_offset < ndr->relative_base_offset) {
    1664           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1665             :                                       "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
    1666             :                                       save_offset, ndr->relative_base_offset);
    1667             :         }
    1668    13894488 :         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset));
    1669    13894488 :         ndr->offset = save_offset;
    1670    13894488 :         return NDR_ERR_SUCCESS;
    1671             : }
    1672             : /*
    1673             :   push a short relative object - stage2
    1674             :   this is called during buffers processing
    1675             : */
    1676       84998 : _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2(struct ndr_push *ndr, const void *p)
    1677             : {
    1678             :         uint32_t save_offset;
    1679       84998 :         uint32_t ptr_offset = 0xFFFF;
    1680             :         uint32_t relative_offset;
    1681             :         size_t pad;
    1682       84998 :         size_t align = 1;
    1683             : 
    1684       84998 :         if (p == NULL) {
    1685           0 :                 return NDR_ERR_SUCCESS;
    1686             :         }
    1687             : 
    1688       84998 :         if (ndr->offset < ndr->relative_base_offset) {
    1689           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1690             :                                       "ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u)",
    1691             :                                       ndr->offset, ndr->relative_base_offset);
    1692             :         }
    1693             : 
    1694       84998 :         relative_offset = ndr->offset - ndr->relative_base_offset;
    1695             : 
    1696       84998 :         if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
    1697           0 :                 align = 1;
    1698       84998 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
    1699        5052 :                 align = 2;
    1700       79946 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
    1701           0 :                 align = 4;
    1702       79946 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
    1703       60930 :                 align = 8;
    1704             :         }
    1705             : 
    1706       84998 :         pad = ndr_align_size(relative_offset, align);
    1707       84998 :         if (pad != 0) {
    1708       58078 :                 NDR_CHECK(ndr_push_zero(ndr, pad));
    1709             :         }
    1710             : 
    1711       84998 :         relative_offset = ndr->offset - ndr->relative_base_offset;
    1712       84998 :         if (relative_offset > UINT16_MAX) {
    1713           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1714             :                                       "ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX",
    1715             :                                       relative_offset);
    1716             :         }
    1717             : 
    1718       84998 :         save_offset = ndr->offset;
    1719       84998 :         NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
    1720       84998 :         if (ptr_offset > ndr->offset) {
    1721           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1722             :                                       "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
    1723             :                                       ptr_offset, ndr->offset);
    1724             :         }
    1725       84998 :         ndr->offset = ptr_offset;
    1726       84998 :         NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, relative_offset));
    1727       84998 :         ndr->offset = save_offset;
    1728       84998 :         return NDR_ERR_SUCCESS;
    1729             : }
    1730             : 
    1731             : /*
    1732             :   push a relative object - stage2 start
    1733             :   this is called during buffers processing
    1734             : */
    1735    13894488 : _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p)
    1736             : {
    1737             :         enum ndr_err_code ret;
    1738    13894488 :         if (p == NULL) {
    1739           0 :                 return NDR_ERR_SUCCESS;
    1740             :         }
    1741    13894488 :         if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
    1742             :                 uint32_t relative_offset;
    1743             :                 size_t pad;
    1744    13894488 :                 size_t align = 1;
    1745             : 
    1746    13894488 :                 if (ndr->offset < ndr->relative_base_offset) {
    1747           0 :                         return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1748             :                                       "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
    1749             :                                       ndr->offset, ndr->relative_base_offset);
    1750             :                 }
    1751             : 
    1752    13894488 :                 relative_offset = ndr->offset - ndr->relative_base_offset;
    1753             : 
    1754    13894488 :                 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
    1755           0 :                         align = 1;
    1756    13894488 :                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
    1757           0 :                         align = 2;
    1758    13894488 :                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
    1759           0 :                         align = 4;
    1760    13894488 :                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
    1761       46978 :                         align = 8;
    1762             :                 }
    1763             : 
    1764    13894488 :                 pad = ndr_align_size(relative_offset, align);
    1765    13894488 :                 if (pad) {
    1766           0 :                         NDR_CHECK(ndr_push_zero(ndr, pad));
    1767             :                 }
    1768             : 
    1769    13894488 :                 return ndr_push_relative_ptr2(ndr, p);
    1770             :         }
    1771           0 :         if (ndr->relative_end_offset == -1) {
    1772           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1773             :                               "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
    1774             :                               ndr->relative_end_offset);
    1775             :         }
    1776           0 :         ret = ndr_token_store(ndr,
    1777             :                               &ndr->relative_begin_list,
    1778             :                               p,
    1779             :                               ndr->offset);
    1780           0 :         if (ret == NDR_ERR_RANGE) {
    1781           0 :                 return ndr_push_error(ndr, ret,
    1782             :                                       "More than %d NDR tokens stored for array_size",
    1783             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1784             :         }
    1785           0 :         return ret;
    1786             : }
    1787             : 
    1788             : /*
    1789             :   push a relative object - stage2 end
    1790             :   this is called during buffers processing
    1791             : */
    1792    13894488 : _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end(struct ndr_push *ndr, const void *p)
    1793             : {
    1794    13894488 :         uint32_t begin_offset = 0xFFFFFFFF;
    1795             :         ssize_t len;
    1796    13894488 :         uint32_t correct_offset = 0;
    1797    13894488 :         uint32_t align = 1;
    1798    13894488 :         uint32_t pad = 0;
    1799             : 
    1800    13894488 :         if (p == NULL) {
    1801           0 :                 return NDR_ERR_SUCCESS;
    1802             :         }
    1803             : 
    1804    13894488 :         if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
    1805    13894488 :                 return NDR_ERR_SUCCESS;
    1806             :         }
    1807             : 
    1808           0 :         if (ndr->flags & LIBNDR_FLAG_NO_NDR_SIZE) {
    1809             :                 /* better say more than calculation a too small buffer */
    1810           0 :                 NDR_PUSH_ALIGN(ndr, 8);
    1811           0 :                 return NDR_ERR_SUCCESS;
    1812             :         }
    1813             : 
    1814           0 :         if (ndr->relative_end_offset < ndr->offset) {
    1815           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1816             :                                       "ndr_push_relative_ptr2_end:"
    1817             :                                       "relative_end_offset %u < offset %u",
    1818             :                                       ndr->relative_end_offset, ndr->offset);
    1819             :         }
    1820             : 
    1821           0 :         NDR_CHECK(ndr_token_retrieve(&ndr->relative_begin_list, p, &begin_offset));
    1822             : 
    1823             :         /* we have marshalled a buffer, see how long it was */
    1824           0 :         len = ndr->offset - begin_offset;
    1825             : 
    1826           0 :         if (len < 0) {
    1827           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1828             :                                       "ndr_push_relative_ptr2_end:"
    1829             :                                       "offset %u - begin_offset %u < 0",
    1830             :                                       ndr->offset, begin_offset);
    1831             :         }
    1832             : 
    1833           0 :         if (ndr->relative_end_offset < len) {
    1834           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1835             :                                       "ndr_push_relative_ptr2_end:"
    1836             :                                       "relative_end_offset %u < len %lld",
    1837             :                                       ndr->offset, (long long)len);
    1838             :         }
    1839             : 
    1840             :         /* the reversed offset is at the end of the main buffer */
    1841           0 :         correct_offset = ndr->relative_end_offset - len;
    1842             : 
    1843           0 :         if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
    1844           0 :                 align = 1;
    1845           0 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
    1846           0 :                 align = 2;
    1847           0 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
    1848           0 :                 align = 4;
    1849           0 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
    1850           0 :                 align = 8;
    1851             :         }
    1852             : 
    1853           0 :         pad = ndr_align_size(correct_offset, align);
    1854           0 :         if (pad) {
    1855           0 :                 correct_offset += pad;
    1856           0 :                 correct_offset -= align;
    1857             :         }
    1858             : 
    1859           0 :         if (correct_offset < begin_offset) {
    1860           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1861             :                                       "ndr_push_relative_ptr2_end: "
    1862             :                                       "correct_offset %u < begin_offset %u",
    1863             :                                       correct_offset, begin_offset);
    1864             :         }
    1865             : 
    1866           0 :         if (len > 0) {
    1867           0 :                 uint32_t clear_size = correct_offset - begin_offset;
    1868             : 
    1869           0 :                 clear_size = MIN(clear_size, len);
    1870             : 
    1871             :                 /* now move the marshalled buffer to the end of the main buffer */
    1872           0 :                 memmove(ndr->data + correct_offset, ndr->data + begin_offset, len);
    1873             : 
    1874           0 :                 if (clear_size) {
    1875             :                         /* and wipe out old buffer within the main buffer */
    1876           0 :                         memset(ndr->data + begin_offset, '\0', clear_size);
    1877             :                 }
    1878             :         }
    1879             : 
    1880             :         /* and set the end offset for the next buffer */
    1881           0 :         ndr->relative_end_offset = correct_offset;
    1882             : 
    1883             :         /* finally write the offset to the main buffer */
    1884           0 :         ndr->offset = correct_offset;
    1885           0 :         NDR_CHECK(ndr_push_relative_ptr2(ndr, p));
    1886             : 
    1887             :         /* restore to where we were in the main buffer */
    1888           0 :         ndr->offset = begin_offset;
    1889             : 
    1890           0 :         return NDR_ERR_SUCCESS;
    1891             : }
    1892             : 
    1893             : /*
    1894             :   get the current base for relative pointers for the pull
    1895             : */
    1896          82 : _PUBLIC_ uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
    1897             : {
    1898          82 :         return ndr->relative_base_offset;
    1899             : }
    1900             : 
    1901             : /*
    1902             :   restore the old base for relative pointers for the pull
    1903             : */
    1904          82 : _PUBLIC_ void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
    1905             : {
    1906          82 :         ndr->relative_base_offset = offset;
    1907          82 : }
    1908             : 
    1909             : /*
    1910             :   setup the current base for relative pointers for the pull
    1911             :   called in the NDR_SCALAR stage
    1912             : */
    1913          62 : _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
    1914             : {
    1915             :         enum ndr_err_code ret;
    1916          62 :         ndr->relative_base_offset = offset;
    1917          62 :         ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
    1918          62 :         if (ret == NDR_ERR_RANGE) {
    1919           0 :                 return ndr_pull_error(ndr, ret,
    1920             :                                       "More than %d NDR tokens stored for relative_base_list",
    1921             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1922             :         }
    1923          62 :         return ret;
    1924             : }
    1925             : 
    1926             : /*
    1927             :   setup the current base for relative pointers for the pull
    1928             :   called in the NDR_BUFFERS stage
    1929             : */
    1930          62 : _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
    1931             : {
    1932          62 :         return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
    1933             : }
    1934             : 
    1935             : /*
    1936             :   pull a relative object - stage1
    1937             :   called during SCALARS processing
    1938             : */
    1939    31332406 : _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
    1940             : {
    1941             :         enum ndr_err_code ret;
    1942    31332406 :         rel_offset += ndr->relative_base_offset;
    1943    31332406 :         if (rel_offset > ndr->data_size) {
    1944         233 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
    1945             :                                       "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
    1946             :                                       rel_offset, ndr->data_size);
    1947             :         }
    1948    31332173 :         ret = ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
    1949    31332173 :         if (ret == NDR_ERR_RANGE) {
    1950           0 :                 return ndr_pull_error(ndr, ret,
    1951             :                                       "More than %d NDR tokens stored for relative_list",
    1952             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1953             :         }
    1954    31332173 :         return ret;
    1955             : }
    1956             : 
    1957             : /*
    1958             :   pull a relative object - stage2
    1959             :   called during BUFFERS processing
    1960             : */
    1961    31332173 : _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
    1962             : {
    1963             :         uint32_t rel_offset;
    1964    31332173 :         NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
    1965    31332173 :         return ndr_pull_set_offset(ndr, rel_offset);
    1966             : }
    1967             : 
    1968             : static const struct {
    1969             :         enum ndr_err_code err;
    1970             :         const char *string;
    1971             : } ndr_err_code_strings[] = {
    1972             :         { NDR_ERR_SUCCESS, "Success" },
    1973             :         { NDR_ERR_ARRAY_SIZE, "Bad Array Size" },
    1974             :         { NDR_ERR_BAD_SWITCH, "Bad Switch" },
    1975             :         { NDR_ERR_OFFSET, "Offset Error" },
    1976             :         { NDR_ERR_RELATIVE, "Relative Pointer Error" },
    1977             :         { NDR_ERR_CHARCNV, "Character Conversion Error" },
    1978             :         { NDR_ERR_LENGTH, "Length Error" },
    1979             :         { NDR_ERR_SUBCONTEXT, "Subcontext Error" },
    1980             :         { NDR_ERR_COMPRESSION, "Compression Error" },
    1981             :         { NDR_ERR_STRING, "String Error" },
    1982             :         { NDR_ERR_VALIDATE, "Validate Error" },
    1983             :         { NDR_ERR_BUFSIZE, "Buffer Size Error" },
    1984             :         { NDR_ERR_ALLOC, "Allocation Error" },
    1985             :         { NDR_ERR_RANGE, "Range Error" },
    1986             :         { NDR_ERR_TOKEN, "Token Error" },
    1987             :         { NDR_ERR_IPV4ADDRESS, "IPv4 Address Error" },
    1988             :         { NDR_ERR_INVALID_POINTER, "Invalid Pointer" },
    1989             :         { NDR_ERR_UNREAD_BYTES, "Unread Bytes" },
    1990             :         { NDR_ERR_NDR64, "NDR64 assertion error" },
    1991             :         { NDR_ERR_INCOMPLETE_BUFFER, "Incomplete Buffer" },
    1992             :         { NDR_ERR_MAX_RECURSION_EXCEEDED, "Maximum Recursion Exceeded" },
    1993             :         { NDR_ERR_UNDERFLOW, "Underflow" },
    1994             :         { 0, NULL }
    1995             : };
    1996             : 
    1997         776 : _PUBLIC_ const char *ndr_map_error2string(enum ndr_err_code ndr_err)
    1998             : {
    1999             :         int i;
    2000       12642 :         for (i = 0; ndr_err_code_strings[i].string != NULL; i++) {
    2001       12522 :                 if (ndr_err_code_strings[i].err == ndr_err)
    2002         656 :                         return ndr_err_code_strings[i].string;
    2003             :         }
    2004         120 :         return "Unknown error";
    2005             : }

Generated by: LCOV version 1.13