#include "lib/cmdline/popt_common.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/raw/raw_proto.h"
-#include "libcli/raw/ioctl.h"
+#include "../libcli/smb/smb_constants.h"
#include "libcli/libcli.h"
#include "system/filesys.h"
#include "system/shmem.h"
#include "system/time.h"
#include "torture/torture.h"
#include "../lib/util/dlinklist.h"
-#include "auth/credentials/credentials.h"
#include "libcli/resolve/resolve.h"
#include "param/param.h"
-
+#include "libcli/security/security.h"
+#include "libcli/util/clilsa.h"
+#include "torture/util.h"
+#include "libcli/smb/smbXcli_base.h"
/**
setup a directory ready for a test
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;
}
}
- /* 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)) {
}
/* 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);
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");
}
}
}
- /* 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)) {
}
/* 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);
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");
}
return fnum;
}
-
-
-/* return a pointer to a anonymous shared memory segment of size "size"
- which will persist across fork() but will disappear when all processes
- exit
-
- The memory is not zeroed
-
- This function uses system5 shared memory. It takes advantage of a property
- that the memory is not destroyed if it is attached when the id is removed
- */
-void *shm_setup(int size)
-{
- int shmid;
- void *ret;
-
- shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
- if (shmid == -1) {
- printf("can't get shared memory\n");
- exit(1);
- }
- ret = (void *)shmat(shmid, 0, 0);
- if (!ret || ret == (void *)-1) {
- printf("can't attach to shared memory\n");
- return NULL;
- }
- /* the following releases the ipc, but note that this process
- and all its children will still have access to the memory, its
- just that the shmid is no longer valid for other shm calls. This
- means we don't leave behind lots of shm segments after we exit
-
- See Stevens "advanced programming in unix env" for details
- */
- shmctl(shmid, IPC_RMID, 0);
-
- return ret;
-}
-
-
/**
check that a wire string matches the flags specified
not 100% accurate, but close enough for testing
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);
+ lpcfg_smbcli_options(tctx->lp_ctx, &options);
+ lpcfg_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),
+ lpcfg_smb_ports(tctx->lp_ctx),
sharename, NULL,
- lp_socket_options(tctx->lp_ctx),
- cmdline_credentials,
- lp_resolve_context(tctx->lp_ctx),
+ lpcfg_socket_options(tctx->lp_ctx),
+ popt_get_cmdline_credentials(),
+ lpcfg_resolve_context(tctx->lp_ctx),
ev, &options, &session_options,
- lp_iconv_convenience(tctx->lp_ctx),
- lp_gensec_settings(tctx, tctx->lp_ctx));
+ lpcfg_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;
}
- if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
- mem_ctx, host, share)) {
+ 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;
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)),
{
}
-double torture_create_procs(struct torture_context *tctx,
- bool (*fn)(struct torture_context *, struct smbcli_state *, int), bool *result)
+struct child_status {
+ pid_t pid;
+ bool start;
+ enum torture_result result;
+ char reason[1024];
+};
+
+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;
+ struct child_status *child_status;
int synccount;
int tries = 8;
int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
signal(SIGCONT, sigcont);
- child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
- if (!child_status) {
+ child_status = (struct child_status *)anonymous_shared_allocate(
+ sizeof(struct child_status)*torture_nprocs);
+ if (child_status == NULL) {
printf("Failed to setup shared memory\n");
return -1;
}
- 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;
- }
-
for (i = 0; i < torture_nprocs; i++) {
- child_status[i] = 0;
- child_status_out[i] = true;
+ ZERO_STRUCT(child_status[i]);
}
tv = timeval_current();
procnum = i;
if (fork() == 0) {
char *myname;
+ bool ok;
pid_t mypid = getpid();
srandom(((int)mypid) ^ ((int)time(NULL)));
- asprintf(&myname, "CLIENT%d", i);
- lp_set_cmdline(tctx->lp_ctx, "netbios name", myname);
+ if (asprintf(&myname, "CLIENT%d", i) == -1) {
+ printf("asprintf failed\n");
+ return -1;
+ }
+ lpcfg_set_cmdline(tctx->lp_ctx, "netbios name", myname);
free(myname);
printf("pid %d failed to start\n", (int)getpid());
_exit(1);
}
- msleep(100);
+ smb_msleep(100);
}
- child_status[i] = getpid();
+ child_status[i].pid = getpid();
pause();
- if (child_status[i]) {
+ if (!child_status[i].start) {
+ child_status[i].result = TORTURE_ERROR;
printf("Child %d failed to start!\n", i);
- child_status_out[i] = 1;
_exit(1);
}
- child_status_out[i] = fn(tctx, current_cli, i);
+ ok = fn(tctx, current_cli, i);
+ if (!ok) {
+ if (tctx->last_result == TORTURE_OK) {
+ torture_result(tctx, TORTURE_ERROR,
+ "unknown error: missing "
+ "torture_result call?\n");
+ }
+
+ child_status[i].result = tctx->last_result;
+
+ if (strlen(tctx->last_reason) > 1023) {
+ /* note: reason already contains \n */
+ torture_comment(tctx,
+ "child %d (pid %u) failed: %s",
+ i,
+ (unsigned)child_status[i].pid,
+ tctx->last_reason);
+ }
+
+ snprintf(child_status[i].reason,
+ 1024, "child %d (pid %u) failed: %s",
+ i, (unsigned)child_status[i].pid,
+ tctx->last_reason);
+ /* ensure proper "\n\0" termination: */
+ if (child_status[i].reason[1022] != '\0') {
+ child_status[i].reason[1022] = '\n';
+ child_status[i].reason[1023] = '\0';
+ }
+ }
_exit(0);
}
}
do {
synccount = 0;
for (i=0;i<torture_nprocs;i++) {
- if (child_status[i]) synccount++;
+ if (child_status[i].pid != 0) {
+ synccount++;
+ }
}
- if (synccount == torture_nprocs) break;
- msleep(100);
+ if (synccount == torture_nprocs) {
+ break;
+ }
+ smb_msleep(100);
} while (timeval_elapsed(&tv) < start_time_limit);
if (synccount != torture_nprocs) {
printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
+
+ /* cleanup child processes */
+ for (i = 0; i < torture_nprocs; i++) {
+ if (child_status[i].pid != 0) {
+ kill(child_status[i].pid, SIGTERM);
+ }
+ }
+
*result = false;
return timeval_elapsed(&tv);
}
/* start the client load */
tv = timeval_current();
for (i=0;i<torture_nprocs;i++) {
- child_status[i] = 0;
+ child_status[i].start = true;
}
printf("%d clients started\n", torture_nprocs);
}
printf("\n");
-
+
for (i=0;i<torture_nprocs;i++) {
- if (!child_status_out[i]) {
+ if (child_status[i].result != TORTURE_OK) {
*result = false;
+ torture_result(tctx, child_status[i].result,
+ "%s", child_status[i].reason);
}
}
+
return timeval_elapsed(&tv);
}
test->fn = run;
test->dangerous = false;
- DLIST_ADD_END(tcase->tests, test, struct torture_test *);
+ DLIST_ADD_END(tcase->tests, test);
return test;
{
bool (*fn) (struct torture_context *, struct smbcli_state *,
struct smbcli_state *);
- bool ret;
+ bool ret = true;
- struct smbcli_state *cli1, *cli2;
+ struct smbcli_state *cli1 = NULL, *cli2 = NULL;
- if (!torture_open_connection(&cli1, torture_ctx, 0) ||
- !torture_open_connection(&cli2, torture_ctx, 1))
- return false;
+ torture_assert_goto(torture_ctx, torture_open_connection(&cli1, torture_ctx, 0), ret, fail, "Failed to open connection");
+ torture_assert_goto(torture_ctx, torture_open_connection(&cli2, torture_ctx, 1), ret, fail, "Failed to open connection");
fn = test->fn;
ret = fn(torture_ctx, cli1, cli2);
-
+fail:
talloc_free(cli1);
talloc_free(cli2);
test->fn = run;
test->dangerous = false;
- DLIST_ADD_END(tcase->tests, test, struct torture_test *);
+ DLIST_ADD_END(tcase->tests, test);
return test;
struct torture_test *test)
{
bool (*fn) (struct torture_context *, struct smbcli_state *);
- bool ret;
+ bool ret = true;
- struct smbcli_state *cli1;
+ struct smbcli_state *cli1 = NULL;
- if (!torture_open_connection(&cli1, torture_ctx, 0))
- return false;
+ torture_assert_goto(torture_ctx, torture_open_connection(&cli1, torture_ctx, 0), ret, fail, "Failed to open connection");
fn = test->fn;
ret = fn(torture_ctx, cli1);
-
+fail:
talloc_free(cli1);
return ret;
test->fn = run;
test->dangerous = false;
- DLIST_ADD_END(tcase->tests, test, struct torture_test *);
+ DLIST_ADD_END(tcase->tests, test);
return test;
}
}
tcon.generic.level = RAW_TCON_TCONX;
- tcon.tconx.in.flags = 0;
+ tcon.tconx.in.flags = TCONX_FLAG_EXTENDED_RESPONSE;
+ tcon.tconx.in.flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
/* Ignore share mode security here */
tcon.tconx.in.password = data_blob(NULL, 0);
}
result->tid = tcon.tconx.out.tid;
+
+ if (tcon.tconx.out.options & SMB_EXTENDED_SIGNATURES) {
+ smb1cli_session_protect_session_key(result->session->smbXcli);
+ }
+
*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);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(tmp_ctx);
+ return status;
+ }
+
+ 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);
+}