s3:util:net_registry: registry_value_cmp() uses NUMERIC_CMP()
[samba.git] / source3 / utils / smbtree.c
1 /*
2    Unix SMB/CIFS implementation.
3    Network neighbourhood browser.
4
5    Copyright (C) Tim Potter      2000
6    Copyright (C) Jelmer Vernooij 2003
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/cmdline/cmdline.h"
24 #include "rpc_client/cli_pipe.h"
25 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
26 #include "libsmb/libsmb.h"
27 #include "libsmb/namequery.h"
28 #include "libsmb/clirap.h"
29 #include "../libcli/smb/smbXcli_base.h"
30 #include "nameserv.h"
31 #include "libsmbclient.h"
32
33 /* How low can we go? */
34
35 enum tree_level {LEV_WORKGROUP, LEV_SERVER, LEV_SHARE};
36 static enum tree_level level = LEV_SHARE;
37
38 static void get_auth_data_with_context_fn(
39         SMBCCTX *context,
40         const char *server,
41         const char *share,
42         char *domain,
43         int domain_len,
44         char *user,
45         int user_len,
46         char *password,
47         int password_len)
48 {
49         struct cli_credentials *creds = samba_cmdline_get_creds();
50         size_t len;
51
52         len = strlcpy(domain, cli_credentials_get_domain(creds), domain_len);
53         if ((int)len >= domain_len) {
54                 return;
55         }
56         len = strlcpy(
57                 user, cli_credentials_get_username(creds), user_len);
58         if ((int)len >= user_len) {
59                 return;
60         }
61         len = strlcpy(
62                 password, cli_credentials_get_password(creds), password_len);
63         if ((int)len >= password_len) {
64                 /* pointless, but what can you do... */
65                 return;
66         }
67 }
68
69 /****************************************************************************
70   main program
71 ****************************************************************************/
72 int main(int argc, char *argv[])
73 {
74         TALLOC_CTX *frame = talloc_stackframe();
75         const char **argv_const = discard_const_p(const char *, argv);
76         struct poptOption long_options[] = {
77                 POPT_AUTOHELP
78                 {
79                         .longName   = "domains",
80                         .shortName  = 'D',
81                         .argInfo    = POPT_ARG_VAL,
82                         .arg        = &level,
83                         .val        = LEV_WORKGROUP,
84                         .descrip    = "List only domains (workgroups) of tree" ,
85                 },
86                 {
87                         .longName   = "servers",
88                         .shortName  = 'S',
89                         .argInfo    = POPT_ARG_VAL,
90                         .arg        = &level,
91                         .val        = LEV_SERVER,
92                         .descrip    = "List domains(workgroups) and servers of tree" ,
93                 },
94                 POPT_COMMON_SAMBA
95                 POPT_COMMON_CREDENTIALS
96                 POPT_COMMON_VERSION
97                 POPT_TABLEEND
98         };
99         poptContext pc;
100         SMBCCTX *ctx = NULL;
101         SMBCFILE *workgroups = NULL;
102         struct smbc_dirent *dirent = NULL;
103         bool ok;
104         int ret, result = 1;
105         int opt;
106         int debuglevel;
107
108         /* Initialise samba stuff */
109         smb_init_locale();
110
111         setlinebuf(stdout);
112
113         ok = samba_cmdline_init(frame,
114                                 SAMBA_CMDLINE_CONFIG_CLIENT,
115                                 false /* require_smbconf */);
116         if (!ok) {
117                 DBG_ERR("Failed to init cmdline parser!\n");
118                 TALLOC_FREE(frame);
119                 exit(1);
120         }
121
122         pc = samba_popt_get_context(getprogname(),
123                                     argc,
124                                     argv_const,
125                                     long_options,
126                                     POPT_CONTEXT_KEEP_FIRST);
127         if (pc == NULL) {
128                 DBG_ERR("Failed to setup popt context!\n");
129                 TALLOC_FREE(frame);
130                 exit(1);
131         }
132
133         while((opt = poptGetNextOpt(pc)) != -1) {
134                 switch (opt) {
135                 case POPT_ERROR_BADOPT:
136                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
137                                 poptBadOption(pc, 0), poptStrerror(opt));
138                         poptPrintUsage(pc, stderr, 0);
139                         exit(1);
140                 }
141         }
142
143         samba_cmdline_burn(argc, argv);
144
145         debuglevel = DEBUGLEVEL;
146
147         ctx = smbc_new_context();
148         if (ctx == NULL) {
149                 perror("smbc_new_context");
150                 goto fail;
151         }
152         ret = smbc_setConfiguration(ctx, get_dyn_CONFIGFILE());
153         if (ret == -1) {
154                 perror("smbc_setConfiguration");
155                 goto fail;
156         }
157         smbc_setDebug(ctx, debuglevel);
158         ok = smbc_setOptionProtocols(ctx, NULL, "NT1");
159         if (!ok) {
160                 perror("smbc_setOptionProtocols");
161                 goto fail;
162         }
163         smbc_setFunctionAuthDataWithContext(
164                 ctx, get_auth_data_with_context_fn);
165
166         ok = smbc_init_context(ctx);
167         if (!ok) {
168                 perror("smbc_init_context");
169                 goto fail;
170         }
171
172         workgroups = smbc_getFunctionOpendir(ctx)(ctx, "smb://");
173         if (workgroups == NULL) {
174                 DBG_ERR("This is utility doesn't work if netbios name "
175                         "resolution is not configured.\n"
176                         "If you are using SMB2 or SMB3, network browsing uses "
177                         "WSD/LLMNR, which is not yet supported by Samba. SMB1 "
178                         "is disabled by default on the latest Windows versions "
179                         "for security reasons. It is still possible to access "
180                         "the Samba resources directly via \\name or "
181                         "\\ip.address.\n");
182                 goto fail;
183         }
184
185         while ((dirent = smbc_getFunctionReaddir(ctx)(ctx, workgroups))
186                != NULL) {
187                 char *url = NULL;
188                 SMBCFILE *servers = NULL;
189
190                 if (dirent->smbc_type != SMBC_WORKGROUP) {
191                         continue;
192                 }
193
194                 printf("%s\n", dirent->name);
195
196                 if (level == LEV_WORKGROUP) {
197                         continue;
198                 }
199
200                 url = talloc_asprintf(
201                         talloc_tos(), "smb://%s/", dirent->name);
202                 if (url == NULL) {
203                         perror("talloc_asprintf");
204                         goto fail;
205                 }
206
207                 servers = smbc_getFunctionOpendir(ctx)(ctx, url);
208                 if (servers == NULL) {
209                         perror("smbc_opendir");
210                         goto fail;
211                 }
212                 TALLOC_FREE(url);
213
214                 while ((dirent = smbc_getFunctionReaddir(ctx)(ctx, servers))
215                        != NULL) {
216                         SMBCFILE *shares = NULL;
217                         char *servername = NULL;
218
219                         if (dirent->smbc_type != SMBC_SERVER) {
220                                 continue;
221                         }
222
223                         printf("\t\\\\%-15s\t\t%s\n",
224                                dirent->name,
225                                dirent->comment);
226
227                         if (level == LEV_SERVER) {
228                                 continue;
229                         }
230
231                         /*
232                          * The subsequent readdir for shares will
233                          * overwrite the "server" readdir
234                          */
235                         servername = talloc_strdup(talloc_tos(), dirent->name);
236                         if (servername == NULL) {
237                                 continue;
238                         }
239
240                         url = talloc_asprintf(
241                                 talloc_tos(), "smb://%s/", servername);
242                         if (url == NULL) {
243                                 perror("talloc_asprintf");
244                                 goto fail;
245                         }
246
247                         shares = smbc_getFunctionOpendir(ctx)(ctx, url);
248                         if (shares == NULL) {
249                                 perror("smbc_opendir");
250                                 goto fail;
251                         }
252
253                         while ((dirent = smbc_getFunctionReaddir(
254                                         ctx)(ctx, shares))
255                                != NULL) {
256                                 printf("\t\t\\\\%s\\%-15s\t%s\n",
257                                        servername,
258                                        dirent->name,
259                                        dirent->comment);
260                         }
261
262                         ret = smbc_getFunctionClosedir(ctx)(ctx, shares);
263                         if (ret == -1) {
264                                 perror("smbc_closedir");
265                                 goto fail;
266                         }
267
268                         TALLOC_FREE(servername);
269                         TALLOC_FREE(url);
270                 }
271
272                 ret = smbc_getFunctionClosedir(ctx)(ctx, servers);
273                 if (ret == -1) {
274                         perror("smbc_closedir");
275                         goto fail;
276                 }
277         }
278
279         ret = smbc_getFunctionClosedir(ctx)(ctx, workgroups);
280         if (ret == -1) {
281                 perror("smbc_closedir");
282                 goto fail;
283         }
284
285         result = 0;
286 fail:
287         if (ctx != NULL) {
288                 smbc_free_context(ctx, 0);
289                 ctx = NULL;
290         }
291         gfree_all();
292         poptFreeContext(pc);
293         TALLOC_FREE(frame);
294         return result;
295 }