2003-11-23 16:44:19 +03:00
/*
Unix SMB / CIFS implementation .
SMB torture tester
Copyright ( C ) Andrew Tridgell 2003
2007-02-27 21:00:15 +03:00
Copyright ( C ) Jelmer Vernooij 2006
2003-11-23 16:44:19 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-11-23 16:44:19 +03:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-11-23 16:44:19 +03:00
*/
# include "includes.h"
2005-03-13 06:16:07 +03:00
# include "system/filesys.h"
2006-05-13 23:14:12 +04:00
# include "system/locale.h"
2007-08-21 23:35:43 +04:00
# include "librpc/ndr/libndr.h"
# include "librpc/ndr/ndr_table.h"
2014-01-06 14:19:04 +04:00
# include "librpc/gen_ndr/ndr_dcerpc.h"
2008-10-20 15:19:39 +04:00
# include "lib/cmdline/popt_common.h"
2007-12-14 00:46:23 +03:00
# include "param/param.h"
2019-11-20 00:00:52 +03:00
# include "lib/util/base64.h"
2003-11-23 16:44:19 +03:00
2007-08-18 14:30:40 +04:00
static const struct ndr_interface_call * find_function (
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * p ,
2003-11-23 16:44:19 +03:00
const char * function )
{
2019-11-12 02:11:53 +03:00
unsigned int i ;
2004-06-14 12:07:26 +04:00
if ( isdigit ( function [ 0 ] ) ) {
2019-11-12 02:11:53 +03:00
char * eptr = NULL ;
i = strtoul ( function , & eptr , 0 ) ;
if ( i > = p - > num_calls
| | eptr = = NULL
| | eptr [ 0 ] ! = ' \0 ' ) {
printf ( " Function number '%s' not found \n " ,
function ) ;
exit ( 1 ) ;
}
2004-06-14 12:07:26 +04:00
return & p - > calls [ i ] ;
}
2003-11-23 16:44:19 +03:00
for ( i = 0 ; i < p - > num_calls ; i + + ) {
if ( strcmp ( p - > calls [ i ] . name , function ) = = 0 ) {
break ;
}
}
if ( i = = p - > num_calls ) {
printf ( " Function '%s' not found \n " , function ) ;
exit ( 1 ) ;
}
return & p - > calls [ i ] ;
}
2019-06-04 23:44:09 +03:00
/*
* Find a public structure on the pipe and return it as if it were
* a function ( as the rest of ndrdump is based around functions )
*/
static const struct ndr_interface_call * find_struct (
const struct ndr_interface_table * p ,
const char * struct_name ,
struct ndr_interface_call * out_buffer )
{
2019-11-12 02:11:53 +03:00
unsigned int i ;
2019-11-14 03:14:08 +03:00
const struct ndr_interface_public_struct * public_struct = NULL ;
2019-11-12 02:11:53 +03:00
if ( isdigit ( struct_name [ 0 ] ) ) {
char * eptr = NULL ;
i = strtoul ( struct_name , & eptr , 0 ) ;
if ( i > = p - > num_public_structs
| | eptr = = NULL
| | eptr [ 0 ] ! = ' \0 ' ) {
printf ( " Public structure number '%s' not found \n " ,
struct_name ) ;
exit ( 1 ) ;
}
2019-11-14 03:14:08 +03:00
public_struct = & p - > public_structs [ i ] ;
} else {
for ( i = 0 ; i < p - > num_public_structs ; i + + ) {
if ( strcmp ( p - > public_structs [ i ] . name , struct_name ) = = 0 ) {
break ;
}
2019-06-04 23:44:09 +03:00
}
2019-11-14 03:14:08 +03:00
if ( i = = p - > num_public_structs ) {
printf ( " Public structure '%s' not found \n " , struct_name ) ;
exit ( 1 ) ;
}
public_struct = & p - > public_structs [ i ] ;
2019-06-04 23:44:09 +03:00
}
* out_buffer = ( struct ndr_interface_call ) {
2019-11-14 03:14:08 +03:00
. name = public_struct - > name ,
. struct_size = public_struct - > struct_size ,
. ndr_pull = public_struct - > ndr_pull ,
. ndr_push = public_struct - > ndr_push ,
. ndr_print = public_struct - > ndr_print
2019-06-04 23:44:09 +03:00
} ;
return out_buffer ;
}
2007-09-07 17:31:15 +04:00
_NORETURN_ static void show_pipes ( void )
2003-11-23 16:44:19 +03:00
{
2007-08-20 00:46:45 +04:00
const struct ndr_interface_list * l ;
2003-11-23 16:44:19 +03:00
printf ( " \n You must specify a pipe \n " ) ;
printf ( " known pipes are: \n " ) ;
2007-08-21 23:35:43 +04:00
for ( l = ndr_table_list ( ) ; l ; l = l - > next ) {
2005-01-09 11:34:05 +03:00
if ( l - > table - > helpstring ) {
printf ( " \t %s - %s \n " , l - > table - > name , l - > table - > helpstring ) ;
2004-08-12 23:32:16 +04:00
} else {
2005-01-09 11:34:05 +03:00
printf ( " \t %s \n " , l - > table - > name ) ;
2004-08-12 23:32:16 +04:00
}
2003-11-23 16:44:19 +03:00
}
exit ( 1 ) ;
}
2007-09-07 17:31:15 +04:00
_NORETURN_ static void show_functions ( const struct ndr_interface_table * p )
2003-11-23 16:44:19 +03:00
{
int i ;
printf ( " \n You must specify a function \n " ) ;
printf ( " known functions on '%s' are: \n " , p - > name ) ;
for ( i = 0 ; i < p - > num_calls ; i + + ) {
printf ( " \t 0x%02x (%2d) %s \n " , i , i , p - > calls [ i ] . name ) ;
}
2019-06-04 23:44:09 +03:00
printf ( " known public structures on '%s' are: \n " , p - > name ) ;
for ( i = 0 ; i < p - > num_public_structs ; i + + ) {
printf ( " \t %s \n " , p - > public_structs [ i ] . name ) ;
}
2003-11-23 16:44:19 +03:00
exit ( 1 ) ;
}
2005-03-13 06:16:07 +03:00
static char * stdin_load ( TALLOC_CTX * mem_ctx , size_t * size )
{
int num_read , total_len = 0 ;
char buf [ 255 ] ;
char * result = NULL ;
while ( ( num_read = read ( STDIN_FILENO , buf , 255 ) ) > 0 ) {
if ( result ) {
2007-09-08 17:34:42 +04:00
result = talloc_realloc (
mem_ctx , result , char , total_len + num_read ) ;
2005-03-13 06:16:07 +03:00
} else {
2007-09-08 17:34:42 +04:00
result = talloc_array ( mem_ctx , char , num_read ) ;
2005-03-13 06:16:07 +03:00
}
memcpy ( result + total_len , buf , num_read ) ;
total_len + = num_read ;
}
if ( size )
* size = total_len ;
return result ;
}
2007-09-08 17:34:42 +04:00
static const struct ndr_interface_table * load_iface_from_plugin ( const char * plugin , const char * pipe_name )
2003-11-23 16:44:19 +03:00
{
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * p ;
2006-04-08 17:43:57 +04:00
void * handle ;
char * symbol ;
handle = dlopen ( plugin , RTLD_NOW ) ;
if ( handle = = NULL ) {
printf ( " %s: Unable to open: %s \n " , plugin , dlerror ( ) ) ;
return NULL ;
}
2007-08-20 01:23:03 +04:00
symbol = talloc_asprintf ( NULL , " ndr_table_%s " , pipe_name ) ;
2007-09-08 17:34:42 +04:00
p = ( const struct ndr_interface_table * ) dlsym ( handle , symbol ) ;
2006-04-08 17:43:57 +04:00
if ( ! p ) {
printf ( " %s: Unable to find DCE/RPC interface table for '%s': %s \n " , plugin , pipe_name , dlerror ( ) ) ;
talloc_free ( symbol ) ;
2013-02-20 13:36:52 +04:00
dlclose ( handle ) ;
2006-04-08 17:43:57 +04:00
return NULL ;
}
talloc_free ( symbol ) ;
return p ;
}
2007-11-02 13:36:06 +03:00
static void ndrdump_data ( uint8_t * d , uint32_t l , bool force )
{
2012-01-25 12:10:04 +04:00
dump_data_file ( d , l , ! force , stdout ) ;
2007-11-02 13:36:06 +03:00
}
2010-09-21 10:34:31 +04:00
static NTSTATUS ndrdump_pull_and_print_pipes ( const char * function ,
struct ndr_pull * ndr_pull ,
struct ndr_print * ndr_print ,
const struct ndr_interface_call_pipes * pipes )
{
enum ndr_err_code ndr_err ;
uint32_t i ;
for ( i = 0 ; i < pipes - > num_pipes ; i + + ) {
uint64_t idx = 0 ;
while ( true ) {
2013-09-10 13:07:48 +04:00
void * saved_mem_ctx ;
2010-09-21 10:34:31 +04:00
uint32_t * count ;
void * c ;
char * n ;
c = talloc_zero_size ( ndr_pull , pipes - > pipes [ i ] . chunk_struct_size ) ;
talloc_set_name ( c , " struct %s " , pipes - > pipes [ i ] . name ) ;
/*
* Note : the first struct member is always
* ' uint32_t count ; '
*/
count = ( uint32_t * ) c ;
n = talloc_asprintf ( c , " %s: %s[%llu] " ,
function , pipes - > pipes [ i ] . name ,
( unsigned long long ) idx ) ;
2013-09-10 13:07:48 +04:00
saved_mem_ctx = ndr_pull - > current_mem_ctx ;
ndr_pull - > current_mem_ctx = c ;
2010-09-21 10:34:31 +04:00
ndr_err = pipes - > pipes [ i ] . ndr_pull ( ndr_pull , NDR_SCALARS , c ) ;
2013-09-10 13:07:48 +04:00
ndr_pull - > current_mem_ctx = saved_mem_ctx ;
2010-09-21 10:34:31 +04:00
2019-11-15 09:25:54 +03:00
printf ( " pull returned %s \n " ,
ndr_map_error2string ( ndr_err ) ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2013-09-10 13:07:48 +04:00
talloc_free ( c ) ;
2019-11-15 09:25:54 +03:00
return ndr_map_error2ntstatus ( ndr_err ) ;
2010-09-21 10:34:31 +04:00
}
pipes - > pipes [ i ] . ndr_print ( ndr_print , n , c ) ;
if ( * count = = 0 ) {
2019-11-16 11:25:11 +03:00
talloc_free ( c ) ;
2010-09-21 10:34:31 +04:00
break ;
}
2019-11-16 11:25:11 +03:00
talloc_free ( c ) ;
2010-09-21 10:34:31 +04:00
idx + + ;
}
}
return NT_STATUS_OK ;
}
2016-03-01 04:13:18 +03:00
static void ndr_print_dummy ( struct ndr_print * ndr , const char * format , . . . )
{
/* This is here so that you can turn ndr printing off for the purposes
of benchmarking ndr parsing . */
}
2006-04-08 17:43:57 +04:00
int main ( int argc , const char * argv [ ] )
{
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * p = NULL ;
2007-08-18 14:30:40 +04:00
const struct ndr_interface_call * f ;
2019-06-04 23:44:09 +03:00
struct ndr_interface_call f_buffer ;
const char * pipe_name = NULL ;
const char * filename = NULL ;
/*
* The format type :
* in : a request
* out : a response
* struct : a public structure
*/
const char * type = NULL ;
/*
* Format is either the name of the decoding function or the
* name of a public structure
*/
const char * format = NULL ;
2019-11-20 00:00:52 +03:00
const char * cmdline_input = NULL ;
2019-11-19 23:58:15 +03:00
const uint8_t * data ;
2003-11-23 16:44:19 +03:00
size_t size ;
DATA_BLOB blob ;
2005-08-22 20:21:29 +04:00
struct ndr_pull * ndr_pull ;
struct ndr_print * ndr_print ;
2003-11-23 16:44:19 +03:00
TALLOC_CTX * mem_ctx ;
2019-04-12 06:10:35 +03:00
int flags = 0 ;
2004-10-16 23:00:27 +04:00
poptContext pc ;
2003-11-23 16:44:19 +03:00
NTSTATUS status ;
2007-11-09 21:24:25 +03:00
enum ndr_err_code ndr_err ;
2003-11-23 16:44:19 +03:00
void * st ;
2005-08-22 20:21:29 +04:00
void * v_st ;
2004-10-31 22:07:28 +03:00
const char * ctx_filename = NULL ;
2006-04-08 17:43:57 +04:00
const char * plugin = NULL ;
2007-02-14 16:22:09 +03:00
bool validate = false ;
bool dumpdata = false ;
2009-09-17 10:57:32 +04:00
bool assume_ndr64 = false ;
2016-03-01 04:13:18 +03:00
bool quiet = false ;
2016-08-27 18:01:18 +03:00
bool hex_input = false ;
2019-11-20 00:00:52 +03:00
bool base64_input = false ;
2019-11-20 03:26:11 +03:00
bool print_after_parse_failure = false ;
2004-10-16 23:00:27 +04:00
int opt ;
2019-10-30 06:05:22 +03:00
enum {
OPT_CONTEXT_FILE = 1000 ,
OPT_VALIDATE ,
OPT_DUMP_DATA ,
OPT_LOAD_DSO ,
OPT_NDR64 ,
OPT_QUIET ,
2019-11-20 00:00:52 +03:00
OPT_BASE64_INPUT ,
2019-10-30 06:05:22 +03:00
OPT_HEX_INPUT ,
2019-11-20 00:00:52 +03:00
OPT_CMDLINE_INPUT ,
2019-11-20 03:26:11 +03:00
OPT_PRINT_AFTER_PARSE_FAILURE ,
2019-10-30 06:05:22 +03:00
} ;
2004-10-16 23:00:27 +04:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2007-02-14 16:22:09 +03:00
{ " context-file " , ' c ' , POPT_ARG_STRING , NULL , OPT_CONTEXT_FILE , " In-filename to parse first " , " CTX-FILE " } ,
{ " validate " , 0 , POPT_ARG_NONE , NULL , OPT_VALIDATE , " try to validate the data " , NULL } ,
{ " dump-data " , 0 , POPT_ARG_NONE , NULL , OPT_DUMP_DATA , " dump the hex data " , NULL } ,
{ " load-dso " , ' l ' , POPT_ARG_STRING , NULL , OPT_LOAD_DSO , " load from shared object file " , NULL } ,
2009-09-18 02:15:36 +04:00
{ " ndr64 " , 0 , POPT_ARG_NONE , NULL , OPT_NDR64 , " Assume NDR64 data " , NULL } ,
2016-03-01 04:13:18 +03:00
{ " quiet " , 0 , POPT_ARG_NONE , NULL , OPT_QUIET , " Don't actually dump anything " , NULL } ,
2019-11-20 00:00:52 +03:00
{ " base64-input " , 0 , POPT_ARG_NONE , NULL , OPT_BASE64_INPUT , " Read the input file in as a base64 string " , NULL } ,
2016-08-27 18:01:18 +03:00
{ " hex-input " , 0 , POPT_ARG_NONE , NULL , OPT_HEX_INPUT , " Read the input file in as a hex dump " , NULL } ,
2019-11-20 00:00:52 +03:00
{ " input " , 0 , POPT_ARG_STRING , NULL , OPT_CMDLINE_INPUT , " Provide the input on the command line (use with --base64-input) " , " INPUT " } ,
2019-11-20 03:26:11 +03:00
{ " print-after-parse-failure " , 0 , POPT_ARG_NONE , NULL , OPT_PRINT_AFTER_PARSE_FAILURE ,
" Try to print structures that fail to parse (used to develop parsers, segfaults are likely). " , NULL } ,
2007-02-14 16:22:09 +03:00
POPT_COMMON_SAMBA
POPT_COMMON_VERSION
2006-09-06 16:28:01 +04:00
{ NULL }
2004-10-16 23:00:27 +04:00
} ;
2013-02-01 20:44:16 +04:00
uint32_t highest_ofs ;
2014-01-06 14:19:04 +04:00
struct dcerpc_sec_verification_trailer * sec_vt = NULL ;
2016-08-27 18:01:18 +03:00
2007-08-20 01:23:03 +04:00
ndr_table_init ( ) ;
2008-10-20 20:59:51 +04:00
2007-03-02 16:44:56 +03:00
/* Initialise samba stuff */
2015-03-21 22:00:06 +03:00
smb_init_locale ( ) ;
2007-03-02 16:44:56 +03:00
setlinebuf ( stdout ) ;
2010-10-29 08:00:01 +04:00
setup_logging ( " ndrdump " , DEBUG_STDOUT ) ;
2004-11-17 00:07:08 +03:00
2004-10-16 23:00:27 +04:00
pc = poptGetContext ( " ndrdump " , argc , argv , long_options , 0 ) ;
2005-03-16 09:18:20 +03:00
poptSetOtherOptionHelp (
2019-06-04 23:44:09 +03:00
pc , " <pipe|uuid> <format> <in|out|struct> [<filename>] " ) ;
2004-10-16 23:00:27 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
2007-02-14 16:22:09 +03:00
switch ( opt ) {
case OPT_CONTEXT_FILE :
ctx_filename = poptGetOptArg ( pc ) ;
break ;
case OPT_VALIDATE :
validate = true ;
break ;
case OPT_DUMP_DATA :
dumpdata = true ;
break ;
case OPT_LOAD_DSO :
plugin = poptGetOptArg ( pc ) ;
break ;
2009-09-17 10:57:32 +04:00
case OPT_NDR64 :
assume_ndr64 = true ;
break ;
2016-03-01 04:13:18 +03:00
case OPT_QUIET :
quiet = true ;
break ;
2019-11-20 00:00:52 +03:00
case OPT_BASE64_INPUT :
base64_input = true ;
break ;
2016-08-27 18:01:18 +03:00
case OPT_HEX_INPUT :
hex_input = true ;
break ;
2019-11-20 00:00:52 +03:00
case OPT_CMDLINE_INPUT :
cmdline_input = poptGetOptArg ( pc ) ;
break ;
2019-11-20 03:26:11 +03:00
case OPT_PRINT_AFTER_PARSE_FAILURE :
print_after_parse_failure = true ;
2019-10-30 06:05:22 +03:00
break ;
2007-02-14 16:22:09 +03:00
}
2004-10-16 23:00:27 +04:00
}
pipe_name = poptGetArg ( pc ) ;
if ( ! pipe_name ) {
poptPrintUsage ( pc , stderr , 0 ) ;
2003-11-23 16:44:19 +03:00
show_pipes ( ) ;
exit ( 1 ) ;
}
2006-04-08 17:43:57 +04:00
if ( plugin ! = NULL ) {
p = load_iface_from_plugin ( plugin , pipe_name ) ;
2007-03-02 15:47:51 +03:00
}
2006-04-08 17:43:57 +04:00
if ( ! p ) {
2007-08-21 23:35:43 +04:00
p = ndr_table_by_name ( pipe_name ) ;
2006-04-08 17:43:57 +04:00
}
2003-11-23 16:44:19 +03:00
2004-11-20 21:51:58 +03:00
if ( ! p ) {
2005-12-27 19:22:35 +03:00
struct GUID uuid ;
2005-03-16 09:18:20 +03:00
2005-12-27 19:22:35 +03:00
status = GUID_from_string ( pipe_name , & uuid ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2007-08-21 23:35:43 +04:00
p = ndr_table_by_uuid ( & uuid ) ;
2005-12-27 19:22:35 +03:00
}
2006-04-08 17:43:57 +04:00
}
2005-03-16 09:18:20 +03:00
2006-04-08 17:43:57 +04:00
if ( ! p ) {
printf ( " Unknown pipe or UUID '%s' \n " , pipe_name ) ;
exit ( 1 ) ;
2004-11-20 21:51:58 +03:00
}
2019-06-04 23:44:09 +03:00
format = poptGetArg ( pc ) ;
type = poptGetArg ( pc ) ;
2004-10-16 23:00:27 +04:00
filename = poptGetArg ( pc ) ;
2019-06-04 23:44:09 +03:00
if ( ! format | | ! type ) {
2004-10-16 23:00:27 +04:00
poptPrintUsage ( pc , stderr , 0 ) ;
2003-11-23 16:44:19 +03:00
show_functions ( p ) ;
exit ( 1 ) ;
}
2019-06-04 23:44:09 +03:00
if ( strcmp ( type , " struct " ) = = 0 ) {
2019-11-05 06:15:38 +03:00
flags = NDR_SCALARS | NDR_BUFFERS ; /* neither NDR_IN nor NDR_OUT */
2019-06-04 23:44:09 +03:00
f = find_struct ( p , format , & f_buffer ) ;
2003-11-23 16:44:19 +03:00
} else {
2019-06-04 23:44:09 +03:00
f = find_function ( p , format ) ;
if ( strcmp ( type , " in " ) = = 0 | |
strcmp ( type , " request " ) = = 0 ) {
flags | = NDR_IN ;
} else if ( strcmp ( type , " out " ) = = 0 | |
strcmp ( type , " response " ) = = 0 ) {
flags | = NDR_OUT ;
} else {
printf ( " Bad type value '%s' \n " , type ) ;
exit ( 1 ) ;
}
2003-11-23 16:44:19 +03:00
}
2019-06-04 23:44:09 +03:00
2004-10-31 22:07:28 +03:00
mem_ctx = talloc_init ( " ndrdump " ) ;
2005-01-07 07:39:16 +03:00
st = talloc_zero_size ( mem_ctx , f - > struct_size ) ;
2004-10-31 22:07:28 +03:00
if ( ! st ) {
2019-11-18 03:44:02 +03:00
printf ( " Unable to allocate %d bytes for %s structure \n " ,
( int ) f - > struct_size ,
f - > name ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2004-10-31 22:07:28 +03:00
exit ( 1 ) ;
}
2005-08-22 20:21:29 +04:00
v_st = talloc_zero_size ( mem_ctx , f - > struct_size ) ;
if ( ! v_st ) {
2019-11-18 03:44:02 +03:00
printf ( " Unable to allocate %d bytes for %s validation "
" structure \n " ,
( int ) f - > struct_size ,
f - > name ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2005-08-22 20:21:29 +04:00
exit ( 1 ) ;
}
2004-10-31 22:07:28 +03:00
if ( ctx_filename ) {
2019-04-12 06:10:35 +03:00
if ( flags & NDR_IN ) {
2004-10-31 22:07:28 +03:00
printf ( " Context file can only be used for \" out \" packages \n " ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2004-10-31 22:07:28 +03:00
exit ( 1 ) ;
}
2008-10-12 21:46:38 +04:00
data = ( uint8_t * ) file_load ( ctx_filename , & size , 0 , mem_ctx ) ;
2004-10-31 22:07:28 +03:00
if ( ! data ) {
perror ( ctx_filename ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2004-10-31 22:07:28 +03:00
exit ( 1 ) ;
}
2019-11-19 23:58:15 +03:00
blob = data_blob_const ( data , size ) ;
2004-10-31 22:07:28 +03:00
2010-05-09 19:20:01 +04:00
ndr_pull = ndr_pull_init_blob ( & blob , mem_ctx ) ;
2013-02-19 11:56:22 +04:00
if ( ndr_pull = = NULL ) {
perror ( " ndr_pull_init_blob " ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2013-02-19 11:56:22 +04:00
exit ( 1 ) ;
}
2005-08-22 20:21:29 +04:00
ndr_pull - > flags | = LIBNDR_FLAG_REF_ALLOC ;
2009-09-17 10:57:32 +04:00
if ( assume_ndr64 ) {
ndr_pull - > flags | = LIBNDR_FLAG_NDR64 ;
}
2004-10-31 22:07:28 +03:00
2007-11-09 21:24:25 +03:00
ndr_err = f - > ndr_pull ( ndr_pull , NDR_IN , st ) ;
2004-10-31 22:07:28 +03:00
2013-02-01 20:44:16 +04:00
if ( ndr_pull - > offset > ndr_pull - > relative_highest_offset ) {
highest_ofs = ndr_pull - > offset ;
} else {
highest_ofs = ndr_pull - > relative_highest_offset ;
}
if ( highest_ofs ! = ndr_pull - > data_size ) {
printf ( " WARNING! %d unread bytes while parsing context file \n " , ndr_pull - > data_size - highest_ofs ) ;
2004-10-31 22:07:28 +03:00
}
2007-11-09 21:24:25 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2019-11-15 09:25:54 +03:00
printf ( " pull for context file returned %s \n " ,
ndr_map_error2string ( ndr_err ) ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2019-11-20 00:39:54 +03:00
exit ( 2 ) ;
2004-10-31 22:07:28 +03:00
}
2005-08-22 20:21:29 +04:00
memcpy ( v_st , st , f - > struct_size ) ;
2016-08-27 18:01:18 +03:00
}
2004-10-31 22:07:28 +03:00
2019-11-20 00:00:52 +03:00
if ( filename & & cmdline_input ) {
printf ( " cannot combine --input with a filename \n " ) ;
TALLOC_FREE ( mem_ctx ) ;
exit ( 1 ) ;
} else if ( cmdline_input ) {
data = ( const uint8_t * ) cmdline_input ;
size = strlen ( cmdline_input ) ;
} else if ( filename ) {
2008-10-12 21:46:38 +04:00
data = ( uint8_t * ) file_load ( filename , & size , 0 , mem_ctx ) ;
2019-11-20 00:00:52 +03:00
} else {
2005-03-13 06:16:07 +03:00
data = ( uint8_t * ) stdin_load ( mem_ctx , & size ) ;
2019-11-20 00:00:52 +03:00
}
2005-03-13 06:16:07 +03:00
2003-11-23 16:44:19 +03:00
if ( ! data ) {
2005-03-13 06:16:07 +03:00
if ( filename )
perror ( filename ) ;
else
perror ( " stdin " ) ;
2003-11-23 16:44:19 +03:00
exit ( 1 ) ;
}
2016-08-27 18:01:18 +03:00
2019-11-20 00:00:52 +03:00
if ( hex_input & & base64_input ) {
printf ( " cannot combine --hex-input with --base64-input \n " ) ;
TALLOC_FREE ( mem_ctx ) ;
exit ( 1 ) ;
} else if ( hex_input ) {
blob = hexdump_to_data_blob ( mem_ctx , ( const char * ) data , size ) ;
} else if ( base64_input ) {
/* Use talloc_strndup() to ensure null termination */
blob = base64_decode_data_blob ( talloc_strndup ( mem_ctx ,
( const char * ) data , size ) ) ;
/* base64_decode_data_blob() allocates on NULL */
talloc_steal ( mem_ctx , blob . data ) ;
2016-08-27 18:01:18 +03:00
} else {
2019-11-19 23:58:15 +03:00
blob = data_blob_const ( data , size ) ;
2016-08-27 18:01:18 +03:00
}
2003-11-23 16:44:19 +03:00
2019-11-19 23:59:07 +03:00
if ( data ! = NULL & & blob . data = = NULL ) {
printf ( " failed to decode input data \n " ) ;
TALLOC_FREE ( mem_ctx ) ;
exit ( 1 ) ;
}
2010-05-09 19:20:01 +04:00
ndr_pull = ndr_pull_init_blob ( & blob , mem_ctx ) ;
2013-02-19 11:56:22 +04:00
if ( ndr_pull = = NULL ) {
perror ( " ndr_pull_init_blob " ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2013-02-19 11:56:22 +04:00
exit ( 1 ) ;
}
2005-08-22 20:21:29 +04:00
ndr_pull - > flags | = LIBNDR_FLAG_REF_ALLOC ;
2009-09-17 10:57:32 +04:00
if ( assume_ndr64 ) {
ndr_pull - > flags | = LIBNDR_FLAG_NDR64 ;
}
2003-11-23 16:44:19 +03:00
2010-09-21 10:34:31 +04:00
ndr_print = talloc_zero ( mem_ctx , struct ndr_print ) ;
2016-03-01 04:13:18 +03:00
if ( quiet ) {
ndr_print - > print = ndr_print_dummy ;
} else {
ndr_print - > print = ndr_print_printf_helper ;
}
2010-09-21 10:34:31 +04:00
ndr_print - > depth = 1 ;
2014-01-06 14:19:04 +04:00
ndr_err = ndr_pop_dcerpc_sec_verification_trailer ( ndr_pull , mem_ctx , & sec_vt ) ;
2019-11-15 09:25:54 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2014-01-06 14:19:04 +04:00
printf ( " ndr_pop_dcerpc_sec_verification_trailer returned %s \n " ,
2019-11-15 09:25:54 +03:00
ndr_map_error2string ( ndr_err ) ) ;
2014-01-06 14:19:04 +04:00
}
if ( sec_vt ! = NULL & & sec_vt - > count . count > 0 ) {
printf ( " SEC_VT: consumed %d bytes \n " ,
( int ) ( blob . length - ndr_pull - > data_size ) ) ;
if ( dumpdata ) {
ndrdump_data ( blob . data + ndr_pull - > data_size ,
blob . length - ndr_pull - > data_size ,
dumpdata ) ;
}
ndr_print_dcerpc_sec_verification_trailer ( ndr_print , " SEC_VT " , sec_vt ) ;
}
TALLOC_FREE ( sec_vt ) ;
2019-04-04 01:04:23 +03:00
if ( flags & NDR_OUT ) {
2019-06-04 23:44:09 +03:00
status = ndrdump_pull_and_print_pipes ( format ,
ndr_pull ,
ndr_print ,
& f - > out_pipes ) ;
2010-09-21 10:34:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2019-11-20 08:54:04 +03:00
printf ( " pull and dump of OUT pipes FAILED: %s \n " ,
nt_errstr ( status ) ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2019-11-20 00:39:54 +03:00
exit ( 2 ) ;
2010-09-21 10:34:31 +04:00
}
}
2007-11-09 21:24:25 +03:00
ndr_err = f - > ndr_pull ( ndr_pull , flags , st ) ;
2019-11-15 09:25:54 +03:00
printf ( " pull returned %s \n " ,
ndr_map_error2string ( ndr_err ) ) ;
2003-11-23 16:44:19 +03:00
2013-02-01 20:44:16 +04:00
if ( ndr_pull - > offset > ndr_pull - > relative_highest_offset ) {
highest_ofs = ndr_pull - > offset ;
} else {
highest_ofs = ndr_pull - > relative_highest_offset ;
}
2019-11-20 00:45:02 +03:00
if ( dumpdata ) {
printf ( " %d bytes consumed \n " , highest_ofs ) ;
ndrdump_data ( blob . data , blob . length , dumpdata ) ;
}
if ( ! print_after_parse_failure & & ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
TALLOC_FREE ( mem_ctx ) ;
exit ( 2 ) ;
}
2013-02-01 20:44:16 +04:00
if ( highest_ofs ! = ndr_pull - > data_size ) {
printf ( " WARNING! %d unread bytes \n " , ndr_pull - > data_size - highest_ofs ) ;
ndrdump_data ( ndr_pull - > data + highest_ofs ,
ndr_pull - > data_size - highest_ofs ,
2007-11-02 13:36:06 +03:00
dumpdata ) ;
2003-11-23 16:44:19 +03:00
}
2019-11-20 00:45:02 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
printf ( " WARNING: pull of %s was incomplete, "
" therefore the parse below may SEGFAULT \n " ,
f - > name ) ;
2005-08-22 20:21:29 +04:00
}
2019-11-20 08:53:09 +03:00
f - > ndr_print ( ndr_print , f - > name , flags , st ) ;
2003-11-23 16:44:19 +03:00
2019-04-04 01:04:23 +03:00
if ( flags & NDR_IN ) {
2019-06-04 23:44:09 +03:00
status = ndrdump_pull_and_print_pipes ( format ,
ndr_pull ,
ndr_print ,
& f - > in_pipes ) ;
2010-09-21 10:34:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2019-11-20 08:54:04 +03:00
printf ( " pull and dump of IN pipes FAILED: %s \n " ,
nt_errstr ( status ) ) ;
2010-09-21 10:34:31 +04:00
exit ( 1 ) ;
}
}
2005-08-22 20:21:29 +04:00
if ( validate ) {
DATA_BLOB v_blob ;
struct ndr_push * ndr_v_push ;
struct ndr_pull * ndr_v_pull ;
struct ndr_print * ndr_v_print ;
2016-01-06 15:28:02 +03:00
uint32_t highest_v_ofs ;
2007-02-14 16:24:37 +03:00
uint32_t i ;
uint8_t byte_a , byte_b ;
bool differ ;
2005-08-22 20:21:29 +04:00
2010-05-09 19:20:01 +04:00
ndr_v_push = ndr_push_init_ctx ( mem_ctx ) ;
2017-02-16 19:34:07 +03:00
if ( ndr_v_push = = NULL ) {
printf ( " No memory \n " ) ;
exit ( 1 ) ;
}
2016-08-23 16:54:26 +03:00
if ( assume_ndr64 ) {
ndr_v_push - > flags | = LIBNDR_FLAG_NDR64 ;
}
2007-11-09 21:24:25 +03:00
ndr_err = f - > ndr_push ( ndr_v_push , flags , st ) ;
2019-11-20 02:17:37 +03:00
printf ( " push returned %s \n " ,
ndr_map_error2string ( ndr_err ) ) ;
2007-11-09 21:24:25 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2005-08-22 20:21:29 +04:00
printf ( " validate push FAILED \n " ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2005-08-22 20:21:29 +04:00
exit ( 1 ) ;
}
v_blob = ndr_push_blob ( ndr_v_push ) ;
if ( dumpdata ) {
2005-09-03 15:52:42 +04:00
printf ( " %ld bytes generated (validate) \n " , ( long ) v_blob . length ) ;
2007-11-02 13:36:06 +03:00
ndrdump_data ( v_blob . data , v_blob . length , dumpdata ) ;
2005-08-22 20:21:29 +04:00
}
2010-05-09 19:20:01 +04:00
ndr_v_pull = ndr_pull_init_blob ( & v_blob , mem_ctx ) ;
2013-02-19 11:56:22 +04:00
if ( ndr_v_pull = = NULL ) {
perror ( " ndr_pull_init_blob " ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2013-02-19 11:56:22 +04:00
exit ( 1 ) ;
}
2005-08-22 20:21:29 +04:00
ndr_v_pull - > flags | = LIBNDR_FLAG_REF_ALLOC ;
2007-11-09 21:24:25 +03:00
ndr_err = f - > ndr_pull ( ndr_v_pull , flags , v_st ) ;
2019-11-15 09:25:54 +03:00
printf ( " pull returned %s \n " ,
ndr_map_error2string ( ndr_err ) ) ;
2007-11-09 21:24:25 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2005-08-22 20:21:29 +04:00
printf ( " validate pull FAILED \n " ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2005-08-22 20:21:29 +04:00
exit ( 1 ) ;
}
2016-01-06 15:28:02 +03:00
if ( ndr_v_pull - > offset > ndr_v_pull - > relative_highest_offset ) {
highest_v_ofs = ndr_v_pull - > offset ;
} else {
highest_v_ofs = ndr_v_pull - > relative_highest_offset ;
}
2005-08-22 20:21:29 +04:00
2016-01-06 15:28:02 +03:00
if ( highest_v_ofs ! = ndr_v_pull - > data_size ) {
printf ( " WARNING! %d unread bytes in validation \n " ,
ndr_v_pull - > data_size - highest_v_ofs ) ;
ndrdump_data ( ndr_v_pull - > data + highest_v_ofs ,
ndr_v_pull - > data_size - highest_v_ofs ,
2007-11-02 13:36:06 +03:00
dumpdata ) ;
2005-08-22 20:21:29 +04:00
}
ndr_v_print = talloc_zero ( mem_ctx , struct ndr_print ) ;
ndr_v_print - > print = ndr_print_debug_helper ;
ndr_v_print - > depth = 1 ;
2019-06-04 23:44:09 +03:00
f - > ndr_print ( ndr_v_print ,
format ,
flags , v_st ) ;
2005-08-22 20:21:29 +04:00
if ( blob . length ! = v_blob . length ) {
2007-08-23 06:10:17 +04:00
printf ( " WARNING! orig bytes:%llu validated pushed bytes:%llu \n " ,
( unsigned long long ) blob . length , ( unsigned long long ) v_blob . length ) ;
2005-08-22 20:21:29 +04:00
}
2016-01-06 15:28:02 +03:00
if ( highest_ofs ! = highest_v_ofs ) {
2007-08-23 06:10:17 +04:00
printf ( " WARNING! orig pulled bytes:%llu validated pulled bytes:%llu \n " ,
2016-01-06 15:28:02 +03:00
( unsigned long long ) highest_ofs , ( unsigned long long ) highest_v_ofs ) ;
2007-02-14 16:24:37 +03:00
}
differ = false ;
byte_a = 0x00 ;
byte_b = 0x00 ;
for ( i = 0 ; i < blob . length ; i + + ) {
byte_a = blob . data [ i ] ;
if ( i = = v_blob . length ) {
byte_b = 0x00 ;
differ = true ;
break ;
}
byte_b = v_blob . data [ i ] ;
if ( byte_a ! = byte_b ) {
differ = true ;
break ;
}
}
if ( differ ) {
printf ( " WARNING! orig and validated differ at byte 0x%02X (%u) \n " , i , i ) ;
printf ( " WARNING! orig byte[0x%02X] = 0x%02X validated byte[0x%02X] = 0x%02X \n " ,
i , byte_a , i , byte_b ) ;
2005-08-22 20:21:29 +04:00
}
}
2003-11-24 00:51:24 +03:00
printf ( " dump OK \n " ) ;
2019-11-18 03:46:53 +03:00
TALLOC_FREE ( mem_ctx ) ;
2005-08-22 20:21:29 +04:00
2004-10-16 23:00:27 +04:00
poptFreeContext ( pc ) ;
2003-11-23 16:44:19 +03:00
return 0 ;
}