summaryrefslogtreecommitdiffstats
path: root/source3/utils/smbtree.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
commit8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch)
tree4099e8021376c7d8c05bdf8503093d80e9c7bad0 /source3/utils/smbtree.c
parentInitial commit. (diff)
downloadsamba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz
samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/utils/smbtree.c')
-rw-r--r--source3/utils/smbtree.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/source3/utils/smbtree.c b/source3/utils/smbtree.c
new file mode 100644
index 0000000..80dfa0a
--- /dev/null
+++ b/source3/utils/smbtree.c
@@ -0,0 +1,295 @@
+/*
+ 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;
+ }
+ gfree_all();
+ poptFreeContext(pc);
+ TALLOC_FREE(frame);
+ return result;
+}