r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[abartlet/samba.git/.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
22 int net_lookup_usage(int argc, const char **argv)
23 {
24         d_printf(
25 "  net lookup [host] HOSTNAME[#<type>]\n\tgives IP for a hostname\n\n"
26 "  net lookup ldap [domain]\n\tgives IP of domain's ldap server\n\n"
27 "  net lookup kdc [realm]\n\tgives IP of realm's kerberos KDC\n\n"
28 "  net lookup dc [domain]\n\tgives IP of domains Domain Controllers\n\n"
29 "  net lookup master [domain|wg]\n\tgive IP of master browser\n\n"
30 "  net lookup name [name]\n\tLookup name's sid and type\n\n"
31 "  net lookup sid [sid]\n\tGive sid's name and type\n\n"
32 );
33         return -1;
34 }
35
36 /* lookup a hostname giving an IP */
37 static int net_lookup_host(int argc, const char **argv)
38 {
39         struct in_addr ip;
40         int name_type = 0x20;
41         const char *name = argv[0];
42         char *p;
43
44         if (argc == 0) 
45                 return net_lookup_usage(argc, argv);
46
47         p = strchr_m(name,'#');
48         if (p) {
49                 *p = '\0';
50                 sscanf(++p,"%x",&name_type);
51         }
52         
53         if (!resolve_name(name, &ip, name_type)) {
54                 /* we deliberately use DEBUG() here to send it to stderr 
55                    so scripts aren't mucked up */
56                 DEBUG(0,("Didn't find %s#%02x\n", name, name_type));
57                 return -1;
58         }
59
60         d_printf("%s\n", inet_ntoa(ip));
61         return 0;
62 }
63
64 #ifdef HAVE_ADS
65 static void print_ldap_srvlist(struct dns_rr_srv *dclist, int numdcs )
66 {
67         struct in_addr ip;
68         int i;
69
70         for ( i=0; i<numdcs; i++ ) {
71                 if ( resolve_name(dclist[i].hostname, &ip, 0x20) ) {
72                         d_printf("%s:%d\n", inet_ntoa(ip), dclist[i].port); 
73                 }
74         }
75 }
76 #endif
77
78 static int net_lookup_ldap(int argc, const char **argv)
79 {
80 #ifdef HAVE_ADS
81         const char *domain;
82         struct in_addr addr;
83         struct hostent *hostent;
84         struct dns_rr_srv *dcs = NULL;
85         int numdcs = 0;
86         char *sitename;
87         TALLOC_CTX *ctx;
88         NTSTATUS status;
89
90         if (argc > 0)
91                 domain = argv[0];
92         else
93                 domain = opt_target_workgroup;
94
95         sitename = sitename_fetch(domain);
96
97         if ( (ctx = talloc_init("net_lookup_ldap")) == NULL ) {
98                 d_fprintf(stderr, "net_lookup_ldap: talloc_inti() failed!\n");
99                 SAFE_FREE(sitename);
100                 return -1;
101         }
102
103         DEBUG(9, ("Lookup up ldap for domain %s\n", domain));
104
105         status = ads_dns_query_dcs( ctx, domain, sitename, &dcs, &numdcs );
106         if ( NT_STATUS_IS_OK(status) && numdcs ) {
107                 print_ldap_srvlist(dcs, numdcs);
108                 TALLOC_FREE( ctx );
109                 SAFE_FREE(sitename);
110                 return 0;
111         }
112
113         DEBUG(9, ("Looking up DC for domain %s\n", domain));
114         if (!get_pdc_ip(domain, &addr)) {
115                 TALLOC_FREE( ctx );
116                 SAFE_FREE(sitename);
117                 return -1;
118         }
119
120         hostent = gethostbyaddr((char *) &addr.s_addr, sizeof(addr.s_addr),
121                                 AF_INET);
122         if (!hostent) {
123                 TALLOC_FREE( ctx );
124                 SAFE_FREE(sitename);
125                 return -1;
126         }
127
128         DEBUG(9, ("Found DC with DNS name %s\n", hostent->h_name));
129         domain = strchr(hostent->h_name, '.');
130         if (!domain) {
131                 TALLOC_FREE( ctx );
132                 SAFE_FREE(sitename);
133                 return -1;
134         }
135         domain++;
136
137         DEBUG(9, ("Looking up ldap for domain %s\n", domain));
138
139         status = ads_dns_query_dcs( ctx, domain, sitename, &dcs, &numdcs );
140         if ( NT_STATUS_IS_OK(status) && numdcs ) {
141                 print_ldap_srvlist(dcs, numdcs);
142                 TALLOC_FREE( ctx );
143                 SAFE_FREE(sitename);
144                 return 0;
145         }
146
147         TALLOC_FREE( ctx );
148         SAFE_FREE(sitename);
149
150         return -1;
151 #endif
152         DEBUG(1,("No ADS support\n"));
153         return -1;
154 }
155
156 static int net_lookup_dc(int argc, const char **argv)
157 {
158         struct ip_service *ip_list;
159         struct in_addr addr;
160         char *pdc_str = NULL;
161         const char *domain=opt_target_workgroup;
162         char *sitename = NULL;
163         int count, i;
164
165         if (argc > 0)
166                 domain=argv[0];
167
168         /* first get PDC */
169         if (!get_pdc_ip(domain, &addr))
170                 return -1;
171
172         asprintf(&pdc_str, "%s", inet_ntoa(addr));
173         d_printf("%s\n", pdc_str);
174
175         sitename = sitename_fetch(domain);
176         if (!NT_STATUS_IS_OK(get_sorted_dc_list(domain, sitename, &ip_list, &count, False))) {
177                 SAFE_FREE(pdc_str);
178                 SAFE_FREE(sitename);
179                 return 0;
180         }
181         SAFE_FREE(sitename);
182         for (i=0;i<count;i++) {
183                 char *dc_str = inet_ntoa(ip_list[i].ip);
184                 if (!strequal(pdc_str, dc_str))
185                         d_printf("%s\n", dc_str);
186         }
187         SAFE_FREE(pdc_str);
188         return 0;
189 }
190
191 static int net_lookup_master(int argc, const char **argv)
192 {
193         struct in_addr master_ip;
194         const char *domain=opt_target_workgroup;
195
196         if (argc > 0)
197                 domain=argv[0];
198
199         if (!find_master_ip(domain, &master_ip))
200                 return -1;
201         d_printf("%s\n", inet_ntoa(master_ip));
202         return 0;
203 }
204
205 static int net_lookup_kdc(int argc, const char **argv)
206 {
207 #ifdef HAVE_KRB5
208         krb5_error_code rc;
209         krb5_context ctx;
210         struct sockaddr_in *addrs;
211         int num_kdcs,i;
212         krb5_data realm;
213         char **realms;
214
215         initialize_krb5_error_table();
216         rc = krb5_init_context(&ctx);
217         if (rc) {
218                 DEBUG(1,("krb5_init_context failed (%s)\n", 
219                          error_message(rc)));
220                 return -1;
221         }
222
223         if (argc>0) {
224                 realm.data = CONST_DISCARD(char *, argv[0]);
225                 realm.length = strlen(argv[0]);
226         } else if (lp_realm() && *lp_realm()) {
227                 realm.data = lp_realm();
228                 realm.length = strlen((const char *)realm.data);
229         } else {
230                 rc = krb5_get_host_realm(ctx, NULL, &realms);
231                 if (rc) {
232                         DEBUG(1,("krb5_gethost_realm failed (%s)\n",
233                                  error_message(rc)));
234                         return -1;
235                 }
236                 realm.data = (char *) *realms;
237                 realm.length = strlen((const char *)realm.data);
238         }
239
240         rc = smb_krb5_locate_kdc(ctx, &realm, (struct sockaddr **)(void *)&addrs, &num_kdcs, 0);
241         if (rc) {
242                 DEBUG(1, ("smb_krb5_locate_kdc failed (%s)\n", error_message(rc)));
243                 return -1;
244         }
245         for (i=0;i<num_kdcs;i++)
246                 if (addrs[i].sin_family == AF_INET) 
247                         d_printf("%s:%hd\n", inet_ntoa(addrs[i].sin_addr),
248                                  ntohs(addrs[i].sin_port));
249         return 0;
250
251 #endif  
252         DEBUG(1, ("No kerberos support\n"));
253         return -1;
254 }
255
256 static int net_lookup_name(int argc, const char **argv)
257 {
258         const char *dom, *name;
259         DOM_SID sid;
260         enum lsa_SidType type;
261
262         if (argc != 1) {
263                 d_printf("usage: net lookup name <name>\n");
264                 return -1;
265         }
266
267         if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ALL,
268                          &dom, &name, &sid, &type)) {
269                 d_printf("Could not lookup name %s\n", argv[0]);
270                 return -1;
271         }
272
273         d_printf("%s %d (%s) %s\\%s\n", sid_string_static(&sid),
274                  type, sid_type_lookup(type), dom, name);
275         return 0;
276 }
277
278 static int net_lookup_sid(int argc, const char **argv)
279 {
280         const char *dom, *name;
281         DOM_SID sid;
282         enum lsa_SidType type;
283
284         if (argc != 1) {
285                 d_printf("usage: net lookup sid <sid>\n");
286                 return -1;
287         }
288
289         if (!string_to_sid(&sid, argv[0])) {
290                 d_printf("Could not convert %s to SID\n", argv[0]);
291                 return -1;
292         }
293
294         if (!lookup_sid(tmp_talloc_ctx(), &sid,
295                         &dom, &name, &type)) {
296                 d_printf("Could not lookup name %s\n", argv[0]);
297                 return -1;
298         }
299
300         d_printf("%s %d (%s) %s\\%s\n", sid_string_static(&sid),
301                  type, sid_type_lookup(type), dom, name);
302         return 0;
303 }
304
305 /* lookup hosts or IP addresses using internal samba lookup fns */
306 int net_lookup(int argc, const char **argv)
307 {
308         int i;
309
310         struct functable table[] = {
311                 {"HOST", net_lookup_host},
312                 {"LDAP", net_lookup_ldap},
313                 {"DC", net_lookup_dc},
314                 {"MASTER", net_lookup_master},
315                 {"KDC", net_lookup_kdc},
316                 {"NAME", net_lookup_name},
317                 {"SID", net_lookup_sid},
318                 {NULL, NULL}
319         };
320
321         if (argc < 1) {
322                 d_printf("\nUsage: \n");
323                 return net_lookup_usage(argc, argv);
324         }
325         for (i=0; table[i].funcname; i++) {
326                 if (StrCaseCmp(argv[0], table[i].funcname) == 0)
327                         return table[i].fn(argc-1, argv+1);
328         }
329
330         /* Default to lookup a hostname so 'net lookup foo#1b' can be 
331            used instead of 'net lookup host foo#1b'.  The host syntax
332            is a bit confusing as non #00 names can't really be 
333            considered hosts as such. */
334
335         return net_lookup_host(argc, argv);
336 }