X-Git-Url: http://git.samba.org/?p=samba.git;a=blobdiff_plain;f=source4%2Ftorture%2Futil_smb.c;h=216927ce70dcc3c527a32d59e38061ccb47ac5d7;hp=c1e4edc5e6f10a29de50b44c0de225f124b08fba;hb=8edab1b96c47e75b2f2c61739f9283fa2ecf5cfe;hpb=0329d755a7611ba3897fc1ee9bdce410cc33d7f8 diff --git a/source4/torture/util_smb.c b/source4/torture/util_smb.c index c1e4edc5e6f..216927ce70d 100644 --- a/source4/torture/util_smb.c +++ b/source4/torture/util_smb.c @@ -2,10 +2,11 @@ Unix SMB/CIFS implementation. SMB torture tester utility functions Copyright (C) Andrew Tridgell 2003 + Copyright (C) Jelmer Vernooij 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,13 +15,13 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" #include "lib/cmdline/popt_common.h" #include "libcli/raw/libcliraw.h" +#include "libcli/raw/raw_proto.h" #include "libcli/raw/ioctl.h" #include "libcli/libcli.h" #include "system/filesys.h" @@ -28,20 +29,25 @@ #include "system/wait.h" #include "system/time.h" #include "torture/torture.h" +#include "../lib/util/dlinklist.h" +#include "libcli/resolve/resolve.h" +#include "param/param.h" +#include "libcli/security/security.h" +#include "libcli/util/clilsa.h" /** setup a directory ready for a test */ -_PUBLIC_ BOOL torture_setup_dir(struct smbcli_state *cli, const char *dname) +_PUBLIC_ bool torture_setup_dir(struct smbcli_state *cli, const char *dname) { smb_raw_exit(cli->session); if (smbcli_deltree(cli->tree, dname) == -1 || NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) { printf("Unable to setup %s - %s\n", dname, smbcli_errstr(cli->tree)); - return False; + return false; } - return True; + return true; } /* @@ -53,15 +59,15 @@ NTSTATUS create_directory_handle(struct smbcli_tree *tree, const char *dname, in union smb_open io; TALLOC_CTX *mem_ctx; - mem_ctx = talloc_init("create_directory_handle"); + mem_ctx = talloc_named_const(tree, 0, "create_directory_handle"); io.generic.level = RAW_OPEN_NTCREATEX; - io.ntcreatex.in.root_fid = 0; + io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.flags = 0; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; - io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; + io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; @@ -123,14 +129,17 @@ _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, } } - /* make sure all the timestamps aren't the same, and are also - in different DST zones*/ - setfile.generic.level = RAW_SFILEINFO_SETATTRE; + /* make sure all the timestamps aren't the same */ + ZERO_STRUCT(setfile); + setfile.generic.level = RAW_SFILEINFO_BASIC_INFO; setfile.generic.in.file.fnum = fnum; - setfile.setattre.in.create_time = t + 9*30*24*60*60; - setfile.setattre.in.access_time = t + 6*30*24*60*60; - setfile.setattre.in.write_time = t + 3*30*24*60*60; + unix_to_nt_time(&setfile.basic_info.in.create_time, + t + 9*30*24*60*60); + unix_to_nt_time(&setfile.basic_info.in.access_time, + t + 6*30*24*60*60); + unix_to_nt_time(&setfile.basic_info.in.write_time, + t + 3*30*24*60*60); status = smb_raw_setfileinfo(cli->tree, &setfile); if (!NT_STATUS_IS_OK(status)) { @@ -138,7 +147,7 @@ _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, } /* make sure all the timestamps aren't the same */ - fileinfo.generic.level = RAW_FILEINFO_GETATTRE; + fileinfo.generic.level = RAW_FILEINFO_BASIC_INFO; fileinfo.generic.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo); @@ -146,13 +155,13 @@ _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, printf("Failed to query file times - %s\n", nt_errstr(status)); } - if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) { + if (setfile.basic_info.in.create_time != fileinfo.basic_info.out.create_time) { printf("create_time not setup correctly\n"); } - if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) { + if (setfile.basic_info.in.access_time != fileinfo.basic_info.out.access_time) { printf("access_time not setup correctly\n"); } - if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) { + if (setfile.basic_info.in.write_time != fileinfo.basic_info.out.write_time) { printf("write_time not setup correctly\n"); } @@ -200,14 +209,17 @@ int create_complex_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char } } - /* make sure all the timestamps aren't the same, and are also - in different DST zones*/ - setfile.generic.level = RAW_SFILEINFO_SETATTRE; + /* make sure all the timestamps aren't the same */ + ZERO_STRUCT(setfile); + setfile.generic.level = RAW_SFILEINFO_BASIC_INFO; setfile.generic.in.file.fnum = fnum; - setfile.setattre.in.create_time = t + 9*30*24*60*60; - setfile.setattre.in.access_time = t + 6*30*24*60*60; - setfile.setattre.in.write_time = t + 3*30*24*60*60; + unix_to_nt_time(&setfile.basic_info.in.create_time, + t + 9*30*24*60*60); + unix_to_nt_time(&setfile.basic_info.in.access_time, + t + 6*30*24*60*60); + unix_to_nt_time(&setfile.basic_info.in.write_time, + t + 3*30*24*60*60); status = smb_raw_setfileinfo(cli->tree, &setfile); if (!NT_STATUS_IS_OK(status)) { @@ -215,7 +227,7 @@ int create_complex_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char } /* make sure all the timestamps aren't the same */ - fileinfo.generic.level = RAW_FILEINFO_GETATTRE; + fileinfo.generic.level = RAW_FILEINFO_BASIC_INFO; fileinfo.generic.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo); @@ -223,13 +235,13 @@ int create_complex_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char printf("Failed to query file times - %s\n", nt_errstr(status)); } - if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) { + if (setfile.basic_info.in.create_time != fileinfo.basic_info.out.create_time) { printf("create_time not setup correctly\n"); } - if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) { + if (setfile.basic_info.in.access_time != fileinfo.basic_info.out.access_time) { printf("access_time not setup correctly\n"); } - if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) { + if (setfile.basic_info.in.write_time != fileinfo.basic_info.out.write_time) { printf("write_time not setup correctly\n"); } @@ -252,6 +264,23 @@ void *shm_setup(int size) int shmid; void *ret; +#ifdef __QNXNTO__ + shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + if (shmid == -1) { + printf("can't get shared memory\n"); + exit(1); + } + shm_unlink("private"); + if (ftruncate(shmid, size) == -1) { + printf("can't set shared memory size\n"); + exit(1); + } + ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0); + if (ret == MAP_FAILED) { + printf("can't map shared memory\n"); + exit(1); + } +#else shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W); if (shmid == -1) { printf("can't get shared memory\n"); @@ -270,26 +299,28 @@ void *shm_setup(int size) See Stevens "advanced programming in unix env" for details */ shmctl(shmid, IPC_RMID, 0); +#endif return ret; } -/* +/** check that a wire string matches the flags specified not 100% accurate, but close enough for testing */ -BOOL wire_bad_flags(struct smb_wire_string *str, int flags, struct smbcli_state *cli) +bool wire_bad_flags(struct smb_wire_string *str, int flags, + struct smbcli_transport *transport) { - BOOL server_unicode; + bool server_unicode; int len; - if (!str || !str->s) return True; + if (!str || !str->s) return true; len = strlen(str->s); if (flags & STR_TERMINATE) len++; - server_unicode = (cli->transport->negotiate.capabilities&CAP_UNICODE)?True:False; - if (getenv("CLI_FORCE_ASCII") || !lp_unicode()) { - server_unicode = False; + server_unicode = (transport->negotiate.capabilities&CAP_UNICODE)?true:false; + if (getenv("CLI_FORCE_ASCII") || !transport->options.unicode) { + server_unicode = false; } if ((flags & STR_UNICODE) || server_unicode) { @@ -300,9 +331,9 @@ BOOL wire_bad_flags(struct smb_wire_string *str, int flags, struct smbcli_state if (str->private_length != len) { printf("Expected wire_length %d but got %d for '%s'\n", len, str->private_length, str->s); - return True; + return true; } - return False; + return false; } /* @@ -329,7 +360,7 @@ void dump_all_info(TALLOC_CTX *mem_ctx, union smb_fileinfo *finfo) */ void torture_all_info(struct smbcli_tree *tree, const char *fname) { - TALLOC_CTX *mem_ctx = talloc_init("%s", fname); + TALLOC_CTX *mem_ctx = talloc_named(tree, 0, "%s", fname); union smb_fileinfo finfo; NTSTATUS status; @@ -350,7 +381,7 @@ void torture_all_info(struct smbcli_tree *tree, const char *fname) /* set a attribute on a file */ -BOOL torture_set_file_attribute(struct smbcli_tree *tree, const char *fname, uint16_t attrib) +bool torture_set_file_attribute(struct smbcli_tree *tree, const char *fname, uint16_t attrib) { union smb_setfileinfo sfinfo; NTSTATUS status; @@ -373,7 +404,7 @@ NTSTATUS torture_set_sparse(struct smbcli_tree *tree, int fnum) NTSTATUS status; TALLOC_CTX *mem_ctx; - mem_ctx = talloc_init("torture_set_sparse"); + mem_ctx = talloc_named_const(tree, 0, "torture_set_sparse"); if (!mem_ctx) { return NT_STATUS_NO_MEMORY; } @@ -381,7 +412,7 @@ NTSTATUS torture_set_sparse(struct smbcli_tree *tree, int fnum) nt.ntioctl.level = RAW_IOCTL_NTIOCTL; nt.ntioctl.in.function = FSCTL_SET_SPARSE; nt.ntioctl.in.file.fnum = fnum; - nt.ntioctl.in.fsctl = True; + nt.ntioctl.in.fsctl = true; nt.ntioctl.in.filter = 0; nt.ntioctl.in.max_data = 0; nt.ntioctl.in.blob = data_blob(NULL, 0); @@ -459,100 +490,113 @@ NTSTATUS torture_check_ea(struct smbcli_state *cli, return NT_STATUS_EA_CORRUPT_ERROR; } -BOOL torture_open_connection_share(TALLOC_CTX *mem_ctx, +_PUBLIC_ bool torture_open_connection_share(TALLOC_CTX *mem_ctx, struct smbcli_state **c, + struct torture_context *tctx, const char *hostname, const char *sharename, - struct event_context *ev) + struct tevent_context *ev) { NTSTATUS status; + struct smbcli_options options; + struct smbcli_session_options session_options; + + lp_smbcli_options(tctx->lp_ctx, &options); + lp_smbcli_session_options(tctx->lp_ctx, &session_options); + + options.use_oplocks = torture_setting_bool(tctx, "use_oplocks", true); + options.use_level2_oplocks = torture_setting_bool(tctx, "use_level2_oplocks", true); + status = smbcli_full_connection(mem_ctx, c, hostname, + lp_smb_ports(tctx->lp_ctx), sharename, NULL, - cmdline_credentials, ev); + lp_socket_options(tctx->lp_ctx), + cmdline_credentials, + lp_resolve_context(tctx->lp_ctx), + ev, &options, &session_options, + lp_iconv_convenience(tctx->lp_ctx), + lp_gensec_settings(tctx, tctx->lp_ctx)); if (!NT_STATUS_IS_OK(status)) { printf("Failed to open connection - %s\n", nt_errstr(status)); - return False; + return false; } - (*c)->transport->options.use_oplocks = use_oplocks; - (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks; - - return True; + return true; } -_PUBLIC_ BOOL torture_open_connection(struct smbcli_state **c, int conn_index) +_PUBLIC_ bool torture_get_conn_index(int conn_index, + TALLOC_CTX *mem_ctx, + struct torture_context *tctx, + char **host, char **share) { - const char *host = lp_parm_string(-1, "torture", "host"); - const char *share = lp_parm_string(-1, "torture", "share"); char **unc_list = NULL; int num_unc_names = 0; const char *p; + + (*host) = talloc_strdup(mem_ctx, torture_setting_string(tctx, "host", NULL)); + (*share) = talloc_strdup(mem_ctx, torture_setting_string(tctx, "share", NULL)); - p = lp_parm_string(-1, "torture", "unclist"); - if (p) { - char *h, *s; - unc_list = file_lines_load(p, &num_unc_names, NULL); - if (!unc_list || num_unc_names <= 0) { - printf("Failed to load unc names list from '%s'\n", p); - exit(1); - } + p = torture_setting_string(tctx, "unclist", NULL); + if (!p) { + return true; + } - if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names], - NULL, &h, &s)) { - printf("Failed to parse UNC name %s\n", - unc_list[conn_index % num_unc_names]); - exit(1); - } - host = h; - share = s; + unc_list = file_lines_load(p, &num_unc_names, 0, NULL); + if (!unc_list || num_unc_names <= 0) { + DEBUG(0,("Failed to load unc names list from '%s'\n", p)); + return false; } - return torture_open_connection_share(NULL, c, host, share, NULL); + p = unc_list[conn_index % num_unc_names]; + if (p[0] != '/' && p[0] != '\\') { + /* allow UNC lists of hosts */ + (*host) = talloc_strdup(mem_ctx, p); + } else if (!smbcli_parse_unc(p, mem_ctx, host, share)) { + DEBUG(0, ("Failed to parse UNC name %s\n", + unc_list[conn_index % num_unc_names])); + return false; + } + + talloc_free(unc_list); + return true; } -_PUBLIC_ BOOL torture_open_connection_ev(struct smbcli_state **c, + + +_PUBLIC_ bool torture_open_connection_ev(struct smbcli_state **c, int conn_index, - struct event_context *ev) + struct torture_context *tctx, + struct tevent_context *ev) { - const char *host = lp_parm_string(-1, "torture", "host"); - const char *share = lp_parm_string(-1, "torture", "share"); - char **unc_list = NULL; - int num_unc_names = 0; - const char *p; - - p = lp_parm_string(-1, "torture", "unclist"); - if (p) { - char *h, *s; - unc_list = file_lines_load(p, &num_unc_names, NULL); - if (!unc_list || num_unc_names <= 0) { - printf("Failed to load unc names list from '%s'\n", p); - exit(1); - } + char *host, *share; + bool ret; - if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names], - NULL, &h, &s)) { - printf("Failed to parse UNC name %s\n", - unc_list[conn_index % num_unc_names]); - exit(1); - } - host = h; - share = s; + if (!torture_get_conn_index(conn_index, ev, tctx, &host, &share)) { + return false; } + ret = torture_open_connection_share(NULL, c, tctx, host, share, ev); + talloc_free(host); + talloc_free(share); - return torture_open_connection_share(NULL, c, host, share, ev); + return ret; +} + +_PUBLIC_ bool torture_open_connection(struct smbcli_state **c, struct torture_context *tctx, int conn_index) +{ + return torture_open_connection_ev(c, conn_index, tctx, tctx->ev); } -_PUBLIC_ BOOL torture_close_connection(struct smbcli_state *c) +_PUBLIC_ bool torture_close_connection(struct smbcli_state *c) { - BOOL ret = True; - if (!c) return True; + bool ret = true; + if (!c) return true; if (NT_STATUS_IS_ERR(smbcli_tdis(c))) { printf("tdis failed (%s)\n", smbcli_errstr(c->tree)); - ret = False; + ret = false; } talloc_free(c); return ret; @@ -560,32 +604,32 @@ _PUBLIC_ BOOL torture_close_connection(struct smbcli_state *c) /* check if the server produced the expected error code */ -_PUBLIC_ BOOL check_error(const char *location, struct smbcli_state *c, +_PUBLIC_ bool check_error(const char *location, struct smbcli_state *c, uint8_t eclass, uint32_t ecode, NTSTATUS nterr) { NTSTATUS status; status = smbcli_nt_error(c->tree); if (NT_STATUS_IS_DOS(status)) { - int class, num; - class = NT_STATUS_DOS_CLASS(status); + int classnum, num; + classnum = NT_STATUS_DOS_CLASS(status); num = NT_STATUS_DOS_CODE(status); - if (eclass != class || ecode != num) { + if (eclass != classnum || ecode != num) { printf("unexpected error code %s\n", nt_errstr(status)); printf(" expected %s or %s (at %s)\n", nt_errstr(NT_STATUS_DOS(eclass, ecode)), nt_errstr(nterr), location); - return False; + return false; } } else { if (!NT_STATUS_EQUAL(nterr, status)) { printf("unexpected error code %s\n", nt_errstr(status)); printf(" expected %s (at %s)\n", nt_errstr(nterr), location); - return False; + return false; } } - return True; + return true; } static struct smbcli_state *current_cli; @@ -595,17 +639,19 @@ static void sigcont(int sig) { } -double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result) +double torture_create_procs(struct torture_context *tctx, + bool (*fn)(struct torture_context *, struct smbcli_state *, int), bool *result) { int i, status; volatile pid_t *child_status; - volatile BOOL *child_status_out; + volatile bool *child_status_out; int synccount; int tries = 8; + int torture_nprocs = torture_setting_int(tctx, "nprocs", 4); double start_time_limit = 10 + (torture_nprocs * 1.5); struct timeval tv; - *result = True; + *result = true; synccount = 0; @@ -617,7 +663,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result return -1; } - child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs); + child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs); if (!child_status_out) { printf("Failed to setup result status shared memory\n"); return -1; @@ -625,7 +671,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result for (i = 0; i < torture_nprocs; i++) { child_status[i] = 0; - child_status_out[i] = True; + child_status_out[i] = true; } tv = timeval_current(); @@ -638,13 +684,16 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result pid_t mypid = getpid(); srandom(((int)mypid) ^ ((int)time(NULL))); - asprintf(&myname, "CLIENT%d", i); - lp_set_cmdline("netbios name", myname); + if (asprintf(&myname, "CLIENT%d", i) == -1) { + printf("asprintf failed\n"); + return -1; + } + lp_set_cmdline(tctx->lp_ctx, "netbios name", myname); free(myname); while (1) { - if (torture_open_connection(¤t_cli, i)) { + if (torture_open_connection(¤t_cli, tctx, i)) { break; } if (tries-- == 0) { @@ -664,7 +713,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result _exit(1); } - child_status_out[i] = fn(current_cli, i); + child_status_out[i] = fn(tctx, current_cli, i); _exit(0); } } @@ -680,7 +729,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result if (synccount != torture_nprocs) { printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount); - *result = False; + *result = false; return timeval_elapsed(&tv); } @@ -700,7 +749,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result int ret; while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ; if (ret == -1 || WEXITSTATUS(status) != 0) { - *result = False; + *result = false; } } @@ -708,36 +757,217 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result for (i=0;ifn; + bool result; - torture_create_procs(fn, &result); + torture_create_procs(torture, fn, &result); return result; } -_PUBLIC_ NTSTATUS register_torture_multi_op(const char *name, - BOOL (*multi_fn)(struct smbcli_state *, int )) +_PUBLIC_ struct torture_test *torture_suite_add_smb_multi_test( + struct torture_suite *suite, + const char *name, + bool (*run) (struct torture_context *, + struct smbcli_state *, + int i)) +{ + struct torture_test *test; + struct torture_tcase *tcase; + + tcase = torture_suite_add_tcase(suite, name); + + test = talloc(tcase, struct torture_test); + + test->name = talloc_strdup(test, name); + test->description = NULL; + test->run = wrap_smb_multi_test; + test->fn = run; + test->dangerous = false; + + DLIST_ADD_END(tcase->tests, test, struct torture_test *); + + return test; + +} + +static bool wrap_simple_2smb_test(struct torture_context *torture_ctx, + struct torture_tcase *tcase, + struct torture_test *test) +{ + bool (*fn) (struct torture_context *, struct smbcli_state *, + struct smbcli_state *); + bool ret; + + struct smbcli_state *cli1, *cli2; + + if (!torture_open_connection(&cli1, torture_ctx, 0) || + !torture_open_connection(&cli2, torture_ctx, 1)) + return false; + + fn = test->fn; + + ret = fn(torture_ctx, cli1, cli2); + + talloc_free(cli1); + talloc_free(cli2); + + return ret; +} + + + +_PUBLIC_ struct torture_test *torture_suite_add_2smb_test( + struct torture_suite *suite, + const char *name, + bool (*run) (struct torture_context *, + struct smbcli_state *, + struct smbcli_state *)) +{ + struct torture_test *test; + struct torture_tcase *tcase; + + tcase = torture_suite_add_tcase(suite, name); + + test = talloc(tcase, struct torture_test); + + test->name = talloc_strdup(test, name); + test->description = NULL; + test->run = wrap_simple_2smb_test; + test->fn = run; + test->dangerous = false; + + DLIST_ADD_END(tcase->tests, test, struct torture_test *); + + return test; + +} + +static bool wrap_simple_1smb_test(struct torture_context *torture_ctx, + struct torture_tcase *tcase, + struct torture_test *test) { - struct torture_suite *suite; + bool (*fn) (struct torture_context *, struct smbcli_state *); + bool ret; + + struct smbcli_state *cli1; + + if (!torture_open_connection(&cli1, torture_ctx, 0)) + return false; - suite = torture_suite_create(talloc_autofree_context(), name); + fn = test->fn; + + ret = fn(torture_ctx, cli1); + + talloc_free(cli1); + + return ret; +} + +_PUBLIC_ struct torture_test *torture_suite_add_1smb_test( + struct torture_suite *suite, + const char *name, + bool (*run) (struct torture_context *, struct smbcli_state *)) +{ + struct torture_test *test; + struct torture_tcase *tcase; + + tcase = torture_suite_add_tcase(suite, name); + + test = talloc(tcase, struct torture_test); + + test->name = talloc_strdup(test, name); + test->description = NULL; + test->run = wrap_simple_1smb_test; + test->fn = run; + test->dangerous = false; + + DLIST_ADD_END(tcase->tests, test, struct torture_test *); + + return test; +} - torture_suite_add_simple_tcase(suite, name, - wrap_old_torture_multifn, - multi_fn); - torture_register_suite(suite); +NTSTATUS torture_second_tcon(TALLOC_CTX *mem_ctx, + struct smbcli_session *session, + const char *sharename, + struct smbcli_tree **res) +{ + union smb_tcon tcon; + struct smbcli_tree *result; + TALLOC_CTX *tmp_ctx; + NTSTATUS status; + + if ((tmp_ctx = talloc_new(mem_ctx)) == NULL) { + return NT_STATUS_NO_MEMORY; + } + + result = smbcli_tree_init(session, tmp_ctx, false); + if (result == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + tcon.generic.level = RAW_TCON_TCONX; + tcon.tconx.in.flags = 0; + + /* Ignore share mode security here */ + tcon.tconx.in.password = data_blob(NULL, 0); + tcon.tconx.in.path = sharename; + tcon.tconx.in.device = "?????"; + + status = smb_raw_tcon(result, tmp_ctx, &tcon); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + + result->tid = tcon.tconx.out.tid; + *res = talloc_steal(mem_ctx, result); + talloc_free(tmp_ctx); return NT_STATUS_OK; } +/* + a wrapper around smblsa_sid_check_privilege, that tries to take + account of the fact that the lsa privileges calls don't expand + group memberships, using an explicit check for administrator. There + must be a better way ... + */ +NTSTATUS torture_check_privilege(struct smbcli_state *cli, + const char *sid_str, + const char *privilege) +{ + struct dom_sid *sid; + TALLOC_CTX *tmp_ctx = talloc_new(cli); + uint32_t rid; + NTSTATUS status; + + sid = dom_sid_parse_talloc(tmp_ctx, sid_str); + if (sid == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_INVALID_SID; + } + status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid); + NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx); + + if (rid == DOMAIN_RID_ADMINISTRATOR) { + /* assume the administrator has them all */ + return NT_STATUS_OK; + } + + talloc_free(tmp_ctx); + + return smblsa_sid_check_privilege(cli, sid_str, privilege); +}