LCOV - code coverage report
Current view: top level - librpc/tools - ndrdump.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 262 444 59.0 %
Date: 2024-02-28 12:06:22 Functions: 4 9 44.4 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB torture tester
       4             :    Copyright (C) Andrew Tridgell 2003
       5             :    Copyright (C) Jelmer Vernooij 2006
       6             :    
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             :    
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             :    
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/filesys.h"
      23             : #include "system/locale.h"
      24             : #include "librpc/ndr/libndr.h"
      25             : #include "librpc/ndr/ndr_table.h"
      26             : #include "librpc/gen_ndr/ndr_dcerpc.h"
      27             : #include "lib/cmdline/cmdline.h"
      28             : #include "param/param.h"
      29             : #include "lib/util/base64.h"
      30             : 
      31          11 : static const struct ndr_interface_call *find_function(
      32             :         const struct ndr_interface_table *p,
      33             :         const char *function)
      34             : {
      35          11 :         unsigned int i;
      36          11 :         if (isdigit(function[0])) {
      37           3 :                 char *eptr = NULL;
      38           3 :                 i = strtoul(function, &eptr, 0);
      39           3 :                 if (i >= p->num_calls
      40           3 :                     || eptr == NULL
      41           3 :                     || eptr[0] != '\0') {
      42           0 :                         printf("Function number '%s' not found\n",
      43             :                                function);
      44           0 :                         exit(1);
      45             :                 }
      46           3 :                 return &p->calls[i];
      47             :         }
      48         247 :         for (i=0;i<p->num_calls;i++) {
      49         247 :                 if (strcmp(p->calls[i].name, function) == 0) {
      50             :                         break;
      51             :                 }
      52             :         }
      53           8 :         if (i == p->num_calls) {
      54           0 :                 printf("Function '%s' not found\n", function);
      55           0 :                 exit(1);
      56             :         }
      57           8 :         return &p->calls[i];
      58             : }
      59             : 
      60             : /*
      61             :  * Find a public structure on the pipe and return it as if it were
      62             :  * a function (as the rest of ndrdump is based around functions)
      63             :  */
      64          24 : static const struct ndr_interface_call *find_struct(
      65             :         const struct ndr_interface_table *p,
      66             :         const char *struct_name,
      67             :         struct ndr_interface_call *out_buffer)
      68             : {
      69          24 :         unsigned int i;
      70          24 :         const struct ndr_interface_public_struct *public_struct = NULL;
      71          24 :         if (isdigit(struct_name[0])) {
      72           1 :                 char *eptr = NULL;
      73           1 :                 i = strtoul(struct_name, &eptr, 0);
      74           1 :                 if (i >= p->num_public_structs
      75           1 :                     || eptr == NULL
      76           1 :                     || eptr[0] != '\0') {
      77           0 :                         printf("Public structure number '%s' not found\n",
      78             :                                struct_name);
      79           0 :                         exit(1);
      80             :                 }
      81           1 :                 public_struct = &p->public_structs[i];
      82             :         } else {
      83         151 :                 for (i=0;i<p->num_public_structs;i++) {
      84         150 :                         if (strcmp(p->public_structs[i].name, struct_name) == 0) {
      85             :                                 break;
      86             :                         }
      87             :                 }
      88          23 :                 if (i == p->num_public_structs) {
      89           1 :                         printf("Public structure '%s' not found\n", struct_name);
      90           1 :                         exit(1);
      91             :                 }
      92          22 :                 public_struct = &p->public_structs[i];
      93             :         }
      94          23 :         *out_buffer = (struct ndr_interface_call) {
      95          23 :                 .name = public_struct->name,
      96          23 :                 .struct_size = public_struct->struct_size,
      97          23 :                 .ndr_pull = public_struct->ndr_pull,
      98          23 :                 .ndr_push = public_struct->ndr_push,
      99          23 :                 .ndr_print = public_struct->ndr_print
     100             :         };
     101          23 :         return out_buffer;
     102             : }
     103             : 
     104           0 : _NORETURN_ static void show_pipes(void)
     105             : {
     106           0 :         const struct ndr_interface_list *l;
     107           0 :         printf("\nYou must specify a pipe\n");
     108           0 :         printf("known pipes are:\n");
     109           0 :         for (l=ndr_table_list();l;l=l->next) {
     110           0 :                 if(l->table->helpstring) {
     111           0 :                         printf("\t%s - %s\n", l->table->name, l->table->helpstring);
     112             :                 } else {
     113           0 :                         printf("\t%s\n", l->table->name);
     114             :                 }
     115             :         }
     116           0 :         exit(1);
     117             : }
     118             : 
     119           0 : _NORETURN_ static void show_functions(const struct ndr_interface_table *p)
     120             : {
     121           0 :         int i;
     122           0 :         printf("\nYou must specify a function\n");
     123           0 :         printf("known functions on '%s' are:\n", p->name);
     124           0 :         for (i=0;i<p->num_calls;i++) {
     125           0 :                 printf("\t0x%02x (%2d) %s\n", i, i, p->calls[i].name);
     126             :         }
     127           0 :         printf("known public structures on '%s' are:\n", p->name);
     128           0 :         for (i=0;i<p->num_public_structs;i++) {
     129           0 :                 printf("\t%s\n", p->public_structs[i].name);
     130             :         }
     131           0 :         exit(1);
     132             : }
     133             : 
     134           0 : static char *stdin_load(TALLOC_CTX *mem_ctx, size_t *size)
     135             : {
     136           0 :         int num_read, total_len = 0;
     137           0 :         char buf[255];
     138           0 :         char *result = NULL;
     139             : 
     140           0 :         while((num_read = read(STDIN_FILENO, buf, 255)) > 0) {
     141             : 
     142           0 :                 if (result) {
     143           0 :                         result = talloc_realloc(
     144             :                                 mem_ctx, result, char, total_len + num_read);
     145             :                 } else {
     146           0 :                         result = talloc_array(mem_ctx, char, num_read);
     147             :                 }
     148             : 
     149           0 :                 memcpy(result + total_len, buf, num_read);
     150             : 
     151           0 :                 total_len += num_read;
     152             :         }
     153             : 
     154           0 :         if (size)
     155           0 :                 *size = total_len;
     156             : 
     157           0 :         return result;
     158             : }
     159             : 
     160           0 : static const struct ndr_interface_table *load_iface_from_plugin(const char *plugin, const char *pipe_name)
     161             : {
     162           0 :         const struct ndr_interface_table *p;
     163           0 :         void *handle;
     164           0 :         char *symbol;
     165             : 
     166           0 :         handle = dlopen(plugin, RTLD_NOW);
     167           0 :         if (handle == NULL) {
     168           0 :                 printf("%s: Unable to open: %s\n", plugin, dlerror());
     169           0 :                 return NULL;
     170             :         }
     171             : 
     172           0 :         symbol = talloc_asprintf(NULL, "ndr_table_%s", pipe_name);
     173           0 :         p = (const struct ndr_interface_table *)dlsym(handle, symbol);
     174             : 
     175           0 :         if (!p) {
     176           0 :                 printf("%s: Unable to find DCE/RPC interface table for '%s': %s\n", plugin, pipe_name, dlerror());
     177           0 :                 talloc_free(symbol);
     178           0 :                 dlclose(handle);
     179           0 :                 return NULL;
     180             :         }
     181             : 
     182           0 :         talloc_free(symbol);
     183             :         
     184           0 :         return p;
     185             : }
     186             : 
     187          14 : static void ndrdump_data(uint8_t *d, uint32_t l, bool force)
     188             : {
     189          14 :         dump_data_file(d, l, !force, stdout);
     190          14 : }
     191             : 
     192           8 : static void ndrdump_data_diff(const uint8_t *d1, size_t l1,
     193             :                               const uint8_t *d2, size_t l2,
     194             :                               bool force)
     195             : {
     196           8 :         dump_data_file_diff(stdout, !force, d1, l1, d2, l2);
     197           8 : }
     198             : 
     199          11 : static NTSTATUS ndrdump_pull_and_print_pipes(const char *function,
     200             :                                 struct ndr_pull *ndr_pull,
     201             :                                 struct ndr_print *ndr_print,
     202             :                                 const struct ndr_interface_call_pipes *pipes)
     203             : {
     204          11 :         enum ndr_err_code ndr_err;
     205          11 :         uint32_t i;
     206             : 
     207          11 :         for (i=0; i < pipes->num_pipes; i++) {
     208             :                 uint64_t idx = 0;
     209           0 :                 while (true) {
     210           0 :                         void *saved_mem_ctx;
     211           0 :                         uint32_t *count;
     212           0 :                         void *c;
     213           0 :                         char *n;
     214             : 
     215           0 :                         c = talloc_zero_size(ndr_pull, pipes->pipes[i].chunk_struct_size);
     216           0 :                         talloc_set_name(c, "struct %s", pipes->pipes[i].name);
     217             :                         /*
     218             :                          * Note: the first struct member is always
     219             :                          * 'uint32_t count;'
     220             :                          */
     221           0 :                         count = (uint32_t *)c;
     222             : 
     223           0 :                         n = talloc_asprintf(c, "%s: %s[%"PRIu64"]",
     224           0 :                                         function, pipes->pipes[i].name,
     225             :                                         idx);
     226             : 
     227           0 :                         saved_mem_ctx = ndr_pull->current_mem_ctx;
     228           0 :                         ndr_pull->current_mem_ctx = c;
     229           0 :                         ndr_err = pipes->pipes[i].ndr_pull(ndr_pull, NDR_SCALARS, c);
     230           0 :                         ndr_pull->current_mem_ctx = saved_mem_ctx;
     231             : 
     232           0 :                         printf("pull returned %s\n",
     233             :                                ndr_map_error2string(ndr_err));
     234           0 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     235           0 :                                 talloc_free(c);
     236           0 :                                 return ndr_map_error2ntstatus(ndr_err);
     237             :                         }
     238           0 :                         pipes->pipes[i].ndr_print(ndr_print, n, c);
     239           0 :                         if (*count == 0) {
     240           0 :                                 talloc_free(c);
     241           0 :                                 break;
     242             :                         }
     243           0 :                         talloc_free(c);
     244           0 :                         idx++;
     245             :                 }
     246             :         }
     247             : 
     248          11 :         return NT_STATUS_OK;
     249             : }
     250             : 
     251           0 : static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
     252             : {
     253             :         /* This is here so that you can turn ndr printing off for the purposes
     254             :            of benchmarking ndr parsing. */
     255           0 : }
     256             : 
     257          35 :  int main(int argc, const char *argv[])
     258             : {
     259          35 :         const struct ndr_interface_table *p = NULL;
     260          35 :         const struct ndr_interface_call *f;
     261          35 :         struct ndr_interface_call f_buffer;
     262          35 :         const char *pipe_name = NULL;
     263          35 :         const char *filename = NULL;
     264             :         /*
     265             :          * The format type:
     266             :          *   in:     a request
     267             :          *   out:    a response
     268             :          *   struct: a public structure
     269             :          */
     270          35 :         const char *type = NULL;
     271             :         /*
     272             :          * Format is either the name of the decoding function or the
     273             :          * name of a public structure
     274             :          */
     275          35 :         const char *format = NULL;
     276          35 :         const char *cmdline_input = NULL;
     277          35 :         const uint8_t *data;
     278          35 :         size_t size;
     279          35 :         DATA_BLOB blob;
     280          35 :         struct ndr_pull *ndr_pull;
     281          35 :         struct ndr_print *ndr_print;
     282          35 :         TALLOC_CTX *mem_ctx;
     283          35 :         ndr_flags_type flags = 0;
     284          35 :         poptContext pc;
     285          35 :         NTSTATUS status;
     286          35 :         enum ndr_err_code ndr_err;
     287          35 :         void *st;
     288          35 :         void *v_st;
     289          35 :         const char *ctx_filename = NULL;
     290          35 :         const char *plugin = NULL;
     291          35 :         bool validate = false;
     292          35 :         bool dumpdata = false;
     293          35 :         bool assume_ndr64 = false;
     294          35 :         bool quiet = false;
     295          35 :         bool hex_input = false;
     296          35 :         bool base64_input = false;
     297          35 :         bool print_after_parse_failure = false;
     298          35 :         int opt;
     299          35 :         enum {
     300             :                 OPT_CONTEXT_FILE=1000,
     301             :                 OPT_VALIDATE,
     302             :                 OPT_DUMP_DATA,
     303             :                 OPT_LOAD_DSO,
     304             :                 OPT_NDR64,
     305             :                 OPT_QUIET,
     306             :                 OPT_BASE64_INPUT,
     307             :                 OPT_HEX_INPUT,
     308             :                 OPT_CMDLINE_INPUT,
     309             :                 OPT_PRINT_AFTER_PARSE_FAILURE,
     310             :         };
     311         105 :         struct poptOption long_options[] = {
     312             :                 POPT_AUTOHELP
     313             :                 {"context-file", 'c', POPT_ARG_STRING, NULL, OPT_CONTEXT_FILE, "In-filename to parse first", "CTX-FILE" },
     314             :                 {"validate", 0, POPT_ARG_NONE, NULL, OPT_VALIDATE, "try to validate the data", NULL },      
     315             :                 {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMP_DATA, "dump the hex data", NULL },   
     316             :                 {"load-dso", 0, POPT_ARG_STRING, NULL, OPT_LOAD_DSO, "load from shared object file", NULL },
     317             :                 {"ndr64", 0, POPT_ARG_NONE, NULL, OPT_NDR64, "Assume NDR64 data", NULL },
     318             :                 {"quiet", 0, POPT_ARG_NONE, NULL, OPT_QUIET, "Don't actually dump anything", NULL },
     319             :                 {"base64-input", 0, POPT_ARG_NONE, NULL, OPT_BASE64_INPUT, "Read the input file in as a base64 string", NULL },
     320             :                 {"hex-input", 0, POPT_ARG_NONE, NULL, OPT_HEX_INPUT, "Read the input file in as a hex dump", NULL },
     321             :                 {"input", 0, POPT_ARG_STRING, NULL, OPT_CMDLINE_INPUT, "Provide the input on the command line (use with --base64-input)", "INPUT" },
     322             :                 {"print-after-parse-failure", 0, POPT_ARG_NONE, NULL, OPT_PRINT_AFTER_PARSE_FAILURE,
     323             :                  "Try to print structures that fail to parse (used to develop parsers, segfaults are likely).", NULL },
     324          35 :                 POPT_COMMON_SAMBA
     325          35 :                 POPT_COMMON_VERSION
     326             :                 POPT_TABLEEND
     327             :         };
     328          35 :         uint32_t highest_ofs;
     329          35 :         struct dcerpc_sec_verification_trailer *sec_vt = NULL;
     330          35 :         bool ok;
     331             : 
     332          35 :         ndr_table_init();
     333             : 
     334             :         /* Initialise samba stuff */
     335          35 :         smb_init_locale();
     336             : 
     337          35 :         setlinebuf(stdout);
     338             : 
     339          35 :         mem_ctx = talloc_init("ndrdump.c/main");
     340          35 :         if (mem_ctx == NULL) {
     341           0 :                 exit(ENOMEM);
     342             :         }
     343             : 
     344          35 :         ok = samba_cmdline_init(mem_ctx,
     345             :                                 SAMBA_CMDLINE_CONFIG_CLIENT,
     346             :                                 false /* require_smbconf */);
     347          35 :         if (!ok) {
     348           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
     349           0 :                 TALLOC_FREE(mem_ctx);
     350           0 :                 exit(1);
     351             :         }
     352             : 
     353          35 :         pc = samba_popt_get_context(getprogname(),
     354             :                                     argc,
     355             :                                     argv,
     356             :                                     long_options,
     357             :                                     0);
     358          35 :         if (pc == NULL) {
     359           0 :                 DBG_ERR("Failed to setup popt context!\n");
     360           0 :                 TALLOC_FREE(mem_ctx);
     361           0 :                 exit(1);
     362             :         }
     363             : 
     364          35 :         poptSetOtherOptionHelp(
     365             :                 pc, "<pipe|uuid> <format> <in|out|struct> [<filename>]");
     366             : 
     367          90 :         while ((opt = poptGetNextOpt(pc)) != -1) {
     368          55 :                 switch (opt) {
     369           1 :                 case OPT_CONTEXT_FILE:
     370           1 :                         ctx_filename = poptGetOptArg(pc);
     371           1 :                         break;
     372          13 :                 case OPT_VALIDATE:
     373          13 :                         validate = true;
     374          13 :                         break;
     375           2 :                 case OPT_DUMP_DATA:
     376           2 :                         dumpdata = true;
     377           2 :                         break;
     378           0 :                 case OPT_LOAD_DSO:
     379           0 :                         plugin = poptGetOptArg(pc);
     380           0 :                         break;
     381           0 :                 case OPT_NDR64:
     382           0 :                         assume_ndr64 = true;
     383           0 :                         break;
     384           0 :                 case OPT_QUIET:
     385           0 :                         quiet = true;
     386           0 :                         break;
     387          15 :                 case OPT_BASE64_INPUT:
     388          15 :                         base64_input = true;
     389          15 :                         break;
     390           7 :                 case OPT_HEX_INPUT:
     391           7 :                         hex_input = true;
     392           7 :                         break;
     393          16 :                 case OPT_CMDLINE_INPUT:
     394          16 :                         cmdline_input = poptGetOptArg(pc);
     395          16 :                         break;
     396           1 :                 case OPT_PRINT_AFTER_PARSE_FAILURE:
     397           1 :                         print_after_parse_failure = true;
     398           1 :                         break;
     399             :                 }
     400             :         }
     401             : 
     402          35 :         pipe_name = poptGetArg(pc);
     403             : 
     404          35 :         if (!pipe_name) {
     405           0 :                 poptPrintUsage(pc, stderr, 0);
     406           0 :                 show_pipes();
     407             :                 exit(1);
     408             :         }
     409             : 
     410          35 :         if (plugin != NULL) {
     411           0 :                 p = load_iface_from_plugin(plugin, pipe_name);
     412             :         } 
     413           0 :         if (!p) {
     414          35 :                 p = ndr_table_by_name(pipe_name);
     415             :         }
     416             : 
     417          35 :         if (!p) {
     418           0 :                 struct GUID uuid;
     419             : 
     420           0 :                 status = GUID_from_string(pipe_name, &uuid);
     421             : 
     422           0 :                 if (NT_STATUS_IS_OK(status)) {
     423           0 :                         p = ndr_table_by_uuid(&uuid);
     424             :                 }
     425             :         }
     426             : 
     427          35 :         if (!p) {
     428           0 :                 printf("Unknown pipe or UUID '%s'\n", pipe_name);
     429           0 :                 exit(1);
     430             :         }
     431             : 
     432          35 :         format = poptGetArg(pc);
     433          35 :         type = poptGetArg(pc);
     434          35 :         filename = poptGetArg(pc);
     435             : 
     436          35 :         if (!format || !type) {
     437           0 :                 poptPrintUsage(pc, stderr, 0);
     438           0 :                 show_functions(p);
     439             :                 exit(1);
     440             :         }
     441             : 
     442          35 :         if (strcmp(type, "struct") == 0) {
     443          24 :                 flags = NDR_SCALARS|NDR_BUFFERS; /* neither NDR_IN nor NDR_OUT */
     444          24 :                 f = find_struct(p, format, &f_buffer);
     445             :         } else {
     446          11 :                 f = find_function(p, format);
     447          11 :                 if (strcmp(type, "in") == 0 ||
     448           7 :                     strcmp(type, "request") == 0) {
     449             :                         flags |= NDR_IN;
     450           7 :                 } else if (strcmp(type, "out") == 0 ||
     451           0 :                            strcmp(type, "response") == 0) {
     452             :                         flags |= NDR_OUT;
     453             :                 } else {
     454           0 :                         printf("Bad type value '%s'\n", type);
     455           0 :                         exit(1);
     456             :                 }
     457             :         }
     458             : 
     459          34 :         st = talloc_zero_size(mem_ctx, f->struct_size);
     460          34 :         if (!st) {
     461           0 :                 printf("Unable to allocate %zu bytes for %s structure\n",
     462           0 :                        f->struct_size,
     463           0 :                        f->name);
     464           0 :                 TALLOC_FREE(mem_ctx);
     465           0 :                 exit(1);
     466             :         }
     467             : 
     468          34 :         v_st = talloc_zero_size(mem_ctx, f->struct_size);
     469          34 :         if (!v_st) {
     470           0 :                 printf("Unable to allocate %zu bytes for %s validation "
     471             :                        "structure\n",
     472           0 :                        f->struct_size,
     473           0 :                        f->name);
     474           0 :                 TALLOC_FREE(mem_ctx);
     475           0 :                 exit(1);
     476             :         }
     477             : 
     478          34 :         if (ctx_filename) {
     479           1 :                 if (flags & NDR_IN) {
     480           0 :                         printf("Context file can only be used for \"out\" packages\n");
     481           0 :                         TALLOC_FREE(mem_ctx);
     482           0 :                         exit(1);
     483             :                 }
     484             :                         
     485           1 :                 data = (uint8_t *)file_load(ctx_filename, &size, 0, mem_ctx);
     486           1 :                 if (!data) {
     487           0 :                         perror(ctx_filename);
     488           0 :                         TALLOC_FREE(mem_ctx);
     489           0 :                         exit(1);
     490             :                 }
     491             : 
     492           1 :                 blob = data_blob_const(data, size);
     493             : 
     494           1 :                 ndr_pull = ndr_pull_init_blob(&blob, mem_ctx);
     495           1 :                 if (ndr_pull == NULL) {
     496           0 :                         perror("ndr_pull_init_blob");
     497           0 :                         TALLOC_FREE(mem_ctx);
     498           0 :                         exit(1);
     499             :                 }
     500           1 :                 ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC;
     501           1 :                 if (assume_ndr64) {
     502           0 :                         ndr_pull->flags |= LIBNDR_FLAG_NDR64;
     503             :                 }
     504             : 
     505           1 :                 ndr_err = f->ndr_pull(ndr_pull, NDR_IN, st);
     506             : 
     507           1 :                 if (ndr_pull->offset > ndr_pull->relative_highest_offset) {
     508             :                         highest_ofs = ndr_pull->offset;
     509             :                 } else {
     510             :                         highest_ofs = ndr_pull->relative_highest_offset;
     511             :                 }
     512             : 
     513           1 :                 if (highest_ofs != ndr_pull->data_size) {
     514           1 :                         printf("WARNING! %"PRIu32" unread bytes while parsing context file\n", ndr_pull->data_size - highest_ofs);
     515             :                 }
     516             : 
     517           1 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     518           0 :                         printf("pull for context file returned %s\n",
     519             :                                ndr_map_error2string(ndr_err));
     520           0 :                         TALLOC_FREE(mem_ctx);
     521           0 :                         exit(2);
     522             :                 }
     523           1 :                 memcpy(v_st, st, f->struct_size);
     524             :         }
     525             : 
     526          34 :         if (filename && cmdline_input) {
     527           0 :                 printf("cannot combine --input with a filename\n");
     528           0 :                 TALLOC_FREE(mem_ctx);
     529           0 :                 exit(1);
     530          34 :         } else if (cmdline_input) {
     531          15 :                 data = (const uint8_t *)cmdline_input;
     532          15 :                 size = strlen(cmdline_input);
     533          19 :         } else if (filename) {
     534          19 :                 data = (uint8_t *)file_load(filename, &size, 0, mem_ctx);
     535             :         } else {
     536           0 :                 data = (uint8_t *)stdin_load(mem_ctx, &size);
     537             :         }
     538             : 
     539          34 :         if (!data) {
     540           0 :                 if (filename)
     541           0 :                         perror(filename);
     542             :                 else
     543           0 :                         perror("stdin");
     544           0 :                 exit(1);
     545             :         }
     546             :         
     547          34 :         if (hex_input && base64_input) {
     548           0 :                 printf("cannot combine --hex-input with --base64-input\n");
     549           0 :                 TALLOC_FREE(mem_ctx);
     550           0 :                 exit(1);
     551             : 
     552          34 :         } else if (hex_input && size >= 1 && data[0] != '[') {
     553           3 :                 blob = strhex_to_data_blob(mem_ctx, (const char *)data);
     554          31 :         } else if (hex_input) {
     555           4 :                 blob = hexdump_to_data_blob(mem_ctx, (const char *)data, size);
     556          27 :         } else if (base64_input) {
     557             :                 /* Use talloc_strndup() to ensure null termination */
     558          15 :                 blob = base64_decode_data_blob_talloc(
     559             :                         mem_ctx,
     560          15 :                         talloc_strndup(mem_ctx, (const char *)data, size));
     561             :         } else {
     562          12 :                 blob = data_blob_const(data, size);
     563             :         }
     564             : 
     565          34 :         if (data != NULL && blob.data == NULL) {
     566           0 :                 printf("failed to decode input data\n");
     567           0 :                 TALLOC_FREE(mem_ctx);
     568           0 :                 exit(1);
     569             :         }
     570             : 
     571          34 :         ndr_pull = ndr_pull_init_blob(&blob, mem_ctx);
     572          34 :         if (ndr_pull == NULL) {
     573           0 :                 perror("ndr_pull_init_blob");
     574           0 :                 TALLOC_FREE(mem_ctx);
     575           0 :                 exit(1);
     576             :         }
     577          34 :         ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC;
     578          34 :         if (assume_ndr64) {
     579           0 :                 ndr_pull->flags |= LIBNDR_FLAG_NDR64;
     580             :         }
     581             : 
     582          34 :         ndr_print = talloc_zero(mem_ctx, struct ndr_print);
     583          34 :         if (quiet) {
     584           0 :                 ndr_print->print = ndr_print_dummy;
     585             :         } else {
     586          34 :                 ndr_print->print = ndr_print_printf_helper;
     587             :         }
     588          34 :         ndr_print->depth = 1;
     589             : 
     590          34 :         ndr_err = ndr_pop_dcerpc_sec_verification_trailer(ndr_pull, mem_ctx, &sec_vt);
     591          34 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     592           0 :                 printf("ndr_pop_dcerpc_sec_verification_trailer returned %s\n",
     593             :                        ndr_map_error2string(ndr_err));
     594             :         }
     595             : 
     596          34 :         if (sec_vt != NULL && sec_vt->count.count > 0) {
     597           0 :                 printf("SEC_VT: consumed %zu bytes\n",
     598           0 :                        blob.length - ndr_pull->data_size);
     599           0 :                 if (dumpdata) {
     600           0 :                         ndrdump_data(blob.data + ndr_pull->data_size,
     601           0 :                                      blob.length - ndr_pull->data_size,
     602             :                                      dumpdata);
     603             :                 }
     604           0 :                 ndr_print_dcerpc_sec_verification_trailer(ndr_print, "SEC_VT", sec_vt);
     605             :         }
     606          34 :         TALLOC_FREE(sec_vt);
     607             : 
     608          34 :         if (flags & NDR_OUT) {
     609           7 :                 status = ndrdump_pull_and_print_pipes(format,
     610             :                                                       ndr_pull,
     611             :                                                       ndr_print,
     612             :                                                       &f->out_pipes);
     613           7 :                 if (!NT_STATUS_IS_OK(status)) {
     614           0 :                         printf("pull and dump of OUT pipes FAILED: %s\n",
     615             :                                nt_errstr(status));
     616           0 :                         TALLOC_FREE(mem_ctx);
     617           0 :                         exit(2);
     618             :                 }
     619             :         }
     620             : 
     621          34 :         ndr_err = f->ndr_pull(ndr_pull, flags, st);
     622          34 :         printf("pull returned %s\n",
     623             :                ndr_map_error2string(ndr_err));
     624             : 
     625          34 :         if (ndr_pull->offset > ndr_pull->relative_highest_offset) {
     626             :                 highest_ofs = ndr_pull->offset;
     627             :         } else {
     628             :                 highest_ofs = ndr_pull->relative_highest_offset;
     629             :         }
     630             : 
     631          34 :         if (dumpdata) {
     632           2 :                 printf("%"PRIu32" bytes consumed\n", highest_ofs);
     633           2 :                 ndrdump_data(blob.data, blob.length, dumpdata);
     634             :         }
     635             : 
     636          34 :         if (!print_after_parse_failure && !NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     637           5 :                 TALLOC_FREE(mem_ctx);
     638           5 :                 exit(2);
     639             :         }
     640             : 
     641          29 :         if (highest_ofs != ndr_pull->data_size) {
     642          12 :                 printf("WARNING! %"PRIu32" unread bytes\n", ndr_pull->data_size - highest_ofs);
     643          41 :                 ndrdump_data(ndr_pull->data+highest_ofs,
     644          12 :                              ndr_pull->data_size - highest_ofs,
     645             :                              dumpdata);
     646             :         }
     647             : 
     648          29 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     649          30 :                 printf("WARNING: pull of %s was incomplete, "
     650             :                        "therefore the parse below may SEGFAULT\n",
     651           1 :                         f->name);
     652             :         }
     653             : 
     654          29 :         f->ndr_print(ndr_print, f->name, flags, st);
     655             : 
     656          29 :         if (flags & NDR_IN) {
     657           4 :                 status = ndrdump_pull_and_print_pipes(format,
     658             :                                                       ndr_pull,
     659             :                                                       ndr_print,
     660             :                                                       &f->in_pipes);
     661           4 :                 if (!NT_STATUS_IS_OK(status)) {
     662           0 :                         printf("pull and dump of IN pipes FAILED: %s\n",
     663             :                                nt_errstr(status));
     664           0 :                         exit(1);
     665             :                 }
     666             :         }
     667             : 
     668             :         /* Do not proceed to validate if we got an error */
     669          29 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     670           2 :                 printf("dump of failed-to-parse %s complete\n",
     671           1 :                        f->name);
     672           1 :                 TALLOC_FREE(mem_ctx);
     673           1 :                 exit(2);
     674             :         }
     675             : 
     676          28 :         if (validate) {
     677          13 :                 DATA_BLOB v_blob;
     678          13 :                 struct ndr_push *ndr_v_push;
     679          13 :                 struct ndr_pull *ndr_v_pull;
     680          13 :                 struct ndr_print *ndr_v_print;
     681          13 :                 uint32_t highest_v_ofs;
     682          13 :                 uint32_t i;
     683          13 :                 uint8_t byte_a, byte_b;
     684          13 :                 bool differ;
     685             : 
     686          13 :                 ndr_v_push = ndr_push_init_ctx(mem_ctx);
     687          13 :                 if (ndr_v_push == NULL) {
     688           0 :                         printf("No memory\n");
     689           0 :                         exit(1);
     690             :                 }
     691             : 
     692          13 :                 if (assume_ndr64) {
     693           0 :                         ndr_v_push->flags |= LIBNDR_FLAG_NDR64;
     694             :                 }
     695             : 
     696          13 :                 ndr_err = f->ndr_push(ndr_v_push, flags, st);
     697          13 :                 printf("push returned %s\n",
     698             :                        ndr_map_error2string(ndr_err));
     699          13 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     700           0 :                         printf("validate push FAILED\n");
     701           0 :                         TALLOC_FREE(mem_ctx);
     702           0 :                         exit(1);
     703             :                 }
     704             : 
     705          13 :                 v_blob = ndr_push_blob(ndr_v_push);
     706             : 
     707          13 :                 if (dumpdata) {
     708           0 :                         printf("%zu bytes generated (validate)\n", v_blob.length);
     709           0 :                         ndrdump_data(v_blob.data, v_blob.length, dumpdata);
     710             :                 }
     711             : 
     712          13 :                 ndr_v_pull = ndr_pull_init_blob(&v_blob, mem_ctx);
     713          13 :                 if (ndr_v_pull == NULL) {
     714           0 :                         perror("ndr_pull_init_blob");
     715           0 :                         TALLOC_FREE(mem_ctx);
     716           0 :                         exit(1);
     717             :                 }
     718          13 :                 ndr_v_pull->flags |= LIBNDR_FLAG_REF_ALLOC;
     719             : 
     720          13 :                 ndr_err = f->ndr_pull(ndr_v_pull, flags, v_st);
     721          13 :                 printf("pull returned %s\n",
     722             :                        ndr_map_error2string(ndr_err));
     723          13 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     724           0 :                         printf("validate pull FAILED\n");
     725           0 :                         TALLOC_FREE(mem_ctx);
     726           0 :                         exit(1);
     727             :                 }
     728             : 
     729          13 :                 if (ndr_v_pull->offset > ndr_v_pull->relative_highest_offset) {
     730             :                         highest_v_ofs = ndr_v_pull->offset;
     731             :                 } else {
     732             :                         highest_v_ofs = ndr_v_pull->relative_highest_offset;
     733             :                 }
     734             : 
     735          13 :                 if (highest_v_ofs != ndr_v_pull->data_size) {
     736           0 :                         printf("WARNING! %"PRIu32" unread bytes in validation\n",
     737             :                                ndr_v_pull->data_size - highest_v_ofs);
     738          13 :                         ndrdump_data(ndr_v_pull->data + highest_v_ofs,
     739           0 :                                      ndr_v_pull->data_size - highest_v_ofs,
     740             :                                      dumpdata);
     741             :                 }
     742             : 
     743          13 :                 ndr_v_print = talloc_zero(mem_ctx, struct ndr_print);
     744          13 :                 ndr_v_print->print = ndr_print_debug_helper;
     745          13 :                 ndr_v_print->depth = 1;
     746          13 :                 f->ndr_print(ndr_v_print,
     747             :                              format,
     748             :                              flags, v_st);
     749             : 
     750          13 :                 if (blob.length != v_blob.length) {
     751           7 :                         printf("WARNING! orig bytes:%zu validated pushed bytes:%zu\n",
     752             :                                blob.length, v_blob.length);
     753             :                 }
     754             : 
     755          13 :                 if (highest_ofs != highest_v_ofs) {
     756           3 :                         printf("WARNING! orig pulled bytes:%"PRIu32" validated pulled bytes:%"PRIu32"\n",
     757             :                                highest_ofs, highest_v_ofs);
     758             :                 }
     759             : 
     760          13 :                 differ = false;
     761          13 :                 byte_a = 0x00;
     762          13 :                 byte_b = 0x00;
     763       18853 :                 for (i=0; i < blob.length; i++) {
     764       18848 :                         byte_a = blob.data[i];
     765             : 
     766       18848 :                         if (i == v_blob.length) {
     767             :                                 byte_b = 0x00;
     768             :                                 differ = true;
     769             :                                 break;
     770             :                         }
     771             : 
     772       18847 :                         byte_b = v_blob.data[i];
     773             : 
     774       18847 :                         if (byte_a != byte_b) {
     775             :                                 differ = true;
     776             :                                 break;
     777             :                         }
     778             :                 }
     779          13 :                 if (differ) {
     780           8 :                         printf("WARNING! orig and validated differ at byte 0x%02"PRIX32" (%"PRIu32")\n", i, i);
     781           8 :                         printf("WARNING! orig byte[0x%02"PRIX32"] = 0x%02"PRIX8" validated byte[0x%02"PRIX32"] = 0x%02"PRIX8"\n",
     782             :                                 i, byte_a, i, byte_b);
     783          13 :                         ndrdump_data_diff(blob.data, blob.length,
     784           8 :                                           v_blob.data, v_blob.length,
     785             :                                           dumpdata);
     786             :                 }
     787             :         }
     788             : 
     789          28 :         printf("dump OK\n");
     790          28 :         TALLOC_FREE(mem_ctx);
     791             : 
     792          28 :         poptFreeContext(pc);
     793             :         
     794          28 :         return 0;
     795             : }

Generated by: LCOV version 1.14