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 "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
,
41 struct torture_suite
*suite
,
45 struct torture_suite
*o
;
46 struct torture_tcase
*t
;
48 for (o
= suite
->children
; o
; o
= o
->next
) {
51 name
= talloc_strdup(torture
, o
->name
);
53 name
= talloc_asprintf(torture
, "%s-%s", prefix
, o
->name
);
54 if (gen_fnmatch(expr
, name
) == 0) {
56 reload_charcnv(torture
->lp_ctx
);
57 torture
->active_testname
= name
;
58 if (restricted
!= NULL
)
59 ret
&= torture_run_suite_restricted(torture
, o
, restricted
);
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) {
70 reload_charcnv(torture
->lp_ctx
);
71 torture
->active_testname
= name
;
72 ret
&= torture_run_tcase(torture
, t
);
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
,
89 struct torture_suite
*o
;
91 if (strequal(name
, "ALL")) {
92 if (restricted
!= NULL
) {
93 printf("--load-list and ALL are incompatible\n");
96 for (o
= torture_root
->children
; o
; o
= o
->next
) {
97 ret
&= torture_run_suite(torture
, o
);
102 ret
= run_matching(torture
, NULL
, name
, restricted
, torture_root
, &matched
);
105 printf("Unknown torture operation '%s'\n", name
);
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
;
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
);
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
);
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
);
138 static void parse_dns(struct loadparm_context
*lp_ctx
, const char *dns
)
140 char *userdn
, *basedn
, *secret
;
143 /* retrievieng the userdn */
144 p
= strchr_m(dns
, '#');
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", "");
151 userdn
= strndup(dns
, p
- dns
);
152 lp_set_cmdline(lp_ctx
, "torture:ldap_userdn", userdn
);
154 /* retrieve the basedn */
156 p
= strchr_m(d
, '#');
158 lp_set_cmdline(lp_ctx
, "torture:ldap_basedn", "");
159 lp_set_cmdline(lp_ctx
, "torture:ldap_secret", "");
162 basedn
= strndup(d
, p
- d
);
163 lp_set_cmdline(lp_ctx
, "torture:ldap_basedn", basedn
);
165 /* retrieve the secret */
168 lp_set_cmdline(lp_ctx
, "torture:ldap_secret", "");
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
)
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
;
205 poptPrintUsage(pc
, stdout
, 0);
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");
262 for (o
= torture_root
->children
; o
; o
= o
->next
) {
263 printf("\n%s (%s):\n ", o
->description
, o
->name
);
266 for (s
= o
->children
; s
; s
= s
->next
) {
267 if (i
+ strlen(o
->name
) + strlen(s
->name
) >= (MAX_COLS
- 3)) {
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)) {
279 i
+=printf("%s-%s ", o
->name
, t
->name
);
285 printf("\nThe default test is ALL.\n");
290 _NORETURN_
static void max_runtime_handler(int sig
)
292 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
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
)
319 printf("OK: %s\n", reason
);
322 printf("TEST %s FAILED! - %s\n", context
->active_test
->name
, reason
);
325 printf("ERROR IN TEST %s! - %s\n", context
->active_test
->name
, reason
);
328 printf("SKIP: %s - %s\n", context
->active_test
->name
, reason
);
333 static void simple_comment(struct torture_context
*test
,
336 printf("%s", comment
);
339 static void simple_warning(struct torture_context
*test
,
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 /****************************************************************************
362 ****************************************************************************/
363 int main(int argc
,char *argv
[])
369 struct torture_context
*torture
;
370 struct torture_results
*results
;
371 const struct torture_ui_ops
*ui_ops
;
374 static const char *target
= "other";
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
[] = {
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
},
417 POPT_COMMON_CONNECTION
418 POPT_COMMON_CREDENTIALS
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) {
436 lp_set_cmdline(cmdline_lp_ctx
, "torture:loadfile", poptGetOptArg(pc
));
439 lp_set_cmdline(cmdline_lp_ctx
, "torture:unclist", poptGetOptArg(pc
));
442 lp_set_cmdline(cmdline_lp_ctx
, "torture:timelimit", poptGetOptArg(pc
));
445 lp_set_cmdline(cmdline_lp_ctx
, "torture:nprocs", poptGetOptArg(pc
));
448 parse_dns(cmdline_lp_ctx
, poptGetOptArg(pc
));
451 lp_set_cmdline(cmdline_lp_ctx
, "torture:dangerous", "Yes");
454 lp_set_cmdline(cmdline_lp_ctx
, "torture:async", "Yes");
457 lp_set_cmdline(cmdline_lp_ctx
, "smb ports", poptGetOptArg(pc
));
461 char *option
= talloc_asprintf(NULL
, "torture:extra_user%u",
463 const char *value
= poptGetOptArg(pc
);
464 lp_set_cmdline(cmdline_lp_ctx
, option
, value
);
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
);
477 printf("bad command line option\n");
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",
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",
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",
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",
516 lp_set_cmdline(cmdline_lp_ctx
, "torture:smblock_pdu_support",
518 lp_set_cmdline(cmdline_lp_ctx
, "torture:2_step_break_to_none",
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");
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
);
538 if (extra_module
!= NULL
) {
539 init_module_fn fn
= load_module(talloc_autofree_context(), poptGetOptArg(pc
));
542 d_printf("Unable to load module from %s\n", poptGetOptArg(pc
));
545 if (NT_STATUS_IS_ERR(status
)) {
546 d_printf("Error initializing module %s: %s\n",
547 poptGetOptArg(pc
), nt_errstr(status
));
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
));
568 for (i
=0; i
<argc
; i
++) {
569 if (argv_new
[i
] == NULL
) {
575 if (!(argc_new
>= 3)) {
580 if (!parse_target(cmdline_lp_ctx
, argv_new
[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
;
590 printf("Unknown output format '%s'\n", ui_ops_name
);
594 results
= torture_results_init(talloc_autofree_context(), ui_ops
);
596 torture
= torture_context_init(s4_event_context_init(talloc_autofree_context()),
598 if (basedir
!= NULL
) {
599 if (basedir
[0] != '/') {
600 fprintf(stderr
, "Please specify an absolute path to --basedir\n");
603 torture
->outputdir
= basedir
;
605 char *pwd
= talloc_size(torture
, PATH_MAX
);
606 if (!getcwd(pwd
, PATH_MAX
)) {
607 fprintf(stderr
, "Unable to determine current working directory\n");
610 torture
->outputdir
= pwd
;
613 torture
->lp_ctx
= cmdline_lp_ctx
;
615 gensec_init(cmdline_lp_ctx
);
618 printf("You must specify a testsuite to run, or 'ALL'\n");
620 for (i
=2;i
<argc_new
;i
++) {
621 if (!run_test(torture
, argv_new
[i
], restricted
)) {
627 if (torture
->results
->returncode
&& correct
) {