2003-11-27 08:34:28 +03:00
/*
Unix SMB / CIFS implementation .
scanner for rpc calls
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"
/*
work out how many calls there are for an interface
*/
static BOOL test_num_calls ( const struct dcerpc_interface_table * iface ,
TALLOC_CTX * mem_ctx ,
struct dcerpc_syntax_id * id )
{
struct dcerpc_pipe * p ;
NTSTATUS status ;
const char * uuid ;
int i ;
DATA_BLOB stub_in , stub_out ;
int idl_calls ;
uuid = GUID_string ( mem_ctx , & id - > uuid ) ;
status = torture_rpc_connection ( & p , iface - > name ,
2003-12-16 12:02:58 +03:00
uuid , id - > if_version ) ;
2003-11-27 08:34:28 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to connect to '%s' on '%s' - %s \n " ,
uuid , iface - > name , nt_errstr ( status ) ) ;
return False ;
}
/* make null calls */
2003-11-28 06:47:45 +03:00
stub_in = data_blob ( NULL , 1000 ) ;
memset ( stub_in . data , 0xFF , stub_in . length ) ;
2003-11-27 08:34:28 +03:00
2003-11-28 06:47:45 +03:00
for ( i = 0 ; i < 200 ; i + + ) {
2003-11-27 08:34:28 +03:00
status = dcerpc_request ( p , i , mem_ctx , & stub_in , & stub_out ) ;
2003-11-28 06:47:45 +03:00
if ( ! NT_STATUS_IS_OK ( status ) & &
p - > last_fault_code = = DCERPC_FAULT_OP_RNG_ERROR ) {
break ;
}
if ( ! NT_STATUS_IS_OK ( status ) & & p - > last_fault_code = = 5 ) {
printf ( " \t pipe disconnected at %d \n " , i ) ;
goto done ;
}
if ( ! NT_STATUS_IS_OK ( status ) & & p - > last_fault_code = = 0x80010111 ) {
printf ( " \t err 0x80010111 at %d \n " , i ) ;
goto done ;
}
2003-11-27 08:34:28 +03:00
}
2003-11-28 06:47:45 +03:00
printf ( " \t %d calls available \n " , i ) ;
2003-12-16 12:02:58 +03:00
idl_calls = idl_num_calls ( uuid , id - > if_version ) ;
2003-11-27 08:34:28 +03:00
if ( idl_calls = = - 1 ) {
printf ( " \t interface not known in local IDL \n " ) ;
2003-11-28 06:47:45 +03:00
} else if ( i ! = idl_calls ) {
2003-11-27 08:34:28 +03:00
printf ( " \t WARNING: local IDL defines %u calls \n " , idl_calls ) ;
} else {
printf ( " \t OK: matches num_calls in local IDL \n " ) ;
}
done :
torture_rpc_close ( p ) ;
return True ;
}
/*
ask the server what interface IDs are available on this endpoint
*/
static BOOL test_inq_if_ids ( struct dcerpc_pipe * p ,
TALLOC_CTX * mem_ctx ,
const struct dcerpc_interface_table * iface )
{
NTSTATUS status ;
struct mgmt_inq_if_ids r ;
int i ;
status = dcerpc_mgmt_inq_if_ids ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " inq_if_ids failed - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
if ( ! W_ERROR_IS_OK ( r . out . result ) ) {
printf ( " inq_if_ids gave error code %s \n " , win_errstr ( r . out . result ) ) ;
return False ;
}
if ( ! r . out . if_id_vector ) {
printf ( " inq_if_ids gave NULL if_id_vector \n " ) ;
return False ;
}
for ( i = 0 ; i < r . out . if_id_vector - > count ; i + + ) {
const char * uuid ;
struct dcerpc_syntax_id * id = r . out . if_id_vector - > if_id [ i ] . id ;
if ( ! id ) continue ;
uuid = GUID_string ( mem_ctx , & id - > uuid ) ,
2003-12-16 12:02:58 +03:00
printf ( " \n \t uuid %s version 0x%08x '%s' \n " ,
2003-11-27 08:34:28 +03:00
uuid ,
2003-12-16 12:02:58 +03:00
id - > if_version , idl_pipe_name ( uuid , id - > if_version ) ) ;
2003-11-27 08:34:28 +03:00
test_num_calls ( iface , mem_ctx , id ) ;
}
return True ;
}
BOOL torture_rpc_scanner ( int dummy )
{
NTSTATUS status ;
struct dcerpc_pipe * p ;
TALLOC_CTX * mem_ctx ;
BOOL ret = True ;
int i ;
2004-06-14 03:50:55 +04:00
const char * binding = lp_parm_string ( - 1 , " torture " , " binding " ) ;
2003-12-16 13:57:17 +03:00
struct dcerpc_binding b ;
2003-11-27 08:34:28 +03:00
mem_ctx = talloc_init ( " torture_rpc_scanner " ) ;
2003-12-16 13:57:17 +03:00
if ( ! binding ) {
printf ( " You must supply a ncacn binding string \n " ) ;
return False ;
}
status = dcerpc_parse_binding ( mem_ctx , binding , & b ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to parse binding '%s' \n " , binding ) ;
return False ;
}
2003-11-27 08:34:28 +03:00
2003-12-16 13:57:17 +03:00
for ( i = 0 ; dcerpc_pipes [ i ] ; i + + ) {
2003-11-27 08:34:28 +03:00
/* some interfaces are not mappable */
if ( dcerpc_pipes [ i ] - > num_calls = = 0 | |
strcmp ( dcerpc_pipes [ i ] - > name , " mgmt " ) = = 0 ) {
continue ;
}
printf ( " \n Testing pipe '%s' \n " , dcerpc_pipes [ i ] - > name ) ;
2003-12-16 13:57:17 +03:00
if ( b . transport = = NCACN_IP_TCP ) {
2004-10-25 03:12:13 +04:00
status = dcerpc_epm_map_binding ( mem_ctx , & b ,
2003-12-16 13:57:17 +03:00
dcerpc_pipes [ i ] - > uuid ,
2004-10-25 02:46:47 +04:00
dcerpc_pipes [ i ] - > if_version ) ;
2003-11-27 08:34:28 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-12-16 13:57:17 +03:00
printf ( " Failed to map port for uuid %s \n " , dcerpc_pipes [ i ] - > uuid ) ;
2003-11-27 08:34:28 +03:00
continue ;
}
2003-12-16 13:57:17 +03:00
} else {
2004-10-25 02:46:47 +04:00
b . endpoint = dcerpc_pipes [ i ] - > name ;
2003-11-27 08:34:28 +03:00
}
2003-12-16 13:57:17 +03:00
lp_set_cmdline ( " torture:binding " , dcerpc_binding_string ( mem_ctx , & b ) ) ;
2003-11-27 08:34:28 +03:00
status = torture_rpc_connection ( & p ,
dcerpc_pipes [ i ] - > name ,
DCERPC_MGMT_UUID ,
DCERPC_MGMT_VERSION ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ret = False ;
continue ;
}
if ( ! test_inq_if_ids ( p , mem_ctx , dcerpc_pipes [ i ] ) ) {
ret = False ;
}
torture_rpc_close ( p ) ;
}
return ret ;
}