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/>.
22 #include "lib/cmdline/popt_common.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "../libcli/smb/smb_constants.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/smb2/smb2.h"
37 #include "libcli/util/clilsa.h"
38 #include "torture/util.h"
39 #include "libcli/smb/smbXcli_base.h"
42 setup a directory ready for a test
44 _PUBLIC_
bool torture_setup_dir(struct smbcli_state
*cli
, const char *dname
)
46 smb_raw_exit(cli
->session
);
47 if (smbcli_deltree(cli
->tree
, dname
) == -1 ||
48 NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, dname
))) {
49 printf("Unable to setup %s - %s\n", dname
, smbcli_errstr(cli
->tree
));
56 create a directory, returning a handle to it
58 NTSTATUS
create_directory_handle(struct smbcli_tree
*tree
, const char *dname
, int *fnum
)
64 mem_ctx
= talloc_named_const(tree
, 0, "create_directory_handle");
66 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
67 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
68 io
.ntcreatex
.in
.flags
= 0;
69 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
70 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
71 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
72 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
73 io
.ntcreatex
.in
.alloc_size
= 0;
74 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
75 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
76 io
.ntcreatex
.in
.security_flags
= 0;
77 io
.ntcreatex
.in
.fname
= dname
;
79 status
= smb_raw_open(tree
, mem_ctx
, &io
);
82 if (NT_STATUS_IS_OK(status
)) {
83 *fnum
= io
.ntcreatex
.out
.file
.fnum
;
91 sometimes we need a fairly complex file to work with, so we can test
92 all possible attributes.
94 _PUBLIC_
int create_complex_file(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
, const char *fname
)
98 union smb_setfileinfo setfile
;
99 union smb_fileinfo fileinfo
;
100 time_t t
= (time(NULL
) & ~1);
103 smbcli_unlink(cli
->tree
, fname
);
104 fnum
= smbcli_nt_create_full(cli
->tree
, fname
, 0,
106 FILE_ATTRIBUTE_NORMAL
,
107 NTCREATEX_SHARE_ACCESS_DELETE
|
108 NTCREATEX_SHARE_ACCESS_READ
|
109 NTCREATEX_SHARE_ACCESS_WRITE
,
110 NTCREATEX_DISP_OVERWRITE_IF
,
112 if (fnum
== -1) return -1;
114 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, sizeof(buf
));
116 if (strchr(fname
, ':') == NULL
) {
118 setfile
.generic
.level
= RAW_SFILEINFO_EA_SET
;
119 setfile
.generic
.in
.file
.fnum
= fnum
;
120 setfile
.ea_set
.in
.num_eas
= 2;
121 setfile
.ea_set
.in
.eas
= talloc_array(mem_ctx
, struct ea_struct
, 2);
122 setfile
.ea_set
.in
.eas
[0].flags
= 0;
123 setfile
.ea_set
.in
.eas
[0].name
.s
= "EAONE";
124 setfile
.ea_set
.in
.eas
[0].value
= data_blob_talloc(mem_ctx
, "VALUE1", 6);
125 setfile
.ea_set
.in
.eas
[1].flags
= 0;
126 setfile
.ea_set
.in
.eas
[1].name
.s
= "SECONDEA";
127 setfile
.ea_set
.in
.eas
[1].value
= data_blob_talloc(mem_ctx
, "ValueTwo", 8);
128 status
= smb_raw_setfileinfo(cli
->tree
, &setfile
);
129 if (!NT_STATUS_IS_OK(status
)) {
130 printf("Failed to setup EAs\n");
134 /* make sure all the timestamps aren't the same */
135 ZERO_STRUCT(setfile
);
136 setfile
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
137 setfile
.generic
.in
.file
.fnum
= fnum
;
139 unix_to_nt_time(&setfile
.basic_info
.in
.create_time
,
141 unix_to_nt_time(&setfile
.basic_info
.in
.access_time
,
143 unix_to_nt_time(&setfile
.basic_info
.in
.write_time
,
146 status
= smb_raw_setfileinfo(cli
->tree
, &setfile
);
147 if (!NT_STATUS_IS_OK(status
)) {
148 printf("Failed to setup file times - %s\n", nt_errstr(status
));
151 /* make sure all the timestamps aren't the same */
152 fileinfo
.generic
.level
= RAW_FILEINFO_BASIC_INFO
;
153 fileinfo
.generic
.in
.file
.fnum
= fnum
;
155 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &fileinfo
);
156 if (!NT_STATUS_IS_OK(status
)) {
157 printf("Failed to query file times - %s\n", nt_errstr(status
));
160 if (setfile
.basic_info
.in
.create_time
!= fileinfo
.basic_info
.out
.create_time
) {
161 printf("create_time not setup correctly\n");
163 if (setfile
.basic_info
.in
.access_time
!= fileinfo
.basic_info
.out
.access_time
) {
164 printf("access_time not setup correctly\n");
166 if (setfile
.basic_info
.in
.write_time
!= fileinfo
.basic_info
.out
.write_time
) {
167 printf("write_time not setup correctly\n");
175 sometimes we need a fairly complex directory to work with, so we can test
176 all possible attributes.
178 int create_complex_dir(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
, const char *dname
)
181 union smb_setfileinfo setfile
;
182 union smb_fileinfo fileinfo
;
183 time_t t
= (time(NULL
) & ~1);
186 smbcli_deltree(cli
->tree
, dname
);
187 fnum
= smbcli_nt_create_full(cli
->tree
, dname
, 0,
189 FILE_ATTRIBUTE_DIRECTORY
,
190 NTCREATEX_SHARE_ACCESS_READ
|
191 NTCREATEX_SHARE_ACCESS_WRITE
,
192 NTCREATEX_DISP_OPEN_IF
,
193 NTCREATEX_OPTIONS_DIRECTORY
, 0);
194 if (fnum
== -1) return -1;
196 if (strchr(dname
, ':') == NULL
) {
198 setfile
.generic
.level
= RAW_SFILEINFO_EA_SET
;
199 setfile
.generic
.in
.file
.fnum
= fnum
;
200 setfile
.ea_set
.in
.num_eas
= 2;
201 setfile
.ea_set
.in
.eas
= talloc_array(mem_ctx
, struct ea_struct
, 2);
202 setfile
.ea_set
.in
.eas
[0].flags
= 0;
203 setfile
.ea_set
.in
.eas
[0].name
.s
= "EAONE";
204 setfile
.ea_set
.in
.eas
[0].value
= data_blob_talloc(mem_ctx
, "VALUE1", 6);
205 setfile
.ea_set
.in
.eas
[1].flags
= 0;
206 setfile
.ea_set
.in
.eas
[1].name
.s
= "SECONDEA";
207 setfile
.ea_set
.in
.eas
[1].value
= data_blob_talloc(mem_ctx
, "ValueTwo", 8);
208 status
= smb_raw_setfileinfo(cli
->tree
, &setfile
);
209 if (!NT_STATUS_IS_OK(status
)) {
210 printf("Failed to setup EAs\n");
214 /* make sure all the timestamps aren't the same */
215 ZERO_STRUCT(setfile
);
216 setfile
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
217 setfile
.generic
.in
.file
.fnum
= fnum
;
219 unix_to_nt_time(&setfile
.basic_info
.in
.create_time
,
221 unix_to_nt_time(&setfile
.basic_info
.in
.access_time
,
223 unix_to_nt_time(&setfile
.basic_info
.in
.write_time
,
226 status
= smb_raw_setfileinfo(cli
->tree
, &setfile
);
227 if (!NT_STATUS_IS_OK(status
)) {
228 printf("Failed to setup file times - %s\n", nt_errstr(status
));
231 /* make sure all the timestamps aren't the same */
232 fileinfo
.generic
.level
= RAW_FILEINFO_BASIC_INFO
;
233 fileinfo
.generic
.in
.file
.fnum
= fnum
;
235 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &fileinfo
);
236 if (!NT_STATUS_IS_OK(status
)) {
237 printf("Failed to query file times - %s\n", nt_errstr(status
));
240 if (setfile
.basic_info
.in
.create_time
!= fileinfo
.basic_info
.out
.create_time
) {
241 printf("create_time not setup correctly\n");
243 if (setfile
.basic_info
.in
.access_time
!= fileinfo
.basic_info
.out
.access_time
) {
244 printf("access_time not setup correctly\n");
246 if (setfile
.basic_info
.in
.write_time
!= fileinfo
.basic_info
.out
.write_time
) {
247 printf("write_time not setup correctly\n");
254 check that a wire string matches the flags specified
255 not 100% accurate, but close enough for testing
257 bool wire_bad_flags(struct smb_wire_string
*str
, int flags
,
258 struct smbcli_transport
*transport
)
262 if (!str
|| !str
->s
) return true;
263 len
= strlen(str
->s
);
264 if (flags
& STR_TERMINATE
) len
++;
266 server_unicode
= (transport
->negotiate
.capabilities
&CAP_UNICODE
)?true:false;
267 if (getenv("CLI_FORCE_ASCII") || !transport
->options
.unicode
) {
268 server_unicode
= false;
271 if ((flags
& STR_UNICODE
) || server_unicode
) {
273 } else if (flags
& STR_TERMINATE_ASCII
) {
276 if (str
->private_length
!= len
) {
277 printf("Expected wire_length %d but got %d for '%s'\n",
278 len
, str
->private_length
, str
->s
);
285 dump a all_info QFILEINFO structure
287 void dump_all_info(TALLOC_CTX
*mem_ctx
, union smb_fileinfo
*finfo
)
289 d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx
, finfo
->all_info
.out
.create_time
));
290 d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx
, finfo
->all_info
.out
.access_time
));
291 d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx
, finfo
->all_info
.out
.write_time
));
292 d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx
, finfo
->all_info
.out
.change_time
));
293 d_printf("\tattrib: 0x%x\n", finfo
->all_info
.out
.attrib
);
294 d_printf("\talloc_size: %llu\n", (long long)finfo
->all_info
.out
.alloc_size
);
295 d_printf("\tsize: %llu\n", (long long)finfo
->all_info
.out
.size
);
296 d_printf("\tnlink: %u\n", finfo
->all_info
.out
.nlink
);
297 d_printf("\tdelete_pending: %u\n", finfo
->all_info
.out
.delete_pending
);
298 d_printf("\tdirectory: %u\n", finfo
->all_info
.out
.directory
);
299 d_printf("\tea_size: %u\n", finfo
->all_info
.out
.ea_size
);
300 d_printf("\tfname: '%s'\n", finfo
->all_info
.out
.fname
.s
);
304 dump file infor by name
306 void torture_all_info(struct smbcli_tree
*tree
, const char *fname
)
308 TALLOC_CTX
*mem_ctx
= talloc_named(tree
, 0, "%s", fname
);
309 union smb_fileinfo finfo
;
312 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
313 finfo
.generic
.in
.file
.path
= fname
;
314 status
= smb_raw_pathinfo(tree
, mem_ctx
, &finfo
);
315 if (!NT_STATUS_IS_OK(status
)) {
316 d_printf("%s - %s\n", fname
, nt_errstr(status
));
320 d_printf("%s:\n", fname
);
321 dump_all_info(mem_ctx
, &finfo
);
322 talloc_free(mem_ctx
);
327 set a attribute on a file
329 bool torture_set_file_attribute(struct smbcli_tree
*tree
, const char *fname
, uint16_t attrib
)
331 union smb_setfileinfo sfinfo
;
334 ZERO_STRUCT(sfinfo
.basic_info
.in
);
335 sfinfo
.basic_info
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
336 sfinfo
.basic_info
.in
.file
.path
= fname
;
337 sfinfo
.basic_info
.in
.attrib
= attrib
;
338 status
= smb_raw_setpathinfo(tree
, &sfinfo
);
339 return NT_STATUS_IS_OK(status
);
344 set a file descriptor as sparse
346 NTSTATUS
torture_set_sparse(struct smbcli_tree
*tree
, int fnum
)
352 mem_ctx
= talloc_named_const(tree
, 0, "torture_set_sparse");
354 return NT_STATUS_NO_MEMORY
;
357 nt
.ntioctl
.level
= RAW_IOCTL_NTIOCTL
;
358 nt
.ntioctl
.in
.function
= FSCTL_SET_SPARSE
;
359 nt
.ntioctl
.in
.file
.fnum
= fnum
;
360 nt
.ntioctl
.in
.fsctl
= true;
361 nt
.ntioctl
.in
.filter
= 0;
362 nt
.ntioctl
.in
.max_data
= 0;
363 nt
.ntioctl
.in
.blob
= data_blob(NULL
, 0);
365 status
= smb_raw_ioctl(tree
, mem_ctx
, &nt
);
367 talloc_free(mem_ctx
);
373 check that an EA has the right value
375 NTSTATUS
torture_check_ea(struct smbcli_state
*cli
,
376 const char *fname
, const char *eaname
, const char *value
)
378 union smb_fileinfo info
;
381 TALLOC_CTX
*mem_ctx
= talloc_new(cli
);
383 info
.ea_list
.level
= RAW_FILEINFO_EA_LIST
;
384 info
.ea_list
.in
.file
.path
= fname
;
385 info
.ea_list
.in
.num_names
= 1;
386 info
.ea_list
.in
.ea_names
= &ea
;
390 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &info
);
391 if (!NT_STATUS_IS_OK(status
)) {
392 talloc_free(mem_ctx
);
396 if (info
.ea_list
.out
.num_eas
!= 1) {
397 printf("Expected 1 ea in ea_list\n");
398 talloc_free(mem_ctx
);
399 return NT_STATUS_EA_CORRUPT_ERROR
;
402 if (strcasecmp_m(eaname
, info
.ea_list
.out
.eas
[0].name
.s
) != 0) {
403 printf("Expected ea '%s' not '%s' in ea_list\n",
404 eaname
, info
.ea_list
.out
.eas
[0].name
.s
);
405 talloc_free(mem_ctx
);
406 return NT_STATUS_EA_CORRUPT_ERROR
;
410 if (info
.ea_list
.out
.eas
[0].value
.length
!= 0) {
411 printf("Expected zero length ea for %s\n", eaname
);
412 talloc_free(mem_ctx
);
413 return NT_STATUS_EA_CORRUPT_ERROR
;
415 talloc_free(mem_ctx
);
419 if (strlen(value
) == info
.ea_list
.out
.eas
[0].value
.length
&&
420 memcmp(value
, info
.ea_list
.out
.eas
[0].value
.data
,
421 info
.ea_list
.out
.eas
[0].value
.length
) == 0) {
422 talloc_free(mem_ctx
);
426 printf("Expected value '%s' not '%*.*s' for ea %s\n",
428 (int)info
.ea_list
.out
.eas
[0].value
.length
,
429 (int)info
.ea_list
.out
.eas
[0].value
.length
,
430 info
.ea_list
.out
.eas
[0].value
.data
,
433 talloc_free(mem_ctx
);
435 return NT_STATUS_EA_CORRUPT_ERROR
;
438 _PUBLIC_
bool torture_open_connection_share(TALLOC_CTX
*mem_ctx
,
439 struct smbcli_state
**c
,
440 struct torture_context
*tctx
,
441 const char *hostname
,
442 const char *sharename
,
443 struct tevent_context
*ev
)
447 struct smbcli_options options
;
448 struct smbcli_session_options session_options
;
450 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
451 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
453 options
.use_oplocks
= torture_setting_bool(tctx
, "use_oplocks", true);
454 options
.use_level2_oplocks
= torture_setting_bool(tctx
, "use_level2_oplocks", true);
456 status
= smbcli_full_connection(mem_ctx
, c
, hostname
,
457 lpcfg_smb_ports(tctx
->lp_ctx
),
459 lpcfg_socket_options(tctx
->lp_ctx
),
460 popt_get_cmdline_credentials(),
461 lpcfg_resolve_context(tctx
->lp_ctx
),
462 ev
, &options
, &session_options
,
463 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
464 if (!NT_STATUS_IS_OK(status
)) {
465 printf("Failed to open connection - %s\n", nt_errstr(status
));
472 _PUBLIC_
bool torture_get_conn_index(int conn_index
,
474 struct torture_context
*tctx
,
475 char **host
, char **share
)
477 char **unc_list
= NULL
;
478 int num_unc_names
= 0;
481 (*host
) = talloc_strdup(mem_ctx
, torture_setting_string(tctx
, "host", NULL
));
482 (*share
) = talloc_strdup(mem_ctx
, torture_setting_string(tctx
, "share", NULL
));
484 p
= torture_setting_string(tctx
, "unclist", NULL
);
489 unc_list
= file_lines_load(p
, &num_unc_names
, 0, NULL
);
490 if (!unc_list
|| num_unc_names
<= 0) {
491 DEBUG(0,("Failed to load unc names list from '%s'\n", p
));
495 p
= unc_list
[conn_index
% num_unc_names
];
496 if (p
[0] != '/' && p
[0] != '\\') {
497 /* allow UNC lists of hosts */
498 (*host
) = talloc_strdup(mem_ctx
, p
);
499 } else if (!smbcli_parse_unc(p
, mem_ctx
, host
, share
)) {
500 DEBUG(0, ("Failed to parse UNC name %s\n",
501 unc_list
[conn_index
% num_unc_names
]));
505 talloc_free(unc_list
);
511 _PUBLIC_
bool torture_open_connection_ev(struct smbcli_state
**c
,
513 struct torture_context
*tctx
,
514 struct tevent_context
*ev
)
519 if (!torture_get_conn_index(conn_index
, ev
, tctx
, &host
, &share
)) {
523 ret
= torture_open_connection_share(NULL
, c
, tctx
, host
, share
, ev
);
530 _PUBLIC_
bool torture_open_connection(struct smbcli_state
**c
, struct torture_context
*tctx
, int conn_index
)
532 return torture_open_connection_ev(c
, conn_index
, tctx
, tctx
->ev
);
537 _PUBLIC_
bool torture_close_connection(struct smbcli_state
*c
)
541 if (NT_STATUS_IS_ERR(smbcli_tdis(c
))) {
542 printf("tdis failed (%s)\n", smbcli_errstr(c
->tree
));
550 /* check if the server produced the expected error code */
551 _PUBLIC_
bool check_error(const char *location
, struct smbcli_state
*c
,
552 uint8_t eclass
, uint32_t ecode
, NTSTATUS nterr
)
556 status
= smbcli_nt_error(c
->tree
);
557 if (NT_STATUS_IS_DOS(status
)) {
559 classnum
= NT_STATUS_DOS_CLASS(status
);
560 num
= NT_STATUS_DOS_CODE(status
);
561 if (eclass
!= classnum
|| ecode
!= num
) {
562 printf("unexpected error code %s\n", nt_errstr(status
));
563 printf(" expected %s or %s (at %s)\n",
564 nt_errstr(NT_STATUS_DOS(eclass
, ecode
)),
565 nt_errstr(nterr
), location
);
569 if (!NT_STATUS_EQUAL(nterr
, status
)) {
570 printf("unexpected error code %s\n", nt_errstr(status
));
571 printf(" expected %s (at %s)\n", nt_errstr(nterr
), location
);
579 static struct smbcli_state
*current_cli
;
580 static int procnum
; /* records process count number when forking */
582 static void sigcont(int sig
)
586 struct child_status
{
589 enum torture_result result
;
593 double torture_create_procs(struct torture_context
*tctx
,
594 bool (*fn
)(struct torture_context
*, struct smbcli_state
*, int),
599 struct child_status
*child_status
;
602 size_t torture_nprocs
= torture_setting_int(tctx
, "nprocs", 4);
603 double start_time_limit
= 10 + (torture_nprocs
* 1.5);
610 signal(SIGCONT
, sigcont
);
612 child_status
= (struct child_status
*)anonymous_shared_allocate(
613 sizeof(struct child_status
)*torture_nprocs
);
614 if (child_status
== NULL
) {
615 printf("Failed to setup shared memory\n");
619 for (i
= 0; i
< torture_nprocs
; i
++) {
620 ZERO_STRUCT(child_status
[i
]);
623 tv
= timeval_current();
625 for (i
=0;i
<torture_nprocs
;i
++) {
631 pid_t mypid
= getpid();
632 srandom(((int)mypid
) ^ ((int)time(NULL
)));
634 if (asprintf(&myname
, "CLIENT%zu", i
) == -1) {
635 printf("asprintf failed\n");
638 lpcfg_set_cmdline(tctx
->lp_ctx
, "netbios name", myname
);
643 if (torture_open_connection(¤t_cli
, tctx
, i
)) {
647 printf("pid %d failed to start\n", (int)getpid());
653 child_status
[i
].pid
= getpid();
657 if (!child_status
[i
].start
) {
658 child_status
[i
].result
= TORTURE_ERROR
;
659 printf("Child %zu failed to start!\n", i
);
663 ok
= fn(tctx
, current_cli
, i
);
665 if (tctx
->last_result
== TORTURE_OK
) {
666 torture_result(tctx
, TORTURE_ERROR
,
667 "unknown error: missing "
668 "torture_result call?\n");
671 child_status
[i
].result
= tctx
->last_result
;
673 if (strlen(tctx
->last_reason
) > 1023) {
674 /* note: reason already contains \n */
675 torture_comment(tctx
,
676 "child %zu (pid %u) failed: %s",
678 (unsigned)child_status
[i
].pid
,
682 snprintf(child_status
[i
].reason
,
683 1024, "child %zu (pid %u) failed: %s",
684 i
, (unsigned)child_status
[i
].pid
,
686 /* ensure proper "\n\0" termination: */
687 if (child_status
[i
].reason
[1022] != '\0') {
688 child_status
[i
].reason
[1022] = '\n';
689 child_status
[i
].reason
[1023] = '\0';
698 for (i
=0;i
<torture_nprocs
;i
++) {
699 if (child_status
[i
].pid
!= 0) {
703 if (synccount
== torture_nprocs
) {
707 } while (timeval_elapsed(&tv
) < start_time_limit
);
709 if (synccount
!= torture_nprocs
) {
710 printf("FAILED TO START %zu CLIENTS (started %zu)\n", torture_nprocs
, synccount
);
712 /* cleanup child processes */
713 for (i
= 0; i
< torture_nprocs
; i
++) {
714 if (child_status
[i
].pid
!= 0) {
715 kill(child_status
[i
].pid
, SIGTERM
);
720 return timeval_elapsed(&tv
);
723 printf("Starting %zu clients\n", torture_nprocs
);
725 /* start the client load */
726 tv
= timeval_current();
727 for (i
=0;i
<torture_nprocs
;i
++) {
728 child_status
[i
].start
= true;
731 printf("%zu clients started\n", torture_nprocs
);
735 for (i
=0;i
<torture_nprocs
;i
++) {
737 while ((ret
=waitpid(0, &status
, 0)) == -1 && errno
== EINTR
) /* noop */ ;
738 if (ret
== -1 || WEXITSTATUS(status
) != 0) {
745 for (i
=0;i
<torture_nprocs
;i
++) {
746 if (child_status
[i
].result
!= TORTURE_OK
) {
748 torture_result(tctx
, child_status
[i
].result
,
749 "%s", child_status
[i
].reason
);
753 return timeval_elapsed(&tv
);
756 static bool wrap_smb_multi_test(struct torture_context
*torture
,
757 struct torture_tcase
*tcase
,
758 struct torture_test
*test
)
760 bool (*fn
)(struct torture_context
*, struct smbcli_state
*, int ) = test
->fn
;
763 torture_create_procs(torture
, fn
, &result
);
768 _PUBLIC_
struct torture_test
*torture_suite_add_smb_multi_test(
769 struct torture_suite
*suite
,
771 bool (*run
) (struct torture_context
*,
772 struct smbcli_state
*,
775 struct torture_test
*test
;
776 struct torture_tcase
*tcase
;
778 tcase
= torture_suite_add_tcase(suite
, name
);
780 test
= talloc(tcase
, struct torture_test
);
782 test
->name
= talloc_strdup(test
, name
);
783 test
->description
= NULL
;
784 test
->run
= wrap_smb_multi_test
;
786 test
->dangerous
= false;
788 DLIST_ADD_END(tcase
->tests
, test
);
794 static bool wrap_simple_2smb_test(struct torture_context
*torture_ctx
,
795 struct torture_tcase
*tcase
,
796 struct torture_test
*test
)
798 bool (*fn
) (struct torture_context
*, struct smbcli_state
*,
799 struct smbcli_state
*);
802 struct smbcli_state
*cli1
= NULL
, *cli2
= NULL
;
804 torture_assert_goto(torture_ctx
, torture_open_connection(&cli1
, torture_ctx
, 0), ret
, fail
, "Failed to open connection");
805 torture_assert_goto(torture_ctx
, torture_open_connection(&cli2
, torture_ctx
, 1), ret
, fail
, "Failed to open connection");
809 ret
= fn(torture_ctx
, cli1
, cli2
);
819 _PUBLIC_
struct torture_test
*torture_suite_add_2smb_test(
820 struct torture_suite
*suite
,
822 bool (*run
) (struct torture_context
*,
823 struct smbcli_state
*,
824 struct smbcli_state
*))
826 struct torture_test
*test
;
827 struct torture_tcase
*tcase
;
829 tcase
= torture_suite_add_tcase(suite
, name
);
831 test
= talloc(tcase
, struct torture_test
);
833 test
->name
= talloc_strdup(test
, name
);
834 test
->description
= NULL
;
835 test
->run
= wrap_simple_2smb_test
;
837 test
->dangerous
= false;
839 DLIST_ADD_END(tcase
->tests
, test
);
845 static bool wrap_simple_1smb_test(struct torture_context
*torture_ctx
,
846 struct torture_tcase
*tcase
,
847 struct torture_test
*test
)
849 bool (*fn
) (struct torture_context
*, struct smbcli_state
*);
852 struct smbcli_state
*cli1
= NULL
;
854 torture_assert_goto(torture_ctx
, torture_open_connection(&cli1
, torture_ctx
, 0), ret
, fail
, "Failed to open connection");
858 ret
= fn(torture_ctx
, cli1
);
865 _PUBLIC_
struct torture_test
*torture_suite_add_1smb_test(
866 struct torture_suite
*suite
,
868 bool (*run
) (struct torture_context
*, struct smbcli_state
*))
870 struct torture_test
*test
;
871 struct torture_tcase
*tcase
;
873 tcase
= torture_suite_add_tcase(suite
, name
);
875 test
= talloc(tcase
, struct torture_test
);
877 test
->name
= talloc_strdup(test
, name
);
878 test
->description
= NULL
;
879 test
->run
= wrap_simple_1smb_test
;
881 test
->dangerous
= false;
883 DLIST_ADD_END(tcase
->tests
, test
);
889 NTSTATUS
torture_second_tcon(TALLOC_CTX
*mem_ctx
,
890 struct smbcli_session
*session
,
891 const char *sharename
,
892 struct smbcli_tree
**res
)
895 struct smbcli_tree
*result
;
899 if ((tmp_ctx
= talloc_new(mem_ctx
)) == NULL
) {
900 return NT_STATUS_NO_MEMORY
;
903 result
= smbcli_tree_init(session
, tmp_ctx
, false);
904 if (result
== NULL
) {
905 talloc_free(tmp_ctx
);
906 return NT_STATUS_NO_MEMORY
;
909 tcon
.generic
.level
= RAW_TCON_TCONX
;
910 tcon
.tconx
.in
.flags
= TCONX_FLAG_EXTENDED_RESPONSE
;
911 tcon
.tconx
.in
.flags
|= TCONX_FLAG_EXTENDED_SIGNATURES
;
913 /* Ignore share mode security here */
914 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
915 tcon
.tconx
.in
.path
= sharename
;
916 tcon
.tconx
.in
.device
= "?????";
918 status
= smb_raw_tcon(result
, tmp_ctx
, &tcon
);
919 if (!NT_STATUS_IS_OK(status
)) {
920 talloc_free(tmp_ctx
);
924 result
->tid
= tcon
.tconx
.out
.tid
;
926 if (tcon
.tconx
.out
.options
& SMB_EXTENDED_SIGNATURES
) {
927 smb1cli_session_protect_session_key(result
->session
->smbXcli
);
930 *res
= talloc_steal(mem_ctx
, result
);
931 talloc_free(tmp_ctx
);
936 a wrapper around smblsa_sid_check_privilege, that tries to take
937 account of the fact that the lsa privileges calls don't expand
938 group memberships, using an explicit check for administrator. There
939 must be a better way ...
941 NTSTATUS
torture_check_privilege(struct smbcli_state
*cli
,
943 const char *privilege
)
946 TALLOC_CTX
*tmp_ctx
= talloc_new(cli
);
950 sid
= dom_sid_parse_talloc(tmp_ctx
, sid_str
);
952 talloc_free(tmp_ctx
);
953 return NT_STATUS_INVALID_SID
;
956 status
= dom_sid_split_rid(tmp_ctx
, sid
, NULL
, &rid
);
957 if (!NT_STATUS_IS_OK(status
)) {
958 TALLOC_FREE(tmp_ctx
);
962 if (rid
== DOMAIN_RID_ADMINISTRATOR
) {
963 /* assume the administrator has them all */
967 talloc_free(tmp_ctx
);
969 return smblsa_sid_check_privilege(cli
, sid_str
, privilege
);