s4:operational LDB module - fix warnings (missing parameters, unused variable)
[Samba/ekacnet.git] / source4 / torture / smbtorture.c
blobbaa9afebb6567b7010cb7f5aea789e1cd070c252
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
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/>.
21 #include "includes.h"
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/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"
37 static bool run_matching(struct torture_context *torture,
38 const char *prefix,
39 const char *expr,
40 char **restricted,
41 struct torture_suite *suite,
42 bool *matched)
44 bool ret = true;
45 struct torture_suite *o;
46 struct torture_tcase *t;
48 for (o = suite->children; o; o = o->next) {
49 char *name = NULL;
50 if (prefix == NULL)
51 name = talloc_strdup(torture, o->name);
52 else
53 name = talloc_asprintf(torture, "%s-%s", prefix, o->name);
54 if (gen_fnmatch(expr, name) == 0) {
55 *matched = true;
56 reload_charcnv(torture->lp_ctx);
57 torture->active_testname = name;
58 if (restricted != NULL)
59 ret &= torture_run_suite_restricted(torture, o, restricted);
60 else
61 ret &= torture_run_suite(torture, o);
63 ret &= run_matching(torture, name, expr, restricted, o, matched);
66 for (t = suite->testcases; t; t = t->next) {
67 char *name = talloc_asprintf(torture, "%s-%s", prefix, t->name);
68 if (gen_fnmatch(expr, name) == 0) {
69 *matched = true;
70 reload_charcnv(torture->lp_ctx);
71 torture->active_testname = name;
72 ret &= torture_run_tcase(torture, t);
76 return ret;
79 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
81 /****************************************************************************
82 run a specified test or "ALL"
83 ****************************************************************************/
84 static bool run_test(struct torture_context *torture, const char *name,
85 char **restricted)
87 bool ret = true;
88 bool matched = false;
89 struct torture_suite *o;
91 if (strequal(name, "ALL")) {
92 if (restricted != NULL) {
93 printf("--load-list and ALL are incompatible\n");
94 return false;
96 for (o = torture_root->children; o; o = o->next) {
97 ret &= torture_run_suite(torture, o);
99 return ret;
102 ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
104 if (!matched) {
105 printf("Unknown torture operation '%s'\n", name);
106 return false;
109 return ret;
112 static bool parse_target(struct loadparm_context *lp_ctx, const char *target)
114 char *host = NULL, *share = NULL;
115 struct dcerpc_binding *binding_struct;
116 NTSTATUS status;
118 /* see if its a RPC transport specifier */
119 if (!smbcli_parse_unc(target, NULL, &host, &share)) {
120 status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct);
121 if (NT_STATUS_IS_ERR(status)) {
122 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
123 return false;
125 lp_set_cmdline(lp_ctx, "torture:host", binding_struct->host);
126 if (lp_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
127 lp_set_cmdline(lp_ctx, "torture:share", "IPC$");
128 lp_set_cmdline(lp_ctx, "torture:binding", target);
129 } else {
130 lp_set_cmdline(lp_ctx, "torture:host", host);
131 lp_set_cmdline(lp_ctx, "torture:share", share);
132 lp_set_cmdline(lp_ctx, "torture:binding", host);
135 return true;
138 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
140 char *userdn, *basedn, *secret;
141 char *p, *d;
143 /* retrievieng the userdn */
144 p = strchr_m(dns, '#');
145 if (!p) {
146 lp_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
147 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
148 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
149 return;
151 userdn = strndup(dns, p - dns);
152 lp_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
154 /* retrieve the basedn */
155 d = p + 1;
156 p = strchr_m(d, '#');
157 if (!p) {
158 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
159 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
160 return;
162 basedn = strndup(d, p - d);
163 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
165 /* retrieve the secret */
166 p = p + 1;
167 if (!p) {
168 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
169 return;
171 secret = strdup(p);
172 lp_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
174 printf ("%s - %s - %s\n", userdn, basedn, secret);
178 static void print_test_list(void)
180 struct torture_suite *o;
181 struct torture_suite *s;
182 struct torture_tcase *t;
184 if (torture_root == NULL)
185 return;
187 for (o = torture_root->children; o; o = o->next) {
188 for (s = o->children; s; s = s->next) {
189 printf("%s-%s\n", o->name, s->name);
192 for (t = o->testcases; t; t = t->next) {
193 printf("%s-%s\n", o->name, t->name);
198 _NORETURN_ static void usage(poptContext pc)
200 struct torture_suite *o;
201 struct torture_suite *s;
202 struct torture_tcase *t;
203 int i;
205 poptPrintUsage(pc, stdout, 0);
206 printf("\n");
208 printf("The binding format is:\n\n");
210 printf(" TRANSPORT:host[flags]\n\n");
212 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
213 printf(" or ncalrpc for local connections.\n\n");
215 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
216 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
217 printf(" string.\n\n");
219 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
220 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
221 printf(" will be auto-determined.\n\n");
223 printf(" other recognised flags are:\n\n");
225 printf(" sign : enable ntlmssp signing\n");
226 printf(" seal : enable ntlmssp sealing\n");
227 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
228 printf(" validate: enable the NDR validator\n");
229 printf(" print: enable debugging of the packets\n");
230 printf(" bigendian: use bigendian RPC\n");
231 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
233 printf(" For example, these all connect to the samr pipe:\n\n");
235 printf(" ncacn_np:myserver\n");
236 printf(" ncacn_np:myserver[samr]\n");
237 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
238 printf(" ncacn_np:myserver[/pipe/samr]\n");
239 printf(" ncacn_np:myserver[samr,sign,print]\n");
240 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
241 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
242 printf(" ncacn_np:\n");
243 printf(" ncacn_np:[/pipe/samr]\n\n");
245 printf(" ncacn_ip_tcp:myserver\n");
246 printf(" ncacn_ip_tcp:myserver[1024]\n");
247 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
249 printf(" ncalrpc:\n\n");
251 printf("The UNC format is:\n\n");
253 printf(" //server/share\n\n");
255 printf("Tests are:");
257 if (torture_root == NULL) {
258 printf("NO TESTS LOADED\n");
259 exit(1);
262 for (o = torture_root->children; o; o = o->next) {
263 printf("\n%s (%s):\n ", o->description, o->name);
265 i = 0;
266 for (s = o->children; s; s = s->next) {
267 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
268 printf("\n ");
269 i = 0;
271 i+=printf("%s-%s ", o->name, s->name);
274 for (t = o->testcases; t; t = t->next) {
275 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
276 printf("\n ");
277 i = 0;
279 i+=printf("%s-%s ", o->name, t->name);
282 if (i) printf("\n");
285 printf("\nThe default test is ALL.\n");
287 exit(1);
290 _NORETURN_ static void max_runtime_handler(int sig)
292 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
293 exit(1);
296 struct timeval last_suite_started;
298 static void simple_suite_start(struct torture_context *ctx,
299 struct torture_suite *suite)
301 last_suite_started = timeval_current();
302 printf("Running %s\n", suite->name);
305 static void simple_suite_finish(struct torture_context *ctx,
306 struct torture_suite *suite)
309 printf("%s took %g secs\n\n", suite->name,
310 timeval_elapsed(&last_suite_started));
313 static void simple_test_result(struct torture_context *context,
314 enum torture_result res, const char *reason)
316 switch (res) {
317 case TORTURE_OK:
318 if (reason)
319 printf("OK: %s\n", reason);
320 break;
321 case TORTURE_FAIL:
322 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
323 break;
324 case TORTURE_ERROR:
325 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason);
326 break;
327 case TORTURE_SKIP:
328 printf("SKIP: %s - %s\n", context->active_test->name, reason);
329 break;
333 static void simple_comment(struct torture_context *test,
334 const char *comment)
336 printf("%s", comment);
339 static void simple_warning(struct torture_context *test,
340 const char *comment)
342 fprintf(stderr, "WARNING: %s\n", comment);
345 static void simple_progress(struct torture_context *test,
346 int offset, enum torture_progress_whence whence)
350 const static struct torture_ui_ops std_ui_ops = {
351 .comment = simple_comment,
352 .warning = simple_warning,
353 .suite_start = simple_suite_start,
354 .suite_finish = simple_suite_finish,
355 .test_result = simple_test_result,
356 .progress = simple_progress,
360 /****************************************************************************
361 main program
362 ****************************************************************************/
363 int main(int argc,char *argv[])
365 int opt, i;
366 bool correct = true;
367 int max_runtime=0;
368 int argc_new;
369 struct torture_context *torture;
370 struct torture_results *results;
371 const struct torture_ui_ops *ui_ops;
372 char **argv_new;
373 poptContext pc;
374 static const char *target = "other";
375 NTSTATUS status;
376 static const char *ui_ops_name = "subunit";
377 const char *basedir = NULL;
378 const char *extra_module = NULL;
379 static int list_tests = 0;
380 int num_extra_users = 0;
381 char **restricted = NULL;
382 int num_restricted = -1;
383 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
384 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
385 OPT_EXTRA_USER,OPT_LOAD_LIST,};
387 struct poptOption long_options[] = {
388 POPT_AUTOHELP
389 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
390 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
391 {"basedir", 0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
392 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "Seed to use for randomizer", NULL},
393 {"num-progs", 0, POPT_ARG_INT, NULL, OPT_NUMPROGS, "num progs", NULL},
394 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
395 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
396 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "NBench load file to use", NULL},
397 {"list", 0, POPT_ARG_NONE, &list_tests, 0, "List available tests and exit", NULL },
398 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
399 {"timelimit", 't', POPT_ARG_INT, NULL, OPT_TIMELIMIT, "Set time limit (in seconds)", NULL},
400 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
401 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
402 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
403 "run dangerous tests (eg. wiping out password database)", NULL},
404 {"load-module", 0, POPT_ARG_STRING, &extra_module, 0, "load tests from DSO file", "SOFILE"},
405 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
406 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
407 "run async tests", NULL},
408 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
409 "number of simultaneous async requests", NULL},
410 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
411 "set maximum time for smbtorture to live", "seconds"},
412 {"extra-user", 0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
413 "extra user credentials", NULL},
414 {"load-list", 0, POPT_ARG_STRING, NULL, OPT_LOAD_LIST,
415 "load a test id list from a text file", NULL},
416 POPT_COMMON_SAMBA
417 POPT_COMMON_CONNECTION
418 POPT_COMMON_CREDENTIALS
419 POPT_COMMON_VERSION
420 { NULL }
423 setlinebuf(stdout);
425 /* we are never interested in SIGPIPE */
426 BlockSignals(true, SIGPIPE);
428 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
429 POPT_CONTEXT_KEEP_FIRST);
431 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
433 while((opt = poptGetNextOpt(pc)) != -1) {
434 switch (opt) {
435 case OPT_LOADFILE:
436 lp_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
437 break;
438 case OPT_UNCLIST:
439 lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
440 break;
441 case OPT_TIMELIMIT:
442 lp_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
443 break;
444 case OPT_NUMPROGS:
445 lp_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
446 break;
447 case OPT_DNS:
448 parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
449 break;
450 case OPT_DANGEROUS:
451 lp_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
452 break;
453 case OPT_ASYNC:
454 lp_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
455 break;
456 case OPT_SMB_PORTS:
457 lp_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
458 break;
459 case OPT_EXTRA_USER:
461 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
462 ++num_extra_users);
463 const char *value = poptGetOptArg(pc);
464 lp_set_cmdline(cmdline_lp_ctx, option, value);
465 talloc_free(option);
467 break;
468 case OPT_LOAD_LIST:
469 restricted = file_lines_load(optarg, &num_restricted, 0,
470 talloc_autofree_context());
471 if (restricted == NULL) {
472 printf("Unable to read load list file '%s'\n", optarg);
473 exit(1);
475 break;
476 default:
477 printf("bad command line option\n");
478 exit(1);
482 if (strcmp(target, "samba3") == 0) {
483 lp_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
484 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
485 } else if (strcmp(target, "samba4") == 0) {
486 lp_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
487 } else if (strcmp(target, "winxp") == 0) {
488 lp_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
489 } else if (strcmp(target, "w2k3") == 0) {
490 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
491 } else if (strcmp(target, "w2k8") == 0) {
492 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
493 lp_set_cmdline(cmdline_lp_ctx,
494 "torture:invalid_lock_range_support", "false");
495 } else if (strcmp(target, "win7") == 0) {
496 lp_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
497 lp_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
498 "0x00010000");
499 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
500 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
502 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
503 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
505 lp_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
506 "true");
507 } else if (strcmp(target, "onefs") == 0) {
508 lp_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
509 lp_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
510 "false");
511 lp_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
512 lp_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
513 lp_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
514 lp_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
515 "false");
516 lp_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
517 "false");
518 lp_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
519 "true");
520 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
521 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
522 lp_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
523 lp_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
524 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
525 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
528 if (max_runtime) {
529 /* this will only work if nobody else uses alarm(),
530 which means it won't work for some tests, but we
531 can't use the event context method we use for smbd
532 as so many tests create their own event
533 context. This will at least catch most cases. */
534 signal(SIGALRM, max_runtime_handler);
535 alarm(max_runtime);
538 if (extra_module != NULL) {
539 init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
541 if (fn == NULL)
542 d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
543 else {
544 status = fn();
545 if (NT_STATUS_IS_ERR(status)) {
546 d_printf("Error initializing module %s: %s\n",
547 poptGetOptArg(pc), nt_errstr(status));
550 } else {
551 torture_init();
554 if (list_tests) {
555 print_test_list();
556 return 0;
559 if (torture_seed == 0) {
560 torture_seed = time(NULL);
562 printf("Using seed %d\n", torture_seed);
563 srandom(torture_seed);
565 argv_new = discard_const_p(char *, poptGetArgs(pc));
567 argc_new = argc;
568 for (i=0; i<argc; i++) {
569 if (argv_new[i] == NULL) {
570 argc_new = i;
571 break;
575 if (!(argc_new >= 3)) {
576 usage(pc);
577 exit(1);
580 if (!parse_target(cmdline_lp_ctx, argv_new[1])) {
581 usage(pc);
582 exit(1);
585 if (!strcmp(ui_ops_name, "simple")) {
586 ui_ops = &std_ui_ops;
587 } else if (!strcmp(ui_ops_name, "subunit")) {
588 ui_ops = &torture_subunit_ui_ops;
589 } else {
590 printf("Unknown output format '%s'\n", ui_ops_name);
591 exit(1);
594 results = torture_results_init(talloc_autofree_context(), ui_ops);
596 torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
597 results);
598 if (basedir != NULL) {
599 if (basedir[0] != '/') {
600 fprintf(stderr, "Please specify an absolute path to --basedir\n");
601 return 1;
603 torture->outputdir = basedir;
604 } else {
605 char *pwd = talloc_size(torture, PATH_MAX);
606 if (!getcwd(pwd, PATH_MAX)) {
607 fprintf(stderr, "Unable to determine current working directory\n");
608 return 1;
610 torture->outputdir = pwd;
613 torture->lp_ctx = cmdline_lp_ctx;
615 gensec_init(cmdline_lp_ctx);
617 if (argc_new == 0) {
618 printf("You must specify a testsuite to run, or 'ALL'\n");
619 } else {
620 for (i=2;i<argc_new;i++) {
621 if (!run_test(torture, argv_new[i], restricted)) {
622 correct = false;
627 if (torture->results->returncode && correct) {
628 return(0);
629 } else {
630 return(1);