9d61be2aa3cbfc468879b3da21d0ec080ce7dd2c
[obnox/samba/samba-obnox.git] / source3 / utils / net_lookup.c
1 /*
2    Samba Unix/Linux SMB client library
3    net lookup command
4    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 #include "includes.h"
20 #include "utils/net.h"
21 #include "libads/sitename_cache.h"
22 #include "../lib/addns/dnsquery.h"
23 #include "../librpc/gen_ndr/ndr_netlogon.h"
24 #include "smb_krb5.h"
25 #include "../libcli/security/security.h"
26 #include "passdb/lookup_sid.h"
27
28 int net_lookup_usage(struct net_context *c, int argc, const char **argv)
29 {
30         d_printf(_(
31 "  net lookup [host] HOSTNAME[#<type>]\n\tgives IP for a hostname\n\n"
32 "  net lookup ldap [domain]\n\tgives IP of domain's ldap server\n\n"
33 "  net lookup kdc [realm]\n\tgives IP of realm's kerberos KDC\n\n"
34 "  net lookup pdc [domain|realm]\n\tgives IP of realm's kerberos KDC\n\n"
35 "  net lookup dc [domain]\n\tgives IP of domains Domain Controllers\n\n"
36 "  net lookup master [domain|wg]\n\tgive IP of master browser\n\n"
37 "  net lookup name [name]\n\tLookup name's sid and type\n\n"
38 "  net lookup sid [sid]\n\tGive sid's name and type\n\n"
39 "  net lookup dsgetdcname [name] [flags] [sitename]\n\n"
40 ));
41         return -1;
42 }
43
44 /* lookup a hostname giving an IP */
45 static int net_lookup_host(struct net_context *c, int argc, const char **argv)
46 {
47         struct sockaddr_storage ss;
48         int name_type = 0x20;
49         char addr[INET6_ADDRSTRLEN];
50         const char *name = argv[0];
51         char *p;
52
53         if (argc == 0)
54                 return net_lookup_usage(c, argc, argv);
55
56         p = strchr_m(name,'#');
57         if (p) {
58                 *p = '\0';
59                 sscanf(++p,"%x",&name_type);
60         }
61
62         if (!resolve_name(name, &ss, name_type, false)) {
63                 /* we deliberately use DEBUG() here to send it to stderr
64                    so scripts aren't mucked up */
65                 DEBUG(0,("Didn't find %s#%02x\n", name, name_type));
66                 return -1;
67         }
68
69         print_sockaddr(addr, sizeof(addr), &ss);
70         d_printf("%s\n", addr);
71         return 0;
72 }
73
74 #ifdef HAVE_ADS
75 static void print_ldap_srvlist(struct dns_rr_srv *dclist, int numdcs )
76 {
77         struct sockaddr_storage ss;
78         int i;
79
80         for ( i=0; i<numdcs; i++ ) {
81                 if (resolve_name(dclist[i].hostname, &ss, 0x20, true) ) {
82                         char addr[INET6_ADDRSTRLEN];
83                         print_sockaddr(addr, sizeof(addr), &ss);
84 #ifdef HAVE_IPV6
85                         if (ss.ss_family == AF_INET6) {
86                                 d_printf("[%s]:%d\n", addr, dclist[i].port);
87                         }
88 #endif
89                         if (ss.ss_family == AF_INET) {
90                                 d_printf("%s:%d\n", addr, dclist[i].port);
91                         }
92                 }
93         }
94 }
95 #endif
96
97 static int net_lookup_ldap(struct net_context *c, int argc, const char **argv)
98 {
99 #ifdef HAVE_ADS
100         const char *domain;
101         struct sockaddr_storage ss;
102         struct dns_rr_srv *dcs = NULL;
103         int numdcs = 0;
104         char *sitename;
105         TALLOC_CTX *ctx;
106         NTSTATUS status;
107         int ret;
108         char h_name[MAX_DNS_NAME_LENGTH];
109         const char *dns_hosts_file;
110
111         if (argc > 0)
112                 domain = argv[0];
113         else
114                 domain = c->opt_target_workgroup;
115
116         if ( (ctx = talloc_init("net_lookup_ldap")) == NULL ) {
117                 d_fprintf(stderr,"net_lookup_ldap: talloc_init() %s!\n",
118                           _("failed"));
119                 return -1;
120         }
121
122         sitename = sitename_fetch(ctx, domain);
123
124         DEBUG(9, ("Lookup up ldap for domain %s\n", domain));
125
126         dns_hosts_file = lp_parm_const_string(-1, "resolv", "host file", NULL);
127         status = ads_dns_query_dcs(ctx, dns_hosts_file, domain, sitename,
128                                    &dcs, &numdcs);
129         if ( NT_STATUS_IS_OK(status) && numdcs ) {
130                 print_ldap_srvlist(dcs, numdcs);
131                 TALLOC_FREE( ctx );
132                 return 0;
133         }
134
135         DEBUG(9, ("Looking up PDC for domain %s\n", domain));
136         if (!get_pdc_ip(domain, &ss)) {
137                 TALLOC_FREE( ctx );
138                 return -1;
139         }
140
141         ret = sys_getnameinfo((struct sockaddr *)&ss,
142                         sizeof(struct sockaddr_storage),
143                         h_name, sizeof(h_name),
144                         NULL, 0,
145                         NI_NAMEREQD);
146
147         if (ret) {
148                 TALLOC_FREE( ctx );
149                 return -1;
150         }
151
152         DEBUG(9, ("Found PDC with DNS name %s\n", h_name));
153         domain = strchr(h_name, '.');
154         if (!domain) {
155                 TALLOC_FREE( ctx );
156                 return -1;
157         }
158         domain++;
159
160         DEBUG(9, ("Looking up ldap for domain %s\n", domain));
161
162         status = ads_dns_query_dcs(ctx, dns_hosts_file, domain, sitename,
163                                    &dcs, &numdcs);
164         if ( NT_STATUS_IS_OK(status) && numdcs ) {
165                 print_ldap_srvlist(dcs, numdcs);
166                 TALLOC_FREE( ctx );
167                 return 0;
168         }
169
170         TALLOC_FREE( ctx );
171
172         return -1;
173 #endif
174         DEBUG(1,("No ADS support\n"));
175         return -1;
176 }
177
178 static int net_lookup_dc(struct net_context *c, int argc, const char **argv)
179 {
180         struct ip_service *ip_list;
181         struct sockaddr_storage ss;
182         char *pdc_str = NULL;
183         const char *domain = NULL;
184         char *sitename = NULL;
185         int count, i;
186         char addr[INET6_ADDRSTRLEN];
187         bool sec_ads = (lp_security() == SEC_ADS);
188
189         if (sec_ads) {
190                 domain = lp_realm();
191         } else {
192                 domain = c->opt_target_workgroup;
193         }
194
195         if (argc > 0)
196                 domain=argv[0];
197
198         /* first get PDC */
199         if (!get_pdc_ip(domain, &ss))
200                 return -1;
201
202         print_sockaddr(addr, sizeof(addr), &ss);
203         if (asprintf(&pdc_str, "%s", addr) == -1) {
204                 return -1;
205         }
206         d_printf("%s\n", pdc_str);
207
208         sitename = sitename_fetch(talloc_tos(), domain);
209         if (!NT_STATUS_IS_OK(get_sorted_dc_list(domain, sitename,
210                                         &ip_list, &count, sec_ads))) {
211                 SAFE_FREE(pdc_str);
212                 TALLOC_FREE(sitename);
213                 return 0;
214         }
215         TALLOC_FREE(sitename);
216         for (i=0;i<count;i++) {
217                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
218                 if (!strequal(pdc_str, addr))
219                         d_printf("%s\n", addr);
220         }
221         SAFE_FREE(pdc_str);
222         return 0;
223 }
224
225 static int net_lookup_pdc(struct net_context *c, int argc, const char **argv)
226 {
227         struct sockaddr_storage ss;
228         char *pdc_str = NULL;
229         const char *domain;
230         char addr[INET6_ADDRSTRLEN];
231
232         if (lp_security() == SEC_ADS) {
233                 domain = lp_realm();
234         } else {
235                 domain = c->opt_target_workgroup;
236         }
237
238         if (argc > 0)
239                 domain=argv[0];
240
241         /* first get PDC */
242         if (!get_pdc_ip(domain, &ss))
243                 return -1;
244
245         print_sockaddr(addr, sizeof(addr), &ss);
246         if (asprintf(&pdc_str, "%s", addr) == -1) {
247                 return -1;
248         }
249         d_printf("%s\n", pdc_str);
250         SAFE_FREE(pdc_str);
251         return 0;
252 }
253
254
255 static int net_lookup_master(struct net_context *c, int argc, const char **argv)
256 {
257         struct sockaddr_storage master_ss;
258         const char *domain = c->opt_target_workgroup;
259         char addr[INET6_ADDRSTRLEN];
260
261         if (argc > 0)
262                 domain=argv[0];
263
264         if (!find_master_ip(domain, &master_ss))
265                 return -1;
266         print_sockaddr(addr, sizeof(addr), &master_ss);
267         d_printf("%s\n", addr);
268         return 0;
269 }
270
271 static int net_lookup_kdc(struct net_context *c, int argc, const char **argv)
272 {
273 #ifdef HAVE_KRB5
274         krb5_error_code rc;
275         krb5_context ctx;
276         struct ip_service *kdcs;
277         const char *realm;
278         int num_kdcs = 0;
279         int i;
280         NTSTATUS status;
281
282         initialize_krb5_error_table();
283         rc = krb5_init_context(&ctx);
284         if (rc) {
285                 DEBUG(1,("krb5_init_context failed (%s)\n",
286                          error_message(rc)));
287                 return -1;
288         }
289
290         if (argc > 0) {
291                 realm = argv[0];
292         } else if (lp_realm() && *lp_realm()) {
293                 realm = lp_realm();
294         } else {
295                 char **realms;
296
297                 rc = krb5_get_host_realm(ctx, NULL, &realms);
298                 if (rc) {
299                         DEBUG(1,("krb5_gethost_realm failed (%s)\n",
300                                  error_message(rc)));
301                         return -1;
302                 }
303                 realm = (const char *) *realms;
304         }
305
306         status = get_kdc_list(realm, NULL, &kdcs, &num_kdcs);
307         if (!NT_STATUS_IS_OK(status)) {
308                 DEBUG(1,("get_kdc_list failed (%s)\n", nt_errstr(status)));
309                 return -1;
310         }
311
312         for (i = 0; i < num_kdcs; i++) {
313                 char addr[INET6_ADDRSTRLEN];
314
315                 print_sockaddr(addr, sizeof(addr), &kdcs[i].ss);
316
317                 d_printf("%s:%u\n", addr, kdcs[i].port);
318         }
319
320         return 0;
321 #endif
322         DEBUG(1, ("No kerberos support\n"));
323         return -1;
324 }
325
326 static int net_lookup_name(struct net_context *c, int argc, const char **argv)
327 {
328         const char *dom, *name;
329         struct dom_sid sid;
330         enum lsa_SidType type;
331
332         if (argc != 1) {
333                 d_printf("%s\n%s",
334                          _("Usage:"),
335                          _(" net lookup name <name>\n"));
336                 return -1;
337         }
338
339         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_ALL,
340                          &dom, &name, &sid, &type)) {
341                 d_printf(_("Could not lookup name %s\n"), argv[0]);
342                 return -1;
343         }
344
345         d_printf("%s %d (%s) %s\\%s\n", sid_string_tos(&sid),
346                  type, sid_type_lookup(type), dom, name);
347         return 0;
348 }
349
350 static int net_lookup_sid(struct net_context *c, int argc, const char **argv)
351 {
352         const char *dom, *name;
353         struct dom_sid sid;
354         enum lsa_SidType type;
355
356         if (argc != 1) {
357                 d_printf("%s\n%s",
358                          _("Usage:"),
359                          _(" net lookup sid <sid>\n"));
360                 return -1;
361         }
362
363         if (!string_to_sid(&sid, argv[0])) {
364                 d_printf(_("Could not convert %s to SID\n"), argv[0]);
365                 return -1;
366         }
367
368         if (!lookup_sid(talloc_tos(), &sid,
369                         &dom, &name, &type)) {
370                 d_printf(_("Could not lookup name %s\n"), argv[0]);
371                 return -1;
372         }
373
374         d_printf("%s %d (%s) %s\\%s\n", sid_string_tos(&sid),
375                  type, sid_type_lookup(type), dom, name);
376         return 0;
377 }
378
379 static int net_lookup_dsgetdcname(struct net_context *c, int argc, const char **argv)
380 {
381         NTSTATUS status;
382         const char *domain_name = NULL;
383         const char *site_name = NULL;
384         uint32_t flags = 0;
385         struct netr_DsRGetDCNameInfo *info = NULL;
386         TALLOC_CTX *mem_ctx;
387         char *s = NULL;
388
389         if (argc < 1 || argc > 3) {
390                 d_printf("%s\n%s",
391                          _("Usage:"),
392                          _(" net lookup dsgetdcname "
393                            "<name> <flags> <sitename>\n"));
394                 return -1;
395         }
396
397         mem_ctx = talloc_init("net_lookup_dsgetdcname");
398         if (!mem_ctx) {
399                 return -1;
400         }
401
402         domain_name = argv[0];
403
404         if (argc >= 2)
405                 sscanf(argv[1], "%x", &flags);
406
407         if (!flags) {
408                 flags |= DS_DIRECTORY_SERVICE_REQUIRED;
409         }
410
411         if (argc == 3) {
412                 site_name = argv[2];
413         }
414
415         if (!c->msg_ctx) {
416                 d_fprintf(stderr, _("Could not initialise message context. "
417                         "Try running as root\n"));
418                 return -1;
419         }
420
421         status = dsgetdcname(mem_ctx, c->msg_ctx, domain_name, NULL, site_name,
422                              flags, &info);
423         if (!NT_STATUS_IS_OK(status)) {
424                 d_printf(_("failed with: %s\n"), nt_errstr(status));
425                 TALLOC_FREE(mem_ctx);
426                 return -1;
427         }
428
429         s = NDR_PRINT_STRUCT_STRING(mem_ctx, netr_DsRGetDCNameInfo, info);
430         printf("%s\n", s);
431         TALLOC_FREE(s);
432
433         TALLOC_FREE(mem_ctx);
434         return 0;
435 }
436
437
438 /* lookup hosts or IP addresses using internal samba lookup fns */
439 int net_lookup(struct net_context *c, int argc, const char **argv)
440 {
441         int i;
442
443         struct functable table[] = {
444                 {"HOST", net_lookup_host},
445                 {"LDAP", net_lookup_ldap},
446                 {"DC", net_lookup_dc},
447                 {"PDC", net_lookup_pdc},
448                 {"MASTER", net_lookup_master},
449                 {"KDC", net_lookup_kdc},
450                 {"NAME", net_lookup_name},
451                 {"SID", net_lookup_sid},
452                 {"DSGETDCNAME", net_lookup_dsgetdcname},
453                 {NULL, NULL}
454         };
455
456         if (argc < 1) {
457                 d_printf(_("\nUsage: \n"));
458                 return net_lookup_usage(c, argc, argv);
459         }
460         for (i=0; table[i].funcname; i++) {
461                 if (strcasecmp_m(argv[0], table[i].funcname) == 0)
462                         return table[i].fn(c, argc-1, argv+1);
463         }
464
465         /* Default to lookup a hostname so 'net lookup foo#1b' can be
466            used instead of 'net lookup host foo#1b'.  The host syntax
467            is a bit confusing as non #00 names can't really be
468            considered hosts as such. */
469
470         return net_lookup_host(c, argc, argv);
471 }