0001-01-01 02:30:17 +02:30
/*
Unix SMB / CIFS implementation .
auto - idl scanner
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-09-21 11:32:01 +04:00
# if 1
2004-04-18 07:57:51 +04:00
/*
2004-09-21 11:32:01 +04:00
get a DRSUAPI policy handle
*/
static BOOL get_policy_handle ( struct dcerpc_pipe * p ,
TALLOC_CTX * mem_ctx ,
struct policy_handle * handle )
{
NTSTATUS status ;
struct drsuapi_Bind r ;
ZERO_STRUCT ( r ) ;
r . out . handle = handle ;
status = dcerpc_drsuapi_Bind ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " drsuapi_Bind failed - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
return True ;
}
# else
/*
get a SAMR handle
2004-04-18 07:57:51 +04:00
*/
static BOOL get_policy_handle ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx ,
struct policy_handle * handle )
{
NTSTATUS status ;
struct samr_Connect r ;
r . in . system_name = 0 ;
r . in . access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED ;
2004-09-21 07:51:38 +04:00
r . out . connect_handle = handle ;
2004-04-18 07:57:51 +04:00
status = dcerpc_samr_Connect ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " samr_Connect failed - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
return True ;
}
2004-09-21 11:32:01 +04:00
# endif
2004-04-18 07:57:51 +04:00
static void fill_blob_handle ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx ,
struct policy_handle * handle )
{
DATA_BLOB b2 ;
if ( blob - > length < 20 ) {
return ;
}
ndr_push_struct_blob ( & b2 , mem_ctx , handle , ( ndr_push_flags_fn_t ) ndr_push_policy_handle ) ;
memcpy ( blob - > data , b2 . data , 20 ) ;
}
0001-01-01 02:30:17 +02:30
static void reopen ( struct dcerpc_pipe * * p , const struct dcerpc_interface_table * iface )
{
NTSTATUS status ;
if ( * p ) {
dcerpc_pipe_close ( * p ) ;
}
status = torture_rpc_connection ( p , iface - > endpoints - > names [ 0 ] , iface - > uuid , iface - > if_version ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to reopen '%s' - %s \n " , iface - > name , nt_errstr ( status ) ) ;
exit ( 1 ) ;
}
}
2004-04-19 09:48:03 +04:00
static void print_depth ( int depth )
{
int i ;
for ( i = 0 ; i < depth ; i + + ) {
printf ( " " ) ;
}
}
0001-01-01 02:30:17 +02:30
static void test_ptr_scan ( TALLOC_CTX * mem_ctx , const struct dcerpc_interface_table * iface ,
2004-04-19 09:48:03 +04:00
int opnum , DATA_BLOB * base_in , int min_ofs , int max_ofs , int depth ) ;
static void try_expand ( TALLOC_CTX * mem_ctx , const struct dcerpc_interface_table * iface ,
int opnum , DATA_BLOB * base_in , int insert_ofs , int depth )
{
DATA_BLOB stub_in , stub_out ;
int n ;
NTSTATUS status ;
struct dcerpc_pipe * p = NULL ;
reopen ( & p , iface ) ;
/* work out how much to expand to get a non fault */
for ( n = 0 ; n < 2000 ; n + + ) {
stub_in = data_blob ( NULL , base_in - > length + n ) ;
data_blob_clear ( & stub_in ) ;
memcpy ( stub_in . data , base_in - > data , insert_ofs ) ;
memcpy ( stub_in . data + insert_ofs + n , base_in - > data + insert_ofs , base_in - > length - insert_ofs ) ;
status = dcerpc_request ( p , opnum , mem_ctx , & stub_in , & stub_out ) ;
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_NET_WRITE_FAULT ) ) {
print_depth ( depth ) ;
printf ( " expand by %d gives %s \n " , n , nt_errstr ( status ) ) ;
if ( n > = 4 ) {
test_ptr_scan ( mem_ctx , iface , opnum , & stub_in ,
insert_ofs , insert_ofs + n , depth + 1 ) ;
}
return ;
2004-04-23 08:21:22 +04:00
} else {
#if 0
print_depth ( depth ) ;
2004-09-21 12:11:53 +04:00
printf ( " expand by %d gives fault %s \n " , n , dcerpc_errstr ( mem_ctx , p - > last_fault_code ) ) ;
2004-04-23 08:21:22 +04:00
# endif
2004-04-19 09:48:03 +04:00
}
if ( p - > last_fault_code = = 5 ) {
reopen ( & p , iface ) ;
}
}
dcerpc_pipe_close ( p ) ;
}
static void test_ptr_scan ( TALLOC_CTX * mem_ctx , const struct dcerpc_interface_table * iface ,
int opnum , DATA_BLOB * base_in , int min_ofs , int max_ofs , int depth )
0001-01-01 02:30:17 +02:30
{
DATA_BLOB stub_in , stub_out ;
int ofs ;
NTSTATUS status ;
struct dcerpc_pipe * p = NULL ;
reopen ( & p , iface ) ;
2004-04-19 09:48:03 +04:00
stub_in = data_blob ( NULL , base_in - > length ) ;
memcpy ( stub_in . data , base_in - > data , base_in - > length ) ;
0001-01-01 02:30:17 +02:30
2004-04-19 09:48:03 +04:00
/* work out which elements are pointers */
for ( ofs = min_ofs ; ofs < = max_ofs - 4 ; ofs + = 4 ) {
0001-01-01 02:30:17 +02:30
SIVAL ( stub_in . data , ofs , 1 ) ;
status = dcerpc_request ( p , opnum , mem_ctx , & stub_in , & stub_out ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NET_WRITE_FAULT ) ) {
2004-04-19 09:48:03 +04:00
print_depth ( depth ) ;
2004-09-21 12:11:53 +04:00
printf ( " possible ptr at ofs %d - fault %s \n " ,
ofs - min_ofs , dcerpc_errstr ( mem_ctx , p - > last_fault_code ) ) ;
0001-01-01 02:30:17 +02:30
if ( p - > last_fault_code = = 5 ) {
reopen ( & p , iface ) ;
}
2004-04-19 09:48:03 +04:00
if ( depth = = 0 ) {
try_expand ( mem_ctx , iface , opnum , & stub_in , ofs + 4 , depth + 1 ) ;
} else {
try_expand ( mem_ctx , iface , opnum , & stub_in , max_ofs , depth + 1 ) ;
}
SIVAL ( stub_in . data , ofs , 0 ) ;
0001-01-01 02:30:17 +02:30
continue ;
}
2004-04-19 09:48:03 +04:00
SIVAL ( stub_in . data , ofs , 0 ) ;
0001-01-01 02:30:17 +02:30
}
dcerpc_pipe_close ( p ) ;
}
static void test_scan_call ( TALLOC_CTX * mem_ctx , const struct dcerpc_interface_table * iface , int opnum )
{
DATA_BLOB stub_in , stub_out ;
int i ;
NTSTATUS status ;
struct dcerpc_pipe * p = NULL ;
2004-04-18 07:57:51 +04:00
struct policy_handle handle ;
0001-01-01 02:30:17 +02:30
reopen ( & p , iface ) ;
2004-04-18 07:57:51 +04:00
get_policy_handle ( p , mem_ctx , & handle ) ;
0001-01-01 02:30:17 +02:30
/* work out the minimum amount of input data */
2004-04-18 07:57:51 +04:00
for ( i = 0 ; i < 2000 ; i + + ) {
0001-01-01 02:30:17 +02:30
stub_in = data_blob ( NULL , i ) ;
data_blob_clear ( & stub_in ) ;
2004-04-18 07:57:51 +04:00
0001-01-01 02:30:17 +02:30
status = dcerpc_request ( p , opnum , mem_ctx , & stub_in , & stub_out ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
printf ( " opnum %d min_input %d - output %d \n " ,
opnum , stub_in . length , stub_out . length ) ;
2004-04-18 07:57:51 +04:00
dump_data ( 0 , stub_out . data , stub_out . length ) ;
0001-01-01 02:30:17 +02:30
dcerpc_pipe_close ( p ) ;
2004-04-19 09:48:03 +04:00
test_ptr_scan ( mem_ctx , iface , opnum , & stub_in , 0 , stub_in . length , 0 ) ;
return ;
}
fill_blob_handle ( & stub_in , mem_ctx , & handle ) ;
status = dcerpc_request ( p , opnum , mem_ctx , & stub_in , & stub_out ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
printf ( " opnum %d min_input %d - output %d (with handle) \n " ,
opnum , stub_in . length , stub_out . length ) ;
dump_data ( 0 , stub_out . data , stub_out . length ) ;
dcerpc_pipe_close ( p ) ;
test_ptr_scan ( mem_ctx , iface , opnum , & stub_in , 0 , stub_in . length , 0 ) ;
0001-01-01 02:30:17 +02:30
return ;
}
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NET_WRITE_FAULT ) ) {
2004-09-21 12:11:53 +04:00
printf ( " opnum %d size %d fault %s \n " , opnum , i , dcerpc_errstr ( mem_ctx , p - > last_fault_code ) ) ;
0001-01-01 02:30:17 +02:30
if ( p - > last_fault_code = = 5 ) {
reopen ( & p , iface ) ;
}
continue ;
}
printf ( " opnum %d size %d error %s \n " , opnum , i , nt_errstr ( status ) ) ;
}
printf ( " opnum %d minimum not found!? \n " , opnum ) ;
dcerpc_pipe_close ( p ) ;
}
static void test_auto_scan ( TALLOC_CTX * mem_ctx , const struct dcerpc_interface_table * iface )
{
2004-09-21 11:32:01 +04:00
test_scan_call ( mem_ctx , iface , 2 ) ;
0001-01-01 02:30:17 +02:30
}
BOOL torture_rpc_autoidl ( int dummy )
{
TALLOC_CTX * mem_ctx ;
const struct dcerpc_interface_table * iface ;
2004-09-21 11:32:01 +04:00
iface = idl_iface_by_name ( " drsuapi " ) ;
0001-01-01 02:30:17 +02:30
if ( ! iface ) {
printf ( " Unknown interface! \n " ) ;
return False ;
}
mem_ctx = talloc_init ( " torture_rpc_autoidl " ) ;
printf ( " \n Probing pipe '%s' \n " , iface - > name ) ;
test_auto_scan ( mem_ctx , iface ) ;
return True ;
}