The branch, master has been updated via ffa1c04 examples: Add winexe re-implemented on current Samba libs via 082f60a libsmb: Expose protocol-agnostic cli_writeall_send/recv via fd20372 libsmb: Rename cli_writeall_send/recv to cli_smb1_writeall_send/recv via a5c4d91 libsmb: Add protocol-agnostic cli_read from 4d72ebb s3: VFS: vfs_full_audit: Ensure smb_fname_str_do_log() only returns absolute pathnames.
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit ffa1c040c625336209a6310e234f5087dd62e984 Author: Volker Lendecke <v...@samba.org> Date: Tue Apr 10 17:18:18 2018 +0200 examples: Add winexe re-implemented on current Samba libs winexe from https://sourceforge.net/projects/winexe/ is a project based on Samba libraries from 2012. According to the winexe git repository the last Samba commit winexe was updated to is 47bbf9886f0c from November 6, 2012. As winexe uses unpublished Samba internal libraries, it broke over time. This is a port of the winexe functionality to more modern Samba versions. It still uses internal APIs, but it being part of the tree means that it is much easier to keep up to date. The Windows service files were taken literally from the original winexe from the sourceforge git. Andrzej Hajda chose GPLv3 only and not GPLv3+. As GPL evolves very slowly, this should not be a practical problem for quite some time. To build it under Linux, you need mingw binaries on your build system. Under Debian stretch, the package names are gcc-mingw-w64 and friends. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Tue Aug 28 02:03:07 CEST 2018 on sn-devel-144 commit 082f60af26f1822c815e70c189aa42d54228e414 Author: Volker Lendecke <v...@samba.org> Date: Wed Apr 4 16:32:01 2018 +0200 libsmb: Expose protocol-agnostic cli_writeall_send/recv Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit fd203725cab0b5b604a4ae8adccc084dfcad9639 Author: Volker Lendecke <v...@samba.org> Date: Wed Apr 4 16:19:52 2018 +0200 libsmb: Rename cli_writeall_send/recv to cli_smb1_writeall_send/recv Preparing a protocol agnostic writeall Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit a5c4d91ebf6527001a2cc8a316db931768ec8249 Author: Volker Lendecke <v...@samba.org> Date: Wed Apr 4 16:18:28 2018 +0200 libsmb: Add protocol-agnostic cli_read So far only cli_pull could be called directly without looking at the protocol. We did not have a simple read that did the right thing depending on the protocol Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: examples/winexe/README | 18 + examples/winexe/winexe.c | 1867 +++++++++++++++++++++++++++++++++++++++++ examples/winexe/winexesvc.c | 745 ++++++++++++++++ examples/winexe/winexesvc.h | 42 + examples/winexe/wscript | 29 + examples/winexe/wscript_build | 87 ++ source3/libsmb/clireadwrite.c | 265 +++++- source3/libsmb/proto.h | 19 + source3/wscript_build | 1 + wscript | 1 + 10 files changed, 3044 insertions(+), 30 deletions(-) create mode 100644 examples/winexe/README create mode 100644 examples/winexe/winexe.c create mode 100644 examples/winexe/winexesvc.c create mode 100644 examples/winexe/winexesvc.h create mode 100644 examples/winexe/wscript create mode 100644 examples/winexe/wscript_build Changeset truncated at 500 lines: diff --git a/examples/winexe/README b/examples/winexe/README new file mode 100644 index 0000000..c688e5d --- /dev/null +++ b/examples/winexe/README @@ -0,0 +1,18 @@ +winexe from https://sourceforge.net/projects/winexe/ is a project +based on Samba libraries from 2012. According to the winexe git +repository the last Samba commit winexe was updated to is 47bbf9886f0c +from November 6, 2012. As winexe uses unpublished Samba internal +libraries, it broke over time. + +This is a port of the winexe functionality to more modern Samba +versions. It still uses internal APIs, but it being part of the tree +means that it is much easier to keep up to date. + +The Windows service files were taken literally from the original +winexe from the sourceforge git. Andrzej Hajda chose GPLv3 only and +not GPLv3+. As GPL evolves very slowly, this should not be a practical +problem for quite some time. + +To build it under Linux, you need mingw binaries on your build +system. Under Debian stretch, the package names are gcc-mingw-w64 and +friends. diff --git a/examples/winexe/winexe.c b/examples/winexe/winexe.c new file mode 100644 index 0000000..cf667a6 --- /dev/null +++ b/examples/winexe/winexe.c @@ -0,0 +1,1867 @@ +/* + * Samba Unix/Linux CIFS implementation + * + * winexe + * + * Copyright (C) 2018 Volker Lendecke <v...@samba.org> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include <tevent.h> +#include <popt.h> +#include "version.h" +#include "lib/param/param.h" +#include "auth/credentials/credentials.h" +#include "lib/util/talloc_stack.h" +#include "lib/util/tevent_ntstatus.h" +#include "lib/util/sys_rw.h" +#include "libsmb/proto.h" +#include "librpc/gen_ndr/ndr_svcctl_c.h" +#include "rpc_client/cli_pipe.h" +#include "libcli/smb/smbXcli_base.h" +#include "libcli/util/werror.h" +#include "lib/async_req/async_sock.h" +#include "client.h" + +#define SVC_INTERACTIVE 1 +#define SVC_IGNORE_INTERACTIVE 2 +#define SVC_INTERACTIVE_MASK 3 +#define SVC_FORCE_UPLOAD 4 +#define SVC_OS64BIT 8 +#define SVC_OSCHOOSE 16 +#define SVC_UNINSTALL 32 +#define SVC_SYSTEM 64 + +#define SERVICE_NAME "winexesvc" + +#define PIPE_NAME "ahexec" +#define PIPE_NAME_IN "ahexec_stdin%08X" +#define PIPE_NAME_OUT "ahexec_stdout%08X" +#define PIPE_NAME_ERR "ahexec_stderr%08X" + +static const char version_message_fmt[] = "winexe version %d.%d\n" + "This program may be freely redistributed under the terms of the " + "GNU GPLv3\n"; + +struct program_options { + char *hostname; + char *cmd; + struct cli_credentials *credentials; + char *runas; + char *runas_file; + int flags; +}; + +static void parse_args(int argc, const char *argv[], + TALLOC_CTX *mem_ctx, + struct program_options *options, + struct loadparm_context *lp_ctx) +{ + poptContext pc; + int opt, i; + struct cli_credentials *cred; + + int argc_new; + char **argv_new; + + int flag_interactive = SVC_IGNORE_INTERACTIVE; + int flag_ostype = 2; + int flag_reinstall = 0; + int flag_uninstall = 0; + int flag_help = 0; + int flag_version = 0; + int flag_nopass = 0; + char *opt_user = NULL; + char *opt_kerberos = NULL; + char *opt_auth_file = NULL; + char *opt_debuglevel = NULL; + + struct poptOption long_options[] = { + { "help", 'h', POPT_ARG_NONE, &flag_help, 0, + "Display help message" }, + { "version", 'V', POPT_ARG_NONE, &flag_version, 0, + "Display version number" }, + { "user", 'U', POPT_ARG_STRING, &opt_user, 0, + "Set the network username", "[DOMAIN/]USERNAME[%PASSWORD]" }, + { "authentication-file", 'A', + POPT_ARG_STRING, &opt_auth_file, 0, + "Get the credentials from a file", "FILE" }, + { "no-pass", 'N', POPT_ARG_NONE, &flag_nopass, 0, + "Do not ask for a password", NULL }, + { "kerberos", 'k', POPT_ARG_STRING, &opt_kerberos, 0, + "Use Kerberos, -k [yes|no]" }, + { "debuglevel", 'd', POPT_ARG_STRING, &opt_debuglevel, 0, + "Set debug level", "DEBUGLEVEL" }, + { "uninstall", 0, POPT_ARG_NONE, &flag_uninstall, 0, + "Uninstall winexe service after remote execution", NULL}, + { "reinstall", 0, POPT_ARG_NONE, &flag_reinstall, 0, + "Reinstall winexe service before remote execution", NULL}, + { "runas", 0, POPT_ARG_STRING, &options->runas, 0, + "Run as the given user (BEWARE: this password is sent " + "in cleartext over the network!)", + "[DOMAIN\\]USERNAME%PASSWORD"}, + { "runas-file", 0, POPT_ARG_STRING, &options->runas_file, 0, + "Run as user options defined in a file", "FILE"}, + { "interactive", 0, POPT_ARG_INT, &flag_interactive, 0, + "Desktop interaction: 0 - disallow, 1 - allow. If allow, " + "also use the --system switch (Windows requirement). Vista " + "does not support this option.", "0|1"}, + { "ostype", 0, POPT_ARG_INT, &flag_ostype, 0, + "OS type: 0 - 32-bit, 1 - 64-bit, 2 - winexe will decide. " + "Determines which version (32-bit or 64-bit) of service " + "will be installed.", "0|1|2"}, + POPT_TABLEEND + }; + + ZERO_STRUCTP(options); + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options, + 0); + + poptSetOtherOptionHelp(pc, "[OPTION]... //HOST COMMAND\nOptions:"); + + if (((opt = poptGetNextOpt(pc)) != -1) || flag_help || flag_version) { + fprintf(stderr, version_message_fmt, SAMBA_VERSION_MAJOR, + SAMBA_VERSION_MINOR); + if (flag_version) { + exit(0); + } + poptPrintHelp(pc, stdout, 0); + if (flag_help) { + exit(0); + } + exit(1); + } + + argv_new = discard_const_p(char *, poptGetArgs(pc)); + + argc_new = argc; + for (i = 0; i < argc; i++) { + if (!argv_new || argv_new[i] == NULL) { + argc_new = i; + break; + } + } + + if (argc_new != 2 || argv_new[0][0] != '/' || argv_new[0][1] != '/') { + fprintf(stderr, version_message_fmt, SAMBA_VERSION_MAJOR, + SAMBA_VERSION_MINOR); + poptPrintHelp(pc, stdout, 0); + exit(1); + } + + if (opt_debuglevel) { + lp_set_cmdline("log level", opt_debuglevel); + } + + cred = cli_credentials_init(mem_ctx); + + if (opt_user) { + cli_credentials_parse_string(cred, opt_user, CRED_SPECIFIED); + } else if (opt_auth_file) { + cli_credentials_parse_file(cred, opt_auth_file, + CRED_SPECIFIED); + } + + cli_credentials_guess(cred, lp_ctx); + if (!cli_credentials_get_password(cred) && !flag_nopass) { + char *p = getpass("Enter password: "); + if (*p) { + cli_credentials_set_password(cred, p, CRED_SPECIFIED); + } + } + + if (opt_kerberos) { + cli_credentials_set_kerberos_state(cred, + strcmp(opt_kerberos, "yes") + ? CRED_MUST_USE_KERBEROS + : CRED_DONT_USE_KERBEROS); + } + + if (options->runas == NULL && options->runas_file != NULL) { + struct cli_credentials *runas_cred; + const char *user; + const char *pass; + + runas_cred = cli_credentials_init(mem_ctx); + cli_credentials_parse_file(runas_cred, options->runas_file, + CRED_SPECIFIED); + + user = cli_credentials_get_username(runas_cred); + pass = cli_credentials_get_password(runas_cred); + + if (user && pass) { + char buffer[1024]; + const char *dom; + + dom = cli_credentials_get_domain(runas_cred); + if (dom) { + snprintf(buffer, sizeof(buffer), "%s\\%s%%%s", + dom, user, pass); + } else { + snprintf(buffer, sizeof(buffer), "%s%%%s", + user, pass); + } + buffer[sizeof(buffer)-1] = '\0'; + options->runas = talloc_strdup(mem_ctx, buffer); + } + } + + options->credentials = cred; + + options->hostname = argv_new[0] + 2; + options->cmd = argv_new[1]; + + options->flags = flag_interactive; + if (flag_reinstall) { + options->flags |= SVC_FORCE_UPLOAD; + } + if (flag_ostype == 1) { + options->flags |= SVC_OS64BIT; + } + if (flag_ostype == 2) { + options->flags |= SVC_OSCHOOSE; + } + if (flag_uninstall) { + options->flags |= SVC_UNINSTALL; + } +} + +static NTSTATUS winexe_svc_upload( + const char *hostname, + const char *service_filename, + const DATA_BLOB *svc32_exe, + const DATA_BLOB *svc64_exe, + struct cli_credentials *credentials, + int flags) +{ + struct cli_state *cli; + uint16_t fnum; + NTSTATUS status; + const DATA_BLOB *binary = NULL; + + status = cli_full_connection_creds( + &cli, + NULL, + hostname, + NULL, + 445, + "ADMIN$", + "?????", + credentials, + 0, + 0); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("cli_full_connection_creds failed: %s\n", + nt_errstr(status)); + return status; + } + + if (flags & SVC_FORCE_UPLOAD) { + status = cli_unlink(cli, service_filename, 0); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("cli_unlink failed: %s\n", + nt_errstr(status)); + } + } + + if (flags & SVC_OSCHOOSE) { + status = cli_chkpath(cli, "SysWoW64"); + if (NT_STATUS_IS_OK(status)) { + flags |= SVC_OS64BIT; + } + } + + if (flags & SVC_OS64BIT) { + binary = svc64_exe; + } else { + binary = svc32_exe; + } + + if (binary == NULL) { + //TODO + } + + status = cli_ntcreate( + cli, + service_filename, + 0, /* CreatFlags */ + SEC_FILE_WRITE_DATA, /* DesiredAccess */ + FILE_ATTRIBUTE_NORMAL, /* FileAttributes */ + FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */ + FILE_OPEN_IF, /* CreateDisposition */ + FILE_NON_DIRECTORY_FILE, /* CreateOptions */ + 0, /* SecurityFlags */ + &fnum, + NULL); /* CreateReturns */ + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("Could not create %s: %s\n", service_filename, + nt_errstr(status)); + goto done; + } + + status = cli_writeall( + cli, + fnum, + 0, + binary->data, + 0, + binary->length, + NULL); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("Could not write file: %s\n", nt_errstr(status)); + goto close_done; + } + +close_done: + status = cli_close(cli, fnum); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("Close(%"PRIu16") failed for %s: %s\n", fnum, + service_filename, nt_errstr(status)); + } +done: + TALLOC_FREE(cli); + return status; +} + +static NTSTATUS winexe_svc_install( + struct cli_state *cli, + const char *hostname, + const char *service_name, + const char *service_filename, + const DATA_BLOB *svc32_exe, + const DATA_BLOB *svc64_exe, + struct cli_credentials *credentials, + int flags) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct rpc_pipe_client *rpccli; + struct policy_handle scmanager_handle; + struct policy_handle service_handle; + struct SERVICE_STATUS service_status; + bool need_start = false; + bool need_conf = false; + NTSTATUS status; + WERROR werr; + + status = cli_rpc_pipe_open_noauth_transport( + cli, + NCACN_NP, + &ndr_table_svcctl, + &rpccli); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("cli_rpc_pipe_open_noauth_transport failed: %s\n", + nt_errstr(status)); + goto done; + } + + status = dcerpc_svcctl_OpenSCManagerW( + rpccli->binding_handle, + frame, + smbXcli_conn_remote_name(cli->conn), + NULL, + SEC_FLAG_MAXIMUM_ALLOWED, + &scmanager_handle, + &werr); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("dcerpc_svcctl_OpenSCManagerW failed: %s\n", + nt_errstr(status)); + goto done; + } + if (!W_ERROR_IS_OK(werr)) { + DBG_WARNING("dcerpc_svcctl_OpenSCManagerW failed: %s\n", + win_errstr(werr)); + goto done; + } + + status = dcerpc_svcctl_OpenServiceW( + rpccli->binding_handle, + frame, + &scmanager_handle, + service_name, + SERVICE_ALL_ACCESS, + &service_handle, + &werr); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("dcerpc_svcctl_OpenServiceW failed: %s\n", + nt_errstr(status)); + goto close_scmanager; + } + + if (W_ERROR_EQUAL(werr, WERR_SERVICE_DOES_NOT_EXIST)) { + status = dcerpc_svcctl_CreateServiceW( + rpccli->binding_handle, + frame, + &scmanager_handle, + service_name, + NULL, + SERVICE_ALL_ACCESS, + SERVICE_TYPE_WIN32_OWN_PROCESS | + ((flags & SVC_INTERACTIVE) ? + SERVICE_TYPE_INTERACTIVE_PROCESS : 0), + SVCCTL_DEMAND_START, + SVCCTL_SVC_ERROR_NORMAL, + service_filename, + NULL, + NULL, + NULL, + 0, + NULL, + NULL, + 0, + &service_handle, + &werr); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("dcerpc_svcctl_CreateServiceW " + "failed: %s\n", nt_errstr(status)); + goto close_scmanager; + } + if (!W_ERROR_IS_OK(werr)) { + DBG_WARNING("dcerpc_svcctl_CreateServiceW " + "failed: %s\n", win_errstr(werr)); + status = werror_to_ntstatus(werr); + goto close_scmanager; + } + } + + status = dcerpc_svcctl_QueryServiceStatus( + rpccli->binding_handle, + frame, + &service_handle, + &service_status, + &werr); + + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("dcerpc_svcctl_QueryServiceStatus " + "failed: %s\n", nt_errstr(status)); + goto close_service; + } + if (!W_ERROR_IS_OK(werr)) { + DBG_WARNING("dcerpc_svcctl_QueryServiceStatus " + "failed: %s\n", win_errstr(werr)); + status = werror_to_ntstatus(werr); + goto close_service; + } + + if (!(flags & SVC_IGNORE_INTERACTIVE)) { + need_conf = + !(service_status.type & + SERVICE_TYPE_INTERACTIVE_PROCESS) ^ + !(flags & SVC_INTERACTIVE); + } + + if (service_status.state == SVCCTL_STOPPED) { + need_start = true; + } else if (need_conf) { + status = dcerpc_svcctl_ControlService( + rpccli->binding_handle, -- Samba Shared Repository