/** * The challenge from the target server, when operating in security=server **/ static NTSTATUS server_get_challenge(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, uint8_t chal[8]) { struct smb_composite_connect io; struct smbcli_options smb_options; const char **host_list; NTSTATUS status; /* Make a connection to the target server, found by 'password server' in smb.conf */ lp_smbcli_options(ctx->auth_ctx->lp_ctx, &smb_options); /* Make a negprot, WITHOUT SPNEGO, so we get a challenge nice an easy */ io.in.options.use_spnego = false; /* Hope we don't get * (the default), as this won't work... */ host_list = lp_passwordserver(ctx->auth_ctx->lp_ctx); if (!host_list) { return NT_STATUS_INTERNAL_ERROR; } io.in.dest_host = host_list[0]; if (strequal(io.in.dest_host, "*")) { return NT_STATUS_INTERNAL_ERROR; } io.in.dest_ports = lp_smb_ports(ctx->auth_ctx->lp_ctx); io.in.socket_options = lp_socket_options(ctx->auth_ctx->lp_ctx); io.in.gensec_settings = lp_gensec_settings(mem_ctx, ctx->auth_ctx->lp_ctx); io.in.called_name = strupper_talloc(mem_ctx, io.in.dest_host); /* We don't want to get as far as the session setup */ io.in.credentials = cli_credentials_init_anon(mem_ctx); cli_credentials_set_workstation(io.in.credentials, lp_netbios_name(ctx->auth_ctx->lp_ctx), CRED_SPECIFIED); io.in.service = NULL; io.in.workgroup = ""; /* only used with SPNEGO, disabled above */ io.in.options = smb_options; io.in.iconv_convenience = lp_iconv_convenience(ctx->auth_ctx->lp_ctx); lp_smbcli_session_options(ctx->auth_ctx->lp_ctx, &io.in.session_options); status = smb_composite_connect(&io, mem_ctx, lp_resolve_context(ctx->auth_ctx->lp_ctx), ctx->auth_ctx->event_ctx); NT_STATUS_NOT_OK_RETURN(status); if (io.out.tree->session->transport->negotiate.secblob.length != 8) { return NT_STATUS_INTERNAL_ERROR; } memcpy(chal, io.out.tree->session->transport->negotiate.secblob.data, 8); ctx->private_data = talloc_steal(ctx, io.out.tree->session); return NT_STATUS_OK; }
NTSTATUS svc_UploadService(const char *hostname, struct cli_credentials * credentials, int flags) { struct smb_composite_savefile *io; struct smbcli_state *cli; NTSTATUS status; struct smbcli_options options; struct smbcli_session_options session_options; lp_smbcli_options(cmdline_lp_ctx, &options); lp_smbcli_session_options(cmdline_lp_ctx, &session_options); status = smbcli_full_connection(NULL, &cli, hostname, lp_smb_ports(cmdline_lp_ctx), "ADMIN$", NULL, lp_socket_options(cmdline_lp_ctx), credentials, lp_resolve_context(cmdline_lp_ctx), ev_ctx, &options, &session_options, lp_iconv_convenience(cmdline_lp_ctx), lp_gensec_settings(NULL, cmdline_lp_ctx)); NT_ERR(status, 1, "Failed to open ADMIN$ share"); if (flags & SVC_FORCE_UPLOAD) { smbcli_unlink(cli->tree, "winexesvc.exe"); } else { int fd = smbcli_open(cli->tree, "winexesvc.exe", O_RDONLY, DENY_NONE); if (fd >= 0) { smbcli_close(cli->tree, fd); return status; } } io = talloc_zero(cli->tree, struct smb_composite_savefile); io->in.fname = "winexesvc.exe"; if (flags & SVC_OSCHOOSE) { status = smbcli_chkpath(cli->tree, "SysWoW64"); } if ((flags & SVC_OSCHOOSE && NT_STATUS_IS_OK(status)) || (flags & SVC_OS64BIT)) { DEBUG(1, ("svc_UploadService: Installing 64bit winexesvc.exe\n")); io->in.data = winexesvc64_exe; io->in.size = winexesvc64_exe_len; } else { DEBUG(1, ("svc_UploadService: Installing 32bit winexesvc.exe\n")); io->in.data = winexesvc32_exe; io->in.size = winexesvc32_exe_len; } status = smb_composite_savefile(cli->tree, io); NT_ERR(status, 1, "Failed to save ADMIN$/%s", io->in.fname); talloc_free(io); smbcli_tdis(cli); return status; }
/***************************************************** return a connection to a server *******************************************************/ static struct smbcli_state *connect_one(struct tevent_context *ev, struct loadparm_context *lp_ctx, TALLOC_CTX *mem_ctx, char *share, int snum, int conn) { struct smbcli_state *c; char *server, *myname; NTSTATUS status; int retries = 10; struct smbcli_options options; struct smbcli_session_options session_options; lp_smbcli_options(lp_ctx, &options); lp_smbcli_session_options(lp_ctx, &session_options); printf("connect_one(%s, %d, %d)\n", share, snum, conn); server = talloc_strdup(mem_ctx, share+2); share = strchr_m(server,'\\'); if (!share) return NULL; *share = 0; share++; if (snum == 0) { char **unc_list = NULL; int num_unc_names; const char *p; p = lp_parm_string(lp_ctx, NULL, "torture", "unclist"); if (p) { char *h, *s; unc_list = file_lines_load(p, &num_unc_names, 0, NULL); if (!unc_list || num_unc_names <= 0) { printf("Failed to load unc names list from '%s'\n", p); exit(1); } if (!smbcli_parse_unc(unc_list[conn % num_unc_names], NULL, &h, &s)) { printf("Failed to parse UNC name %s\n", unc_list[conn % num_unc_names]); exit(1); } server = talloc_strdup(mem_ctx, h); share = talloc_strdup(mem_ctx, s); } } myname = talloc_asprintf(mem_ctx, "lock-%u-%u", getpid(), snum); cli_credentials_set_workstation(servers[snum], myname, CRED_SPECIFIED); do { printf("\\\\%s\\%s\n", server, share); status = smbcli_full_connection(NULL, &c, server, lp_smb_ports(lp_ctx), share, NULL, lp_socket_options(lp_ctx), servers[snum], lp_resolve_context(lp_ctx), ev, &options, &session_options, lp_iconv_convenience(lp_ctx), lp_gensec_settings(mem_ctx, lp_ctx)); if (!NT_STATUS_IS_OK(status)) { sleep(2); } } while (!NT_STATUS_IS_OK(status) && retries--); if (!NT_STATUS_IS_OK(status)) { return NULL; } return c; }
static int copy_files(struct tevent_context *ev, struct loadparm_context *lp_ctx) { uint8_t * iobuf; /* IO buffer. */ uint64_t iomax; /* Size of the IO buffer. */ uint64_t data_size; /* Amount of data in the IO buffer. */ uint64_t ibs; uint64_t obs; uint64_t count; struct dd_iohandle * ifile; struct dd_iohandle * ofile; struct smbcli_options options; struct smbcli_session_options session_options; ibs = check_arg_numeric("ibs"); obs = check_arg_numeric("obs"); count = check_arg_numeric("count"); lp_smbcli_options(lp_ctx, &options); lp_smbcli_session_options(lp_ctx, &session_options); /* Allocate IO buffer. We need more than the max IO size because we * could accumulate a remainder if ibs and obs don't match. */ iomax = 2 * MAX(ibs, obs); if ((iobuf = malloc_array_p(uint8_t, iomax)) == NULL) { fprintf(stderr, "%s: failed to allocate IO buffer of %llu bytes\n", PROGNAME, (unsigned long long)iomax); return(EOM_EXIT_CODE); } options.max_xmit = MAX(ibs, obs); DEBUG(4, ("IO buffer size is %llu, max xmit is %d\n", (unsigned long long)iomax, options.max_xmit)); if (!(ifile = open_file(lp_resolve_context(lp_ctx), ev, "if", lp_smb_ports(lp_ctx), &options, lp_socket_options(lp_ctx), &session_options, lp_iconv_convenience(lp_ctx), lp_gensec_settings(lp_ctx, lp_ctx)))) { return(FILESYS_EXIT_CODE); } if (!(ofile = open_file(lp_resolve_context(lp_ctx), ev, "of", lp_smb_ports(lp_ctx), &options, lp_socket_options(lp_ctx), &session_options, lp_iconv_convenience(lp_ctx), lp_gensec_settings(lp_ctx, lp_ctx)))) { return(FILESYS_EXIT_CODE); } /* Seek the files to their respective starting points. */ ifile->io_seek(ifile, check_arg_numeric("skip") * ibs); ofile->io_seek(ofile, check_arg_numeric("seek") * obs); DEBUG(4, ("max xmit was negotiated to be %d\n", options.max_xmit)); for (data_size = 0;;) { /* Handle signals. We are somewhat compatible with GNU dd. * SIGINT makes us stop, but still print transfer statistics. * SIGUSR1 makes us print transfer statistics but we continue * copying. */ if (dd_sigint) { break; } if (dd_sigusr1) { print_transfer_stats(); dd_sigusr1 = 0; } if (ifile->io_flags & DD_END_OF_FILE) { DEBUG(4, ("flushing %llu bytes at EOF\n", (unsigned long long)data_size)); while (data_size > 0) { if (!dd_flush_block(ofile, iobuf, &data_size, obs)) { return(IOERROR_EXIT_CODE); } } goto done; } /* Try and read enough blocks of ibs bytes to be able write * out one of obs bytes. */ if (!dd_fill_block(ifile, iobuf, &data_size, obs, ibs)) { return(IOERROR_EXIT_CODE); } if (data_size == 0) { /* Done. */ SMB_ASSERT(ifile->io_flags & DD_END_OF_FILE); } /* Stop reading when we hit the block count. */ if (dd_stats.in.bytes >= (ibs * count)) { ifile->io_flags |= DD_END_OF_FILE; } /* If we wanted to be a legitimate dd, we would do character * conversions and other shenanigans here. */ /* Flush what we read in units of obs bytes. We want to have * at least obs bytes in the IO buffer but might not if the * file is too small. */ if (data_size && !dd_flush_block(ofile, iobuf, &data_size, obs)) { return(IOERROR_EXIT_CODE); } } done: print_transfer_stats(); return(0); }
static int fork_tcon_client(struct torture_context *tctx, int *tcon_count, unsigned tcon_timelimit, const char *host, const char *share) { pid_t child; struct smbcli_state *cli; struct timeval end; struct timeval now; 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); child = fork(); if (child == -1) { printf("failed to fork child: %s\n,", strerror(errno)); return -1; } else if (child != 0) { /* Parent, just return. */ return 0; } /* Child. Just make as many connections as possible within the * time limit. Don't bother synchronising the child start times * because it's probably not work the effort, and a bit of startup * jitter is probably a more realistic test. */ end = timeval_current(); now = timeval_current(); end.tv_sec += tcon_timelimit; *tcon_count = 0; while (timeval_compare(&now, &end) == -1) { NTSTATUS status; status = smbcli_full_connection(NULL, &cli, host, lp_smb_ports(tctx->lp_ctx), share, NULL, lp_socket_options(tctx->lp_ctx), cmdline_credentials, lp_resolve_context(tctx->lp_ctx), tctx->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 connect to //%s/%s: %s\n", host, share, nt_errstr(status)); goto done; } smbcli_tdis(cli); talloc_free(cli); *tcon_count = *tcon_count + 1; now = timeval_current(); } done: exit(0); }
NTSTATUS svc_uninstall(const char *hostname, struct cli_credentials * credentials) { NTSTATUS status; struct dcerpc_pipe *svc_pipe; struct policy_handle scm_handle; struct policy_handle svc_handle; struct SERVICE_STATUS svc_status; struct smbcli_options options; struct smbcli_session_options session_options; lp_smbcli_options(cmdline_lp_ctx, &options); lp_smbcli_session_options(cmdline_lp_ctx, &session_options); status = svc_pipe_connect(&svc_pipe, hostname, credentials); NT_ERR(status, 1, "Cannot connect to svcctl pipe"); status = svc_OpenSCManager(svc_pipe, hostname, &scm_handle); NT_ERR(status, 1, "OpenSCManager failed"); status = svc_OpenService(svc_pipe, &scm_handle, "winexesvc", &svc_handle); NT_ERR(status, 1, "OpenService failed"); DEBUG(1, ("OpenService - %s\n", nt_errstr(status))); if (NT_STATUS_IS_OK(status)) { status = svc_ControlService(svc_pipe, &svc_handle, SERVICE_CONTROL_STOP, &svc_status); { struct SERVICE_STATUS s; do { msleep(100); status = svc_QueryServiceStatus(svc_pipe, &svc_handle, &s); NT_ERR(status, 1, "QueryServiceStatus failed"); } while (s.state == SVCCTL_STOP_PENDING); if (s.state != SVCCTL_STOPPED) { DEBUG(0, ("Service cannot stop, status=0x%08X\n", s.state)); return NT_STATUS_UNSUCCESSFUL; } } DEBUG(1, ("StopService - %s\n", nt_errstr(status))); status = svc_DeleteService(svc_pipe, &svc_handle); DEBUG(1, ("DeleteService - %s\n", nt_errstr(status))); status = svc_CloseServiceHandle(svc_pipe, &svc_handle); DEBUG(1, ("CloseServiceHandle - %s\n", nt_errstr(status))); } svc_CloseServiceHandle(svc_pipe, &scm_handle); DEBUG(1, ("CloseSCMHandle - %s\n", nt_errstr(status))); struct smbcli_state *cli; status = smbcli_full_connection(NULL, &cli, hostname, lp_smb_ports(cmdline_lp_ctx), "ADMIN$", NULL, lp_socket_options(cmdline_lp_ctx), credentials, lp_resolve_context(cmdline_lp_ctx), ev_ctx, &options, &session_options, lp_iconv_convenience(cmdline_lp_ctx), lp_gensec_settings(NULL, cmdline_lp_ctx)); NT_ERR(status, 1, "Failed to open ADMIN$ share"); /* Give winexesvc some time to exit */ msleep(300); status = smbcli_unlink(cli->tree, "winexesvc.exe"); DEBUG(1, ("Delete winexesvc.exe - %s\n", nt_errstr(status))); status = smbcli_tdis(cli); DEBUG(1, ("Closing ADMIN$ - %s\n", nt_errstr(status))); return status; }
/* test a simple savefile/loadfile combination */ static bool test_fetchfile(struct smbcli_state *cli, struct torture_context *tctx) { const char *fname = BASEDIR "\\test.txt"; NTSTATUS status; struct smb_composite_savefile io1; struct smb_composite_fetchfile io2; struct composite_context **c; uint8_t *data; int i; size_t len = random() % 10000; extern int torture_numops; struct tevent_context *event_ctx; int *count = talloc_zero(tctx, int); bool ret = true; data = talloc_array(tctx, uint8_t, len); generate_random_buffer(data, len); io1.in.fname = fname; io1.in.data = data; io1.in.size = len; printf("testing savefile\n"); status = smb_composite_savefile(cli->tree, &io1); if (!NT_STATUS_IS_OK(status)) { printf("(%s) savefile failed: %s\n",__location__, nt_errstr(status)); return false; } io2.in.dest_host = torture_setting_string(tctx, "host", NULL); io2.in.ports = lp_smb_ports(tctx->lp_ctx); io2.in.called_name = torture_setting_string(tctx, "host", NULL); io2.in.service = torture_setting_string(tctx, "share", NULL); io2.in.service_type = "A:"; io2.in.credentials = cmdline_credentials; io2.in.workgroup = lp_workgroup(tctx->lp_ctx); io2.in.filename = fname; io2.in.resolve_ctx = lp_resolve_context(tctx->lp_ctx); io2.in.iconv_convenience = lp_iconv_convenience(tctx->lp_ctx); io2.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx); lp_smbcli_options(tctx->lp_ctx, &io2.in.options); lp_smbcli_session_options(tctx->lp_ctx, &io2.in.session_options); printf("testing parallel fetchfile with %d ops\n", torture_numops); event_ctx = cli->transport->socket->event.ctx; c = talloc_array(tctx, struct composite_context *, torture_numops); for (i=0; i<torture_numops; i++) { c[i] = smb_composite_fetchfile_send(&io2, event_ctx); c[i]->async.fn = loadfile_complete; c[i]->async.private_data = count; } printf("waiting for completion\n"); while (*count != torture_numops) { event_loop_once(event_ctx); if (torture_setting_bool(tctx, "progress", true)) { printf("(%s) count=%d\r", __location__, *count); fflush(stdout); } } printf("count=%d\n", *count); for (i=0;i<torture_numops;i++) { status = smb_composite_fetchfile_recv(c[i], tctx); if (!NT_STATUS_IS_OK(status)) { printf("(%s) loadfile[%d] failed - %s\n", __location__, i, nt_errstr(status)); ret = false; continue; } if (io2.out.size != len) { printf("(%s) wrong length in returned data - %d " "should be %d\n", __location__, io2.out.size, (int)len); ret = false; continue; } if (memcmp(io2.out.data, data, len) != 0) { printf("(%s) wrong data in loadfile!\n", __location__); ret = false; continue; } } return ret; }