mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
5562674a21
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>
295 lines
6.8 KiB
C
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;
|
|
}
|