1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00
samba-mirror/source3/utils/smbtree.c
Ralph Boehme 5562674a21 smbtree: don't ignore unknown options
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14828

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
2021-09-10 15:10:30 +00:00

295 lines
6.8 KiB
C

/*
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;
}