diff options
Diffstat (limited to 'source3/utils/smbtree.c')
-rw-r--r-- | source3/utils/smbtree.c | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/source3/utils/smbtree.c b/source3/utils/smbtree.c new file mode 100644 index 0000000..4719640 --- /dev/null +++ b/source3/utils/smbtree.c @@ -0,0 +1,294 @@ +/* + Unix SMB/CIFS implementation. + Network neighbourhood browser. + + Copyright (C) Tim Potter 2000 + Copyright (C) Jelmer Vernooij 2003 + + 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 "lib/cmdline/cmdline.h" +#include "rpc_client/cli_pipe.h" +#include "../librpc/gen_ndr/ndr_srvsvc_c.h" +#include "libsmb/libsmb.h" +#include "libsmb/namequery.h" +#include "libsmb/clirap.h" +#include "../libcli/smb/smbXcli_base.h" +#include "nameserv.h" +#include "libsmbclient.h" + +/* How low can we go? */ + +enum tree_level {LEV_WORKGROUP, LEV_SERVER, LEV_SHARE}; +static enum tree_level level = LEV_SHARE; + +static void get_auth_data_with_context_fn( + SMBCCTX *context, + const char *server, + const char *share, + char *domain, + int domain_len, + char *user, + int user_len, + char *password, + int password_len) +{ + struct cli_credentials *creds = samba_cmdline_get_creds(); + size_t len; + + len = strlcpy(domain, cli_credentials_get_domain(creds), domain_len); + if ((int)len >= domain_len) { + return; + } + len = strlcpy( + user, cli_credentials_get_username(creds), user_len); + if ((int)len >= user_len) { + return; + } + len = strlcpy( + password, cli_credentials_get_password(creds), password_len); + if ((int)len >= password_len) { + /* pointless, but what can you do... */ + return; + } +} + +/**************************************************************************** + main program +****************************************************************************/ +int main(int argc, char *argv[]) +{ + TALLOC_CTX *frame = talloc_stackframe(); + const char **argv_const = discard_const_p(const char *, argv); + struct poptOption long_options[] = { + POPT_AUTOHELP + { + .longName = "domains", + .shortName = 'D', + .argInfo = POPT_ARG_VAL, + .arg = &level, + .val = LEV_WORKGROUP, + .descrip = "List only domains (workgroups) of tree" , + }, + { + .longName = "servers", + .shortName = 'S', + .argInfo = POPT_ARG_VAL, + .arg = &level, + .val = LEV_SERVER, + .descrip = "List domains(workgroups) and servers of tree" , + }, + POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS + POPT_COMMON_VERSION + POPT_TABLEEND + }; + poptContext pc; + SMBCCTX *ctx = NULL; + SMBCFILE *workgroups = NULL; + struct smbc_dirent *dirent = NULL; + bool ok; + int ret, result = 1; + int opt; + int debuglevel; + + /* Initialise samba stuff */ + smb_init_locale(); + + setlinebuf(stdout); + + ok = samba_cmdline_init(frame, + SAMBA_CMDLINE_CONFIG_CLIENT, + false /* require_smbconf */); + if (!ok) { + DBG_ERR("Failed to init cmdline parser!\n"); + TALLOC_FREE(frame); + exit(1); + } + + pc = samba_popt_get_context(getprogname(), + argc, + argv_const, + long_options, + POPT_CONTEXT_KEEP_FIRST); + if (pc == NULL) { + DBG_ERR("Failed to setup popt context!\n"); + TALLOC_FREE(frame); + exit(1); + } + + while((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case POPT_ERROR_BADOPT: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + exit(1); + } + } + + samba_cmdline_burn(argc, argv); + + debuglevel = DEBUGLEVEL; + + ctx = smbc_new_context(); + if (ctx == NULL) { + perror("smbc_new_context"); + goto fail; + } + ret = smbc_setConfiguration(ctx, get_dyn_CONFIGFILE()); + if (ret == -1) { + perror("smbc_setConfiguration"); + goto fail; + } + smbc_setDebug(ctx, debuglevel); + ok = smbc_setOptionProtocols(ctx, NULL, "NT1"); + if (!ok) { + perror("smbc_setOptionProtocols"); + goto fail; + } + smbc_setFunctionAuthDataWithContext( + ctx, get_auth_data_with_context_fn); + + ok = smbc_init_context(ctx); + if (!ok) { + perror("smbc_init_context"); + goto fail; + } + + workgroups = smbc_getFunctionOpendir(ctx)(ctx, "smb://"); + if (workgroups == NULL) { + DBG_ERR("This is utility doesn't work if netbios name " + "resolution is not configured.\n" + "If you are using SMB2 or SMB3, network browsing uses " + "WSD/LLMNR, which is not yet supported by Samba. SMB1 " + "is disabled by default on the latest Windows versions " + "for security reasons. It is still possible to access " + "the Samba resources directly via \\name or " + "\\ip.address.\n"); + goto fail; + } + + while ((dirent = smbc_getFunctionReaddir(ctx)(ctx, workgroups)) + != NULL) { + char *url = NULL; + SMBCFILE *servers = NULL; + + if (dirent->smbc_type != SMBC_WORKGROUP) { + continue; + } + + printf("%s\n", dirent->name); + + if (level == LEV_WORKGROUP) { + continue; + } + + url = talloc_asprintf( + talloc_tos(), "smb://%s/", dirent->name); + if (url == NULL) { + perror("talloc_asprintf"); + goto fail; + } + + servers = smbc_getFunctionOpendir(ctx)(ctx, url); + if (servers == NULL) { + perror("smbc_opendir"); + goto fail; + } + TALLOC_FREE(url); + + while ((dirent = smbc_getFunctionReaddir(ctx)(ctx, servers)) + != NULL) { + SMBCFILE *shares = NULL; + char *servername = NULL; + + if (dirent->smbc_type != SMBC_SERVER) { + continue; + } + + printf("\t\\\\%-15s\t\t%s\n", + dirent->name, + dirent->comment); + + if (level == LEV_SERVER) { + continue; + } + + /* + * The subsequent readdir for shares will + * overwrite the "server" readdir + */ + servername = talloc_strdup(talloc_tos(), dirent->name); + if (servername == NULL) { + continue; + } + + url = talloc_asprintf( + talloc_tos(), "smb://%s/", servername); + if (url == NULL) { + perror("talloc_asprintf"); + goto fail; + } + + shares = smbc_getFunctionOpendir(ctx)(ctx, url); + if (shares == NULL) { + perror("smbc_opendir"); + goto fail; + } + + while ((dirent = smbc_getFunctionReaddir( + ctx)(ctx, shares)) + != NULL) { + printf("\t\t\\\\%s\\%-15s\t%s\n", + servername, + dirent->name, + dirent->comment); + } + + ret = smbc_getFunctionClosedir(ctx)(ctx, shares); + if (ret == -1) { + perror("smbc_closedir"); + goto fail; + } + + TALLOC_FREE(servername); + TALLOC_FREE(url); + } + + ret = smbc_getFunctionClosedir(ctx)(ctx, servers); + if (ret == -1) { + perror("smbc_closedir"); + goto fail; + } + } + + ret = smbc_getFunctionClosedir(ctx)(ctx, workgroups); + if (ret == -1) { + perror("smbc_closedir"); + goto fail; + } + + result = 0; +fail: + if (ctx != NULL) { + smbc_free_context(ctx, 0); + ctx = NULL; + } + poptFreeContext(pc); + TALLOC_FREE(frame); + return result; +} |