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/cmdline.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 #ifdef HAVE_READLINE_HISTORY_H
38 #include <readline/history.h>
41 static int use_fullname;
43 static char *prefix_name(TALLOC_CTX *mem_ctx, const char *prefix, const char *name)
46 return talloc_strdup(mem_ctx, name);
48 return talloc_asprintf(mem_ctx, "%s.%s", prefix, name);
51 static void print_test_list(const struct torture_suite *suite, const char *prefix, const char *expr)
53 struct torture_suite *o;
54 struct torture_tcase *t;
55 struct torture_test *p;
57 for (o = suite->children; o; o = o->next) {
58 char *name = prefix_name(NULL, prefix, o->name);
59 print_test_list(o, name, expr);
63 for (t = suite->testcases; t; t = t->next) {
64 for (p = t->tests; p; p = p->next) {
65 char *name = talloc_asprintf(NULL, "%s.%s.%s", prefix, t->name, p->name);
66 if (strncmp(name, expr, strlen(expr)) == 0) {
74 static bool run_matching(struct torture_context *torture,
77 const char **restricted,
78 struct torture_suite *suite,
82 struct torture_suite *o;
83 struct torture_tcase *t;
84 struct torture_test *p;
86 for (o = suite->children; o; o = o->next) {
88 name = prefix_name(torture, prefix, o->name);
89 if (gen_fnmatch(expr, name) == 0) {
91 reload_charcnv(torture->lp_ctx);
92 if (use_fullname == 1) {
93 torture_subunit_prefix_reset(torture, prefix);
95 ret &= torture_run_suite_restricted(torture, o, restricted);
96 if (use_fullname == 1) {
97 torture_subunit_prefix_reset(torture, NULL);
100 * torture_run_suite_restricted() already implements
101 * recursion, so we're done with this child suite.
105 ret &= run_matching(torture, name, expr, restricted, o, matched);
108 for (t = suite->testcases; t; t = t->next) {
109 char *tname = prefix_name(torture, prefix, t->name);
110 if (gen_fnmatch(expr, tname) == 0) {
112 reload_charcnv(torture->lp_ctx);
113 if (use_fullname == 1) {
114 torture_subunit_prefix_reset(torture, prefix);
116 ret &= torture_run_tcase_restricted(torture, t, restricted);
117 if (use_fullname == 1) {
118 torture_subunit_prefix_reset(torture, NULL);
121 * torture_run_tcase_restricted() already implements
122 * recursion, so we're done for this tcase.
126 for (p = t->tests; p; p = p->next) {
127 char *pname = prefix_name(torture, tname, p->name);
128 if (gen_fnmatch(expr, pname) == 0) {
130 reload_charcnv(torture->lp_ctx);
131 if (use_fullname == 1) {
132 torture_subunit_prefix_reset(torture,
135 ret &= torture_run_test_restricted(torture, t, p, restricted);
136 if (use_fullname == 1) {
137 torture_subunit_prefix_reset(torture,
147 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
149 /****************************************************************************
150 run a specified test or "ALL"
151 ****************************************************************************/
152 bool torture_run_named_tests(struct torture_context *torture, const char *name,
153 const char **restricted)
156 bool matched = false;
157 struct torture_suite *o;
159 torture_ui_report_time(torture);
161 if (strequal(name, "ALL")) {
162 if (restricted != NULL) {
163 printf("--load-list and ALL are incompatible\n");
166 for (o = torture_root->children; o; o = o->next) {
167 ret &= torture_run_suite(torture, o);
172 ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
175 printf("Unknown torture operation '%s'\n", name);
182 bool torture_parse_target(TALLOC_CTX *ctx,
183 struct loadparm_context *lp_ctx,
186 char *host = NULL, *share = NULL;
187 struct dcerpc_binding *binding_struct;
190 /* see if its a RPC transport specifier */
191 if (!smbcli_parse_unc(target, NULL, &host, &share)) {
194 status = dcerpc_parse_binding(ctx, target, &binding_struct);
195 if (NT_STATUS_IS_ERR(status)) {
196 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
200 h = dcerpc_binding_get_string_option(binding_struct, "host");
201 host = discard_const_p(char, h);
203 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
206 if (lpcfg_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
207 lpcfg_set_cmdline(lp_ctx, "torture:share", "IPC$");
208 lpcfg_set_cmdline(lp_ctx, "torture:binding", target);
210 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
211 lpcfg_set_cmdline(lp_ctx, "torture:share", share);
212 lpcfg_set_cmdline(lp_ctx, "torture:binding", host);
218 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
220 char *userdn, *basedn, *secret;
223 /* retrieve the userdn */
224 p = strchr_m(dns, '#');
226 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
227 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
228 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
231 userdn = strndup(dns, p - dns);
232 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
234 /* retrieve the basedn */
236 p = strchr_m(d, '#');
238 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
239 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
242 basedn = strndup(d, p - d);
243 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
245 /* retrieve the secret */
248 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
252 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
254 printf ("%s - %s - %s\n", userdn, basedn, secret);
258 /* Print the full test list, formatted into separate labelled test
261 static void print_structured_testsuite_list(void)
263 struct torture_suite *o;
264 struct torture_suite *s;
265 struct torture_tcase *t;
268 if (torture_root == NULL) {
269 printf("NO TESTS LOADED\n");
273 for (o = torture_root->children; o; o = o->next) {
274 printf("\n%s (%s):\n ", o->description, o->name);
277 for (s = o->children; s; s = s->next) {
278 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
282 i+=printf("%s.%s ", o->name, s->name);
285 for (t = o->testcases; t; t = t->next) {
286 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
290 i+=printf("%s.%s ", o->name, t->name);
296 printf("\nThe default test is ALL.\n");
299 static void print_testsuite_list(void)
301 struct torture_suite *o;
302 struct torture_suite *s;
303 struct torture_tcase *t;
305 if (torture_root == NULL)
308 for (o = torture_root->children; o; o = o->next) {
309 for (s = o->children; s; s = s->next) {
310 printf("%s.%s\n", o->name, s->name);
313 for (t = o->testcases; t; t = t->next) {
314 printf("%s.%s\n", o->name, t->name);
319 void torture_print_testsuites(bool structured)
322 print_structured_testsuite_list();
324 print_testsuite_list();
328 static void usage(poptContext pc)
330 poptPrintUsage(pc, stdout, 0);
333 printf("The binding format is:\n\n");
335 printf(" TRANSPORT:host[flags]\n\n");
337 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
338 printf(" or ncalrpc for local connections.\n\n");
340 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
341 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
342 printf(" string.\n\n");
344 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
345 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
346 printf(" will be auto-determined.\n\n");
348 printf(" other recognised flags are:\n\n");
350 printf(" sign : enable ntlmssp signing\n");
351 printf(" seal : enable ntlmssp sealing\n");
352 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
353 printf(" validate: enable the NDR validator\n");
354 printf(" print: enable debugging of the packets\n");
355 printf(" bigendian: use bigendian RPC\n");
356 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
358 printf(" For example, these all connect to the samr pipe:\n\n");
360 printf(" ncacn_np:myserver\n");
361 printf(" ncacn_np:myserver[samr]\n");
362 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
363 printf(" ncacn_np:myserver[/pipe/samr]\n");
364 printf(" ncacn_np:myserver[samr,sign,print]\n");
365 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
366 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
367 printf(" ncacn_np:\n");
368 printf(" ncacn_np:[/pipe/samr]\n\n");
370 printf(" ncacn_ip_tcp:myserver\n");
371 printf(" ncacn_ip_tcp:myserver[1024]\n");
372 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
374 printf(" ncalrpc:\n\n");
376 printf("The UNC format is:\n\n");
378 printf(" //server/share\n\n");
380 printf("Tests are:");
382 print_structured_testsuite_list();
386 _NORETURN_ static void max_runtime_handler(int sig)
388 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
392 /****************************************************************************
394 ****************************************************************************/
395 int main(int argc, const char *argv[])
401 struct torture_context *torture;
402 struct torture_results *results;
403 const struct torture_ui_ops *ui_ops;
406 static const char *target = "other";
409 static const char *ui_ops_name = "subunit";
410 const char *basedir = NULL;
412 const char *extra_module = NULL;
413 static int list_tests = 0, list_testsuites = 0;
414 int num_extra_users = 0;
415 const char **restricted = NULL;
416 int num_restricted = -1;
417 const char *load_list = NULL;
418 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
419 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
421 TALLOC_CTX *mem_ctx = NULL;
422 struct loadparm_context *lp_ctx = NULL;
425 struct poptOption long_options[] = {
427 {"fullname", 0, POPT_ARG_NONE, &use_fullname, 0,
428 "use full name for the test", NULL },
429 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
430 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
431 {"basedir", 0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
432 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "Seed to use for randomizer", NULL},
433 {"num-progs", 0, POPT_ARG_INT, NULL, OPT_NUMPROGS, "num progs", NULL},
434 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
435 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
436 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "NBench load file to use", NULL},
437 {"list-suites", 0, POPT_ARG_NONE, &list_testsuites, 0, "List available testsuites and exit", NULL },
438 {"list", 0, POPT_ARG_NONE, &list_tests, 0, "List available tests in specified suites and exit", NULL },
439 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
440 {"timelimit", 't', POPT_ARG_INT, NULL, OPT_TIMELIMIT, "Set time limit (in seconds)", NULL},
441 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
442 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
443 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
444 "run dangerous tests (eg. wiping out password database)", NULL},
445 {"load-module", 0, POPT_ARG_STRING, &extra_module, 0, "load tests from DSO file", "SOFILE"},
446 {"shell", 0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
447 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
448 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
449 "run async tests", NULL},
450 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
451 "number of simultaneous async requests", NULL},
452 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
453 "set maximum time for smbtorture to live", "seconds"},
454 {"extra-user", 0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
455 "extra user credentials", NULL},
456 {"load-list", 0, POPT_ARG_STRING, &load_list, 0,
457 "load a test id list from a text file", NULL},
459 POPT_COMMON_CONNECTION
460 POPT_COMMON_CREDENTIALS
468 mem_ctx = talloc_named_const(NULL, 0, "torture_ctx");
469 if (mem_ctx == NULL) {
470 printf("Unable to allocate torture_ctx\n");
474 printf("smbtorture %s\n", samba_version_string());
476 /* we are never interested in SIGPIPE */
477 BlockSignals(true, SIGPIPE);
479 ok = samba_cmdline_init(mem_ctx,
480 SAMBA_CMDLINE_CONFIG_CLIENT,
481 false /* require_smbconf */);
483 DBG_ERR("Unable to init cmdline parser\n");
484 TALLOC_FREE(mem_ctx);
488 pc = samba_popt_get_context(getprogname(),
492 POPT_CONTEXT_KEEP_FIRST);
494 DBG_ERR("Failed cmdline parser\n");
495 TALLOC_FREE(mem_ctx);
499 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
501 lp_ctx = samba_cmdline_get_lp_ctx();
503 while((opt = poptGetNextOpt(pc)) != -1) {
506 lpcfg_set_cmdline(lp_ctx, "torture:loadfile", poptGetOptArg(pc));
509 lpcfg_set_cmdline(lp_ctx, "torture:unclist", poptGetOptArg(pc));
512 lpcfg_set_cmdline(lp_ctx, "torture:timelimit", poptGetOptArg(pc));
515 lpcfg_set_cmdline(lp_ctx, "torture:nprocs", poptGetOptArg(pc));
518 parse_dns(lp_ctx, poptGetOptArg(pc));
521 lpcfg_set_cmdline(lp_ctx, "torture:dangerous", "Yes");
524 lpcfg_set_cmdline(lp_ctx, "torture:async", "Yes");
527 lpcfg_set_cmdline(lp_ctx, "smb ports", poptGetOptArg(pc));
531 char *option = talloc_asprintf(mem_ctx,
532 "torture:extra_user%u",
534 const char *value = poptGetOptArg(pc);
535 if (option == NULL) {
536 printf("talloc fail\n");
537 talloc_free(mem_ctx);
540 lpcfg_set_cmdline(lp_ctx, option, value);
546 printf("Invalid command line option %s (%d)\n",
547 poptBadOption(pc, 0),
549 talloc_free(mem_ctx);
555 if (load_list != NULL) {
557 r = file_lines_load(load_list, &num_restricted, 0, mem_ctx);
558 restricted = discard_const_p(const char *, r);
559 if (restricted == NULL) {
560 printf("Unable to read load list file '%s'\n", load_list);
561 talloc_free(mem_ctx);
566 if (strcmp(target, "samba3") == 0) {
567 lpcfg_set_cmdline(lp_ctx, "torture:samba3", "true");
568 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
569 } else if (strcmp(target, "samba4") == 0) {
570 lpcfg_set_cmdline(lp_ctx, "torture:samba4", "true");
571 } else if (strcmp(target, "samba4-ntvfs") == 0) {
572 lpcfg_set_cmdline(lp_ctx, "torture:samba4", "true");
573 lpcfg_set_cmdline(lp_ctx, "torture:samba4-ntvfs", "true");
574 } else if (strcmp(target, "winxp") == 0) {
575 lpcfg_set_cmdline(lp_ctx, "torture:winxp", "true");
576 } else if (strcmp(target, "w2k3") == 0) {
577 lpcfg_set_cmdline(lp_ctx, "torture:w2k3", "true");
578 } else if (strcmp(target, "w2k8") == 0) {
579 lpcfg_set_cmdline(lp_ctx, "torture:w2k8", "true");
580 lpcfg_set_cmdline(lp_ctx,
581 "torture:invalid_lock_range_support", "false");
582 } else if (strcmp(target, "w2k12") == 0) {
583 lpcfg_set_cmdline(lp_ctx, "torture:w2k12", "true");
584 } else if (strcmp(target, "win7") == 0) {
585 lpcfg_set_cmdline(lp_ctx, "torture:win7", "true");
586 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
587 lpcfg_set_cmdline(lp_ctx, "torture:rewind_support", "false");
589 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
590 lpcfg_set_cmdline(lp_ctx, "torture:search_ea_support", "false");
592 lpcfg_set_cmdline(lp_ctx, "torture:hide_on_access_denied",
594 } else if (strcmp(target, "onefs") == 0) {
595 lpcfg_set_cmdline(lp_ctx, "torture:onefs", "true");
596 lpcfg_set_cmdline(lp_ctx, "torture:openx_deny_dos_support",
598 lpcfg_set_cmdline(lp_ctx, "torture:range_not_locked_on_file_close", "false");
599 lpcfg_set_cmdline(lp_ctx, "torture:sacl_support", "false");
600 lpcfg_set_cmdline(lp_ctx, "torture:ea_support", "false");
601 lpcfg_set_cmdline(lp_ctx, "torture:smbexit_pdu_support",
603 lpcfg_set_cmdline(lp_ctx, "torture:smblock_pdu_support",
605 lpcfg_set_cmdline(lp_ctx, "torture:2_step_break_to_none",
607 lpcfg_set_cmdline(lp_ctx, "torture:deny_dos_support", "false");
608 lpcfg_set_cmdline(lp_ctx, "torture:deny_fcb_support", "false");
609 lpcfg_set_cmdline(lp_ctx, "torture:read_support", "false");
610 lpcfg_set_cmdline(lp_ctx, "torture:writeclose_support", "false");
611 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
612 lpcfg_set_cmdline(lp_ctx, "torture:rewind_support", "false");
613 lpcfg_set_cmdline(lp_ctx, "torture:raw_search_search", "false");
614 lpcfg_set_cmdline(lp_ctx, "torture:search_ea_size", "false");
618 /* this will only work if nobody else uses alarm(),
619 which means it won't work for some tests, but we
620 can't use the event context method we use for smbd
621 as so many tests create their own event
622 context. This will at least catch most cases. */
623 signal(SIGALRM, max_runtime_handler);
627 if (extra_module != NULL) {
628 init_module_fn fn = load_module(poptGetOptArg(pc), false, NULL);
631 d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
633 status = fn(mem_ctx);
634 if (NT_STATUS_IS_ERR(status)) {
635 d_printf("Error initializing module %s: %s\n",
636 poptGetOptArg(pc), nt_errstr(status));
640 torture_init(mem_ctx);
643 if (list_testsuites) {
644 print_testsuite_list();
646 talloc_free(mem_ctx);
650 argv_new = discard_const_p(char *, poptGetArgs(pc));
653 for (i=0; i<argc; i++) {
654 if (argv_new[i] == NULL) {
662 print_test_list(torture_root, NULL, "");
664 for (i=1;i<argc_new;i++) {
665 print_test_list(torture_root, NULL, argv_new[i]);
669 talloc_free(mem_ctx);
673 if (torture_seed == 0) {
674 torture_seed = time(NULL);
676 printf("Using seed %d\n", torture_seed);
677 srandom(torture_seed);
679 if (!strcmp(ui_ops_name, "simple")) {
680 ui_ops = &torture_simple_ui_ops;
681 } else if (!strcmp(ui_ops_name, "subunit")) {
682 ui_ops = &torture_subunit_ui_ops;
684 printf("Unknown output format '%s'\n", ui_ops_name);
685 talloc_free(mem_ctx);
689 results = torture_results_init(mem_ctx, ui_ops);
691 torture = torture_context_init(s4_event_context_init(mem_ctx),
693 if (basedir != NULL) {
694 if (basedir[0] != '/') {
695 fprintf(stderr, "Please specify an absolute path to --basedir\n");
697 talloc_free(mem_ctx);
700 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
702 char *pwd = talloc_size(torture, PATH_MAX);
703 if (!getcwd(pwd, PATH_MAX)) {
704 fprintf(stderr, "Unable to determine current working directory\n");
706 talloc_free(mem_ctx);
709 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
712 fprintf(stderr, "Could not allocate per-run output dir\n");
714 talloc_free(mem_ctx);
717 torture->outputdir = mkdtemp(outputdir);
718 if (!torture->outputdir) {
719 perror("Failed to make temp output dir");
721 talloc_free(mem_ctx);
725 torture->lp_ctx = lp_ctx;
730 /* In shell mode, just ignore any remaining test names. */
731 torture_shell(torture);
734 /* At this point, we should just have a target string,
735 * followed by a series of test names. Unless we are in
736 * shell mode, in which case we don't need anything more.
740 printf("You must specify a test to run, or 'ALL'\n");
742 torture->results->returncode = 1;
743 } else if (!torture_parse_target(torture,
744 lp_ctx, argv_new[1])) {
745 /* Take the target name or binding. */
747 torture->results->returncode = 1;
749 for (i=2;i<argc_new;i++) {
750 if (!torture_run_named_tests(torture, argv_new[i],
751 (const char **)restricted)) {
758 /* Now delete the temp dir we created */
759 torture_deltree_outputdir(torture);
761 if (torture->results->returncode && correct) {
763 talloc_free(mem_ctx);
767 talloc_free(mem_ctx);