2003-11-23 16:44:19 +03:00
/*
Unix SMB / CIFS implementation .
SMB torture tester
Copyright ( C ) Andrew Tridgell 2003
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
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-02 05:57:18 +03:00
# include "lib/cmdline/popt_common.h"
2004-11-02 04:42:45 +03:00
# include "system/iconv.h"
2004-11-03 03:38:05 +03:00
# include "librpc/gen_ndr/tables.h"
2003-11-23 16:44:19 +03:00
2004-04-11 00:18:22 +04:00
static const struct dcerpc_interface_table * find_pipe ( const char * pipe_name )
2003-11-23 16:44:19 +03:00
{
int i ;
2003-11-24 04:24:29 +03:00
for ( i = 0 ; dcerpc_pipes [ i ] ; i + + ) {
if ( strcmp ( dcerpc_pipes [ i ] - > name , pipe_name ) = = 0 ) {
2003-11-23 16:44:19 +03:00
break ;
}
}
2003-11-24 04:24:29 +03:00
if ( ! dcerpc_pipes [ i ] ) {
2003-11-23 16:44:19 +03:00
printf ( " pipe '%s' not in table \n " , pipe_name ) ;
exit ( 1 ) ;
}
2003-11-24 04:24:29 +03:00
return dcerpc_pipes [ i ] ;
2003-11-23 16:44:19 +03:00
}
static const struct dcerpc_interface_call * find_function (
const struct dcerpc_interface_table * p ,
const char * function )
{
int i ;
2004-06-14 12:07:26 +04:00
if ( isdigit ( function [ 0 ] ) ) {
i = strtol ( function , NULL , 0 ) ;
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 ] ;
}
static void show_pipes ( void )
{
int i ;
printf ( " \n You must specify a pipe \n " ) ;
printf ( " known pipes are: \n " ) ;
2003-11-24 04:24:29 +03:00
for ( i = 0 ; dcerpc_pipes [ i ] ; i + + ) {
2004-08-12 23:32:16 +04:00
if ( dcerpc_pipes [ i ] - > helpstring ) {
printf ( " \t %s - %s \n " , dcerpc_pipes [ i ] - > name , dcerpc_pipes [ i ] - > helpstring ) ;
} else {
printf ( " \t %s \n " , dcerpc_pipes [ i ] - > name ) ;
}
2003-11-23 16:44:19 +03:00
}
exit ( 1 ) ;
}
static void show_functions ( const struct dcerpc_interface_table * p )
{
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 ) ;
}
exit ( 1 ) ;
}
2004-10-16 23:00:27 +04:00
int main ( int argc , const char * argv [ ] )
2003-11-23 16:44:19 +03:00
{
const struct dcerpc_interface_table * p ;
const struct dcerpc_interface_call * f ;
const char * pipe_name , * function , * inout , * filename ;
char * data ;
size_t size ;
DATA_BLOB blob ;
struct ndr_pull * ndr ;
TALLOC_CTX * mem_ctx ;
int flags ;
2004-10-16 23:00:27 +04:00
poptContext pc ;
2003-11-23 16:44:19 +03:00
NTSTATUS status ;
void * st ;
2004-10-31 22:07:28 +03:00
const char * ctx_filename = NULL ;
2004-10-16 23:00:27 +04:00
int opt ;
2004-08-21 11:43:29 +04:00
struct ndr_print * pr ;
2004-10-16 23:00:27 +04:00
struct poptOption long_options [ ] = {
2004-10-31 22:07:28 +03:00
{ " context-file " , ' c ' , POPT_ARG_STRING , & ctx_filename , 0 , " In-filename to parse first " , " CTX-FILE " } ,
2004-10-16 23:00:27 +04:00
POPT_AUTOHELP
POPT_TABLEEND
} ;
2003-11-23 16:44:19 +03:00
2004-11-07 02:23:15 +03:00
ndrdump_init_subsystems ;
2003-11-23 16:44:19 +03:00
DEBUGLEVEL = 10 ;
2004-08-16 23:03:22 +04:00
setup_logging ( " ndrdump " , DEBUG_STDOUT ) ;
2003-11-23 16:44:19 +03:00
2004-10-16 23:00:27 +04:00
pc = poptGetContext ( " ndrdump " , argc , argv , long_options , 0 ) ;
poptSetOtherOptionHelp ( pc , " <pipe> <function> <inout> <filename> " ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
}
pipe_name = poptGetArg ( pc ) ;
if ( ! pipe_name ) {
poptPrintUsage ( pc , stderr , 0 ) ;
2003-11-23 16:44:19 +03:00
show_pipes ( ) ;
exit ( 1 ) ;
}
p = find_pipe ( pipe_name ) ;
2004-10-16 23:00:27 +04:00
function = poptGetArg ( pc ) ;
inout = poptGetArg ( pc ) ;
filename = poptGetArg ( pc ) ;
if ( ! function | | ! inout | | ! filename ) {
poptPrintUsage ( pc , stderr , 0 ) ;
2003-11-23 16:44:19 +03:00
show_functions ( p ) ;
exit ( 1 ) ;
}
if ( strcmp ( inout , " in " ) = = 0 | |
strcmp ( inout , " request " ) = = 0 ) {
flags = NDR_IN ;
} else if ( strcmp ( inout , " out " ) = = 0 | |
strcmp ( inout , " response " ) = = 0 ) {
flags = NDR_OUT ;
} else {
printf ( " Bad inout value '%s' \n " , inout ) ;
exit ( 1 ) ;
}
f = find_function ( p , function ) ;
2004-10-31 22:07:28 +03:00
mem_ctx = talloc_init ( " ndrdump " ) ;
st = talloc_zero ( mem_ctx , f - > struct_size ) ;
if ( ! st ) {
printf ( " Unable to allocate %d bytes \n " , f - > struct_size ) ;
exit ( 1 ) ;
}
if ( ctx_filename ) {
if ( flags = = NDR_IN ) {
printf ( " Context file can only be used for \" out \" packages \n " ) ;
exit ( 1 ) ;
}
data = file_load ( ctx_filename , & size ) ;
if ( ! data ) {
perror ( ctx_filename ) ;
exit ( 1 ) ;
}
blob . data = data ;
blob . length = size ;
ndr = ndr_pull_init_blob ( & blob , mem_ctx ) ;
status = f - > ndr_pull ( ndr , NDR_IN , st ) ;
if ( ndr - > offset ! = ndr - > data_size ) {
printf ( " WARNING! %d unread bytes while parsing context file \n " , ndr - > data_size - ndr - > offset ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " pull for context file returned %s \n " , nt_errstr ( status ) ) ;
exit ( 1 ) ;
}
}
2003-11-23 16:44:19 +03:00
data = file_load ( filename , & size ) ;
if ( ! data ) {
perror ( filename ) ;
exit ( 1 ) ;
}
blob . data = data ;
blob . length = size ;
ndr = ndr_pull_init_blob ( & blob , mem_ctx ) ;
if ( flags = = NDR_OUT ) {
ndr - > flags | = LIBNDR_FLAG_REF_ALLOC ;
}
status = f - > ndr_pull ( ndr , flags , st ) ;
printf ( " pull returned %s \n " , nt_errstr ( status ) ) ;
if ( ndr - > offset ! = ndr - > data_size ) {
printf ( " WARNING! %d unread bytes \n " , ndr - > data_size - ndr - > offset ) ;
2004-06-14 12:07:26 +04:00
dump_data ( 0 , ndr - > data + ndr - > offset , ndr - > data_size - ndr - > offset ) ;
2003-11-23 16:44:19 +03:00
}
2004-08-21 11:43:29 +04:00
pr = talloc_p ( NULL , struct ndr_print ) ;
pr - > print = ndr_print_debug_helper ;
pr - > depth = 1 ;
2004-11-02 22:52:51 +03:00
f - > ndr_print ( pr , function , flags , st ) ;
2003-11-23 16:44:19 +03:00
2003-11-24 00:51:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) | |
ndr - > offset ! = ndr - > data_size ) {
printf ( " dump FAILED \n " ) ;
exit ( 1 ) ;
}
printf ( " dump OK \n " ) ;
2004-08-21 11:43:29 +04:00
talloc_free ( pr ) ;
2003-11-24 00:51:24 +03:00
2004-10-16 23:00:27 +04:00
poptFreeContext ( pc ) ;
2003-11-23 16:44:19 +03:00
return 0 ;
}