s4:samba3.py (and test) - deactivate the tests until those parameters are fixed
[Samba/ekacnet.git] / source4 / torture / util_smb.c
blob967faaead273e8a78cb878d1bb45c7c74982c377
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester utility functions
4 Copyright (C) Andrew Tridgell 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/>.
21 #include "includes.h"
22 #include "lib/cmdline/popt_common.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "libcli/raw/ioctl.h"
26 #include "libcli/libcli.h"
27 #include "system/filesys.h"
28 #include "system/shmem.h"
29 #include "system/wait.h"
30 #include "system/time.h"
31 #include "torture/torture.h"
32 #include "../lib/util/dlinklist.h"
33 #include "libcli/resolve/resolve.h"
34 #include "param/param.h"
35 #include "libcli/security/security.h"
36 #include "libcli/util/clilsa.h"
39 /**
40 setup a directory ready for a test
42 _PUBLIC_ bool torture_setup_dir(struct smbcli_state *cli, const char *dname)
44 smb_raw_exit(cli->session);
45 if (smbcli_deltree(cli->tree, dname) == -1 ||
46 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
47 printf("Unable to setup %s - %s\n", dname, smbcli_errstr(cli->tree));
48 return false;
50 return true;
54 create a directory, returning a handle to it
56 NTSTATUS create_directory_handle(struct smbcli_tree *tree, const char *dname, int *fnum)
58 NTSTATUS status;
59 union smb_open io;
60 TALLOC_CTX *mem_ctx;
62 mem_ctx = talloc_named_const(tree, 0, "create_directory_handle");
64 io.generic.level = RAW_OPEN_NTCREATEX;
65 io.ntcreatex.in.root_fid.fnum = 0;
66 io.ntcreatex.in.flags = 0;
67 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
68 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
69 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
70 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
71 io.ntcreatex.in.alloc_size = 0;
72 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
73 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
74 io.ntcreatex.in.security_flags = 0;
75 io.ntcreatex.in.fname = dname;
77 status = smb_raw_open(tree, mem_ctx, &io);
78 talloc_free(mem_ctx);
80 if (NT_STATUS_IS_OK(status)) {
81 *fnum = io.ntcreatex.out.file.fnum;
84 return status;
88 /**
89 sometimes we need a fairly complex file to work with, so we can test
90 all possible attributes.
92 _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *fname)
94 int fnum;
95 char buf[7] = "abc";
96 union smb_setfileinfo setfile;
97 union smb_fileinfo fileinfo;
98 time_t t = (time(NULL) & ~1);
99 NTSTATUS status;
101 smbcli_unlink(cli->tree, fname);
102 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
103 SEC_RIGHTS_FILE_ALL,
104 FILE_ATTRIBUTE_NORMAL,
105 NTCREATEX_SHARE_ACCESS_DELETE|
106 NTCREATEX_SHARE_ACCESS_READ|
107 NTCREATEX_SHARE_ACCESS_WRITE,
108 NTCREATEX_DISP_OVERWRITE_IF,
109 0, 0);
110 if (fnum == -1) return -1;
112 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
114 if (strchr(fname, ':') == NULL) {
115 /* setup some EAs */
116 setfile.generic.level = RAW_SFILEINFO_EA_SET;
117 setfile.generic.in.file.fnum = fnum;
118 setfile.ea_set.in.num_eas = 2;
119 setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2);
120 setfile.ea_set.in.eas[0].flags = 0;
121 setfile.ea_set.in.eas[0].name.s = "EAONE";
122 setfile.ea_set.in.eas[0].value = data_blob_talloc(mem_ctx, "VALUE1", 6);
123 setfile.ea_set.in.eas[1].flags = 0;
124 setfile.ea_set.in.eas[1].name.s = "SECONDEA";
125 setfile.ea_set.in.eas[1].value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
126 status = smb_raw_setfileinfo(cli->tree, &setfile);
127 if (!NT_STATUS_IS_OK(status)) {
128 printf("Failed to setup EAs\n");
132 /* make sure all the timestamps aren't the same, and are also
133 in different DST zones*/
134 setfile.generic.level = RAW_SFILEINFO_SETATTRE;
135 setfile.generic.in.file.fnum = fnum;
137 setfile.setattre.in.create_time = t + 9*30*24*60*60;
138 setfile.setattre.in.access_time = t + 6*30*24*60*60;
139 setfile.setattre.in.write_time = t + 3*30*24*60*60;
141 status = smb_raw_setfileinfo(cli->tree, &setfile);
142 if (!NT_STATUS_IS_OK(status)) {
143 printf("Failed to setup file times - %s\n", nt_errstr(status));
146 /* make sure all the timestamps aren't the same */
147 fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
148 fileinfo.generic.in.file.fnum = fnum;
150 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
151 if (!NT_STATUS_IS_OK(status)) {
152 printf("Failed to query file times - %s\n", nt_errstr(status));
155 if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
156 printf("create_time not setup correctly\n");
158 if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
159 printf("access_time not setup correctly\n");
161 if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
162 printf("write_time not setup correctly\n");
165 return fnum;
170 sometimes we need a fairly complex directory to work with, so we can test
171 all possible attributes.
173 int create_complex_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *dname)
175 int fnum;
176 union smb_setfileinfo setfile;
177 union smb_fileinfo fileinfo;
178 time_t t = (time(NULL) & ~1);
179 NTSTATUS status;
181 smbcli_deltree(cli->tree, dname);
182 fnum = smbcli_nt_create_full(cli->tree, dname, 0,
183 SEC_RIGHTS_DIR_ALL,
184 FILE_ATTRIBUTE_DIRECTORY,
185 NTCREATEX_SHARE_ACCESS_READ|
186 NTCREATEX_SHARE_ACCESS_WRITE,
187 NTCREATEX_DISP_OPEN_IF,
188 NTCREATEX_OPTIONS_DIRECTORY, 0);
189 if (fnum == -1) return -1;
191 if (strchr(dname, ':') == NULL) {
192 /* setup some EAs */
193 setfile.generic.level = RAW_SFILEINFO_EA_SET;
194 setfile.generic.in.file.fnum = fnum;
195 setfile.ea_set.in.num_eas = 2;
196 setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2);
197 setfile.ea_set.in.eas[0].flags = 0;
198 setfile.ea_set.in.eas[0].name.s = "EAONE";
199 setfile.ea_set.in.eas[0].value = data_blob_talloc(mem_ctx, "VALUE1", 6);
200 setfile.ea_set.in.eas[1].flags = 0;
201 setfile.ea_set.in.eas[1].name.s = "SECONDEA";
202 setfile.ea_set.in.eas[1].value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
203 status = smb_raw_setfileinfo(cli->tree, &setfile);
204 if (!NT_STATUS_IS_OK(status)) {
205 printf("Failed to setup EAs\n");
209 /* make sure all the timestamps aren't the same, and are also
210 in different DST zones*/
211 setfile.generic.level = RAW_SFILEINFO_SETATTRE;
212 setfile.generic.in.file.fnum = fnum;
214 setfile.setattre.in.create_time = t + 9*30*24*60*60;
215 setfile.setattre.in.access_time = t + 6*30*24*60*60;
216 setfile.setattre.in.write_time = t + 3*30*24*60*60;
218 status = smb_raw_setfileinfo(cli->tree, &setfile);
219 if (!NT_STATUS_IS_OK(status)) {
220 printf("Failed to setup file times - %s\n", nt_errstr(status));
223 /* make sure all the timestamps aren't the same */
224 fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
225 fileinfo.generic.in.file.fnum = fnum;
227 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
228 if (!NT_STATUS_IS_OK(status)) {
229 printf("Failed to query file times - %s\n", nt_errstr(status));
232 if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
233 printf("create_time not setup correctly\n");
235 if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
236 printf("access_time not setup correctly\n");
238 if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
239 printf("write_time not setup correctly\n");
242 return fnum;
247 /* return a pointer to a anonymous shared memory segment of size "size"
248 which will persist across fork() but will disappear when all processes
249 exit
251 The memory is not zeroed
253 This function uses system5 shared memory. It takes advantage of a property
254 that the memory is not destroyed if it is attached when the id is removed
256 void *shm_setup(int size)
258 int shmid;
259 void *ret;
261 #ifdef __QNXNTO__
262 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
263 if (shmid == -1) {
264 printf("can't get shared memory\n");
265 exit(1);
267 shm_unlink("private");
268 if (ftruncate(shmid, size) == -1) {
269 printf("can't set shared memory size\n");
270 exit(1);
272 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
273 if (ret == MAP_FAILED) {
274 printf("can't map shared memory\n");
275 exit(1);
277 #else
278 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
279 if (shmid == -1) {
280 printf("can't get shared memory\n");
281 exit(1);
283 ret = (void *)shmat(shmid, 0, 0);
284 if (!ret || ret == (void *)-1) {
285 printf("can't attach to shared memory\n");
286 return NULL;
288 /* the following releases the ipc, but note that this process
289 and all its children will still have access to the memory, its
290 just that the shmid is no longer valid for other shm calls. This
291 means we don't leave behind lots of shm segments after we exit
293 See Stevens "advanced programming in unix env" for details
295 shmctl(shmid, IPC_RMID, 0);
296 #endif
298 return ret;
303 check that a wire string matches the flags specified
304 not 100% accurate, but close enough for testing
306 bool wire_bad_flags(struct smb_wire_string *str, int flags,
307 struct smbcli_transport *transport)
309 bool server_unicode;
310 int len;
311 if (!str || !str->s) return true;
312 len = strlen(str->s);
313 if (flags & STR_TERMINATE) len++;
315 server_unicode = (transport->negotiate.capabilities&CAP_UNICODE)?true:false;
316 if (getenv("CLI_FORCE_ASCII") || !transport->options.unicode) {
317 server_unicode = false;
320 if ((flags & STR_UNICODE) || server_unicode) {
321 len *= 2;
322 } else if (flags & STR_TERMINATE_ASCII) {
323 len++;
325 if (str->private_length != len) {
326 printf("Expected wire_length %d but got %d for '%s'\n",
327 len, str->private_length, str->s);
328 return true;
330 return false;
334 dump a all_info QFILEINFO structure
336 void dump_all_info(TALLOC_CTX *mem_ctx, union smb_fileinfo *finfo)
338 d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.create_time));
339 d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.access_time));
340 d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.write_time));
341 d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.change_time));
342 d_printf("\tattrib: 0x%x\n", finfo->all_info.out.attrib);
343 d_printf("\talloc_size: %llu\n", (long long)finfo->all_info.out.alloc_size);
344 d_printf("\tsize: %llu\n", (long long)finfo->all_info.out.size);
345 d_printf("\tnlink: %u\n", finfo->all_info.out.nlink);
346 d_printf("\tdelete_pending: %u\n", finfo->all_info.out.delete_pending);
347 d_printf("\tdirectory: %u\n", finfo->all_info.out.directory);
348 d_printf("\tea_size: %u\n", finfo->all_info.out.ea_size);
349 d_printf("\tfname: '%s'\n", finfo->all_info.out.fname.s);
353 dump file infor by name
355 void torture_all_info(struct smbcli_tree *tree, const char *fname)
357 TALLOC_CTX *mem_ctx = talloc_named(tree, 0, "%s", fname);
358 union smb_fileinfo finfo;
359 NTSTATUS status;
361 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
362 finfo.generic.in.file.path = fname;
363 status = smb_raw_pathinfo(tree, mem_ctx, &finfo);
364 if (!NT_STATUS_IS_OK(status)) {
365 d_printf("%s - %s\n", fname, nt_errstr(status));
366 return;
369 d_printf("%s:\n", fname);
370 dump_all_info(mem_ctx, &finfo);
371 talloc_free(mem_ctx);
376 set a attribute on a file
378 bool torture_set_file_attribute(struct smbcli_tree *tree, const char *fname, uint16_t attrib)
380 union smb_setfileinfo sfinfo;
381 NTSTATUS status;
383 ZERO_STRUCT(sfinfo.basic_info.in);
384 sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION;
385 sfinfo.basic_info.in.file.path = fname;
386 sfinfo.basic_info.in.attrib = attrib;
387 status = smb_raw_setpathinfo(tree, &sfinfo);
388 return NT_STATUS_IS_OK(status);
393 set a file descriptor as sparse
395 NTSTATUS torture_set_sparse(struct smbcli_tree *tree, int fnum)
397 union smb_ioctl nt;
398 NTSTATUS status;
399 TALLOC_CTX *mem_ctx;
401 mem_ctx = talloc_named_const(tree, 0, "torture_set_sparse");
402 if (!mem_ctx) {
403 return NT_STATUS_NO_MEMORY;
406 nt.ntioctl.level = RAW_IOCTL_NTIOCTL;
407 nt.ntioctl.in.function = FSCTL_SET_SPARSE;
408 nt.ntioctl.in.file.fnum = fnum;
409 nt.ntioctl.in.fsctl = true;
410 nt.ntioctl.in.filter = 0;
411 nt.ntioctl.in.max_data = 0;
412 nt.ntioctl.in.blob = data_blob(NULL, 0);
414 status = smb_raw_ioctl(tree, mem_ctx, &nt);
416 talloc_free(mem_ctx);
418 return status;
422 check that an EA has the right value
424 NTSTATUS torture_check_ea(struct smbcli_state *cli,
425 const char *fname, const char *eaname, const char *value)
427 union smb_fileinfo info;
428 NTSTATUS status;
429 struct ea_name ea;
430 TALLOC_CTX *mem_ctx = talloc_new(cli);
432 info.ea_list.level = RAW_FILEINFO_EA_LIST;
433 info.ea_list.in.file.path = fname;
434 info.ea_list.in.num_names = 1;
435 info.ea_list.in.ea_names = &ea;
437 ea.name.s = eaname;
439 status = smb_raw_pathinfo(cli->tree, mem_ctx, &info);
440 if (!NT_STATUS_IS_OK(status)) {
441 talloc_free(mem_ctx);
442 return status;
445 if (info.ea_list.out.num_eas != 1) {
446 printf("Expected 1 ea in ea_list\n");
447 talloc_free(mem_ctx);
448 return NT_STATUS_EA_CORRUPT_ERROR;
451 if (strcasecmp_m(eaname, info.ea_list.out.eas[0].name.s) != 0) {
452 printf("Expected ea '%s' not '%s' in ea_list\n",
453 eaname, info.ea_list.out.eas[0].name.s);
454 talloc_free(mem_ctx);
455 return NT_STATUS_EA_CORRUPT_ERROR;
458 if (value == NULL) {
459 if (info.ea_list.out.eas[0].value.length != 0) {
460 printf("Expected zero length ea for %s\n", eaname);
461 talloc_free(mem_ctx);
462 return NT_STATUS_EA_CORRUPT_ERROR;
464 talloc_free(mem_ctx);
465 return NT_STATUS_OK;
468 if (strlen(value) == info.ea_list.out.eas[0].value.length &&
469 memcmp(value, info.ea_list.out.eas[0].value.data,
470 info.ea_list.out.eas[0].value.length) == 0) {
471 talloc_free(mem_ctx);
472 return NT_STATUS_OK;
475 printf("Expected value '%s' not '%*.*s' for ea %s\n",
476 value,
477 (int)info.ea_list.out.eas[0].value.length,
478 (int)info.ea_list.out.eas[0].value.length,
479 info.ea_list.out.eas[0].value.data,
480 eaname);
482 talloc_free(mem_ctx);
484 return NT_STATUS_EA_CORRUPT_ERROR;
487 _PUBLIC_ bool torture_open_connection_share(TALLOC_CTX *mem_ctx,
488 struct smbcli_state **c,
489 struct torture_context *tctx,
490 const char *hostname,
491 const char *sharename,
492 struct tevent_context *ev)
494 NTSTATUS status;
496 struct smbcli_options options;
497 struct smbcli_session_options session_options;
499 lp_smbcli_options(tctx->lp_ctx, &options);
500 lp_smbcli_session_options(tctx->lp_ctx, &session_options);
502 options.use_oplocks = torture_setting_bool(tctx, "use_oplocks", true);
503 options.use_level2_oplocks = torture_setting_bool(tctx, "use_level2_oplocks", true);
505 status = smbcli_full_connection(mem_ctx, c, hostname,
506 lp_smb_ports(tctx->lp_ctx),
507 sharename, NULL,
508 lp_socket_options(tctx->lp_ctx),
509 cmdline_credentials,
510 lp_resolve_context(tctx->lp_ctx),
511 ev, &options, &session_options,
512 lp_iconv_convenience(tctx->lp_ctx),
513 lp_gensec_settings(tctx, tctx->lp_ctx));
514 if (!NT_STATUS_IS_OK(status)) {
515 printf("Failed to open connection - %s\n", nt_errstr(status));
516 return false;
519 return true;
522 _PUBLIC_ bool torture_get_conn_index(int conn_index,
523 TALLOC_CTX *mem_ctx,
524 struct torture_context *tctx,
525 char **host, char **share)
527 char **unc_list = NULL;
528 int num_unc_names = 0;
529 const char *p;
531 (*host) = talloc_strdup(mem_ctx, torture_setting_string(tctx, "host", NULL));
532 (*share) = talloc_strdup(mem_ctx, torture_setting_string(tctx, "share", NULL));
534 p = torture_setting_string(tctx, "unclist", NULL);
535 if (!p) {
536 return true;
539 unc_list = file_lines_load(p, &num_unc_names, 0, NULL);
540 if (!unc_list || num_unc_names <= 0) {
541 DEBUG(0,("Failed to load unc names list from '%s'\n", p));
542 return false;
545 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
546 mem_ctx, host, share)) {
547 DEBUG(0, ("Failed to parse UNC name %s\n",
548 unc_list[conn_index % num_unc_names]));
549 return false;
552 talloc_free(unc_list);
553 return true;
558 _PUBLIC_ bool torture_open_connection_ev(struct smbcli_state **c,
559 int conn_index,
560 struct torture_context *tctx,
561 struct tevent_context *ev)
563 char *host, *share;
564 bool ret;
566 if (!torture_get_conn_index(conn_index, ev, tctx, &host, &share)) {
567 return false;
570 ret = torture_open_connection_share(NULL, c, tctx, host, share, ev);
571 talloc_free(host);
572 talloc_free(share);
574 return ret;
577 _PUBLIC_ bool torture_open_connection(struct smbcli_state **c, struct torture_context *tctx, int conn_index)
579 return torture_open_connection_ev(c, conn_index, tctx, tctx->ev);
584 _PUBLIC_ bool torture_close_connection(struct smbcli_state *c)
586 bool ret = true;
587 if (!c) return true;
588 if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
589 printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
590 ret = false;
592 talloc_free(c);
593 return ret;
597 /* check if the server produced the expected error code */
598 _PUBLIC_ bool check_error(const char *location, struct smbcli_state *c,
599 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
601 NTSTATUS status;
603 status = smbcli_nt_error(c->tree);
604 if (NT_STATUS_IS_DOS(status)) {
605 int classnum, num;
606 classnum = NT_STATUS_DOS_CLASS(status);
607 num = NT_STATUS_DOS_CODE(status);
608 if (eclass != classnum || ecode != num) {
609 printf("unexpected error code %s\n", nt_errstr(status));
610 printf(" expected %s or %s (at %s)\n",
611 nt_errstr(NT_STATUS_DOS(eclass, ecode)),
612 nt_errstr(nterr), location);
613 return false;
615 } else {
616 if (!NT_STATUS_EQUAL(nterr, status)) {
617 printf("unexpected error code %s\n", nt_errstr(status));
618 printf(" expected %s (at %s)\n", nt_errstr(nterr), location);
619 return false;
623 return true;
626 static struct smbcli_state *current_cli;
627 static int procnum; /* records process count number when forking */
629 static void sigcont(int sig)
633 double torture_create_procs(struct torture_context *tctx,
634 bool (*fn)(struct torture_context *, struct smbcli_state *, int), bool *result)
636 int i, status;
637 volatile pid_t *child_status;
638 volatile bool *child_status_out;
639 int synccount;
640 int tries = 8;
641 int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
642 double start_time_limit = 10 + (torture_nprocs * 1.5);
643 struct timeval tv;
645 *result = true;
647 synccount = 0;
649 signal(SIGCONT, sigcont);
651 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
652 if (!child_status) {
653 printf("Failed to setup shared memory\n");
654 return -1;
657 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs);
658 if (!child_status_out) {
659 printf("Failed to setup result status shared memory\n");
660 return -1;
663 for (i = 0; i < torture_nprocs; i++) {
664 child_status[i] = 0;
665 child_status_out[i] = true;
668 tv = timeval_current();
670 for (i=0;i<torture_nprocs;i++) {
671 procnum = i;
672 if (fork() == 0) {
673 char *myname;
675 pid_t mypid = getpid();
676 srandom(((int)mypid) ^ ((int)time(NULL)));
678 if (asprintf(&myname, "CLIENT%d", i) == -1) {
679 printf("asprintf failed\n");
680 return -1;
682 lp_set_cmdline(tctx->lp_ctx, "netbios name", myname);
683 free(myname);
686 while (1) {
687 if (torture_open_connection(&current_cli, tctx, i)) {
688 break;
690 if (tries-- == 0) {
691 printf("pid %d failed to start\n", (int)getpid());
692 _exit(1);
694 msleep(100);
697 child_status[i] = getpid();
699 pause();
701 if (child_status[i]) {
702 printf("Child %d failed to start!\n", i);
703 child_status_out[i] = 1;
704 _exit(1);
707 child_status_out[i] = fn(tctx, current_cli, i);
708 _exit(0);
712 do {
713 synccount = 0;
714 for (i=0;i<torture_nprocs;i++) {
715 if (child_status[i]) synccount++;
717 if (synccount == torture_nprocs) break;
718 msleep(100);
719 } while (timeval_elapsed(&tv) < start_time_limit);
721 if (synccount != torture_nprocs) {
722 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
723 *result = false;
724 return timeval_elapsed(&tv);
727 printf("Starting %d clients\n", torture_nprocs);
729 /* start the client load */
730 tv = timeval_current();
731 for (i=0;i<torture_nprocs;i++) {
732 child_status[i] = 0;
735 printf("%d clients started\n", torture_nprocs);
737 kill(0, SIGCONT);
739 for (i=0;i<torture_nprocs;i++) {
740 int ret;
741 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
742 if (ret == -1 || WEXITSTATUS(status) != 0) {
743 *result = false;
747 printf("\n");
749 for (i=0;i<torture_nprocs;i++) {
750 if (!child_status_out[i]) {
751 *result = false;
754 return timeval_elapsed(&tv);
757 static bool wrap_smb_multi_test(struct torture_context *torture,
758 struct torture_tcase *tcase,
759 struct torture_test *test)
761 bool (*fn)(struct torture_context *, struct smbcli_state *, int ) = test->fn;
762 bool result;
764 torture_create_procs(torture, fn, &result);
766 return result;
769 _PUBLIC_ struct torture_test *torture_suite_add_smb_multi_test(
770 struct torture_suite *suite,
771 const char *name,
772 bool (*run) (struct torture_context *,
773 struct smbcli_state *,
774 int i))
776 struct torture_test *test;
777 struct torture_tcase *tcase;
779 tcase = torture_suite_add_tcase(suite, name);
781 test = talloc(tcase, struct torture_test);
783 test->name = talloc_strdup(test, name);
784 test->description = NULL;
785 test->run = wrap_smb_multi_test;
786 test->fn = run;
787 test->dangerous = false;
789 DLIST_ADD_END(tcase->tests, test, struct torture_test *);
791 return test;
795 static bool wrap_simple_2smb_test(struct torture_context *torture_ctx,
796 struct torture_tcase *tcase,
797 struct torture_test *test)
799 bool (*fn) (struct torture_context *, struct smbcli_state *,
800 struct smbcli_state *);
801 bool ret;
803 struct smbcli_state *cli1, *cli2;
805 if (!torture_open_connection(&cli1, torture_ctx, 0) ||
806 !torture_open_connection(&cli2, torture_ctx, 1))
807 return false;
809 fn = test->fn;
811 ret = fn(torture_ctx, cli1, cli2);
813 talloc_free(cli1);
814 talloc_free(cli2);
816 return ret;
821 _PUBLIC_ struct torture_test *torture_suite_add_2smb_test(
822 struct torture_suite *suite,
823 const char *name,
824 bool (*run) (struct torture_context *,
825 struct smbcli_state *,
826 struct smbcli_state *))
828 struct torture_test *test;
829 struct torture_tcase *tcase;
831 tcase = torture_suite_add_tcase(suite, name);
833 test = talloc(tcase, struct torture_test);
835 test->name = talloc_strdup(test, name);
836 test->description = NULL;
837 test->run = wrap_simple_2smb_test;
838 test->fn = run;
839 test->dangerous = false;
841 DLIST_ADD_END(tcase->tests, test, struct torture_test *);
843 return test;
847 static bool wrap_simple_1smb_test(struct torture_context *torture_ctx,
848 struct torture_tcase *tcase,
849 struct torture_test *test)
851 bool (*fn) (struct torture_context *, struct smbcli_state *);
852 bool ret;
854 struct smbcli_state *cli1;
856 if (!torture_open_connection(&cli1, torture_ctx, 0))
857 return false;
859 fn = test->fn;
861 ret = fn(torture_ctx, cli1);
863 talloc_free(cli1);
865 return ret;
868 _PUBLIC_ struct torture_test *torture_suite_add_1smb_test(
869 struct torture_suite *suite,
870 const char *name,
871 bool (*run) (struct torture_context *, struct smbcli_state *))
873 struct torture_test *test;
874 struct torture_tcase *tcase;
876 tcase = torture_suite_add_tcase(suite, name);
878 test = talloc(tcase, struct torture_test);
880 test->name = talloc_strdup(test, name);
881 test->description = NULL;
882 test->run = wrap_simple_1smb_test;
883 test->fn = run;
884 test->dangerous = false;
886 DLIST_ADD_END(tcase->tests, test, struct torture_test *);
888 return test;
892 NTSTATUS torture_second_tcon(TALLOC_CTX *mem_ctx,
893 struct smbcli_session *session,
894 const char *sharename,
895 struct smbcli_tree **res)
897 union smb_tcon tcon;
898 struct smbcli_tree *result;
899 TALLOC_CTX *tmp_ctx;
900 NTSTATUS status;
902 if ((tmp_ctx = talloc_new(mem_ctx)) == NULL) {
903 return NT_STATUS_NO_MEMORY;
906 result = smbcli_tree_init(session, tmp_ctx, false);
907 if (result == NULL) {
908 talloc_free(tmp_ctx);
909 return NT_STATUS_NO_MEMORY;
912 tcon.generic.level = RAW_TCON_TCONX;
913 tcon.tconx.in.flags = 0;
915 /* Ignore share mode security here */
916 tcon.tconx.in.password = data_blob(NULL, 0);
917 tcon.tconx.in.path = sharename;
918 tcon.tconx.in.device = "?????";
920 status = smb_raw_tcon(result, tmp_ctx, &tcon);
921 if (!NT_STATUS_IS_OK(status)) {
922 talloc_free(tmp_ctx);
923 return status;
926 result->tid = tcon.tconx.out.tid;
927 *res = talloc_steal(mem_ctx, result);
928 talloc_free(tmp_ctx);
929 return NT_STATUS_OK;
933 a wrapper around smblsa_sid_check_privilege, that tries to take
934 account of the fact that the lsa privileges calls don't expand
935 group memberships, using an explicit check for administrator. There
936 must be a better way ...
938 NTSTATUS torture_check_privilege(struct smbcli_state *cli,
939 const char *sid_str,
940 const char *privilege)
942 struct dom_sid *sid;
943 TALLOC_CTX *tmp_ctx = talloc_new(cli);
944 uint32_t rid;
945 NTSTATUS status;
947 sid = dom_sid_parse_talloc(tmp_ctx, sid_str);
948 if (sid == NULL) {
949 talloc_free(tmp_ctx);
950 return NT_STATUS_INVALID_SID;
953 status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
954 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
956 if (rid == DOMAIN_RID_ADMINISTRATOR) {
957 /* assume the administrator has them all */
958 return NT_STATUS_OK;
961 talloc_free(tmp_ctx);
963 return smblsa_sid_check_privilege(cli, sid_str, privilege);