2006-03-17 19:27:22 +03:00
/*
Unix SMB / CIFS implementation .
SMB torture tester
Copyright ( C ) Andrew Tridgell 1997 - 2003
2008-05-23 18:19:00 +04:00
Copyright ( C ) Jelmer Vernooij 2006 - 2008
2006-03-17 19:27:22 +03:00
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
2006-03-17 19:27:22 +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/>.
2006-03-17 19:27:22 +03:00
*/
# include "includes.h"
2024-04-10 14:02:39 +03:00
# include "lib/util/util_file.h"
2020-12-02 19:24:22 +03:00
# include "lib/cmdline/cmdline.h"
2006-03-17 19:27:22 +03:00
# include "system/time.h"
# include "system/wait.h"
# include "system/filesys.h"
2006-10-30 04:19:31 +03:00
# include "system/readline.h"
2010-10-01 12:34:14 +04:00
# include "../libcli/smbreadline/smbreadline.h"
2006-03-17 19:27:22 +03:00
# include "libcli/libcli.h"
# include "lib/events/events.h"
2008-04-27 17:02:46 +04:00
# include "torture/smbtorture.h"
2006-03-18 18:42:57 +03:00
# include "librpc/rpc/dcerpc.h"
2008-11-03 01:58:49 +03:00
# include "auth/gensec/gensec.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2011-12-03 10:03:35 +04:00
# include "lib/util/samba_modules.h"
2006-03-17 19:27:22 +03:00
2018-11-21 13:38:24 +03:00
# ifdef HAVE_READLINE_HISTORY_H
2010-03-19 07:25:17 +03:00
# include <readline/history.h>
# endif
2008-04-14 20:43:37 +04:00
2020-07-03 15:17:43 +03:00
static int use_fullname ;
2010-12-11 19:56:37 +03:00
static char * prefix_name ( TALLOC_CTX * mem_ctx , const char * prefix , const char * name )
{
if ( prefix = = NULL )
return talloc_strdup ( mem_ctx , name ) ;
else
return talloc_asprintf ( mem_ctx , " %s.%s " , prefix , name ) ;
}
static void print_test_list ( const struct torture_suite * suite , const char * prefix , const char * expr )
{
struct torture_suite * o ;
struct torture_tcase * t ;
struct torture_test * p ;
for ( o = suite - > children ; o ; o = o - > next ) {
char * name = prefix_name ( NULL , prefix , o - > name ) ;
print_test_list ( o , name , expr ) ;
talloc_free ( name ) ;
}
for ( t = suite - > testcases ; t ; t = t - > next ) {
for ( p = t - > tests ; p ; p = p - > next ) {
char * name = talloc_asprintf ( NULL , " %s.%s.%s " , prefix , t - > name , p - > name ) ;
if ( strncmp ( name , expr , strlen ( expr ) ) = = 0 ) {
printf ( " %s \n " , name ) ;
}
talloc_free ( name ) ;
}
}
}
2006-10-16 17:06:41 +04:00
static bool run_matching ( struct torture_context * torture ,
const char * prefix ,
const char * expr ,
2010-03-20 07:24:15 +03:00
const char * * restricted ,
2006-10-16 17:06:41 +04:00
struct torture_suite * suite ,
bool * matched )
{
bool ret = true ;
2010-04-10 23:24:33 +04:00
struct torture_suite * o ;
struct torture_tcase * t ;
2010-06-03 19:08:55 +04:00
struct torture_test * p ;
2010-04-10 23:24:33 +04:00
for ( o = suite - > children ; o ; o = o - > next ) {
char * name = NULL ;
2010-12-11 19:56:37 +03:00
name = prefix_name ( torture , prefix , o - > name ) ;
2010-04-10 23:24:33 +04:00
if ( gen_fnmatch ( expr , name ) = = 0 ) {
* matched = true ;
reload_charcnv ( torture - > lp_ctx ) ;
2020-07-03 15:17:43 +03:00
if ( use_fullname = = 1 ) {
torture_subunit_prefix_reset ( torture , prefix ) ;
}
2020-07-03 16:58:38 +03:00
ret & = torture_run_suite_restricted ( torture , o , restricted ) ;
2020-07-03 15:17:43 +03:00
if ( use_fullname = = 1 ) {
torture_subunit_prefix_reset ( torture , NULL ) ;
}
2020-07-03 16:58:38 +03:00
/*
* torture_run_suite_restricted ( ) already implements
* recursion , so we ' re done with this child suite .
*/
continue ;
2006-10-16 17:06:41 +04:00
}
2010-04-10 23:24:33 +04:00
ret & = run_matching ( torture , name , expr , restricted , o , matched ) ;
}
2006-10-16 17:06:41 +04:00
2010-04-10 23:24:33 +04:00
for ( t = suite - > testcases ; t ; t = t - > next ) {
2020-07-03 16:53:18 +03:00
char * tname = prefix_name ( torture , prefix , t - > name ) ;
if ( gen_fnmatch ( expr , tname ) = = 0 ) {
2010-04-10 23:24:33 +04:00
* matched = true ;
reload_charcnv ( torture - > lp_ctx ) ;
2020-07-03 15:17:43 +03:00
if ( use_fullname = = 1 ) {
torture_subunit_prefix_reset ( torture , prefix ) ;
}
2010-09-22 07:11:43 +04:00
ret & = torture_run_tcase_restricted ( torture , t , restricted ) ;
2020-07-03 15:17:43 +03:00
if ( use_fullname = = 1 ) {
torture_subunit_prefix_reset ( torture , NULL ) ;
}
2020-07-03 16:58:38 +03:00
/*
* torture_run_tcase_restricted ( ) already implements
* recursion , so we ' re done for this tcase .
*/
continue ;
2006-10-16 17:06:41 +04:00
}
2010-06-03 19:08:55 +04:00
for ( p = t - > tests ; p ; p = p - > next ) {
2020-07-03 16:53:18 +03:00
char * pname = prefix_name ( torture , tname , p - > name ) ;
if ( gen_fnmatch ( expr , pname ) = = 0 ) {
2010-06-03 19:08:55 +04:00
* matched = true ;
reload_charcnv ( torture - > lp_ctx ) ;
2020-07-03 15:17:43 +03:00
if ( use_fullname = = 1 ) {
torture_subunit_prefix_reset ( torture ,
tname ) ;
}
2010-09-22 07:11:43 +04:00
ret & = torture_run_test_restricted ( torture , t , p , restricted ) ;
2020-07-03 15:17:43 +03:00
if ( use_fullname = = 1 ) {
torture_subunit_prefix_reset ( torture ,
NULL ) ;
}
2010-06-03 19:08:55 +04:00
}
}
2006-10-16 17:06:41 +04:00
}
return ret ;
}
2006-03-17 19:27:22 +03:00
# define MAX_COLS 80 /* FIXME: Determine this at run-time */
/****************************************************************************
run a specified test or " ALL "
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-03-20 07:24:15 +03:00
bool torture_run_named_tests ( struct torture_context * torture , const char * name ,
const char * * restricted )
2006-03-17 19:27:22 +03:00
{
2006-10-16 17:06:41 +04:00
bool ret = true ;
bool matched = false ;
2006-10-17 03:09:15 +04:00
struct torture_suite * o ;
2006-03-17 19:27:22 +03:00
2010-09-23 08:03:05 +04:00
torture_ui_report_time ( torture ) ;
2006-10-16 17:06:41 +04:00
if ( strequal ( name , " ALL " ) ) {
2010-04-10 23:24:33 +04:00
if ( restricted ! = NULL ) {
printf ( " --load-list and ALL are incompatible \n " ) ;
return false ;
}
2006-10-17 03:09:15 +04:00
for ( o = torture_root - > children ; o ; o = o - > next ) {
ret & = torture_run_suite ( torture , o ) ;
2006-03-17 19:27:22 +03:00
}
return ret ;
}
2010-04-10 23:24:33 +04:00
ret = run_matching ( torture , NULL , name , restricted , torture_root , & matched ) ;
2006-03-17 19:27:22 +03:00
if ( ! matched ) {
printf ( " Unknown torture operation '%s' \n " , name ) ;
2006-10-16 17:06:41 +04:00
return false ;
2006-03-17 19:27:22 +03:00
}
return ret ;
}
2017-04-25 02:00:17 +03:00
bool torture_parse_target ( TALLOC_CTX * ctx ,
struct loadparm_context * lp_ctx ,
const char * target )
2007-12-03 02:28:22 +03:00
{
char * host = NULL , * share = NULL ;
struct dcerpc_binding * binding_struct ;
NTSTATUS status ;
/* see if its a RPC transport specifier */
if ( ! smbcli_parse_unc ( target , NULL , & host , & share ) ) {
2014-02-27 12:08:17 +04:00
const char * h ;
2017-04-25 02:00:17 +03:00
status = dcerpc_parse_binding ( ctx , target , & binding_struct ) ;
2007-12-03 02:28:22 +03:00
if ( NT_STATUS_IS_ERR ( status ) ) {
d_printf ( " Invalid option: %s is not a valid torture target (share or binding string) \n \n " , target ) ;
return false ;
}
2014-02-04 15:14:37 +04:00
2014-02-27 12:08:17 +04:00
h = dcerpc_binding_get_string_option ( binding_struct , " host " ) ;
host = discard_const_p ( char , h ) ;
2014-02-04 15:14:37 +04:00
if ( host ! = NULL ) {
lpcfg_set_cmdline ( lp_ctx , " torture:host " , host ) ;
2014-01-26 04:55:52 +04:00
}
2014-02-04 15:14:37 +04:00
2010-07-16 08:32:42 +04:00
if ( lpcfg_parm_string ( lp_ctx , NULL , " torture " , " share " ) = = NULL )
lpcfg_set_cmdline ( lp_ctx , " torture:share " , " IPC$ " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:binding " , target ) ;
2007-12-03 02:28:22 +03:00
} else {
2010-07-16 08:32:42 +04:00
lpcfg_set_cmdline ( lp_ctx , " torture:host " , host ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:share " , share ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:binding " , host ) ;
2007-12-03 02:28:22 +03:00
}
return true ;
}
static void parse_dns ( struct loadparm_context * lp_ctx , const char * dns )
2006-03-17 19:27:22 +03:00
{
char * userdn , * basedn , * secret ;
char * p , * d ;
2020-08-04 10:43:28 +03:00
/* retrieve the userdn */
2006-03-17 19:27:22 +03:00
p = strchr_m ( dns , ' # ' ) ;
if ( ! p ) {
2010-07-16 08:32:42 +04:00
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_userdn " , " " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_basedn " , " " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_secret " , " " ) ;
2006-03-17 19:27:22 +03:00
return ;
}
userdn = strndup ( dns , p - dns ) ;
2010-07-16 08:32:42 +04:00
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_userdn " , userdn ) ;
2006-03-17 19:27:22 +03:00
/* retrieve the basedn */
d = p + 1 ;
p = strchr_m ( d , ' # ' ) ;
if ( ! p ) {
2010-07-16 08:32:42 +04:00
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_basedn " , " " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_secret " , " " ) ;
2006-03-17 19:27:22 +03:00
return ;
}
basedn = strndup ( d , p - d ) ;
2010-07-16 08:32:42 +04:00
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_basedn " , basedn ) ;
2006-03-17 19:27:22 +03:00
/* retrieve the secret */
p = p + 1 ;
if ( ! p ) {
2010-07-16 08:32:42 +04:00
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_secret " , " " ) ;
2006-03-17 19:27:22 +03:00
return ;
}
secret = strdup ( p ) ;
2010-07-16 08:32:42 +04:00
lpcfg_set_cmdline ( lp_ctx , " torture:ldap_secret " , secret ) ;
2006-03-17 19:27:22 +03:00
printf ( " %s - %s - %s \n " , userdn , basedn , secret ) ;
}
2010-03-19 07:14:47 +03:00
/* Print the full test list, formatted into separate labelled test
* groups .
*/
2010-12-09 18:57:45 +03:00
static void print_structured_testsuite_list ( void )
2010-03-19 07:14:47 +03:00
{
struct torture_suite * o ;
struct torture_suite * s ;
struct torture_tcase * t ;
int i ;
if ( torture_root = = NULL ) {
printf ( " NO TESTS LOADED \n " ) ;
return ;
}
for ( o = torture_root - > children ; o ; o = o - > next ) {
printf ( " \n %s (%s): \n " , o - > description , o - > name ) ;
i = 0 ;
for ( s = o - > children ; s ; s = s - > next ) {
if ( i + strlen ( o - > name ) + strlen ( s - > name ) > = ( MAX_COLS - 3 ) ) {
printf ( " \n " ) ;
i = 0 ;
}
2010-12-11 05:26:31 +03:00
i + = printf ( " %s.%s " , o - > name , s - > name ) ;
2010-03-19 07:14:47 +03:00
}
for ( t = o - > testcases ; t ; t = t - > next ) {
if ( i + strlen ( o - > name ) + strlen ( t - > name ) > = ( MAX_COLS - 3 ) ) {
printf ( " \n " ) ;
i = 0 ;
}
2010-12-11 05:26:31 +03:00
i + = printf ( " %s.%s " , o - > name , t - > name ) ;
2010-03-19 07:14:47 +03:00
}
if ( i ) printf ( " \n " ) ;
}
printf ( " \n The default test is ALL. \n " ) ;
}
2010-12-09 18:57:45 +03:00
static void print_testsuite_list ( void )
2007-01-26 16:03:28 +03:00
{
struct torture_suite * o ;
struct torture_suite * s ;
struct torture_tcase * t ;
2007-10-06 00:33:55 +04:00
if ( torture_root = = NULL )
return ;
2007-01-26 16:03:28 +03:00
for ( o = torture_root - > children ; o ; o = o - > next ) {
for ( s = o - > children ; s ; s = s - > next ) {
2010-12-11 05:26:31 +03:00
printf ( " %s.%s \n " , o - > name , s - > name ) ;
2007-01-26 16:03:28 +03:00
}
for ( t = o - > testcases ; t ; t = t - > next ) {
2010-12-11 05:26:31 +03:00
printf ( " %s.%s \n " , o - > name , t - > name ) ;
2007-01-26 16:03:28 +03:00
}
}
}
2010-12-09 18:57:45 +03:00
void torture_print_testsuites ( bool structured )
2010-03-20 07:24:15 +03:00
{
if ( structured ) {
2010-12-09 18:57:45 +03:00
print_structured_testsuite_list ( ) ;
2010-03-20 07:24:15 +03:00
} else {
2010-12-09 18:57:45 +03:00
print_testsuite_list ( ) ;
2010-03-20 07:24:15 +03:00
}
}
2011-02-18 17:02:35 +03:00
static void usage ( poptContext pc )
2006-03-17 19:27:22 +03:00
{
poptPrintUsage ( pc , stdout , 0 ) ;
printf ( " \n " ) ;
printf ( " The binding format is: \n \n " ) ;
printf ( " TRANSPORT:host[flags] \n \n " ) ;
2006-05-27 16:16:48 +04:00
printf ( " where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP \n " ) ;
printf ( " or ncalrpc for local connections. \n \n " ) ;
2006-03-17 19:27:22 +03:00
printf ( " 'host' is an IP or hostname or netbios name. If the binding string \n " ) ;
printf ( " identifies the server side of an endpoint, 'host' may be an empty \n " ) ;
printf ( " string. \n \n " ) ;
printf ( " 'flags' can include a SMB pipe name if using the ncacn_np transport or \n " ) ;
printf ( " a TCP port number if using the ncacn_ip_tcp transport, otherwise they \n " ) ;
printf ( " will be auto-determined. \n \n " ) ;
printf ( " other recognised flags are: \n \n " ) ;
printf ( " sign : enable ntlmssp signing \n " ) ;
printf ( " seal : enable ntlmssp sealing \n " ) ;
printf ( " connect : enable rpc connect level auth (auth, but no sign or seal) \n " ) ;
printf ( " validate: enable the NDR validator \n " ) ;
printf ( " print: enable debugging of the packets \n " ) ;
printf ( " bigendian: use bigendian RPC \n " ) ;
printf ( " padcheck: check reply data for non-zero pad bytes \n \n " ) ;
printf ( " For example, these all connect to the samr pipe: \n \n " ) ;
printf ( " ncacn_np:myserver \n " ) ;
printf ( " ncacn_np:myserver[samr] \n " ) ;
printf ( " ncacn_np:myserver[ \\ pipe \\ samr] \n " ) ;
printf ( " ncacn_np:myserver[/pipe/samr] \n " ) ;
printf ( " ncacn_np:myserver[samr,sign,print] \n " ) ;
printf ( " ncacn_np:myserver[ \\ pipe \\ samr,sign,seal,bigendian] \n " ) ;
printf ( " ncacn_np:myserver[/pipe/samr,seal,validate] \n " ) ;
printf ( " ncacn_np: \n " ) ;
printf ( " ncacn_np:[/pipe/samr] \n \n " ) ;
printf ( " ncacn_ip_tcp:myserver \n " ) ;
printf ( " ncacn_ip_tcp:myserver[1024] \n " ) ;
printf ( " ncacn_ip_tcp:myserver[1024,sign,seal] \n \n " ) ;
2006-05-27 16:16:48 +04:00
printf ( " ncalrpc: \n \n " ) ;
2006-04-19 07:06:50 +04:00
printf ( " The UNC format is: \n \n " ) ;
2006-03-17 19:27:22 +03:00
2006-04-19 07:06:50 +04:00
printf ( " //server/share \n \n " ) ;
2006-03-17 19:27:22 +03:00
2006-04-19 07:06:50 +04:00
printf ( " Tests are: " ) ;
2006-03-17 19:27:22 +03:00
2010-12-09 18:57:45 +03:00
print_structured_testsuite_list ( ) ;
2006-03-17 19:27:22 +03:00
}
2007-09-07 17:31:15 +04:00
_NORETURN_ static void max_runtime_handler ( int sig )
2006-03-17 19:27:22 +03:00
{
DEBUG ( 0 , ( " maximum runtime exceeded for smbtorture - terminating \n " ) ) ;
exit ( 1 ) ;
}
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-02-27 12:08:17 +04:00
int main ( int argc , const char * argv [ ] )
2006-03-17 19:27:22 +03:00
{
int opt , i ;
2006-10-16 17:06:41 +04:00
bool correct = true ;
2006-03-17 19:27:22 +03:00
int max_runtime = 0 ;
int argc_new ;
2006-03-25 22:12:08 +03:00
struct torture_context * torture ;
2008-11-01 02:24:55 +03:00
struct torture_results * results ;
2006-10-18 02:06:43 +04:00
const struct torture_ui_ops * ui_ops ;
2006-03-17 19:27:22 +03:00
char * * argv_new ;
poptContext pc ;
2007-12-20 02:02:15 +03:00
static const char * target = " other " ;
2006-11-24 18:50:18 +03:00
NTSTATUS status ;
2010-03-20 07:24:15 +03:00
int shell = false ;
2009-06-13 18:14:39 +04:00
static const char * ui_ops_name = " subunit " ;
2007-08-28 18:42:37 +04:00
const char * basedir = NULL ;
2010-07-06 09:25:54 +04:00
char * outputdir ;
2007-08-31 22:35:30 +04:00
const char * extra_module = NULL ;
2010-12-09 18:57:45 +03:00
static int list_tests = 0 , list_testsuites = 0 ;
2008-05-14 11:47:18 +04:00
int num_extra_users = 0 ;
2014-02-27 12:08:17 +04:00
const char * * restricted = NULL ;
2010-04-09 03:58:28 +04:00
int num_restricted = - 1 ;
2010-06-25 04:40:37 +04:00
const char * load_list = NULL ;
2007-01-26 16:03:28 +03:00
enum { OPT_LOADFILE = 1000 , OPT_UNCLIST , OPT_TIMELIMIT , OPT_DNS , OPT_LIST ,
2009-10-03 04:02:20 +04:00
OPT_DANGEROUS , OPT_SMB_PORTS , OPT_ASYNC , OPT_NUMPROGS ,
2010-06-25 04:40:37 +04:00
OPT_EXTRA_USER , } ;
2017-04-25 00:24:15 +03:00
TALLOC_CTX * mem_ctx = NULL ;
2020-12-02 19:24:22 +03:00
struct loadparm_context * lp_ctx = NULL ;
bool ok ;
2009-10-03 04:02:20 +04:00
2006-03-17 19:27:22 +03:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2020-07-03 15:17:43 +03:00
{ " fullname " , 0 , POPT_ARG_NONE , & use_fullname , 0 ,
" use full name for the test " , NULL } ,
2007-08-28 04:16:58 +04:00
{ " format " , 0 , POPT_ARG_STRING , & ui_ops_name , 0 , " Output format (one of: simple, subunit) " , NULL } ,
2006-03-17 19:27:22 +03:00
{ " smb-ports " , ' p ' , POPT_ARG_STRING , NULL , OPT_SMB_PORTS , " SMB ports " , NULL } ,
2007-08-28 18:42:37 +04:00
{ " basedir " , 0 , POPT_ARG_STRING , & basedir , 0 , " base directory " , " BASEDIR " } ,
2007-11-12 01:36:57 +03:00
{ " seed " , 0 , POPT_ARG_INT , & torture_seed , 0 , " Seed to use for randomizer " , NULL } ,
2006-11-05 07:28:45 +03:00
{ " num-progs " , 0 , POPT_ARG_INT , NULL , OPT_NUMPROGS , " num progs " , NULL } ,
2006-03-17 19:27:22 +03:00
{ " num-ops " , 0 , POPT_ARG_INT , & torture_numops , 0 , " num ops " , NULL } ,
{ " entries " , 0 , POPT_ARG_INT , & torture_entries , 0 , " entries " , NULL } ,
2007-11-12 01:36:57 +03:00
{ " loadfile " , 0 , POPT_ARG_STRING , NULL , OPT_LOADFILE , " NBench load file to use " , NULL } ,
2010-12-09 18:57:45 +03:00
{ " list-suites " , 0 , POPT_ARG_NONE , & list_testsuites , 0 , " List available testsuites and exit " , NULL } ,
{ " list " , 0 , POPT_ARG_NONE , & list_tests , 0 , " List available tests in specified suites and exit " , NULL } ,
2006-03-17 19:27:22 +03:00
{ " unclist " , 0 , POPT_ARG_STRING , NULL , OPT_UNCLIST , " unclist " , NULL } ,
2007-11-12 01:36:57 +03:00
{ " timelimit " , ' t ' , POPT_ARG_INT , NULL , OPT_TIMELIMIT , " Set time limit (in seconds) " , NULL } ,
2006-03-17 19:27:22 +03:00
{ " failures " , ' f ' , POPT_ARG_INT , & torture_failures , 0 , " failures " , NULL } ,
{ " parse-dns " , ' D ' , POPT_ARG_STRING , NULL , OPT_DNS , " parse-dns " , NULL } ,
2006-05-05 13:52:12 +04:00
{ " dangerous " , ' X ' , POPT_ARG_NONE , NULL , OPT_DANGEROUS ,
" run dangerous tests (eg. wiping out password database) " , NULL } ,
2007-08-31 22:35:30 +04:00
{ " load-module " , 0 , POPT_ARG_STRING , & extra_module , 0 , " load tests from DSO file " , " SOFILE " } ,
2010-03-20 07:24:15 +03:00
{ " shell " , 0 , POPT_ARG_NONE , & shell , true , " Run shell " , NULL } ,
2006-09-12 11:35:04 +04:00
{ " target " , ' T ' , POPT_ARG_STRING , & target , 0 , " samba3|samba4|other " , NULL } ,
2006-05-05 13:52:12 +04:00
{ " async " , ' a ' , POPT_ARG_NONE , NULL , OPT_ASYNC ,
" run async tests " , NULL } ,
{ " num-async " , 0 , POPT_ARG_INT , & torture_numasync , 0 ,
" number of simultaneous async requests " , NULL } ,
2006-03-17 19:27:22 +03:00
{ " maximum-runtime " , 0 , POPT_ARG_INT , & max_runtime , 0 ,
" set maximum time for smbtorture to live " , " seconds " } ,
2008-05-14 11:47:18 +04:00
{ " extra-user " , 0 , POPT_ARG_STRING , NULL , OPT_EXTRA_USER ,
" extra user credentials " , NULL } ,
2010-06-25 04:40:37 +04:00
{ " load-list " , 0 , POPT_ARG_STRING , & load_list , 0 ,
2010-04-09 03:58:28 +04:00
" load a test id list from a text file " , NULL } ,
2006-03-17 19:27:22 +03:00
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
POPT_COMMON_VERSION
2020-12-02 19:24:22 +03:00
POPT_LEGACY_S4
POPT_TABLEEND
2006-03-17 19:27:22 +03:00
} ;
2006-09-10 18:19:38 +04:00
setlinebuf ( stdout ) ;
2006-03-17 19:27:22 +03:00
2017-04-25 00:24:15 +03:00
mem_ctx = talloc_named_const ( NULL , 0 , " torture_ctx " ) ;
if ( mem_ctx = = NULL ) {
printf ( " Unable to allocate torture_ctx \n " ) ;
exit ( 1 ) ;
}
2013-02-07 01:02:13 +04:00
printf ( " smbtorture %s \n " , samba_version_string ( ) ) ;
2006-03-17 19:27:22 +03:00
/* we are never interested in SIGPIPE */
2006-10-30 14:34:59 +03:00
BlockSignals ( true , SIGPIPE ) ;
2006-03-17 19:27:22 +03:00
2020-12-02 19:24:22 +03:00
ok = samba_cmdline_init ( mem_ctx ,
SAMBA_CMDLINE_CONFIG_CLIENT ,
false /* require_smbconf */ ) ;
if ( ! ok ) {
DBG_ERR ( " Unable to init cmdline parser \n " ) ;
TALLOC_FREE ( mem_ctx ) ;
exit ( 1 ) ;
}
pc = samba_popt_get_context ( getprogname ( ) ,
argc ,
argv ,
long_options ,
POPT_CONTEXT_KEEP_FIRST ) ;
if ( pc = = NULL ) {
DBG_ERR ( " Failed cmdline parser \n " ) ;
TALLOC_FREE ( mem_ctx ) ;
exit ( 1 ) ;
}
2006-03-17 19:27:22 +03:00
poptSetOtherOptionHelp ( pc , " <binding>|<unc> TEST1 TEST2 ... " ) ;
2020-12-02 19:24:22 +03:00
lp_ctx = samba_cmdline_get_lp_ctx ( ) ;
2006-03-17 19:27:22 +03:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
case OPT_LOADFILE :
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:loadfile " , poptGetOptArg ( pc ) ) ;
2006-03-17 19:27:22 +03:00
break ;
case OPT_UNCLIST :
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:unclist " , poptGetOptArg ( pc ) ) ;
2006-03-17 19:27:22 +03:00
break ;
case OPT_TIMELIMIT :
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:timelimit " , poptGetOptArg ( pc ) ) ;
2006-03-17 19:27:22 +03:00
break ;
2006-11-05 07:28:45 +03:00
case OPT_NUMPROGS :
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:nprocs " , poptGetOptArg ( pc ) ) ;
2006-11-05 07:28:45 +03:00
break ;
2006-03-17 19:27:22 +03:00
case OPT_DNS :
2020-12-02 19:24:22 +03:00
parse_dns ( lp_ctx , poptGetOptArg ( pc ) ) ;
2006-03-17 19:27:22 +03:00
break ;
case OPT_DANGEROUS :
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:dangerous " , " Yes " ) ;
2006-03-17 19:27:22 +03:00
break ;
2006-05-05 13:52:12 +04:00
case OPT_ASYNC :
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:async " , " Yes " ) ;
2006-05-05 13:52:12 +04:00
break ;
2006-03-17 19:27:22 +03:00
case OPT_SMB_PORTS :
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " smb ports " , poptGetOptArg ( pc ) ) ;
2006-03-17 19:27:22 +03:00
break ;
2008-05-14 11:47:18 +04:00
case OPT_EXTRA_USER :
{
2017-04-25 00:24:15 +03:00
char * option = talloc_asprintf ( mem_ctx ,
" torture:extra_user%u " ,
+ + num_extra_users ) ;
2009-10-18 00:39:15 +04:00
const char * value = poptGetOptArg ( pc ) ;
2017-04-25 00:24:15 +03:00
if ( option = = NULL ) {
printf ( " talloc fail \n " ) ;
talloc_free ( mem_ctx ) ;
exit ( 1 ) ;
}
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , option , value ) ;
2008-05-14 11:47:18 +04:00
talloc_free ( option ) ;
}
break ;
2009-10-15 11:27:57 +04:00
default :
2010-03-19 07:14:47 +03:00
if ( opt < 0 ) {
2020-12-09 12:49:51 +03:00
printf ( " Invalid command line option %s (%d) \n " ,
poptBadOption ( pc , 0 ) ,
opt ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2010-03-19 07:14:47 +03:00
exit ( 1 ) ;
}
2006-03-17 19:27:22 +03:00
}
}
2010-06-25 04:40:37 +04:00
if ( load_list ! = NULL ) {
2014-02-27 12:08:17 +04:00
char * * r ;
2017-04-25 00:24:15 +03:00
r = file_lines_load ( load_list , & num_restricted , 0 , mem_ctx ) ;
2014-02-27 12:08:17 +04:00
restricted = discard_const_p ( const char * , r ) ;
2010-06-25 04:40:37 +04:00
if ( restricted = = NULL ) {
printf ( " Unable to read load list file '%s' \n " , load_list ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2010-06-25 04:40:37 +04:00
exit ( 1 ) ;
}
}
2006-10-17 16:06:20 +04:00
if ( strcmp ( target , " samba3 " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:samba3 " , " true " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:resume_key_support " , " false " ) ;
2006-10-17 16:06:20 +04:00
} else if ( strcmp ( target , " samba4 " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:samba4 " , " true " ) ;
2012-02-09 07:33:09 +04:00
} else if ( strcmp ( target , " samba4-ntvfs " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:samba4 " , " true " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:samba4-ntvfs " , " true " ) ;
2009-12-02 03:27:10 +03:00
} else if ( strcmp ( target , " winxp " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:winxp " , " true " ) ;
2009-12-02 03:27:10 +03:00
} else if ( strcmp ( target , " w2k3 " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:w2k3 " , " true " ) ;
2009-07-06 17:36:03 +04:00
} else if ( strcmp ( target , " w2k8 " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:w2k8 " , " true " ) ;
lpcfg_set_cmdline ( lp_ctx ,
2009-11-14 02:13:19 +03:00
" torture:invalid_lock_range_support " , " false " ) ;
2013-09-05 16:03:07 +04:00
} else if ( strcmp ( target , " w2k12 " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:w2k12 " , " true " ) ;
2009-02-10 08:58:50 +03:00
} else if ( strcmp ( target , " win7 " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:win7 " , " true " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:resume_key_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:rewind_support " , " false " ) ;
2009-11-18 03:29:23 +03:00
/* RAW-SEARCH for fails for inexplicable reasons against win7 */
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:search_ea_support " , " false " ) ;
2009-12-05 03:07:35 +03:00
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:hide_on_access_denied " ,
2009-12-05 03:07:35 +03:00
" true " ) ;
2009-10-03 04:02:20 +04:00
} else if ( strcmp ( target , " onefs " ) = = 0 ) {
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:onefs " , " true " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:openx_deny_dos_support " ,
2009-11-25 03:58:25 +03:00
" false " ) ;
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:range_not_locked_on_file_close " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:sacl_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:ea_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:smbexit_pdu_support " ,
2010-01-11 03:06:57 +03:00
" false " ) ;
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:smblock_pdu_support " ,
2009-11-25 03:58:25 +03:00
" false " ) ;
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:2_step_break_to_none " ,
2009-12-02 02:29:00 +03:00
" true " ) ;
2020-12-02 19:24:22 +03:00
lpcfg_set_cmdline ( lp_ctx , " torture:deny_dos_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:deny_fcb_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:read_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:writeclose_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:resume_key_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:rewind_support " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:raw_search_search " , " false " ) ;
lpcfg_set_cmdline ( lp_ctx , " torture:search_ea_size " , " false " ) ;
2006-10-17 16:06:20 +04:00
}
2006-03-17 19:27:22 +03:00
if ( max_runtime ) {
/* this will only work if nobody else uses alarm(),
which means it won ' t work for some tests , but we
can ' t use the event context method we use for smbd
as so many tests create their own event
context . This will at least catch most cases . */
signal ( SIGALRM , max_runtime_handler ) ;
alarm ( max_runtime ) ;
}
2007-08-31 22:35:30 +04:00
if ( extra_module ! = NULL ) {
2011-12-03 10:03:35 +04:00
init_module_fn fn = load_module ( poptGetOptArg ( pc ) , false , NULL ) ;
2007-08-31 22:35:30 +04:00
2010-04-09 03:58:28 +04:00
if ( fn = = NULL )
d_printf ( " Unable to load module from %s \n " , poptGetOptArg ( pc ) ) ;
else {
2017-04-25 00:24:15 +03:00
status = fn ( mem_ctx ) ;
2010-04-09 03:58:28 +04:00
if ( NT_STATUS_IS_ERR ( status ) ) {
d_printf ( " Error initializing module %s: %s \n " ,
poptGetOptArg ( pc ) , nt_errstr ( status ) ) ;
}
2007-08-31 22:35:30 +04:00
}
} else {
2017-04-25 00:27:36 +03:00
torture_init ( mem_ctx ) ;
2007-08-31 22:35:30 +04:00
}
2010-12-09 18:57:45 +03:00
if ( list_testsuites ) {
print_testsuite_list ( ) ;
2019-08-19 15:18:06 +03:00
poptFreeContext ( pc ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2007-01-26 16:03:28 +03:00
return 0 ;
}
2006-03-17 19:27:22 +03:00
argv_new = discard_const_p ( char * , poptGetArgs ( pc ) ) ;
argc_new = argc ;
for ( i = 0 ; i < argc ; i + + ) {
if ( argv_new [ i ] = = NULL ) {
argc_new = i ;
break ;
}
}
2010-12-11 19:56:37 +03:00
if ( list_tests ) {
2010-12-11 20:00:24 +03:00
if ( argc_new = = 1 ) {
print_test_list ( torture_root , NULL , " " ) ;
} else {
for ( i = 1 ; i < argc_new ; i + + ) {
print_test_list ( torture_root , NULL , argv_new [ i ] ) ;
}
2010-12-11 19:56:37 +03:00
}
2019-08-19 15:18:06 +03:00
poptFreeContext ( pc ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2010-12-11 19:56:37 +03:00
return 0 ;
}
if ( torture_seed = = 0 ) {
torture_seed = time ( NULL ) ;
}
printf ( " Using seed %d \n " , torture_seed ) ;
srandom ( torture_seed ) ;
2006-06-12 16:24:33 +04:00
if ( ! strcmp ( ui_ops_name , " simple " ) ) {
2011-10-18 15:15:22 +04:00
ui_ops = & torture_simple_ui_ops ;
2006-06-12 16:24:33 +04:00
} else if ( ! strcmp ( ui_ops_name , " subunit " ) ) {
2008-10-23 23:30:41 +04:00
ui_ops = & torture_subunit_ui_ops ;
2006-06-12 16:24:33 +04:00
} else {
printf ( " Unknown output format '%s' \n " , ui_ops_name ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2006-06-12 16:24:33 +04:00
exit ( 1 ) ;
}
2006-03-25 22:12:08 +03:00
2017-04-25 00:24:15 +03:00
results = torture_results_init ( mem_ctx , ui_ops ) ;
2008-11-01 02:24:55 +03:00
2017-04-25 00:24:15 +03:00
torture = torture_context_init ( s4_event_context_init ( mem_ctx ) ,
2010-03-30 01:13:46 +04:00
results ) ;
2007-09-02 20:12:49 +04:00
if ( basedir ! = NULL ) {
if ( basedir [ 0 ] ! = ' / ' ) {
fprintf ( stderr , " Please specify an absolute path to --basedir \n " ) ;
2019-08-19 15:18:06 +03:00
poptFreeContext ( pc ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2007-09-02 20:12:49 +04:00
return 1 ;
}
2010-07-06 09:25:54 +04:00
outputdir = talloc_asprintf ( torture , " %s/smbtortureXXXXXX " , basedir ) ;
2007-09-02 20:12:49 +04:00
} else {
char * pwd = talloc_size ( torture , PATH_MAX ) ;
if ( ! getcwd ( pwd , PATH_MAX ) ) {
fprintf ( stderr , " Unable to determine current working directory \n " ) ;
2019-08-19 15:18:06 +03:00
poptFreeContext ( pc ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2007-09-02 20:12:49 +04:00
return 1 ;
}
2010-07-06 09:25:54 +04:00
outputdir = talloc_asprintf ( torture , " %s/smbtortureXXXXXX " , pwd ) ;
}
if ( ! outputdir ) {
fprintf ( stderr , " Could not allocate per-run output dir \n " ) ;
2019-08-19 15:18:06 +03:00
poptFreeContext ( pc ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2010-07-06 09:25:54 +04:00
return 1 ;
}
torture - > outputdir = mkdtemp ( outputdir ) ;
if ( ! torture - > outputdir ) {
perror ( " Failed to make temp output dir " ) ;
2019-08-19 15:18:06 +03:00
poptFreeContext ( pc ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
return 1 ;
2007-09-02 20:12:49 +04:00
}
2006-10-18 02:06:43 +04:00
2020-12-02 19:24:22 +03:00
torture - > lp_ctx = lp_ctx ;
2007-12-03 02:28:22 +03:00
2011-06-06 08:58:28 +04:00
gensec_init ( ) ;
2008-11-03 01:58:49 +03:00
2010-06-21 22:09:45 +04:00
if ( shell ) {
/* In shell mode, just ignore any remaining test names. */
torture_shell ( torture ) ;
} else {
2010-03-23 07:55:49 +03:00
2010-06-21 22:09:45 +04:00
/* At this point, we should just have a target string,
* followed by a series of test names . Unless we are in
2023-08-03 16:46:43 +03:00
* shell mode , in which case we don ' t need anything more .
2010-06-21 22:09:45 +04:00
*/
if ( argc_new < 3 ) {
printf ( " You must specify a test to run, or 'ALL' \n " ) ;
2010-03-23 07:55:49 +03:00
usage ( pc ) ;
2011-02-18 17:02:35 +03:00
torture - > results - > returncode = 1 ;
2017-04-25 02:00:17 +03:00
} else if ( ! torture_parse_target ( torture ,
2020-12-02 19:24:22 +03:00
lp_ctx , argv_new [ 1 ] ) ) {
2017-04-25 02:00:17 +03:00
/* Take the target name or binding. */
2010-06-21 22:09:45 +04:00
usage ( pc ) ;
2011-02-18 17:02:35 +03:00
torture - > results - > returncode = 1 ;
} else {
for ( i = 2 ; i < argc_new ; i + + ) {
if ( ! torture_run_named_tests ( torture , argv_new [ i ] ,
( const char * * ) restricted ) ) {
correct = false ;
}
2006-03-17 19:27:22 +03:00
}
}
}
2010-07-06 09:25:54 +04:00
/* Now delete the temp dir we created */
torture_deltree_outputdir ( torture ) ;
2008-11-01 02:24:55 +03:00
if ( torture - > results - > returncode & & correct ) {
2019-08-19 15:18:06 +03:00
poptFreeContext ( pc ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2006-03-17 19:27:22 +03:00
return ( 0 ) ;
} else {
2019-08-19 15:18:06 +03:00
poptFreeContext ( pc ) ;
2017-04-25 00:24:15 +03:00
talloc_free ( mem_ctx ) ;
2006-03-17 19:27:22 +03:00
return ( 1 ) ;
}
}