2003-11-28 11:51:09 +03:00
/*
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-11-28 11:51:09 +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-28 11:51:09 +03:00
*/
# include "includes.h"
2006-03-15 02:35:30 +03:00
# include "librpc/gen_ndr/ndr_drsuapi_c.h"
2007-08-21 23:35:43 +04:00
# include "librpc/ndr/ndr_table.h"
2010-04-14 00:06:51 +04:00
# include "torture/rpc/torture_rpc.h"
2003-11-28 11:51:09 +03:00
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
*/
2010-03-16 12:55:12 +03:00
static bool get_policy_handle ( struct dcerpc_binding_handle * b ,
TALLOC_CTX * mem_ctx ,
2004-09-21 11:32:01 +04:00
struct policy_handle * handle )
{
NTSTATUS status ;
2004-10-10 05:30:54 +04:00
struct drsuapi_DsBind r ;
2004-09-21 11:32:01 +04:00
ZERO_STRUCT ( r ) ;
2004-10-10 05:30:54 +04:00
r . out . bind_handle = handle ;
2004-09-21 11:32:01 +04:00
2010-03-16 12:55:12 +03:00
status = dcerpc_drsuapi_DsBind_r ( b , mem_ctx , & r ) ;
2004-09-21 11:32:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-10-10 05:30:54 +04:00
printf ( " drsuapi_DsBind failed - %s \n " , nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-09-21 11:32:01 +04:00
}
2007-10-07 02:28:14 +04:00
return true ;
2004-09-21 11:32:01 +04:00
}
# else
/*
get a SAMR handle
2004-04-18 07:57:51 +04:00
*/
2010-03-16 12:55:12 +03:00
static bool get_policy_handle ( struct dcerpc_binding_handle * b ,
TALLOC_CTX * mem_ctx ,
2004-04-18 07:57:51 +04:00
struct policy_handle * handle )
{
NTSTATUS status ;
struct samr_Connect r ;
r . in . system_name = 0 ;
2004-12-02 07:37:36 +03:00
r . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
2004-09-21 07:51:38 +04:00
r . out . connect_handle = handle ;
2004-04-18 07:57:51 +04:00
2010-03-16 12:55:12 +03:00
status = dcerpc_samr_Connect_r ( b , mem_ctx , & r ) ;
2004-04-18 07:57:51 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " samr_Connect failed - %s \n " , nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-04-18 07:57:51 +04:00
}
2007-10-07 02:28:14 +04:00
return true ;
2004-04-18 07:57:51 +04:00
}
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 ;
}
2010-05-09 19:20:01 +04:00
ndr_push_struct_blob ( & b2 , mem_ctx , handle , ( ndr_push_flags_fn_t ) ndr_push_policy_handle ) ;
2004-04-18 07:57:51 +04:00
memcpy ( blob - > data , b2 . data , 20 ) ;
}
2007-12-03 04:58:12 +03:00
static void reopen ( struct torture_context * tctx ,
2005-03-22 11:00:45 +03:00
struct dcerpc_pipe * * p ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * iface )
2003-11-28 11:51:09 +03:00
{
NTSTATUS status ;
2005-03-22 11:00:45 +03:00
talloc_free ( * p ) ;
2003-11-28 11:51:09 +03:00
2007-12-03 04:58:12 +03:00
status = torture_rpc_connection ( tctx , p , iface ) ;
2003-11-28 11:51:09 +03:00
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 ( " " ) ;
}
}
2003-11-28 11:51:09 +03:00
2007-12-03 04:58:12 +03:00
static void test_ptr_scan ( struct torture_context * tctx , const struct ndr_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 ) ;
2007-12-03 04:58:12 +03:00
static void try_expand ( struct torture_context * tctx , const struct ndr_interface_table * iface ,
2004-04-19 09:48:03 +04:00
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 ;
2007-12-03 04:58:12 +03:00
reopen ( tctx , & p , iface ) ;
2004-04-19 09:48:03 +04:00
/* work out how much to expand to get a non fault */
for ( n = 0 ; n < 2000 ; n + + ) {
2011-03-13 18:15:06 +03:00
uint32_t out_flags = 0 ;
2004-04-19 09:48:03 +04:00
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 ) ;
2011-03-13 18:15:06 +03:00
status = dcerpc_binding_handle_raw_call ( p - > binding_handle ,
NULL , opnum ,
0 , /* in_flags */
stub_in . data ,
stub_in . length ,
tctx ,
& stub_out . data ,
& stub_out . length ,
& out_flags ) ;
2010-04-12 16:11:50 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2004-04-19 09:48:03 +04:00
print_depth ( depth ) ;
printf ( " expand by %d gives %s \n " , n , nt_errstr ( status ) ) ;
if ( n > = 4 ) {
2007-12-03 04:58:12 +03:00
test_ptr_scan ( tctx , iface , opnum , & stub_in ,
2004-04-19 09:48:03 +04:00
insert_ofs , insert_ofs + n , depth + 1 ) ;
}
return ;
2004-04-23 08:21:22 +04:00
} else {
#if 0
print_depth ( depth ) ;
2010-04-12 16:11:50 +04:00
printf ( " expand by %d gives fault %s \n " , n , nt_errstr ( status ) ) ;
2004-04-23 08:21:22 +04:00
# endif
2004-04-19 09:48:03 +04:00
}
2010-04-12 16:11:50 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) ) {
2007-12-03 04:58:12 +03:00
reopen ( tctx , & p , iface ) ;
2004-04-19 09:48:03 +04:00
}
}
2005-03-22 11:00:45 +03:00
talloc_free ( p ) ;
2004-04-19 09:48:03 +04:00
}
2007-12-03 04:58:12 +03:00
static void test_ptr_scan ( struct torture_context * tctx , const struct ndr_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 )
2003-11-28 11:51:09 +03:00
{
DATA_BLOB stub_in , stub_out ;
int ofs ;
NTSTATUS status ;
struct dcerpc_pipe * p = NULL ;
2007-12-03 04:58:12 +03:00
reopen ( tctx , & p , iface ) ;
2003-11-28 11:51:09 +03:00
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 ) ;
2003-11-28 11:51:09 +03:00
2004-04-19 09:48:03 +04:00
/* work out which elements are pointers */
for ( ofs = min_ofs ; ofs < = max_ofs - 4 ; ofs + = 4 ) {
2011-03-13 18:15:06 +03:00
uint32_t out_flags = 0 ;
2003-11-28 11:51:09 +03:00
SIVAL ( stub_in . data , ofs , 1 ) ;
2011-03-13 18:15:06 +03:00
status = dcerpc_binding_handle_raw_call ( p - > binding_handle ,
NULL , opnum ,
0 , /* in_flags */
stub_in . data ,
stub_in . length ,
tctx ,
& stub_out . data ,
& stub_out . length ,
& out_flags ) ;
2003-11-28 11:51:09 +03:00
2010-04-12 16:11:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
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 " ,
2010-04-12 16:11:50 +04:00
ofs - min_ofs , nt_errstr ( status ) ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) ) {
2007-12-03 04:58:12 +03:00
reopen ( tctx , & p , iface ) ;
2003-11-28 11:51:09 +03:00
}
2004-04-19 09:48:03 +04:00
if ( depth = = 0 ) {
2007-12-03 04:58:12 +03:00
try_expand ( tctx , iface , opnum , & stub_in , ofs + 4 , depth + 1 ) ;
2004-04-19 09:48:03 +04:00
} else {
2007-12-03 04:58:12 +03:00
try_expand ( tctx , iface , opnum , & stub_in , max_ofs , depth + 1 ) ;
2004-04-19 09:48:03 +04:00
}
SIVAL ( stub_in . data , ofs , 0 ) ;
2003-11-28 11:51:09 +03:00
continue ;
}
2004-04-19 09:48:03 +04:00
SIVAL ( stub_in . data , ofs , 0 ) ;
2003-11-28 11:51:09 +03:00
}
2005-03-22 11:00:45 +03:00
talloc_free ( p ) ;
2003-11-28 11:51:09 +03:00
}
2007-12-03 04:58:12 +03:00
static void test_scan_call ( struct torture_context * tctx , const struct ndr_interface_table * iface , int opnum )
2003-11-28 11:51:09 +03:00
{
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 ;
2003-11-28 11:51:09 +03:00
2007-12-03 04:58:12 +03:00
reopen ( tctx , & p , iface ) ;
2003-11-28 11:51:09 +03:00
2010-03-16 12:55:12 +03:00
get_policy_handle ( p - > binding_handle , tctx , & handle ) ;
2004-04-18 07:57:51 +04:00
2003-11-28 11:51:09 +03:00
/* work out the minimum amount of input data */
2004-04-18 07:57:51 +04:00
for ( i = 0 ; i < 2000 ; i + + ) {
2011-03-13 18:15:06 +03:00
uint32_t out_flags = 0 ;
2003-11-28 11:51:09 +03:00
stub_in = data_blob ( NULL , i ) ;
data_blob_clear ( & stub_in ) ;
2011-03-13 18:15:06 +03:00
status = dcerpc_binding_handle_raw_call ( p - > binding_handle ,
NULL , opnum ,
0 , /* in_flags */
stub_in . data ,
stub_in . length ,
tctx ,
& stub_out . data ,
& stub_out . length ,
& out_flags ) ;
2003-11-28 11:51:09 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
printf ( " opnum %d min_input %d - output %d \n " ,
2005-07-17 13:20:52 +04:00
opnum , ( int ) stub_in . length , ( int ) stub_out . length ) ;
2004-04-18 07:57:51 +04:00
dump_data ( 0 , stub_out . data , stub_out . length ) ;
2005-03-22 11:00:45 +03:00
talloc_free ( p ) ;
2007-12-03 04:58:12 +03:00
test_ptr_scan ( tctx , iface , opnum , & stub_in , 0 , stub_in . length , 0 ) ;
2004-04-19 09:48:03 +04:00
return ;
}
2007-12-03 04:58:12 +03:00
fill_blob_handle ( & stub_in , tctx , & handle ) ;
2004-04-19 09:48:03 +04:00
2011-03-13 18:15:06 +03:00
status = dcerpc_binding_handle_raw_call ( p - > binding_handle ,
NULL , opnum ,
0 , /* in_flags */
stub_in . data ,
stub_in . length ,
tctx ,
& stub_out . data ,
& stub_out . length ,
& out_flags ) ;
2004-04-19 09:48:03 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
printf ( " opnum %d min_input %d - output %d (with handle) \n " ,
2005-07-17 13:20:52 +04:00
opnum , ( int ) stub_in . length , ( int ) stub_out . length ) ;
2004-04-19 09:48:03 +04:00
dump_data ( 0 , stub_out . data , stub_out . length ) ;
2005-03-22 11:00:45 +03:00
talloc_free ( p ) ;
2007-12-03 04:58:12 +03:00
test_ptr_scan ( tctx , iface , opnum , & stub_in , 0 , stub_in . length , 0 ) ;
2003-11-28 11:51:09 +03:00
return ;
}
2010-04-12 16:11:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " opnum %d size %d fault %s \n " , opnum , i , nt_errstr ( status ) ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) ) {
2007-12-03 04:58:12 +03:00
reopen ( tctx , & p , iface ) ;
2003-11-28 11:51:09 +03:00
}
continue ;
}
printf ( " opnum %d size %d error %s \n " , opnum , i , nt_errstr ( status ) ) ;
}
printf ( " opnum %d minimum not found!? \n " , opnum ) ;
2005-03-22 11:00:45 +03:00
talloc_free ( p ) ;
2003-11-28 11:51:09 +03:00
}
2007-12-03 04:58:12 +03:00
static void test_auto_scan ( struct torture_context * tctx , const struct ndr_interface_table * iface )
2003-11-28 11:51:09 +03:00
{
2007-12-03 04:58:12 +03:00
test_scan_call ( tctx , iface , 2 ) ;
2003-11-28 11:51:09 +03:00
}
2007-10-07 02:28:14 +04:00
bool torture_rpc_autoidl ( struct torture_context * torture )
2003-11-28 11:51:09 +03:00
{
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * iface ;
2003-11-28 11:51:09 +03:00
2007-08-21 23:35:43 +04:00
iface = ndr_table_by_name ( " drsuapi " ) ;
2003-11-28 11:51:09 +03:00
if ( ! iface ) {
printf ( " Unknown interface! \n " ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-11-28 11:51:09 +03:00
}
printf ( " \n Probing pipe '%s' \n " , iface - > name ) ;
2007-12-03 04:58:12 +03:00
test_auto_scan ( torture , iface ) ;
2003-11-28 11:51:09 +03:00
2007-10-07 02:28:14 +04:00
return true ;
2003-11-28 11:51:09 +03:00
}