2001-08-27 22:01:05 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-08-27 22:01:05 +04:00
SMB torture tester - scanning functions
Copyright ( C ) Andrew Tridgell 2001
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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2001-08-27 22:01:05 +04: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 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-08-27 22:01:05 +04:00
*/
# include "includes.h"
# define VERBOSE 0
# define OP_MIN 0
# define OP_MAX 20
/****************************************************************************
look for a partial hit
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
static void trans2_check_hit ( const char * format , int op , int level , NTSTATUS status )
2001-08-27 22:01:05 +04:00
{
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_INVALID_LEVEL ) | |
NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_NOT_IMPLEMENTED ) | |
NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_NOT_SUPPORTED ) | |
NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_UNSUCCESSFUL ) | |
NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_INVALID_INFO_CLASS ) ) {
return ;
}
2001-08-27 22:01:05 +04:00
# if VERBOSE
2001-09-04 15:52:42 +04:00
printf ( " possible %s hit op=%3d level=%5d status=%s \n " ,
2002-03-17 07:36:35 +03:00
format , op , level , nt_errstr ( status ) ) ;
2001-08-27 22:01:05 +04:00
# endif
}
/****************************************************************************
check for existance of a trans2 call
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-04 15:52:42 +04:00
static NTSTATUS try_trans2 ( struct cli_state * cli ,
2001-08-27 22:01:05 +04:00
int op ,
char * param , char * data ,
int param_len , int data_len ,
2006-07-11 22:01:26 +04:00
unsigned int * rparam_len , unsigned int * rdata_len )
2001-08-27 22:01:05 +04:00
{
uint16 setup = op ;
char * rparam = NULL , * rdata = NULL ;
if ( ! cli_send_trans ( cli , SMBtrans2 ,
NULL , /* name */
- 1 , 0 , /* fid, flags */
& setup , 1 , 0 , /* setup, length, max */
param , param_len , 2 , /* param, length, max */
data , data_len , cli - > max_xmit /* data, length, max */
) ) {
return cli_nt_error ( cli ) ;
}
cli_receive_trans ( cli , SMBtrans2 ,
& rparam , rparam_len ,
& rdata , rdata_len ) ;
2001-09-17 15:37:57 +04:00
SAFE_FREE ( rdata ) ;
SAFE_FREE ( rparam ) ;
2001-08-27 22:01:05 +04:00
return cli_nt_error ( cli ) ;
}
2001-09-04 15:52:42 +04:00
static NTSTATUS try_trans2_len ( struct cli_state * cli ,
2003-01-03 11:28:12 +03:00
const char * format ,
2001-08-27 22:01:05 +04:00
int op , int level ,
char * param , char * data ,
int param_len , int * data_len ,
2006-07-11 22:01:26 +04:00
unsigned int * rparam_len , unsigned int * rdata_len )
2001-08-27 22:01:05 +04:00
{
2001-09-04 15:52:42 +04:00
NTSTATUS ret = NT_STATUS_OK ;
2001-08-27 22:01:05 +04:00
ret = try_trans2 ( cli , op , param , data , param_len ,
sizeof ( pstring ) , rparam_len , rdata_len ) ;
# if VERBOSE
2002-03-17 07:36:35 +03:00
printf ( " op=%d level=%d ret=%s \n " , op , level , nt_errstr ( ret ) ) ;
2001-08-27 22:01:05 +04:00
# endif
2001-09-04 15:52:42 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) return ret ;
2001-08-27 22:01:05 +04:00
* data_len = 0 ;
while ( * data_len < sizeof ( pstring ) ) {
ret = try_trans2 ( cli , op , param , data , param_len ,
* data_len , rparam_len , rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( ret ) ) break ;
2001-08-27 22:01:05 +04:00
* data_len + = 2 ;
}
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( ret ) ) {
2001-08-27 22:01:05 +04:00
printf ( " found %s level=%d data_len=%d rparam_len=%d rdata_len=%d \n " ,
format , level , * data_len , * rparam_len , * rdata_len ) ;
} else {
trans2_check_hit ( format , op , level , ret ) ;
}
return ret ;
}
/****************************************************************************
check for existance of a trans2 call
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool scan_trans2 ( struct cli_state * cli , int op , int level ,
2003-01-03 11:28:12 +03:00
int fnum , int dnum , const char * fname )
2001-08-27 22:01:05 +04:00
{
int data_len = 0 ;
int param_len = 0 ;
2006-07-11 22:01:26 +04:00
unsigned int rparam_len , rdata_len ;
2001-08-27 22:01:05 +04:00
pstring param , data ;
2001-08-27 23:46:22 +04:00
NTSTATUS status ;
2001-08-27 22:01:05 +04:00
memset ( data , 0 , sizeof ( data ) ) ;
data_len = 4 ;
/* try with a info level only */
param_len = 2 ;
SSVAL ( param , 0 , level ) ;
status = try_trans2_len ( cli , " void " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try with a file descriptor */
param_len = 6 ;
SSVAL ( param , 0 , fnum ) ;
SSVAL ( param , 2 , level ) ;
SSVAL ( param , 4 , 0 ) ;
status = try_trans2_len ( cli , " fnum " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try with a notify style */
param_len = 6 ;
SSVAL ( param , 0 , dnum ) ;
SSVAL ( param , 2 , dnum ) ;
SSVAL ( param , 4 , level ) ;
status = try_trans2_len ( cli , " notify " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try with a file name */
param_len = 6 ;
SSVAL ( param , 0 , level ) ;
SSVAL ( param , 2 , 0 ) ;
SSVAL ( param , 4 , 0 ) ;
param_len + = clistr_push ( cli , & param [ 6 ] , fname , - 1 , STR_TERMINATE ) ;
status = try_trans2_len ( cli , " fname " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try with a new file name */
param_len = 6 ;
SSVAL ( param , 0 , level ) ;
SSVAL ( param , 2 , 0 ) ;
SSVAL ( param , 4 , 0 ) ;
param_len + = clistr_push ( cli , & param [ 6 ] , " \\ newfile.dat " , - 1 , STR_TERMINATE ) ;
status = try_trans2_len ( cli , " newfile " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
cli_unlink ( cli , " \\ newfile.dat " ) ;
cli_rmdir ( cli , " \\ newfile.dat " ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try dfs style */
cli_mkdir ( cli , " \\ testdir " ) ;
param_len = 2 ;
SSVAL ( param , 0 , level ) ;
param_len + = clistr_push ( cli , & param [ 2 ] , " \\ testdir " , - 1 , STR_TERMINATE ) ;
status = try_trans2_len ( cli , " dfs " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
cli_rmdir ( cli , " \\ testdir " ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
return False ;
}
2007-10-19 04:40:25 +04:00
bool torture_trans2_scan ( int dummy )
2001-08-27 22:01:05 +04:00
{
2003-04-23 12:12:34 +04:00
static struct cli_state * cli ;
2001-08-27 22:01:05 +04:00
int op , level ;
2003-01-03 11:28:12 +03:00
const char * fname = " \\ scanner.dat " ;
2001-08-27 22:01:05 +04:00
int fnum , dnum ;
printf ( " starting trans2 scan test \n " ) ;
2006-07-31 13:41:25 +04:00
if ( ! torture_open_connection ( & cli , 0 ) ) {
2001-08-27 22:01:05 +04:00
return False ;
}
2003-04-23 12:12:34 +04:00
fnum = cli_open ( cli , fname , O_RDWR | O_CREAT | O_TRUNC ,
2001-08-27 22:01:05 +04:00
DENY_NONE ) ;
2003-04-23 12:12:34 +04:00
dnum = cli_open ( cli , " \\ " , O_RDONLY , DENY_NONE ) ;
2001-08-27 22:01:05 +04:00
for ( op = OP_MIN ; op < = OP_MAX ; op + + ) {
printf ( " Scanning op=%d \n " , op ) ;
for ( level = 0 ; level < = 50 ; level + + ) {
2003-04-23 12:12:34 +04:00
scan_trans2 ( cli , op , level , fnum , dnum , fname ) ;
2001-08-27 22:01:05 +04:00
}
for ( level = 0x100 ; level < = 0x130 ; level + + ) {
2003-04-23 12:12:34 +04:00
scan_trans2 ( cli , op , level , fnum , dnum , fname ) ;
2001-08-27 22:01:05 +04:00
}
for ( level = 1000 ; level < 1050 ; level + + ) {
2003-04-23 12:12:34 +04:00
scan_trans2 ( cli , op , level , fnum , dnum , fname ) ;
2001-08-27 22:01:05 +04:00
}
}
2003-04-23 12:12:34 +04:00
torture_close_connection ( cli ) ;
2001-08-27 22:01:05 +04:00
printf ( " trans2 scan finished \n " ) ;
return True ;
}
/****************************************************************************
look for a partial hit
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
static void nttrans_check_hit ( const char * format , int op , int level , NTSTATUS status )
2001-08-27 22:01:05 +04:00
{
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_INVALID_LEVEL ) | |
NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_NOT_IMPLEMENTED ) | |
NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_NOT_SUPPORTED ) | |
NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_UNSUCCESSFUL ) | |
NT_STATUS_V ( status ) = = NT_STATUS_V ( NT_STATUS_INVALID_INFO_CLASS ) ) {
return ;
}
2001-08-27 22:01:05 +04:00
# if VERBOSE
printf ( " possible %s hit op=%3d level=%5d status=%s \n " ,
2002-03-17 07:36:35 +03:00
format , op , level , nt_errstr ( status ) ) ;
2001-08-27 22:01:05 +04:00
# endif
}
/****************************************************************************
check for existance of a nttrans call
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-04 15:52:42 +04:00
static NTSTATUS try_nttrans ( struct cli_state * cli ,
2001-08-27 22:01:05 +04:00
int op ,
char * param , char * data ,
int param_len , int data_len ,
2006-07-11 22:01:26 +04:00
unsigned int * rparam_len , unsigned int * rdata_len )
2001-08-27 22:01:05 +04:00
{
char * rparam = NULL , * rdata = NULL ;
if ( ! cli_send_nt_trans ( cli , op ,
0 ,
NULL , 0 , 0 ,
param , param_len , 2 , /* param, length, max */
data , data_len , cli - > max_xmit /* data, length, max */
) ) {
return cli_nt_error ( cli ) ;
}
cli_receive_nt_trans ( cli ,
& rparam , rparam_len ,
& rdata , rdata_len ) ;
2001-09-17 15:37:57 +04:00
SAFE_FREE ( rdata ) ;
SAFE_FREE ( rparam ) ;
2001-08-27 22:01:05 +04:00
return cli_nt_error ( cli ) ;
}
2001-09-04 15:52:42 +04:00
static NTSTATUS try_nttrans_len ( struct cli_state * cli ,
2003-01-03 11:28:12 +03:00
const char * format ,
2001-08-27 22:01:05 +04:00
int op , int level ,
char * param , char * data ,
int param_len , int * data_len ,
2006-07-11 22:01:26 +04:00
unsigned int * rparam_len , unsigned int * rdata_len )
2001-08-27 22:01:05 +04:00
{
2001-09-04 15:52:42 +04:00
NTSTATUS ret = NT_STATUS_OK ;
2001-08-27 22:01:05 +04:00
ret = try_nttrans ( cli , op , param , data , param_len ,
sizeof ( pstring ) , rparam_len , rdata_len ) ;
# if VERBOSE
2002-03-17 07:36:35 +03:00
printf ( " op=%d level=%d ret=%s \n " , op , level , nt_errstr ( ret ) ) ;
2001-08-27 22:01:05 +04:00
# endif
2001-09-04 15:52:42 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) return ret ;
2001-08-27 22:01:05 +04:00
* data_len = 0 ;
while ( * data_len < sizeof ( pstring ) ) {
ret = try_nttrans ( cli , op , param , data , param_len ,
* data_len , rparam_len , rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( ret ) ) break ;
2001-08-27 22:01:05 +04:00
* data_len + = 2 ;
}
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( ret ) ) {
2001-08-27 22:01:05 +04:00
printf ( " found %s level=%d data_len=%d rparam_len=%d rdata_len=%d \n " ,
format , level , * data_len , * rparam_len , * rdata_len ) ;
} else {
nttrans_check_hit ( format , op , level , ret ) ;
}
return ret ;
}
/****************************************************************************
check for existance of a nttrans call
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool scan_nttrans ( struct cli_state * cli , int op , int level ,
2003-01-03 11:28:12 +03:00
int fnum , int dnum , const char * fname )
2001-08-27 22:01:05 +04:00
{
int data_len = 0 ;
int param_len = 0 ;
2006-07-11 22:01:26 +04:00
unsigned int rparam_len , rdata_len ;
2001-08-27 22:01:05 +04:00
pstring param , data ;
2001-08-27 23:46:22 +04:00
NTSTATUS status ;
2001-08-27 22:01:05 +04:00
memset ( data , 0 , sizeof ( data ) ) ;
data_len = 4 ;
/* try with a info level only */
param_len = 2 ;
SSVAL ( param , 0 , level ) ;
status = try_nttrans_len ( cli , " void " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try with a file descriptor */
param_len = 6 ;
SSVAL ( param , 0 , fnum ) ;
SSVAL ( param , 2 , level ) ;
SSVAL ( param , 4 , 0 ) ;
status = try_nttrans_len ( cli , " fnum " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try with a notify style */
param_len = 6 ;
SSVAL ( param , 0 , dnum ) ;
SSVAL ( param , 2 , dnum ) ;
SSVAL ( param , 4 , level ) ;
status = try_nttrans_len ( cli , " notify " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try with a file name */
param_len = 6 ;
SSVAL ( param , 0 , level ) ;
SSVAL ( param , 2 , 0 ) ;
SSVAL ( param , 4 , 0 ) ;
param_len + = clistr_push ( cli , & param [ 6 ] , fname , - 1 , STR_TERMINATE ) ;
status = try_nttrans_len ( cli , " fname " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try with a new file name */
param_len = 6 ;
SSVAL ( param , 0 , level ) ;
SSVAL ( param , 2 , 0 ) ;
SSVAL ( param , 4 , 0 ) ;
param_len + = clistr_push ( cli , & param [ 6 ] , " \\ newfile.dat " , - 1 , STR_TERMINATE ) ;
status = try_nttrans_len ( cli , " newfile " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
cli_unlink ( cli , " \\ newfile.dat " ) ;
cli_rmdir ( cli , " \\ newfile.dat " ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
/* try dfs style */
cli_mkdir ( cli , " \\ testdir " ) ;
param_len = 2 ;
SSVAL ( param , 0 , level ) ;
param_len + = clistr_push ( cli , & param [ 2 ] , " \\ testdir " , - 1 , STR_TERMINATE ) ;
status = try_nttrans_len ( cli , " dfs " , op , level , param , data , param_len , & data_len ,
& rparam_len , & rdata_len ) ;
cli_rmdir ( cli , " \\ testdir " ) ;
2001-09-04 15:52:42 +04:00
if ( NT_STATUS_IS_OK ( status ) ) return True ;
2001-08-27 22:01:05 +04:00
return False ;
}
2007-10-19 04:40:25 +04:00
bool torture_nttrans_scan ( int dummy )
2001-08-27 22:01:05 +04:00
{
2003-04-23 12:12:34 +04:00
static struct cli_state * cli ;
2001-08-27 22:01:05 +04:00
int op , level ;
2003-01-03 11:28:12 +03:00
const char * fname = " \\ scanner.dat " ;
2001-08-27 22:01:05 +04:00
int fnum , dnum ;
printf ( " starting nttrans scan test \n " ) ;
2006-07-31 13:41:25 +04:00
if ( ! torture_open_connection ( & cli , 0 ) ) {
2001-08-27 22:01:05 +04:00
return False ;
}
2003-04-23 12:12:34 +04:00
fnum = cli_open ( cli , fname , O_RDWR | O_CREAT | O_TRUNC ,
2001-08-27 22:01:05 +04:00
DENY_NONE ) ;
2003-04-23 12:12:34 +04:00
dnum = cli_open ( cli , " \\ " , O_RDONLY , DENY_NONE ) ;
2001-08-27 22:01:05 +04:00
for ( op = OP_MIN ; op < = OP_MAX ; op + + ) {
printf ( " Scanning op=%d \n " , op ) ;
for ( level = 0 ; level < = 50 ; level + + ) {
2003-04-23 12:12:34 +04:00
scan_nttrans ( cli , op , level , fnum , dnum , fname ) ;
2001-08-27 22:01:05 +04:00
}
for ( level = 0x100 ; level < = 0x130 ; level + + ) {
2003-04-23 12:12:34 +04:00
scan_nttrans ( cli , op , level , fnum , dnum , fname ) ;
2001-08-27 22:01:05 +04:00
}
for ( level = 1000 ; level < 1050 ; level + + ) {
2003-04-23 12:12:34 +04:00
scan_nttrans ( cli , op , level , fnum , dnum , fname ) ;
2001-08-27 22:01:05 +04:00
}
}
2003-04-23 12:12:34 +04:00
torture_close_connection ( cli ) ;
2001-08-27 22:01:05 +04:00
printf ( " nttrans scan finished \n " ) ;
return True ;
}