2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
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 "lib/smbreadline/smbreadline.h"
28 #include "libcli/libcli.h"
29 #include "lib/ldb/include/ldb.h"
30 #include "lib/events/events.h"
31 #include "dynconfig.h"
33 #include "torture/torture.h"
35 #include "lib/util/dlinklist.h"
36 #include "librpc/rpc/dcerpc.h"
38 static bool run_matching(struct torture_context *torture,
41 struct torture_suite *suite,
47 struct torture_suite *o;
49 for (o = torture_root->children; o; o = o->next) {
50 if (gen_fnmatch(expr, o->name) == 0) {
53 ret &= torture_run_suite(torture, o);
57 ret &= run_matching(torture, o->name, expr, o, matched);
61 struct torture_suite *c;
62 struct torture_tcase *t;
64 for (c = suite->children; c; c = c->next) {
65 asprintf(&name, "%s-%s", prefix, c->name);
67 if (gen_fnmatch(expr, name) == 0) {
70 torture->active_testname = talloc_strdup(torture, prefix);
71 ret &= torture_run_suite(torture, c);
76 ret &= run_matching(torture, name, expr, c, matched);
81 for (t = suite->testcases; t; t = t->next) {
82 asprintf(&name, "%s-%s", prefix, t->name);
83 if (gen_fnmatch(expr, name) == 0) {
86 torture->active_testname = talloc_strdup(torture, prefix);
87 ret &= torture_run_tcase(torture, t);
88 talloc_free(torture->active_testname);
97 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
99 /****************************************************************************
100 run a specified test or "ALL"
101 ****************************************************************************/
102 static bool run_test(struct torture_context *torture, const char *name)
105 bool matched = false;
106 struct torture_suite *o;
108 if (strequal(name, "ALL")) {
109 for (o = torture_root->children; o; o = o->next) {
110 ret &= torture_run_suite(torture, o);
115 ret = run_matching(torture, NULL, name, NULL, &matched);
118 printf("Unknown torture operation '%s'\n", name);
125 static void parse_dns(const char *dns)
127 char *userdn, *basedn, *secret;
130 /* retrievieng the userdn */
131 p = strchr_m(dns, '#');
133 lp_set_cmdline("torture:ldap_userdn", "");
134 lp_set_cmdline("torture:ldap_basedn", "");
135 lp_set_cmdline("torture:ldap_secret", "");
138 userdn = strndup(dns, p - dns);
139 lp_set_cmdline("torture:ldap_userdn", userdn);
141 /* retrieve the basedn */
143 p = strchr_m(d, '#');
145 lp_set_cmdline("torture:ldap_basedn", "");
146 lp_set_cmdline("torture:ldap_secret", "");
149 basedn = strndup(d, p - d);
150 lp_set_cmdline("torture:ldap_basedn", basedn);
152 /* retrieve the secret */
155 lp_set_cmdline("torture:ldap_secret", "");
159 lp_set_cmdline("torture:ldap_secret", secret);
161 printf ("%s - %s - %s\n", userdn, basedn, secret);
165 static void print_test_list(void)
167 struct torture_suite *o;
168 struct torture_suite *s;
169 struct torture_tcase *t;
171 for (o = torture_root->children; o; o = o->next) {
172 for (s = o->children; s; s = s->next) {
173 printf("%s-%s\n", o->name, s->name);
176 for (t = o->testcases; t; t = t->next) {
177 printf("%s-%s\n", o->name, t->name);
182 static void usage(poptContext pc)
184 struct torture_suite *o;
185 struct torture_suite *s;
186 struct torture_tcase *t;
189 poptPrintUsage(pc, stdout, 0);
192 printf("The binding format is:\n\n");
194 printf(" TRANSPORT:host[flags]\n\n");
196 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
197 printf(" or ncalrpc for local connections.\n\n");
199 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
200 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
201 printf(" string.\n\n");
203 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
204 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
205 printf(" will be auto-determined.\n\n");
207 printf(" other recognised flags are:\n\n");
209 printf(" sign : enable ntlmssp signing\n");
210 printf(" seal : enable ntlmssp sealing\n");
211 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
212 printf(" validate: enable the NDR validator\n");
213 printf(" print: enable debugging of the packets\n");
214 printf(" bigendian: use bigendian RPC\n");
215 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
217 printf(" For example, these all connect to the samr pipe:\n\n");
219 printf(" ncacn_np:myserver\n");
220 printf(" ncacn_np:myserver[samr]\n");
221 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
222 printf(" ncacn_np:myserver[/pipe/samr]\n");
223 printf(" ncacn_np:myserver[samr,sign,print]\n");
224 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
225 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
226 printf(" ncacn_np:\n");
227 printf(" ncacn_np:[/pipe/samr]\n\n");
229 printf(" ncacn_ip_tcp:myserver\n");
230 printf(" ncacn_ip_tcp:myserver[1024]\n");
231 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
233 printf(" ncalrpc:\n\n");
235 printf("The UNC format is:\n\n");
237 printf(" //server/share\n\n");
239 printf("Tests are:");
241 for (o = torture_root->children; o; o = o->next) {
242 printf("\n%s (%s):\n ", o->description, o->name);
245 for (s = o->children; s; s = s->next) {
246 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
250 i+=printf("%s-%s ", o->name, s->name);
253 for (t = o->testcases; t; t = t->next) {
254 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
258 i+=printf("%s-%s ", o->name, t->name);
264 printf("\nThe default test is ALL.\n");
269 static void max_runtime_handler(int sig)
271 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
275 struct timeval last_suite_started;
277 static void simple_suite_start(struct torture_context *ctx,
278 struct torture_suite *suite)
280 last_suite_started = timeval_current();
281 printf("Running %s\n", suite->name);
284 static void simple_suite_finish(struct torture_context *ctx,
285 struct torture_suite *suite)
288 printf("%s took %g secs\n\n", suite->name,
289 timeval_elapsed(&last_suite_started));
292 static void simple_test_result (struct torture_context *context,
293 enum torture_result res, const char *reason)
298 printf("OK: %s\n", reason);
301 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
304 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason);
307 printf("SKIP: %s - %s\n", context->active_test->name, reason);
312 static void simple_comment (struct torture_context *test,
315 printf("%s", comment);
318 static void simple_warning(struct torture_context *test,
321 fprintf(stderr, "WARNING: %s\n", comment);
324 const static struct torture_ui_ops std_ui_ops = {
325 .comment = simple_comment,
326 .warning = simple_warning,
327 .suite_start = simple_suite_start,
328 .suite_finish = simple_suite_finish,
329 .test_result = simple_test_result
332 static void subunit_init(struct torture_context *ctx)
334 /* FIXME: register segv and bus handler */
337 static void subunit_suite_start(struct torture_context *ctx,
338 struct torture_suite *suite)
340 printf("testsuite: %s\n", suite->name);
343 static void subunit_test_start (struct torture_context *ctx,
344 struct torture_tcase *tcase,
345 struct torture_test *test)
347 printf("test: %s\n", test->name);
350 static void subunit_test_result (struct torture_context *context,
351 enum torture_result res, const char *reason)
355 printf("success: %s", context->active_test->name);
358 printf("failure: %s", context->active_test->name);
361 printf("error: %s", context->active_test->name);
364 printf("skip: %s", context->active_test->name);
368 printf(" [\n%s\n]", reason);
372 static void subunit_comment (struct torture_context *test,
375 fprintf(stderr, "%s", comment);
378 const static struct torture_ui_ops subunit_ui_ops = {
379 .init = subunit_init,
380 .comment = subunit_comment,
381 .test_start = subunit_test_start,
382 .test_result = subunit_test_result,
383 .suite_start = subunit_suite_start
386 static void harness_test_start (struct torture_context *ctx,
387 struct torture_tcase *tcase,
388 struct torture_test *test)
392 static void harness_test_result (struct torture_context *context,
393 enum torture_result res, const char *reason)
397 printf("ok %s - %s\n", context->active_test->name, reason);
401 printf("not ok %s - %s\n", context->active_test->name, reason);
404 printf("skip %s - %s\n", context->active_test->name, reason);
409 static void harness_comment (struct torture_context *test,
412 printf("# %s\n", comment);
415 const static struct torture_ui_ops harness_ui_ops = {
416 .comment = harness_comment,
417 .test_start = harness_test_start,
418 .test_result = harness_test_result
421 static void quiet_suite_start(struct torture_context *ctx,
422 struct torture_suite *suite)
426 for (i = 1; i < ctx->level; i++) putchar('\t');
427 printf("%s: ", suite->name);
431 static void quiet_suite_finish(struct torture_context *ctx,
432 struct torture_suite *suite)
437 static void quiet_test_result (struct torture_context *context,
438 enum torture_result res, const char *reason)
442 case TORTURE_OK: putchar('.'); break;
443 case TORTURE_FAIL: putchar('F'); break;
444 case TORTURE_ERROR: putchar('E'); break;
445 case TORTURE_SKIP: putchar('I'); break;
449 const static struct torture_ui_ops quiet_ui_ops = {
450 .suite_start = quiet_suite_start,
451 .suite_finish = quiet_suite_finish,
452 .test_result = quiet_test_result
455 void run_shell(struct torture_context *tctx)
463 cline = smb_readline("torture> ", NULL, NULL);
468 ret = poptParseArgvString(cline, &argc, &argv);
470 fprintf(stderr, "Error parsing line\n");
474 if (!strcmp(argv[0], "quit")) {
476 } else if (!strcmp(argv[0], "set")) {
478 fprintf(stderr, "Usage: set <variable> <value>\n");
480 char *name = talloc_asprintf(NULL, "torture:%s", argv[1]);
481 lp_set_cmdline(name, argv[2]);
484 } else if (!strcmp(argv[0], "help")) {
485 fprintf(stderr, "Available commands:\n"
486 " help - This help command\n"
488 " set - Change variables\n"
490 } else if (!strcmp(argv[0], "run")) {
492 fprintf(stderr, "Usage: run TEST-NAME [OPTIONS...]\n");
494 run_test(tctx, argv[1]);
500 /****************************************************************************
502 ****************************************************************************/
503 int main(int argc,char *argv[])
509 struct torture_context *torture;
510 const struct torture_ui_ops *ui_ops;
513 static const char *target = "other";
514 struct dcerpc_binding *binding_struct;
517 static const char *ui_ops_name = "simple";
518 static int list_tests = 0;
519 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
520 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS, OPT_BASEDIR};
522 struct poptOption long_options[] = {
524 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit, harness)", NULL },
525 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
526 {"basedir", 0, POPT_ARG_STRING, NULL, OPT_BASEDIR, "base directory", "BSAEDIR" },
527 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
528 {"num-progs", 0, POPT_ARG_INT, NULL, OPT_NUMPROGS, "num progs", NULL},
529 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
530 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
531 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
532 {"list", 0, POPT_ARG_NONE, &list_tests, 0, NULL, NULL },
533 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
534 {"timelimit", 't', POPT_ARG_INT, NULL, OPT_TIMELIMIT, "timelimit", NULL},
535 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
536 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
537 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
538 "run dangerous tests (eg. wiping out password database)", NULL},
539 {"shell", 0, POPT_ARG_NONE, &shell, True, "Run shell", NULL},
540 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
541 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
542 "run async tests", NULL},
543 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
544 "number of simultaneous async requests", NULL},
545 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
546 "set maximum time for smbtorture to live", "seconds"},
548 POPT_COMMON_CONNECTION
549 POPT_COMMON_CREDENTIALS
556 /* we are never interested in SIGPIPE */
557 BlockSignals(true, SIGPIPE);
559 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
560 POPT_CONTEXT_KEEP_FIRST);
562 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
564 while((opt = poptGetNextOpt(pc)) != -1) {
567 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
570 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
573 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
576 lp_set_cmdline("torture:nprocs", poptGetOptArg(pc));
579 lp_set_cmdline("torture:basedir", poptGetOptArg(pc));
582 parse_dns(poptGetOptArg(pc));
585 lp_set_cmdline("torture:dangerous", "Yes");
588 lp_set_cmdline("torture:async", "Yes");
591 lp_set_cmdline("smb ports", poptGetOptArg(pc));
596 if (strcmp(target, "samba3") == 0) {
597 lp_set_cmdline("torture:samba3", "true");
598 } else if (strcmp(target, "samba4") == 0) {
599 lp_set_cmdline("torture:samba4", "true");
603 /* this will only work if nobody else uses alarm(),
604 which means it won't work for some tests, but we
605 can't use the event context method we use for smbd
606 as so many tests create their own event
607 context. This will at least catch most cases. */
608 signal(SIGALRM, max_runtime_handler);
620 if (torture_seed == 0) {
621 torture_seed = time(NULL);
623 printf("Using seed %d\n", torture_seed);
624 srandom(torture_seed);
626 argv_new = discard_const_p(char *, poptGetArgs(pc));
629 for (i=0; i<argc; i++) {
630 if (argv_new[i] == NULL) {
636 if (!(argc_new >= 3 || (shell && argc_new >= 2))) {
641 /* see if its a RPC transport specifier */
642 status = dcerpc_parse_binding(talloc_autofree_context(), argv_new[1], &binding_struct);
643 if (NT_STATUS_IS_OK(status)) {
644 lp_set_cmdline("torture:host", binding_struct->host);
645 lp_set_cmdline("torture:share", "IPC$");
646 lp_set_cmdline("torture:binding", argv_new[1]);
648 char *binding = NULL;
649 char *host = NULL, *share = NULL;
651 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
652 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
656 lp_set_cmdline("torture:host", host);
657 lp_set_cmdline("torture:share", share);
658 asprintf(&binding, "ncacn_np:%s", host);
659 lp_set_cmdline("torture:binding", binding);
662 if (!strcmp(ui_ops_name, "simple")) {
663 ui_ops = &std_ui_ops;
664 } else if (!strcmp(ui_ops_name, "subunit")) {
665 ui_ops = &subunit_ui_ops;
666 } else if (!strcmp(ui_ops_name, "harness")) {
667 ui_ops = &harness_ui_ops;
668 } else if (!strcmp(ui_ops_name, "quiet")) {
669 ui_ops = &quiet_ui_ops;
671 printf("Unknown output format '%s'\n", ui_ops_name);
675 torture = torture_context_init(talloc_autofree_context(), ui_ops);
678 printf("You must specify a test to run, or 'ALL'\n");
682 for (i=2;i<argc_new;i++) {
683 if (!run_test(torture, argv_new[i])) {
689 if (torture->returncode) {