2005-11-12 02:37:51 +00:00
/*
Unix SMB / CIFS implementation .
SMB2 opcode scanner
Copyright ( C ) Andrew Tridgell 2005
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"
# include "libcli/smb2/smb2.h"
# include "libcli/smb2/smb2_calls.h"
# include "lib/cmdline/popt_common.h"
# include "lib/events/events.h"
2005-11-17 00:50:42 +00:00
# define FNAME "scan-getinfo.dat"
# define DNAME "scan-getinfo.dir"
2005-11-12 07:48:56 +00:00
/*
scan for valid SMB2 getinfo levels
*/
BOOL torture_smb2_getinfo_scan ( void )
{
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
struct smb2_tree * tree ;
NTSTATUS status ;
struct smb2_getinfo io ;
2005-11-17 00:50:42 +00:00
struct smb2_handle fhandle , dhandle ;
2005-11-12 07:48:56 +00:00
int c , i ;
2005-11-15 04:38:59 +00:00
if ( ! torture_smb2_connection ( mem_ctx , & tree ) ) {
2005-11-12 07:48:56 +00:00
return False ;
}
2005-11-18 09:51:13 +00:00
status = torture_setup_complex_file ( tree , FNAME ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-11-17 00:50:42 +00:00
printf ( " Failed to setup complex file '%s' \n " , FNAME ) ;
2005-11-18 09:51:13 +00:00
return False ;
2005-11-12 08:19:39 +00:00
}
2005-11-18 09:51:13 +00:00
torture_setup_complex_file ( tree , FNAME " :2ndstream " ) ;
2005-11-12 08:19:39 +00:00
2005-11-18 09:51:13 +00:00
status = torture_setup_complex_dir ( tree , DNAME ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-11-17 00:50:42 +00:00
printf ( " Failed to setup complex dir '%s' \n " , DNAME ) ;
2005-11-18 09:51:13 +00:00
return False ;
2005-11-12 07:48:56 +00:00
}
2005-11-18 09:51:13 +00:00
torture_setup_complex_file ( tree , DNAME " :2ndstream " ) ;
2005-11-12 07:48:56 +00:00
2005-11-17 00:50:42 +00:00
torture_smb2_testfile ( tree , FNAME , & fhandle ) ;
torture_smb2_testdir ( tree , DNAME , & dhandle ) ;
2005-11-12 07:48:56 +00:00
ZERO_STRUCT ( io ) ;
io . in . max_response_size = 0xFFFF ;
2005-11-15 04:38:59 +00:00
2005-11-17 00:50:42 +00:00
for ( c = 1 ; c < 5 ; c + + ) {
2005-11-12 07:48:56 +00:00
for ( i = 0 ; i < 0x100 ; i + + ) {
io . in . level = ( i < < 8 ) | c ;
2005-11-17 00:50:42 +00:00
io . in . handle = fhandle ;
status = smb2_getinfo ( tree , mem_ctx , & io ) ;
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_INFO_CLASS ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_PARAMETER ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_NOT_SUPPORTED ) ) {
2005-11-30 02:08:15 +00:00
printf ( " file level 0x%04x is %ld bytes - %s \n " ,
io . in . level , ( long ) io . out . blob . length , nt_errstr ( status ) ) ;
2005-11-17 00:50:42 +00:00
dump_data ( 1 , io . out . blob . data , io . out . blob . length ) ;
}
io . in . handle = dhandle ;
2005-11-12 07:48:56 +00:00
status = smb2_getinfo ( tree , mem_ctx , & io ) ;
2005-11-17 00:50:42 +00:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_INFO_CLASS ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_PARAMETER ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_NOT_SUPPORTED ) ) {
2005-11-30 02:08:15 +00:00
printf ( " dir level 0x%04x is %ld bytes - %s \n " ,
io . in . level , ( long ) io . out . blob . length , nt_errstr ( status ) ) ;
2005-11-17 00:50:42 +00:00
dump_data ( 1 , io . out . blob . data , io . out . blob . length ) ;
2005-11-12 07:48:56 +00:00
}
}
}
talloc_free ( mem_ctx ) ;
return True ;
}
2005-11-18 09:25:25 +00:00
/*
scan for valid SMB2 setinfo levels
*/
BOOL torture_smb2_setinfo_scan ( void )
{
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
struct smb2_tree * tree ;
NTSTATUS status ;
struct smb2_setinfo io ;
struct smb2_handle handle ;
int c , i ;
if ( ! torture_smb2_connection ( mem_ctx , & tree ) ) {
return False ;
}
2005-11-18 09:51:13 +00:00
status = torture_setup_complex_file ( tree , FNAME ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-11-18 09:25:25 +00:00
printf ( " Failed to setup complex file '%s' \n " , FNAME ) ;
2005-11-18 09:51:13 +00:00
return False ;
2005-11-18 09:25:25 +00:00
}
2005-11-18 09:51:13 +00:00
torture_setup_complex_file ( tree , FNAME " :2ndstream " ) ;
2005-11-18 09:25:25 +00:00
torture_smb2_testfile ( tree , FNAME , & handle ) ;
ZERO_STRUCT ( io ) ;
io . in . blob = data_blob_talloc ( mem_ctx , NULL , 1024 ) ;
for ( c = 1 ; c < 5 ; c + + ) {
for ( i = 0 ; i < 0x100 ; i + + ) {
io . in . level = ( i < < 8 ) | c ;
io . in . handle = handle ;
status = smb2_setinfo ( tree , & io ) ;
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_INFO_CLASS ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_NOT_SUPPORTED ) ) {
printf ( " file level 0x%04x - %s \n " ,
io . in . level , nt_errstr ( status ) ) ;
}
}
}
talloc_free ( mem_ctx ) ;
return True ;
}
2005-11-19 06:39:12 +00:00
/*
scan for valid SMB2 scan levels
*/
BOOL torture_smb2_find_scan ( void )
{
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
struct smb2_tree * tree ;
NTSTATUS status ;
struct smb2_find io ;
struct smb2_handle handle ;
int i ;
if ( ! torture_smb2_connection ( mem_ctx , & tree ) ) {
return False ;
}
status = smb2_util_roothandle ( tree , & handle ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to open roothandle - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
ZERO_STRUCT ( io ) ;
io . in . pattern = " * " ;
io . in . continue_flags = SMB2_CONTINUE_FLAG_RESTART ;
io . in . max_response_size = 0x10000 ;
io . in . handle = handle ;
for ( i = 1 ; i < 0x100 ; i + + ) {
io . in . level = i ;
io . in . handle = handle ;
status = smb2_find ( tree , mem_ctx , & io ) ;
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_INFO_CLASS ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_PARAMETER ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_NOT_SUPPORTED ) ) {
2005-11-30 02:08:15 +00:00
printf ( " find level 0x%04x is %ld bytes - %s \n " ,
io . in . level , ( long ) io . out . blob . length , nt_errstr ( status ) ) ;
2005-11-19 06:39:12 +00:00
dump_data ( 1 , io . out . blob . data , io . out . blob . length ) ;
}
}
talloc_free ( mem_ctx ) ;
return True ;
}
2005-11-12 02:37:51 +00:00
/*
scan for valid SMB2 opcodes
*/
BOOL torture_smb2_scan ( void )
{
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
struct smb2_tree * tree ;
const char * host = lp_parm_string ( - 1 , " torture " , " host " ) ;
const char * share = lp_parm_string ( - 1 , " torture " , " share " ) ;
struct cli_credentials * credentials = cmdline_credentials ;
NTSTATUS status ;
int opcode ;
struct smb2_request * req ;
status = smb2_connect ( mem_ctx , host , share , credentials , & tree ,
event_context_find ( mem_ctx ) ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Connection failed - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
tree - > session - > transport - > options . timeout = 3 ;
for ( opcode = 0 ; opcode < 1000 ; opcode + + ) {
2005-11-16 11:01:15 +00:00
req = smb2_request_init_tree ( tree , opcode , 2 , 0 ) ;
2005-11-12 02:37:51 +00:00
SSVAL ( req - > out . body , 0 , 0 ) ;
smb2_transport_send ( req ) ;
if ( ! smb2_request_receive ( req ) ) {
talloc_free ( tree ) ;
status = smb2_connect ( mem_ctx , host , share , credentials , & tree ,
event_context_find ( mem_ctx ) ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Connection failed - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
tree - > session - > transport - > options . timeout = 3 ;
} else {
status = smb2_request_destroy ( req ) ;
printf ( " active opcode %4d gave status %s \n " , opcode , nt_errstr ( status ) ) ;
}
}
talloc_free ( mem_ctx ) ;
return True ;
}