2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006-2008
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "lib/cmdline/popt_common.h"
23 #include "system/time.h"
24 #include "system/wait.h"
25 #include "system/filesys.h"
26 #include "system/readline.h"
27 #include "../libcli/smbreadline/smbreadline.h"
28 #include "libcli/libcli.h"
29 #include "lib/events/events.h"
31 #include "torture/smbtorture.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "auth/gensec/gensec.h"
34 #include "param/param.h"
35 #include "lib/util/samba_modules.h"
37 #if HAVE_READLINE_HISTORY_H
38 #include <readline/history.h>
41 static char *prefix_name(TALLOC_CTX
*mem_ctx
, const char *prefix
, const char *name
)
44 return talloc_strdup(mem_ctx
, name
);
46 return talloc_asprintf(mem_ctx
, "%s.%s", prefix
, name
);
49 static void print_test_list(const struct torture_suite
*suite
, const char *prefix
, const char *expr
)
51 struct torture_suite
*o
;
52 struct torture_tcase
*t
;
53 struct torture_test
*p
;
55 for (o
= suite
->children
; o
; o
= o
->next
) {
56 char *name
= prefix_name(NULL
, prefix
, o
->name
);
57 print_test_list(o
, name
, expr
);
61 for (t
= suite
->testcases
; t
; t
= t
->next
) {
62 for (p
= t
->tests
; p
; p
= p
->next
) {
63 char *name
= talloc_asprintf(NULL
, "%s.%s.%s", prefix
, t
->name
, p
->name
);
64 if (strncmp(name
, expr
, strlen(expr
)) == 0) {
72 static bool run_matching(struct torture_context
*torture
,
75 const char **restricted
,
76 struct torture_suite
*suite
,
80 struct torture_suite
*o
;
81 struct torture_tcase
*t
;
82 struct torture_test
*p
;
84 for (o
= suite
->children
; o
; o
= o
->next
) {
86 name
= prefix_name(torture
, prefix
, o
->name
);
87 if (gen_fnmatch(expr
, name
) == 0) {
89 reload_charcnv(torture
->lp_ctx
);
90 if (restricted
!= NULL
)
91 ret
&= torture_run_suite_restricted(torture
, o
, restricted
);
93 ret
&= torture_run_suite(torture
, o
);
95 ret
&= run_matching(torture
, name
, expr
, restricted
, o
, matched
);
98 for (t
= suite
->testcases
; t
; t
= t
->next
) {
99 char *name
= talloc_asprintf(torture
, "%s.%s", prefix
, t
->name
);
100 if (gen_fnmatch(expr
, name
) == 0) {
102 reload_charcnv(torture
->lp_ctx
);
103 ret
&= torture_run_tcase_restricted(torture
, t
, restricted
);
105 for (p
= t
->tests
; p
; p
= p
->next
) {
106 name
= talloc_asprintf(torture
, "%s.%s.%s", prefix
, t
->name
, p
->name
);
107 if (gen_fnmatch(expr
, name
) == 0) {
109 reload_charcnv(torture
->lp_ctx
);
110 ret
&= torture_run_test_restricted(torture
, t
, p
, restricted
);
118 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
120 /****************************************************************************
121 run a specified test or "ALL"
122 ****************************************************************************/
123 bool torture_run_named_tests(struct torture_context
*torture
, const char *name
,
124 const char **restricted
)
127 bool matched
= false;
128 struct torture_suite
*o
;
130 torture_ui_report_time(torture
);
132 if (strequal(name
, "ALL")) {
133 if (restricted
!= NULL
) {
134 printf("--load-list and ALL are incompatible\n");
137 for (o
= torture_root
->children
; o
; o
= o
->next
) {
138 ret
&= torture_run_suite(torture
, o
);
143 ret
= run_matching(torture
, NULL
, name
, restricted
, torture_root
, &matched
);
146 printf("Unknown torture operation '%s'\n", name
);
153 bool torture_parse_target(struct loadparm_context
*lp_ctx
, const char *target
)
155 char *host
= NULL
, *share
= NULL
;
156 struct dcerpc_binding
*binding_struct
;
159 /* see if its a RPC transport specifier */
160 if (!smbcli_parse_unc(target
, NULL
, &host
, &share
)) {
161 status
= dcerpc_parse_binding(talloc_autofree_context(), target
, &binding_struct
);
162 if (NT_STATUS_IS_ERR(status
)) {
163 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target
);
167 host
= dcerpc_binding_get_string_option(binding_struct
, "host");
169 lpcfg_set_cmdline(lp_ctx
, "torture:host", host
);
172 if (lpcfg_parm_string(lp_ctx
, NULL
, "torture", "share") == NULL
)
173 lpcfg_set_cmdline(lp_ctx
, "torture:share", "IPC$");
174 lpcfg_set_cmdline(lp_ctx
, "torture:binding", target
);
176 lpcfg_set_cmdline(lp_ctx
, "torture:host", host
);
177 lpcfg_set_cmdline(lp_ctx
, "torture:share", share
);
178 lpcfg_set_cmdline(lp_ctx
, "torture:binding", host
);
184 static void parse_dns(struct loadparm_context
*lp_ctx
, const char *dns
)
186 char *userdn
, *basedn
, *secret
;
189 /* retrievieng the userdn */
190 p
= strchr_m(dns
, '#');
192 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_userdn", "");
193 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_basedn", "");
194 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_secret", "");
197 userdn
= strndup(dns
, p
- dns
);
198 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_userdn", userdn
);
200 /* retrieve the basedn */
202 p
= strchr_m(d
, '#');
204 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_basedn", "");
205 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_secret", "");
208 basedn
= strndup(d
, p
- d
);
209 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_basedn", basedn
);
211 /* retrieve the secret */
214 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_secret", "");
218 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_secret", secret
);
220 printf ("%s - %s - %s\n", userdn
, basedn
, secret
);
224 /* Print the full test list, formatted into separate labelled test
227 static void print_structured_testsuite_list(void)
229 struct torture_suite
*o
;
230 struct torture_suite
*s
;
231 struct torture_tcase
*t
;
234 if (torture_root
== NULL
) {
235 printf("NO TESTS LOADED\n");
239 for (o
= torture_root
->children
; o
; o
= o
->next
) {
240 printf("\n%s (%s):\n ", o
->description
, o
->name
);
243 for (s
= o
->children
; s
; s
= s
->next
) {
244 if (i
+ strlen(o
->name
) + strlen(s
->name
) >= (MAX_COLS
- 3)) {
248 i
+=printf("%s.%s ", o
->name
, s
->name
);
251 for (t
= o
->testcases
; t
; t
= t
->next
) {
252 if (i
+ strlen(o
->name
) + strlen(t
->name
) >= (MAX_COLS
- 3)) {
256 i
+=printf("%s.%s ", o
->name
, t
->name
);
262 printf("\nThe default test is ALL.\n");
265 static void print_testsuite_list(void)
267 struct torture_suite
*o
;
268 struct torture_suite
*s
;
269 struct torture_tcase
*t
;
271 if (torture_root
== NULL
)
274 for (o
= torture_root
->children
; o
; o
= o
->next
) {
275 for (s
= o
->children
; s
; s
= s
->next
) {
276 printf("%s.%s\n", o
->name
, s
->name
);
279 for (t
= o
->testcases
; t
; t
= t
->next
) {
280 printf("%s.%s\n", o
->name
, t
->name
);
285 void torture_print_testsuites(bool structured
)
288 print_structured_testsuite_list();
290 print_testsuite_list();
294 static void usage(poptContext pc
)
296 poptPrintUsage(pc
, stdout
, 0);
299 printf("The binding format is:\n\n");
301 printf(" TRANSPORT:host[flags]\n\n");
303 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
304 printf(" or ncalrpc for local connections.\n\n");
306 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
307 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
308 printf(" string.\n\n");
310 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
311 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
312 printf(" will be auto-determined.\n\n");
314 printf(" other recognised flags are:\n\n");
316 printf(" sign : enable ntlmssp signing\n");
317 printf(" seal : enable ntlmssp sealing\n");
318 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
319 printf(" validate: enable the NDR validator\n");
320 printf(" print: enable debugging of the packets\n");
321 printf(" bigendian: use bigendian RPC\n");
322 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
324 printf(" For example, these all connect to the samr pipe:\n\n");
326 printf(" ncacn_np:myserver\n");
327 printf(" ncacn_np:myserver[samr]\n");
328 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
329 printf(" ncacn_np:myserver[/pipe/samr]\n");
330 printf(" ncacn_np:myserver[samr,sign,print]\n");
331 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
332 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
333 printf(" ncacn_np:\n");
334 printf(" ncacn_np:[/pipe/samr]\n\n");
336 printf(" ncacn_ip_tcp:myserver\n");
337 printf(" ncacn_ip_tcp:myserver[1024]\n");
338 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
340 printf(" ncalrpc:\n\n");
342 printf("The UNC format is:\n\n");
344 printf(" //server/share\n\n");
346 printf("Tests are:");
348 print_structured_testsuite_list();
352 _NORETURN_
static void max_runtime_handler(int sig
)
354 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
358 /****************************************************************************
360 ****************************************************************************/
361 int main(int argc
,char *argv
[])
367 struct torture_context
*torture
;
368 struct torture_results
*results
;
369 const struct torture_ui_ops
*ui_ops
;
372 static const char *target
= "other";
375 static const char *ui_ops_name
= "subunit";
376 const char *basedir
= NULL
;
378 const char *extra_module
= NULL
;
379 static int list_tests
= 0, list_testsuites
= 0;
380 int num_extra_users
= 0;
381 char **restricted
= NULL
;
382 int num_restricted
= -1;
383 const char *load_list
= NULL
;
384 enum {OPT_LOADFILE
=1000,OPT_UNCLIST
,OPT_TIMELIMIT
,OPT_DNS
, OPT_LIST
,
385 OPT_DANGEROUS
,OPT_SMB_PORTS
,OPT_ASYNC
,OPT_NUMPROGS
,
388 struct poptOption long_options
[] = {
390 {"format", 0, POPT_ARG_STRING
, &ui_ops_name
, 0, "Output format (one of: simple, subunit)", NULL
},
391 {"smb-ports", 'p', POPT_ARG_STRING
, NULL
, OPT_SMB_PORTS
, "SMB ports", NULL
},
392 {"basedir", 0, POPT_ARG_STRING
, &basedir
, 0, "base directory", "BASEDIR" },
393 {"seed", 0, POPT_ARG_INT
, &torture_seed
, 0, "Seed to use for randomizer", NULL
},
394 {"num-progs", 0, POPT_ARG_INT
, NULL
, OPT_NUMPROGS
, "num progs", NULL
},
395 {"num-ops", 0, POPT_ARG_INT
, &torture_numops
, 0, "num ops", NULL
},
396 {"entries", 0, POPT_ARG_INT
, &torture_entries
, 0, "entries", NULL
},
397 {"loadfile", 0, POPT_ARG_STRING
, NULL
, OPT_LOADFILE
, "NBench load file to use", NULL
},
398 {"list-suites", 0, POPT_ARG_NONE
, &list_testsuites
, 0, "List available testsuites and exit", NULL
},
399 {"list", 0, POPT_ARG_NONE
, &list_tests
, 0, "List available tests in specified suites and exit", NULL
},
400 {"unclist", 0, POPT_ARG_STRING
, NULL
, OPT_UNCLIST
, "unclist", NULL
},
401 {"timelimit", 't', POPT_ARG_INT
, NULL
, OPT_TIMELIMIT
, "Set time limit (in seconds)", NULL
},
402 {"failures", 'f', POPT_ARG_INT
, &torture_failures
, 0, "failures", NULL
},
403 {"parse-dns", 'D', POPT_ARG_STRING
, NULL
, OPT_DNS
, "parse-dns", NULL
},
404 {"dangerous", 'X', POPT_ARG_NONE
, NULL
, OPT_DANGEROUS
,
405 "run dangerous tests (eg. wiping out password database)", NULL
},
406 {"load-module", 0, POPT_ARG_STRING
, &extra_module
, 0, "load tests from DSO file", "SOFILE"},
407 {"shell", 0, POPT_ARG_NONE
, &shell
, true, "Run shell", NULL
},
408 {"target", 'T', POPT_ARG_STRING
, &target
, 0, "samba3|samba4|other", NULL
},
409 {"async", 'a', POPT_ARG_NONE
, NULL
, OPT_ASYNC
,
410 "run async tests", NULL
},
411 {"num-async", 0, POPT_ARG_INT
, &torture_numasync
, 0,
412 "number of simultaneous async requests", NULL
},
413 {"maximum-runtime", 0, POPT_ARG_INT
, &max_runtime
, 0,
414 "set maximum time for smbtorture to live", "seconds"},
415 {"extra-user", 0, POPT_ARG_STRING
, NULL
, OPT_EXTRA_USER
,
416 "extra user credentials", NULL
},
417 {"load-list", 0, POPT_ARG_STRING
, &load_list
, 0,
418 "load a test id list from a text file", NULL
},
420 POPT_COMMON_CONNECTION
421 POPT_COMMON_CREDENTIALS
428 printf("smbtorture %s\n", samba_version_string());
430 /* we are never interested in SIGPIPE */
431 BlockSignals(true, SIGPIPE
);
433 pc
= poptGetContext("smbtorture", argc
, (const char **) argv
, long_options
,
434 POPT_CONTEXT_KEEP_FIRST
);
436 poptSetOtherOptionHelp(pc
, "<binding>|<unc> TEST1 TEST2 ...");
438 while((opt
= poptGetNextOpt(pc
)) != -1) {
441 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:loadfile", poptGetOptArg(pc
));
444 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:unclist", poptGetOptArg(pc
));
447 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:timelimit", poptGetOptArg(pc
));
450 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:nprocs", poptGetOptArg(pc
));
453 parse_dns(cmdline_lp_ctx
, poptGetOptArg(pc
));
456 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:dangerous", "Yes");
459 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:async", "Yes");
462 lpcfg_set_cmdline(cmdline_lp_ctx
, "smb ports", poptGetOptArg(pc
));
466 char *option
= talloc_asprintf(NULL
, "torture:extra_user%u",
468 const char *value
= poptGetOptArg(pc
);
469 lpcfg_set_cmdline(cmdline_lp_ctx
, option
, value
);
475 printf("bad command line option %d\n", opt
);
481 if (load_list
!= NULL
) {
482 restricted
= file_lines_load(load_list
, &num_restricted
, 0,
483 talloc_autofree_context());
484 if (restricted
== NULL
) {
485 printf("Unable to read load list file '%s'\n", load_list
);
490 if (strcmp(target
, "samba3") == 0) {
491 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:samba3", "true");
492 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:resume_key_support", "false");
493 } else if (strcmp(target
, "samba4") == 0) {
494 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:samba4", "true");
495 } else if (strcmp(target
, "samba4-ntvfs") == 0) {
496 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:samba4", "true");
497 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:samba4-ntvfs", "true");
498 } else if (strcmp(target
, "winxp") == 0) {
499 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:winxp", "true");
500 } else if (strcmp(target
, "w2k3") == 0) {
501 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:w2k3", "true");
502 } else if (strcmp(target
, "w2k8") == 0) {
503 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:w2k8", "true");
504 lpcfg_set_cmdline(cmdline_lp_ctx
,
505 "torture:invalid_lock_range_support", "false");
506 } else if (strcmp(target
, "w2k12") == 0) {
507 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:w2k12", "true");
508 } else if (strcmp(target
, "win7") == 0) {
509 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:win7", "true");
510 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:cn_max_buffer_size",
512 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:resume_key_support", "false");
513 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:rewind_support", "false");
515 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
516 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:search_ea_support", "false");
518 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:hide_on_access_denied",
520 } else if (strcmp(target
, "onefs") == 0) {
521 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:onefs", "true");
522 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:openx_deny_dos_support",
524 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:range_not_locked_on_file_close", "false");
525 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:sacl_support", "false");
526 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:ea_support", "false");
527 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:smbexit_pdu_support",
529 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:smblock_pdu_support",
531 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:2_step_break_to_none",
533 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:deny_dos_support", "false");
534 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:deny_fcb_support", "false");
535 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:read_support", "false");
536 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:writeclose_support", "false");
537 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:resume_key_support", "false");
538 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:rewind_support", "false");
539 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:raw_search_search", "false");
540 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:search_ea_size", "false");
544 /* this will only work if nobody else uses alarm(),
545 which means it won't work for some tests, but we
546 can't use the event context method we use for smbd
547 as so many tests create their own event
548 context. This will at least catch most cases. */
549 signal(SIGALRM
, max_runtime_handler
);
553 if (extra_module
!= NULL
) {
554 init_module_fn fn
= load_module(poptGetOptArg(pc
), false, NULL
);
557 d_printf("Unable to load module from %s\n", poptGetOptArg(pc
));
560 if (NT_STATUS_IS_ERR(status
)) {
561 d_printf("Error initializing module %s: %s\n",
562 poptGetOptArg(pc
), nt_errstr(status
));
569 if (list_testsuites
) {
570 print_testsuite_list();
574 argv_new
= discard_const_p(char *, poptGetArgs(pc
));
577 for (i
=0; i
<argc
; i
++) {
578 if (argv_new
[i
] == NULL
) {
586 print_test_list(torture_root
, NULL
, "");
588 for (i
=1;i
<argc_new
;i
++) {
589 print_test_list(torture_root
, NULL
, argv_new
[i
]);
595 if (torture_seed
== 0) {
596 torture_seed
= time(NULL
);
598 printf("Using seed %d\n", torture_seed
);
599 srandom(torture_seed
);
601 if (!strcmp(ui_ops_name
, "simple")) {
602 ui_ops
= &torture_simple_ui_ops
;
603 } else if (!strcmp(ui_ops_name
, "subunit")) {
604 ui_ops
= &torture_subunit_ui_ops
;
606 printf("Unknown output format '%s'\n", ui_ops_name
);
610 results
= torture_results_init(talloc_autofree_context(), ui_ops
);
612 torture
= torture_context_init(s4_event_context_init(talloc_autofree_context()),
614 if (basedir
!= NULL
) {
615 if (basedir
[0] != '/') {
616 fprintf(stderr
, "Please specify an absolute path to --basedir\n");
619 outputdir
= talloc_asprintf(torture
, "%s/smbtortureXXXXXX", basedir
);
621 char *pwd
= talloc_size(torture
, PATH_MAX
);
622 if (!getcwd(pwd
, PATH_MAX
)) {
623 fprintf(stderr
, "Unable to determine current working directory\n");
626 outputdir
= talloc_asprintf(torture
, "%s/smbtortureXXXXXX", pwd
);
629 fprintf(stderr
, "Could not allocate per-run output dir\n");
632 torture
->outputdir
= mkdtemp(outputdir
);
633 if (!torture
->outputdir
) {
634 perror("Failed to make temp output dir");
637 torture
->lp_ctx
= cmdline_lp_ctx
;
642 /* In shell mode, just ignore any remaining test names. */
643 torture_shell(torture
);
646 /* At this point, we should just have a target string,
647 * followed by a series of test names. Unless we are in
648 * shell mode, in which case we don't need anythig more.
652 printf("You must specify a test to run, or 'ALL'\n");
654 torture
->results
->returncode
= 1;
655 } else if (!torture_parse_target(cmdline_lp_ctx
, argv_new
[1])) {
656 /* Take the target name or binding. */
658 torture
->results
->returncode
= 1;
660 for (i
=2;i
<argc_new
;i
++) {
661 if (!torture_run_named_tests(torture
, argv_new
[i
],
662 (const char **)restricted
)) {
669 /* Now delete the temp dir we created */
670 torture_deltree_outputdir(torture
);
672 if (torture
->results
->returncode
&& correct
) {