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/util/util_file.h"
23 #include "lib/cmdline/cmdline.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/raw/raw_proto.h"
26 #include "../libcli/smb/smb_constants.h"
27 #include "libcli/libcli.h"
28 #include "system/filesys.h"
29 #include "system/shmem.h"
30 #include "system/wait.h"
31 #include "system/time.h"
32 #include "torture/torture.h"
33 #include "../lib/util/dlinklist.h"
34 #include "libcli/resolve/resolve.h"
35 #include "param/param.h"
36 #include "libcli/security/security.h"
37 #include "libcli/smb2/smb2.h"
38 #include "libcli/util/clilsa.h"
39 #include "torture/util.h"
40 #include "libcli/smb/smbXcli_base.h"
41 #include "auth/credentials/credentials.h"
42 #include "auth/credentials/credentials_krb5.h"
45 setup a directory ready for a test
47 _PUBLIC_
bool torture_setup_dir(struct smbcli_state
*cli
, const char *dname
)
49 smb_raw_exit(cli
->session
);
50 if (smbcli_deltree(cli
->tree
, dname
) == -1 ||
51 NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, dname
))) {
52 printf("Unable to setup %s - %s\n", dname
, smbcli_errstr(cli
->tree
));
59 create a directory, returning a handle to it
61 NTSTATUS
create_directory_handle(struct smbcli_tree
*tree
, const char *dname
, int *fnum
)
67 mem_ctx
= talloc_named_const(tree
, 0, "create_directory_handle");
69 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
70 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
71 io
.ntcreatex
.in
.flags
= 0;
72 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
73 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
74 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
75 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
76 io
.ntcreatex
.in
.alloc_size
= 0;
77 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
78 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
79 io
.ntcreatex
.in
.security_flags
= 0;
80 io
.ntcreatex
.in
.fname
= dname
;
82 status
= smb_raw_open(tree
, mem_ctx
, &io
);
85 if (NT_STATUS_IS_OK(status
)) {
86 *fnum
= io
.ntcreatex
.out
.file
.fnum
;
94 sometimes we need a fairly complex file to work with, so we can test
95 all possible attributes.
97 _PUBLIC_
int create_complex_file(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
, const char *fname
)
101 union smb_setfileinfo setfile
;
102 union smb_fileinfo fileinfo
;
103 time_t t
= (time(NULL
) & ~1);
106 smbcli_unlink(cli
->tree
, fname
);
107 fnum
= smbcli_nt_create_full(cli
->tree
, fname
, 0,
109 FILE_ATTRIBUTE_NORMAL
,
110 NTCREATEX_SHARE_ACCESS_DELETE
|
111 NTCREATEX_SHARE_ACCESS_READ
|
112 NTCREATEX_SHARE_ACCESS_WRITE
,
113 NTCREATEX_DISP_OVERWRITE_IF
,
115 if (fnum
== -1) return -1;
117 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, sizeof(buf
));
119 if (strchr(fname
, ':') == NULL
) {
121 setfile
.generic
.level
= RAW_SFILEINFO_EA_SET
;
122 setfile
.generic
.in
.file
.fnum
= fnum
;
123 setfile
.ea_set
.in
.num_eas
= 2;
124 setfile
.ea_set
.in
.eas
= talloc_array(mem_ctx
, struct ea_struct
, 2);
125 setfile
.ea_set
.in
.eas
[0].flags
= 0;
126 setfile
.ea_set
.in
.eas
[0].name
.s
= "EAONE";
127 setfile
.ea_set
.in
.eas
[0].value
= data_blob_talloc(mem_ctx
, "VALUE1", 6);
128 setfile
.ea_set
.in
.eas
[1].flags
= 0;
129 setfile
.ea_set
.in
.eas
[1].name
.s
= "SECONDEA";
130 setfile
.ea_set
.in
.eas
[1].value
= data_blob_talloc(mem_ctx
, "ValueTwo", 8);
131 status
= smb_raw_setfileinfo(cli
->tree
, &setfile
);
132 if (!NT_STATUS_IS_OK(status
)) {
133 printf("Failed to setup EAs\n");
137 /* make sure all the timestamps aren't the same */
138 ZERO_STRUCT(setfile
);
139 setfile
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
140 setfile
.generic
.in
.file
.fnum
= fnum
;
142 unix_to_nt_time(&setfile
.basic_info
.in
.create_time
,
144 unix_to_nt_time(&setfile
.basic_info
.in
.access_time
,
146 unix_to_nt_time(&setfile
.basic_info
.in
.write_time
,
149 status
= smb_raw_setfileinfo(cli
->tree
, &setfile
);
150 if (!NT_STATUS_IS_OK(status
)) {
151 printf("Failed to setup file times - %s\n", nt_errstr(status
));
154 /* make sure all the timestamps aren't the same */
155 fileinfo
.generic
.level
= RAW_FILEINFO_BASIC_INFO
;
156 fileinfo
.generic
.in
.file
.fnum
= fnum
;
158 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &fileinfo
);
159 if (!NT_STATUS_IS_OK(status
)) {
160 printf("Failed to query file times - %s\n", nt_errstr(status
));
163 if (setfile
.basic_info
.in
.create_time
!= fileinfo
.basic_info
.out
.create_time
) {
164 printf("create_time not setup correctly\n");
166 if (setfile
.basic_info
.in
.access_time
!= fileinfo
.basic_info
.out
.access_time
) {
167 printf("access_time not setup correctly\n");
169 if (setfile
.basic_info
.in
.write_time
!= fileinfo
.basic_info
.out
.write_time
) {
170 printf("write_time not setup correctly\n");
178 sometimes we need a fairly complex directory to work with, so we can test
179 all possible attributes.
181 int create_complex_dir(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
, const char *dname
)
184 union smb_setfileinfo setfile
;
185 union smb_fileinfo fileinfo
;
186 time_t t
= (time(NULL
) & ~1);
189 smbcli_deltree(cli
->tree
, dname
);
190 fnum
= smbcli_nt_create_full(cli
->tree
, dname
, 0,
192 FILE_ATTRIBUTE_DIRECTORY
,
193 NTCREATEX_SHARE_ACCESS_READ
|
194 NTCREATEX_SHARE_ACCESS_WRITE
,
195 NTCREATEX_DISP_OPEN_IF
,
196 NTCREATEX_OPTIONS_DIRECTORY
, 0);
197 if (fnum
== -1) return -1;
199 if (strchr(dname
, ':') == NULL
) {
201 setfile
.generic
.level
= RAW_SFILEINFO_EA_SET
;
202 setfile
.generic
.in
.file
.fnum
= fnum
;
203 setfile
.ea_set
.in
.num_eas
= 2;
204 setfile
.ea_set
.in
.eas
= talloc_array(mem_ctx
, struct ea_struct
, 2);
205 setfile
.ea_set
.in
.eas
[0].flags
= 0;
206 setfile
.ea_set
.in
.eas
[0].name
.s
= "EAONE";
207 setfile
.ea_set
.in
.eas
[0].value
= data_blob_talloc(mem_ctx
, "VALUE1", 6);
208 setfile
.ea_set
.in
.eas
[1].flags
= 0;
209 setfile
.ea_set
.in
.eas
[1].name
.s
= "SECONDEA";
210 setfile
.ea_set
.in
.eas
[1].value
= data_blob_talloc(mem_ctx
, "ValueTwo", 8);
211 status
= smb_raw_setfileinfo(cli
->tree
, &setfile
);
212 if (!NT_STATUS_IS_OK(status
)) {
213 printf("Failed to setup EAs\n");
217 /* make sure all the timestamps aren't the same */
218 ZERO_STRUCT(setfile
);
219 setfile
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
220 setfile
.generic
.in
.file
.fnum
= fnum
;
222 unix_to_nt_time(&setfile
.basic_info
.in
.create_time
,
224 unix_to_nt_time(&setfile
.basic_info
.in
.access_time
,
226 unix_to_nt_time(&setfile
.basic_info
.in
.write_time
,
229 status
= smb_raw_setfileinfo(cli
->tree
, &setfile
);
230 if (!NT_STATUS_IS_OK(status
)) {
231 printf("Failed to setup file times - %s\n", nt_errstr(status
));
234 /* make sure all the timestamps aren't the same */
235 fileinfo
.generic
.level
= RAW_FILEINFO_BASIC_INFO
;
236 fileinfo
.generic
.in
.file
.fnum
= fnum
;
238 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &fileinfo
);
239 if (!NT_STATUS_IS_OK(status
)) {
240 printf("Failed to query file times - %s\n", nt_errstr(status
));
243 if (setfile
.basic_info
.in
.create_time
!= fileinfo
.basic_info
.out
.create_time
) {
244 printf("create_time not setup correctly\n");
246 if (setfile
.basic_info
.in
.access_time
!= fileinfo
.basic_info
.out
.access_time
) {
247 printf("access_time not setup correctly\n");
249 if (setfile
.basic_info
.in
.write_time
!= fileinfo
.basic_info
.out
.write_time
) {
250 printf("write_time not setup correctly\n");
257 check that a wire string matches the flags specified
258 not 100% accurate, but close enough for testing
260 bool wire_bad_flags(struct smb_wire_string
*str
, int flags
,
261 struct smbcli_transport
*transport
)
265 if (!str
|| !str
->s
) return true;
266 len
= strlen(str
->s
);
267 if (flags
& STR_TERMINATE
) len
++;
269 server_unicode
= (transport
->negotiate
.capabilities
&CAP_UNICODE
)?true:false;
270 if (getenv("CLI_FORCE_ASCII") || !transport
->options
.unicode
) {
271 server_unicode
= false;
274 if ((flags
& STR_UNICODE
) || server_unicode
) {
276 } else if (flags
& STR_TERMINATE_ASCII
) {
279 if (str
->private_length
!= len
) {
280 printf("Expected wire_length %d but got %d for '%s'\n",
281 len
, str
->private_length
, str
->s
);
288 dump a all_info QFILEINFO structure
290 void dump_all_info(TALLOC_CTX
*mem_ctx
, union smb_fileinfo
*finfo
)
292 d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx
, finfo
->all_info
.out
.create_time
));
293 d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx
, finfo
->all_info
.out
.access_time
));
294 d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx
, finfo
->all_info
.out
.write_time
));
295 d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx
, finfo
->all_info
.out
.change_time
));
296 d_printf("\tattrib: 0x%x\n", finfo
->all_info
.out
.attrib
);
297 d_printf("\talloc_size: %llu\n", (long long)finfo
->all_info
.out
.alloc_size
);
298 d_printf("\tsize: %llu\n", (long long)finfo
->all_info
.out
.size
);
299 d_printf("\tnlink: %u\n", finfo
->all_info
.out
.nlink
);
300 d_printf("\tdelete_pending: %u\n", finfo
->all_info
.out
.delete_pending
);
301 d_printf("\tdirectory: %u\n", finfo
->all_info
.out
.directory
);
302 d_printf("\tea_size: %u\n", finfo
->all_info
.out
.ea_size
);
303 d_printf("\tfname: '%s'\n", finfo
->all_info
.out
.fname
.s
);
307 dump file info by name
309 void torture_all_info(struct smbcli_tree
*tree
, const char *fname
)
311 TALLOC_CTX
*mem_ctx
= talloc_named(tree
, 0, "%s", fname
);
312 union smb_fileinfo finfo
;
315 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
316 finfo
.generic
.in
.file
.path
= fname
;
317 status
= smb_raw_pathinfo(tree
, mem_ctx
, &finfo
);
318 if (!NT_STATUS_IS_OK(status
)) {
319 d_printf("%s - %s\n", fname
, nt_errstr(status
));
323 d_printf("%s:\n", fname
);
324 dump_all_info(mem_ctx
, &finfo
);
325 talloc_free(mem_ctx
);
330 set a attribute on a file
332 bool torture_set_file_attribute(struct smbcli_tree
*tree
, const char *fname
, uint16_t attrib
)
334 union smb_setfileinfo sfinfo
;
337 ZERO_STRUCT(sfinfo
.basic_info
.in
);
338 sfinfo
.basic_info
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
339 sfinfo
.basic_info
.in
.file
.path
= fname
;
340 sfinfo
.basic_info
.in
.attrib
= attrib
;
341 status
= smb_raw_setpathinfo(tree
, &sfinfo
);
342 return NT_STATUS_IS_OK(status
);
347 set a file descriptor as sparse
349 NTSTATUS
torture_set_sparse(struct smbcli_tree
*tree
, int fnum
)
355 mem_ctx
= talloc_named_const(tree
, 0, "torture_set_sparse");
357 return NT_STATUS_NO_MEMORY
;
360 nt
.ntioctl
.level
= RAW_IOCTL_NTIOCTL
;
361 nt
.ntioctl
.in
.function
= FSCTL_SET_SPARSE
;
362 nt
.ntioctl
.in
.file
.fnum
= fnum
;
363 nt
.ntioctl
.in
.fsctl
= true;
364 nt
.ntioctl
.in
.filter
= 0;
365 nt
.ntioctl
.in
.max_data
= 0;
366 nt
.ntioctl
.in
.blob
= data_blob(NULL
, 0);
368 status
= smb_raw_ioctl(tree
, mem_ctx
, &nt
);
370 talloc_free(mem_ctx
);
376 check that an EA has the right value
378 NTSTATUS
torture_check_ea(struct smbcli_state
*cli
,
379 const char *fname
, const char *eaname
, const char *value
)
381 union smb_fileinfo info
;
384 TALLOC_CTX
*mem_ctx
= talloc_new(cli
);
386 info
.ea_list
.level
= RAW_FILEINFO_EA_LIST
;
387 info
.ea_list
.in
.file
.path
= fname
;
388 info
.ea_list
.in
.num_names
= 1;
389 info
.ea_list
.in
.ea_names
= &ea
;
393 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &info
);
394 if (!NT_STATUS_IS_OK(status
)) {
395 talloc_free(mem_ctx
);
399 if (info
.ea_list
.out
.num_eas
!= 1) {
400 printf("Expected 1 ea in ea_list\n");
401 talloc_free(mem_ctx
);
402 return NT_STATUS_EA_CORRUPT_ERROR
;
405 if (strcasecmp_m(eaname
, info
.ea_list
.out
.eas
[0].name
.s
) != 0) {
406 printf("Expected ea '%s' not '%s' in ea_list\n",
407 eaname
, info
.ea_list
.out
.eas
[0].name
.s
);
408 talloc_free(mem_ctx
);
409 return NT_STATUS_EA_CORRUPT_ERROR
;
413 if (info
.ea_list
.out
.eas
[0].value
.length
!= 0) {
414 printf("Expected zero length ea for %s\n", eaname
);
415 talloc_free(mem_ctx
);
416 return NT_STATUS_EA_CORRUPT_ERROR
;
418 talloc_free(mem_ctx
);
422 if (strlen(value
) == info
.ea_list
.out
.eas
[0].value
.length
&&
423 memcmp(value
, info
.ea_list
.out
.eas
[0].value
.data
,
424 info
.ea_list
.out
.eas
[0].value
.length
) == 0) {
425 talloc_free(mem_ctx
);
429 printf("Expected value '%s' not '%*.*s' for ea %s\n",
431 (int)info
.ea_list
.out
.eas
[0].value
.length
,
432 (int)info
.ea_list
.out
.eas
[0].value
.length
,
433 info
.ea_list
.out
.eas
[0].value
.data
,
436 talloc_free(mem_ctx
);
438 return NT_STATUS_EA_CORRUPT_ERROR
;
441 _PUBLIC_
bool torture_open_connection_share(TALLOC_CTX
*mem_ctx
,
442 struct smbcli_state
**c
,
443 struct torture_context
*tctx
,
444 const char *hostname
,
445 const char *sharename
,
446 struct tevent_context
*ev
)
450 struct smbcli_options options
;
451 struct smbcli_session_options session_options
;
453 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
454 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
456 options
.use_oplocks
= torture_setting_bool(tctx
, "use_oplocks", true);
457 options
.use_level2_oplocks
= torture_setting_bool(tctx
, "use_level2_oplocks", true);
459 status
= smbcli_full_connection(mem_ctx
, c
, hostname
,
460 lpcfg_smb_ports(tctx
->lp_ctx
),
462 lpcfg_socket_options(tctx
->lp_ctx
),
463 samba_cmdline_get_creds(),
464 lpcfg_resolve_context(tctx
->lp_ctx
),
465 ev
, &options
, &session_options
,
466 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
467 if (!NT_STATUS_IS_OK(status
)) {
468 printf("Failed to open connection - %s\n", nt_errstr(status
));
475 _PUBLIC_
bool torture_get_conn_index(int conn_index
,
477 struct torture_context
*tctx
,
478 char **host
, char **share
)
480 char **unc_list
= NULL
;
481 int num_unc_names
= 0;
484 (*host
) = talloc_strdup(mem_ctx
, torture_setting_string(tctx
, "host", NULL
));
485 (*share
) = talloc_strdup(mem_ctx
, torture_setting_string(tctx
, "share", NULL
));
487 p
= torture_setting_string(tctx
, "unclist", NULL
);
492 unc_list
= file_lines_load(p
, &num_unc_names
, 0, NULL
);
493 if (!unc_list
|| num_unc_names
<= 0) {
494 DEBUG(0,("Failed to load unc names list from '%s'\n", p
));
498 p
= unc_list
[conn_index
% num_unc_names
];
499 if (p
[0] != '/' && p
[0] != '\\') {
500 /* allow UNC lists of hosts */
501 (*host
) = talloc_strdup(mem_ctx
, p
);
502 } else if (!smbcli_parse_unc(p
, mem_ctx
, host
, share
)) {
503 DEBUG(0, ("Failed to parse UNC name %s\n",
504 unc_list
[conn_index
% num_unc_names
]));
508 talloc_free(unc_list
);
514 _PUBLIC_
bool torture_open_connection_ev(struct smbcli_state
**c
,
516 struct torture_context
*tctx
,
517 struct tevent_context
*ev
)
522 if (!torture_get_conn_index(conn_index
, ev
, tctx
, &host
, &share
)) {
526 ret
= torture_open_connection_share(NULL
, c
, tctx
, host
, share
, ev
);
533 _PUBLIC_
bool torture_open_connection(struct smbcli_state
**c
, struct torture_context
*tctx
, int conn_index
)
535 return torture_open_connection_ev(c
, conn_index
, tctx
, tctx
->ev
);
540 _PUBLIC_
bool torture_close_connection(struct smbcli_state
*c
)
544 if (NT_STATUS_IS_ERR(smbcli_tdis(c
))) {
545 printf("tdis failed (%s)\n", smbcli_errstr(c
->tree
));
553 /* check if the server produced the expected error code */
554 _PUBLIC_
bool check_error(const char *location
, struct smbcli_state
*c
,
555 uint8_t eclass
, uint32_t ecode
, NTSTATUS nterr
)
559 status
= smbcli_nt_error(c
->tree
);
560 if (NT_STATUS_IS_DOS(status
)) {
562 classnum
= NT_STATUS_DOS_CLASS(status
);
563 num
= NT_STATUS_DOS_CODE(status
);
564 if (eclass
!= classnum
|| ecode
!= num
) {
565 printf("unexpected error code %s\n", nt_errstr(status
));
566 printf(" expected %s or %s (at %s)\n",
567 nt_errstr(NT_STATUS_DOS(eclass
, ecode
)),
568 nt_errstr(nterr
), location
);
572 if (!NT_STATUS_EQUAL(nterr
, status
)) {
573 printf("unexpected error code %s\n", nt_errstr(status
));
574 printf(" expected %s (at %s)\n", nt_errstr(nterr
), location
);
582 static struct smbcli_state
*current_cli
;
583 static int procnum
; /* records process count number when forking */
585 static void sigcont(int sig
)
589 struct child_status
{
592 enum torture_result result
;
596 double torture_create_procs(struct torture_context
*tctx
,
597 bool (*fn
)(struct torture_context
*, struct smbcli_state
*, int),
602 struct child_status
*child_status
;
605 size_t torture_nprocs
= torture_setting_int(tctx
, "nprocs", 4);
606 double start_time_limit
= 10 + (torture_nprocs
* 1.5);
613 signal(SIGCONT
, sigcont
);
615 child_status
= (struct child_status
*)anonymous_shared_allocate(
616 sizeof(struct child_status
)*torture_nprocs
);
617 if (child_status
== NULL
) {
618 printf("Failed to setup shared memory\n");
622 for (i
= 0; i
< torture_nprocs
; i
++) {
623 ZERO_STRUCT(child_status
[i
]);
626 tv
= timeval_current();
628 for (i
=0;i
<torture_nprocs
;i
++) {
634 pid_t mypid
= getpid();
635 srandom(((int)mypid
) ^ ((int)time(NULL
)));
637 if (asprintf(&myname
, "CLIENT%zu", i
) == -1) {
638 printf("asprintf failed\n");
641 lpcfg_set_cmdline(tctx
->lp_ctx
, "netbios name", myname
);
646 if (torture_open_connection(¤t_cli
, tctx
, i
)) {
650 printf("pid %d failed to start\n", (int)getpid());
656 child_status
[i
].pid
= getpid();
660 if (!child_status
[i
].start
) {
661 child_status
[i
].result
= TORTURE_ERROR
;
662 printf("Child %zu failed to start!\n", i
);
666 ok
= fn(tctx
, current_cli
, i
);
668 if (tctx
->last_result
== TORTURE_OK
) {
669 torture_result(tctx
, TORTURE_ERROR
,
670 "unknown error: missing "
671 "torture_result call?\n");
674 child_status
[i
].result
= tctx
->last_result
;
676 if (strlen(tctx
->last_reason
) > 1023) {
677 /* note: reason already contains \n */
678 torture_comment(tctx
,
679 "child %zu (pid %u) failed: %s",
681 (unsigned)child_status
[i
].pid
,
685 snprintf(child_status
[i
].reason
,
686 1024, "child %zu (pid %u) failed: %s",
687 i
, (unsigned)child_status
[i
].pid
,
689 /* ensure proper "\n\0" termination: */
690 if (child_status
[i
].reason
[1022] != '\0') {
691 child_status
[i
].reason
[1022] = '\n';
692 child_status
[i
].reason
[1023] = '\0';
701 for (i
=0;i
<torture_nprocs
;i
++) {
702 if (child_status
[i
].pid
!= 0) {
706 if (synccount
== torture_nprocs
) {
710 } while (timeval_elapsed(&tv
) < start_time_limit
);
712 if (synccount
!= torture_nprocs
) {
713 printf("FAILED TO START %zu CLIENTS (started %zu)\n", torture_nprocs
, synccount
);
715 /* cleanup child processes */
716 for (i
= 0; i
< torture_nprocs
; i
++) {
717 if (child_status
[i
].pid
!= 0) {
718 kill(child_status
[i
].pid
, SIGTERM
);
723 return timeval_elapsed(&tv
);
726 printf("Starting %zu clients\n", torture_nprocs
);
728 /* start the client load */
729 tv
= timeval_current();
730 for (i
=0;i
<torture_nprocs
;i
++) {
731 child_status
[i
].start
= true;
734 printf("%zu clients started\n", torture_nprocs
);
738 for (i
=0;i
<torture_nprocs
;i
++) {
740 while ((ret
=waitpid(0, &status
, 0)) == -1 && errno
== EINTR
) /* noop */ ;
741 if (ret
== -1 || WEXITSTATUS(status
) != 0) {
748 for (i
=0;i
<torture_nprocs
;i
++) {
749 if (child_status
[i
].result
!= TORTURE_OK
) {
751 torture_result(tctx
, child_status
[i
].result
,
752 "%s", child_status
[i
].reason
);
756 return timeval_elapsed(&tv
);
759 static bool wrap_smb_multi_test(struct torture_context
*torture
,
760 struct torture_tcase
*tcase
,
761 struct torture_test
*test
)
763 bool (*fn
)(struct torture_context
*, struct smbcli_state
*, int ) = test
->fn
;
766 torture_create_procs(torture
, fn
, &result
);
771 _PUBLIC_
struct torture_test
*torture_suite_add_smb_multi_test(
772 struct torture_suite
*suite
,
774 bool (*run
) (struct torture_context
*,
775 struct smbcli_state
*,
778 struct torture_test
*test
;
779 struct torture_tcase
*tcase
;
781 tcase
= torture_suite_add_tcase(suite
, name
);
783 test
= talloc(tcase
, struct torture_test
);
785 test
->name
= talloc_strdup(test
, name
);
786 test
->description
= NULL
;
787 test
->run
= wrap_smb_multi_test
;
789 test
->dangerous
= false;
791 DLIST_ADD_END(tcase
->tests
, test
);
797 static bool wrap_simple_2smb_test(struct torture_context
*torture_ctx
,
798 struct torture_tcase
*tcase
,
799 struct torture_test
*test
)
801 bool (*fn
) (struct torture_context
*, struct smbcli_state
*,
802 struct smbcli_state
*);
805 struct smbcli_state
*cli1
= NULL
, *cli2
= NULL
;
807 torture_assert_goto(torture_ctx
, torture_open_connection(&cli1
, torture_ctx
, 0), ret
, fail
, "Failed to open connection");
808 torture_assert_goto(torture_ctx
, torture_open_connection(&cli2
, torture_ctx
, 1), ret
, fail
, "Failed to open connection");
812 ret
= fn(torture_ctx
, cli1
, cli2
);
822 _PUBLIC_
struct torture_test
*torture_suite_add_2smb_test(
823 struct torture_suite
*suite
,
825 bool (*run
) (struct torture_context
*,
826 struct smbcli_state
*,
827 struct smbcli_state
*))
829 struct torture_test
*test
;
830 struct torture_tcase
*tcase
;
832 tcase
= torture_suite_add_tcase(suite
, name
);
834 test
= talloc(tcase
, struct torture_test
);
836 test
->name
= talloc_strdup(test
, name
);
837 test
->description
= NULL
;
838 test
->run
= wrap_simple_2smb_test
;
840 test
->dangerous
= false;
842 DLIST_ADD_END(tcase
->tests
, test
);
848 static bool wrap_simple_1smb_test(struct torture_context
*torture_ctx
,
849 struct torture_tcase
*tcase
,
850 struct torture_test
*test
)
852 bool (*fn
) (struct torture_context
*, struct smbcli_state
*);
855 struct smbcli_state
*cli1
= NULL
;
857 torture_assert_goto(torture_ctx
, torture_open_connection(&cli1
, torture_ctx
, 0), ret
, fail
, "Failed to open connection");
861 ret
= fn(torture_ctx
, cli1
);
868 _PUBLIC_
struct torture_test
*torture_suite_add_1smb_test(
869 struct torture_suite
*suite
,
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
;
884 test
->dangerous
= false;
886 DLIST_ADD_END(tcase
->tests
, test
);
892 NTSTATUS
torture_second_tcon(TALLOC_CTX
*mem_ctx
,
893 struct smbcli_session
*session
,
894 const char *sharename
,
895 struct smbcli_tree
**res
)
898 struct smbcli_tree
*result
;
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
= TCONX_FLAG_EXTENDED_RESPONSE
;
914 tcon
.tconx
.in
.flags
|= TCONX_FLAG_EXTENDED_SIGNATURES
;
916 /* Ignore share mode security here */
917 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
918 tcon
.tconx
.in
.path
= sharename
;
919 tcon
.tconx
.in
.device
= "?????";
921 status
= smb_raw_tcon(result
, tmp_ctx
, &tcon
);
922 if (!NT_STATUS_IS_OK(status
)) {
923 talloc_free(tmp_ctx
);
927 result
->tid
= tcon
.tconx
.out
.tid
;
929 if (tcon
.tconx
.out
.options
& SMB_EXTENDED_SIGNATURES
) {
930 smb1cli_session_protect_session_key(result
->session
->smbXcli
);
933 *res
= talloc_steal(mem_ctx
, result
);
934 talloc_free(tmp_ctx
);
939 a wrapper around smblsa_sid_check_privilege, that tries to take
940 account of the fact that the lsa privileges calls don't expand
941 group memberships, using an explicit check for administrator. There
942 must be a better way ...
944 NTSTATUS
torture_check_privilege(struct smbcli_state
*cli
,
946 const char *privilege
)
949 TALLOC_CTX
*tmp_ctx
= talloc_new(cli
);
953 sid
= dom_sid_parse_talloc(tmp_ctx
, sid_str
);
955 talloc_free(tmp_ctx
);
956 return NT_STATUS_INVALID_SID
;
959 status
= dom_sid_split_rid(tmp_ctx
, sid
, NULL
, &rid
);
960 if (!NT_STATUS_IS_OK(status
)) {
961 TALLOC_FREE(tmp_ctx
);
965 if (rid
== DOMAIN_RID_ADMINISTRATOR
) {
966 /* assume the administrator has them all */
970 talloc_free(tmp_ctx
);
972 return smblsa_sid_check_privilege(cli
, sid_str
, privilege
);
976 * Use this to pass a 2nd user:
978 * --option='torture:user2name=user2'
979 * --option='torture:user2domain=domain2'
980 * --option='torture:user2password=password2'
982 struct cli_credentials
*torture_user2_credentials(struct torture_context
*tctx
,
985 struct cli_credentials
*credentials1
= samba_cmdline_get_creds();
986 const char *user1domain
= cli_credentials_get_domain(credentials1
);
987 const char *user2name
= torture_setting_string(tctx
, "user2name", NULL
);
988 const char *user2domain
= torture_setting_string(tctx
, "user2domain", user1domain
);
989 const char *user2password
= torture_setting_string(tctx
, "user2password", NULL
);
990 struct cli_credentials
*credentials2
= NULL
;
992 credentials2
= cli_credentials_shallow_copy(mem_ctx
, credentials1
);
993 if (credentials2
== NULL
) {
994 torture_comment(tctx
,
995 "%s: cli_credentials_shallow_copy() failed\n",
999 if (user2name
!= NULL
) {
1000 torture_comment(tctx
,
1002 "'torture:user2name'='%s' "
1003 "'torture:user2domain'='%s' "
1004 "'torture:user2password'='REDACTED'",
1007 cli_credentials_set_username(credentials2
, user2name
, CRED_SPECIFIED
);
1008 cli_credentials_set_domain(credentials2
, user2domain
, CRED_SPECIFIED
);
1009 cli_credentials_set_password(credentials2
, user2password
, CRED_SPECIFIED
);
1011 torture_comment(tctx
,
1012 "Fallback to anonymous for "
1013 "'torture:user2name'=NULL "
1014 "'torture:user2domain'='%s' "
1015 "'torture:user2password'='REDACTED'",
1017 cli_credentials_set_anonymous(credentials2
);
1020 return credentials2
;