pyldb: avoid segfault when adding an element with no name
[nivanova/samba-autobuild/.git] / nsswitch / wbinfo.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind status program.
5
6    Copyright (C) Tim Potter      2000-2003
7    Copyright (C) Andrew Bartlett 2002-2007
8    Copyright (C) Volker Lendecke 2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "winbind_client.h"
26 #include "libwbclient/wbclient.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "lib/afs/afs_settoken.h"
30
31 #ifdef DBGC_CLASS
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_WINBIND
34 #endif
35
36 static struct wbcInterfaceDetails *init_interface_details(void)
37 {
38         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
39         static struct wbcInterfaceDetails *details;
40
41         if (details) {
42                 return details;
43         }
44
45         wbc_status = wbcInterfaceDetails(&details);
46         if (!WBC_ERROR_IS_OK(wbc_status)) {
47                 d_fprintf(stderr, "could not obtain winbind interface "
48                                   "details: %s\n", wbcErrorString(wbc_status));
49         }
50
51         return details;
52 }
53
54 static char winbind_separator(void)
55 {
56         struct wbcInterfaceDetails *details;
57         static bool got_sep;
58         static char sep;
59
60         if (got_sep)
61                 return sep;
62
63         details = init_interface_details();
64
65         if (!details) {
66                 d_fprintf(stderr, "could not obtain winbind separator!\n");
67                 return 0;
68         }
69
70         sep = details->winbind_separator;
71         got_sep = true;
72
73         if (!sep) {
74                 d_fprintf(stderr, "winbind separator was NULL!\n");
75                 return 0;
76         }
77
78         return sep;
79 }
80
81 static const char *get_winbind_domain(void)
82 {
83         static struct wbcInterfaceDetails *details;
84
85         details = init_interface_details();
86
87         if (!details) {
88                 d_fprintf(stderr, "could not obtain winbind domain name!\n");
89                 return 0;
90         }
91
92         return details->netbios_domain;
93 }
94
95 static const char *get_winbind_netbios_name(void)
96 {
97         static struct wbcInterfaceDetails *details;
98
99         details = init_interface_details();
100
101         if (!details) {
102                 d_fprintf(stderr, "could not obtain winbind netbios name!\n");
103                 return 0;
104         }
105
106         return details->netbios_name;
107 }
108
109 /* Copy of parse_domain_user from winbindd_util.c.  Parse a string of the
110    form DOMAIN/user into a domain and a user */
111
112 static bool parse_wbinfo_domain_user(const char *domuser, fstring domain,
113                                      fstring user)
114 {
115
116         char *p = strchr(domuser,winbind_separator());
117
118         if (!p) {
119                 /* Maybe it was a UPN? */
120                 p = strchr(domuser, '@');
121                 if (p != NULL) {
122                         fstrcpy(domain, "");
123                         fstrcpy(user, domuser);
124                         return true;
125                 }
126
127                 fstrcpy(user, domuser);
128                 fstrcpy(domain, get_winbind_domain());
129                 return true;
130         }
131
132         fstrcpy(user, p+1);
133         fstrcpy(domain, domuser);
134         domain[PTR_DIFF(p, domuser)] = 0;
135
136         return true;
137 }
138
139 /* Parse string of "uid,sid" or "gid,sid" into separate int and string values.
140  * Return true if input was valid, false otherwise. */
141 static bool parse_mapping_arg(char *arg, int *id, char **sid)
142 {
143         char *tmp, *endptr;
144         int error = 0;
145
146         if (!arg || !*arg)
147                 return false;
148
149         tmp = strtok(arg, ",");
150         *sid = strtok(NULL, ",");
151
152         if (!tmp || !*tmp || !*sid || !**sid)
153                 return false;
154
155         /* Because atoi() can return 0 on invalid input, which would be a valid
156          * UID/GID we must use strtoul() and do error checking */
157         *id = strtoul_err(tmp, &endptr, 10, &error);
158
159         if (endptr[0] != '\0' || error != 0)
160                 return false;
161
162         return true;
163 }
164
165 /* pull pwent info for a given user */
166
167 static bool wbinfo_get_userinfo(char *user)
168 {
169         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
170         struct passwd *pwd = NULL;
171
172         wbc_status = wbcGetpwnam(user, &pwd);
173         if (!WBC_ERROR_IS_OK(wbc_status)) {
174                 d_fprintf(stderr, "failed to call wbcGetpwnam: %s\n",
175                           wbcErrorString(wbc_status));
176                 return false;
177         }
178
179         d_printf("%s:%s:%u:%u:%s:%s:%s\n",
180                  pwd->pw_name,
181                  pwd->pw_passwd,
182                  (unsigned int)pwd->pw_uid,
183                  (unsigned int)pwd->pw_gid,
184                  pwd->pw_gecos,
185                  pwd->pw_dir,
186                  pwd->pw_shell);
187
188         wbcFreeMemory(pwd);
189
190         return true;
191 }
192
193 /* pull pwent info for a given uid */
194 static bool wbinfo_get_uidinfo(int uid)
195 {
196         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
197         struct passwd *pwd = NULL;
198
199         wbc_status = wbcGetpwuid(uid, &pwd);
200         if (!WBC_ERROR_IS_OK(wbc_status)) {
201                 d_fprintf(stderr, "failed to call wbcGetpwuid: %s\n",
202                           wbcErrorString(wbc_status));
203                 return false;
204         }
205
206         d_printf("%s:%s:%u:%u:%s:%s:%s\n",
207                  pwd->pw_name,
208                  pwd->pw_passwd,
209                  (unsigned int)pwd->pw_uid,
210                  (unsigned int)pwd->pw_gid,
211                  pwd->pw_gecos,
212                  pwd->pw_dir,
213                  pwd->pw_shell);
214
215         wbcFreeMemory(pwd);
216
217         return true;
218 }
219
220 static bool wbinfo_get_user_sidinfo(const char *sid_str)
221 {
222         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
223         struct passwd *pwd = NULL;
224         struct wbcDomainSid sid;
225
226         wbc_status = wbcStringToSid(sid_str, &sid);
227         wbc_status = wbcGetpwsid(&sid, &pwd);
228         if (!WBC_ERROR_IS_OK(wbc_status)) {
229                 d_fprintf(stderr, "failed to call wbcGetpwsid: %s\n",
230                           wbcErrorString(wbc_status));
231                 return false;
232         }
233
234         d_printf("%s:%s:%u:%u:%s:%s:%s\n",
235                  pwd->pw_name,
236                  pwd->pw_passwd,
237                  (unsigned int)pwd->pw_uid,
238                  (unsigned int)pwd->pw_gid,
239                  pwd->pw_gecos,
240                  pwd->pw_dir,
241                  pwd->pw_shell);
242
243         wbcFreeMemory(pwd);
244
245         return true;
246 }
247
248
249 /* pull grent for a given group */
250 static bool wbinfo_get_groupinfo(const char *group)
251 {
252         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
253         struct group *grp;
254         char **mem;
255
256         wbc_status = wbcGetgrnam(group, &grp);
257         if (!WBC_ERROR_IS_OK(wbc_status)) {
258                 d_fprintf(stderr, "failed to call wbcGetgrnam: %s\n",
259                           wbcErrorString(wbc_status));
260                 return false;
261         }
262
263         d_printf("%s:%s:%u:",
264                  grp->gr_name,
265                  grp->gr_passwd,
266                  (unsigned int)grp->gr_gid);
267
268         mem = grp->gr_mem;
269         while (*mem != NULL) {
270                 d_printf("%s%s", *mem, *(mem+1) != NULL ? "," : "");
271                 mem += 1;
272         }
273         d_printf("\n");
274
275         wbcFreeMemory(grp);
276
277         return true;
278 }
279
280 /* pull grent for a given gid */
281 static bool wbinfo_get_gidinfo(int gid)
282 {
283         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
284         struct group *grp;
285         char **mem;
286
287         wbc_status = wbcGetgrgid(gid, &grp);
288         if (!WBC_ERROR_IS_OK(wbc_status)) {
289                 d_fprintf(stderr, "failed to call wbcGetgrgid: %s\n",
290                           wbcErrorString(wbc_status));
291                 return false;
292         }
293
294         d_printf("%s:%s:%u:",
295                  grp->gr_name,
296                  grp->gr_passwd,
297                  (unsigned int)grp->gr_gid);
298
299         mem = grp->gr_mem;
300         while (*mem != NULL) {
301                 d_printf("%s%s", *mem, *(mem+1) != NULL ? "," : "");
302                 mem += 1;
303         }
304         d_printf("\n");
305
306         wbcFreeMemory(grp);
307
308         return true;
309 }
310
311 /* List groups a user is a member of */
312
313 static bool wbinfo_get_usergroups(const char *user)
314 {
315         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
316         uint32_t num_groups;
317         uint32_t i;
318         gid_t *groups = NULL;
319
320         /* Send request */
321
322         wbc_status = wbcGetGroups(user, &num_groups, &groups);
323         if (!WBC_ERROR_IS_OK(wbc_status)) {
324                 d_fprintf(stderr, "failed to call wbcGetGroups: %s\n",
325                           wbcErrorString(wbc_status));
326                 return false;
327         }
328
329         for (i = 0; i < num_groups; i++) {
330                 d_printf("%d\n", (int)groups[i]);
331         }
332
333         wbcFreeMemory(groups);
334
335         return true;
336 }
337
338
339 /* List group SIDs a user SID is a member of */
340 static bool wbinfo_get_usersids(const char *user_sid_str)
341 {
342         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
343         uint32_t num_sids;
344         uint32_t i;
345         struct wbcDomainSid user_sid, *sids = NULL;
346
347         /* Send request */
348
349         wbc_status = wbcStringToSid(user_sid_str, &user_sid);
350         if (!WBC_ERROR_IS_OK(wbc_status)) {
351                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
352                           wbcErrorString(wbc_status));
353                 return false;
354         }
355
356         wbc_status = wbcLookupUserSids(&user_sid, false, &num_sids, &sids);
357         if (!WBC_ERROR_IS_OK(wbc_status)) {
358                 d_fprintf(stderr, "failed to call wbcLookupUserSids: %s\n",
359                           wbcErrorString(wbc_status));
360                 return false;
361         }
362
363         for (i = 0; i < num_sids; i++) {
364                 char str[WBC_SID_STRING_BUFLEN];
365                 wbcSidToStringBuf(&sids[i], str, sizeof(str));
366                 d_printf("%s\n", str);
367         }
368
369         wbcFreeMemory(sids);
370
371         return true;
372 }
373
374 static bool wbinfo_get_userdomgroups(const char *user_sid_str)
375 {
376         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
377         uint32_t num_sids;
378         uint32_t i;
379         struct wbcDomainSid user_sid, *sids = NULL;
380
381         /* Send request */
382
383         wbc_status = wbcStringToSid(user_sid_str, &user_sid);
384         if (!WBC_ERROR_IS_OK(wbc_status)) {
385                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
386                           wbcErrorString(wbc_status));
387                 return false;
388         }
389
390         wbc_status = wbcLookupUserSids(&user_sid, true, &num_sids, &sids);
391         if (!WBC_ERROR_IS_OK(wbc_status)) {
392                 d_fprintf(stderr, "failed to call wbcLookupUserSids: %s\n",
393                           wbcErrorString(wbc_status));
394                 return false;
395         }
396
397         for (i = 0; i < num_sids; i++) {
398                 char str[WBC_SID_STRING_BUFLEN];
399                 wbcSidToStringBuf(&sids[i], str, sizeof(str));
400                 d_printf("%s\n", str);
401         }
402
403         wbcFreeMemory(sids);
404
405         return true;
406 }
407
408 static bool wbinfo_get_sidaliases(const char *domain,
409                                   const char *user_sid_str)
410 {
411         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
412         struct wbcDomainInfo *dinfo = NULL;
413         uint32_t i;
414         struct wbcDomainSid user_sid;
415         uint32_t *alias_rids = NULL;
416         uint32_t num_alias_rids;
417         char domain_sid_str[WBC_SID_STRING_BUFLEN];
418
419         /* Send request */
420         if ((domain == NULL) || (strequal(domain, ".")) ||
421            (domain[0] == '\0')) {
422                 domain = get_winbind_domain();
423         }
424
425         /* Send request */
426
427         wbc_status = wbcDomainInfo(domain, &dinfo);
428         if (!WBC_ERROR_IS_OK(wbc_status)) {
429                 d_fprintf(stderr, "wbcDomainInfo(%s) failed: %s\n", domain,
430                           wbcErrorString(wbc_status));
431                 goto done;
432         }
433         wbc_status = wbcStringToSid(user_sid_str, &user_sid);
434         if (!WBC_ERROR_IS_OK(wbc_status)) {
435                 goto done;
436         }
437
438         wbc_status = wbcGetSidAliases(&dinfo->sid, &user_sid, 1,
439             &alias_rids, &num_alias_rids);
440         if (!WBC_ERROR_IS_OK(wbc_status)) {
441                 goto done;
442         }
443
444         wbcSidToStringBuf(&dinfo->sid, domain_sid_str, sizeof(domain_sid_str));
445
446         for (i = 0; i < num_alias_rids; i++) {
447                 d_printf("%s-%d\n", domain_sid_str, alias_rids[i]);
448         }
449
450         wbcFreeMemory(alias_rids);
451
452 done:
453         wbcFreeMemory(dinfo);
454         return (WBC_ERR_SUCCESS == wbc_status);
455 }
456
457
458 /* Convert NetBIOS name to IP */
459
460 static bool wbinfo_wins_byname(const char *name)
461 {
462         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
463         char *ip = NULL;
464
465         wbc_status = wbcResolveWinsByName(name, &ip);
466         if (!WBC_ERROR_IS_OK(wbc_status)) {
467                 d_fprintf(stderr, "failed to call wbcResolveWinsByName: %s\n",
468                           wbcErrorString(wbc_status));
469                 return false;
470         }
471
472         /* Display response */
473
474         d_printf("%s\n", ip);
475
476         wbcFreeMemory(ip);
477
478         return true;
479 }
480
481 /* Convert IP to NetBIOS name */
482
483 static bool wbinfo_wins_byip(const char *ip)
484 {
485         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
486         char *name = NULL;
487
488         wbc_status = wbcResolveWinsByIP(ip, &name);
489         if (!WBC_ERROR_IS_OK(wbc_status)) {
490                 d_fprintf(stderr, "failed to call wbcResolveWinsByIP: %s\n",
491                           wbcErrorString(wbc_status));
492                 return false;
493         }
494
495         /* Display response */
496
497         d_printf("%s\n", name);
498
499         wbcFreeMemory(name);
500
501         return true;
502 }
503
504 /* List all/trusted domains */
505
506 static bool wbinfo_list_domains(bool list_all_domains, bool verbose)
507 {
508         struct wbcDomainInfo *domain_list = NULL;
509         size_t num_domains;
510         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
511         bool print_all = !list_all_domains && verbose;
512         int i;
513
514         wbc_status = wbcListTrusts(&domain_list, &num_domains);
515         if (!WBC_ERROR_IS_OK(wbc_status)) {
516                 d_fprintf(stderr, "failed to call wbcListTrusts: %s\n",
517                           wbcErrorString(wbc_status));
518                 return false;
519         }
520
521         if (print_all) {
522                 d_printf("%-16s%-65s%-12s%-12s%-5s%-5s\n",
523                          "Domain Name", "DNS Domain", "Trust Type",
524                          "Transitive", "In", "Out");
525         }
526
527         for (i=0; i<num_domains; i++) {
528                 if (print_all) {
529                         d_printf("%-16s", domain_list[i].short_name);
530                 } else {
531                         d_printf("%s", domain_list[i].short_name);
532                         d_printf("\n");
533                         continue;
534                 }
535
536                 d_printf("%-65s", domain_list[i].dns_name);
537
538                 switch(domain_list[i].trust_type) {
539                 case WBC_DOMINFO_TRUSTTYPE_NONE:
540                         if (domain_list[i].trust_routing != NULL) {
541                                 d_printf("%s\n", domain_list[i].trust_routing);
542                         } else {
543                                 d_printf("None\n");
544                         }
545                         continue;
546                 case WBC_DOMINFO_TRUSTTYPE_LOCAL:
547                         d_printf("Local\n");
548                         continue;
549                 case WBC_DOMINFO_TRUSTTYPE_RWDC:
550                         d_printf("RWDC\n");
551                         continue;
552                 case WBC_DOMINFO_TRUSTTYPE_RODC:
553                         d_printf("RODC\n");
554                         continue;
555                 case WBC_DOMINFO_TRUSTTYPE_PDC:
556                         d_printf("PDC\n");
557                         continue;
558                 case WBC_DOMINFO_TRUSTTYPE_WKSTA:
559                         d_printf("Workstation ");
560                         break;
561                 case WBC_DOMINFO_TRUSTTYPE_FOREST:
562                         d_printf("Forest      ");
563                         break;
564                 case WBC_DOMINFO_TRUSTTYPE_EXTERNAL:
565                         d_printf("External    ");
566                         break;
567                 case WBC_DOMINFO_TRUSTTYPE_IN_FOREST:
568                         d_printf("In-Forest   ");
569                         break;
570                 }
571
572                 if (domain_list[i].trust_flags & WBC_DOMINFO_TRUST_TRANSITIVE) {
573                         d_printf("Yes         ");
574                 } else {
575                         d_printf("No          ");
576                 }
577
578                 if (domain_list[i].trust_flags & WBC_DOMINFO_TRUST_INCOMING) {
579                         d_printf("Yes  ");
580                 } else {
581                         d_printf("No   ");
582                 }
583
584                 if (domain_list[i].trust_flags & WBC_DOMINFO_TRUST_OUTGOING) {
585                         d_printf("Yes  ");
586                 } else {
587                         d_printf("No   ");
588                 }
589
590                 d_printf("\n");
591         }
592
593         wbcFreeMemory(domain_list);
594
595         return true;
596 }
597
598 /* List own domain */
599
600 static bool wbinfo_list_own_domain(void)
601 {
602         d_printf("%s\n", get_winbind_domain());
603
604         return true;
605 }
606
607 /* show sequence numbers */
608 static bool wbinfo_show_sequence(const char *domain)
609 {
610         d_printf("This command has been deprecated.  Please use the "
611                  "--online-status option instead.\n");
612         return false;
613 }
614
615 /* show sequence numbers */
616 static bool wbinfo_show_onlinestatus(const char *domain)
617 {
618         struct wbcDomainInfo *domain_list = NULL;
619         size_t num_domains;
620         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
621         int i;
622
623         wbc_status = wbcListTrusts(&domain_list, &num_domains);
624         if (!WBC_ERROR_IS_OK(wbc_status)) {
625                 d_fprintf(stderr, "failed to call wbcListTrusts: %s\n",
626                           wbcErrorString(wbc_status));
627                 return false;
628         }
629
630         for (i=0; i<num_domains; i++) {
631                 bool is_offline;
632
633                 if (domain) {
634                         if (!strequal(domain_list[i].short_name, domain)) {
635                                 continue;
636                         }
637                 }
638
639                 is_offline = (domain_list[i].domain_flags &
640                               WBC_DOMINFO_DOMAIN_OFFLINE);
641
642                 d_printf("%s : %s\n",
643                          domain_list[i].short_name,
644                          is_offline ? "no active connection" : "active connection" );
645         }
646
647         wbcFreeMemory(domain_list);
648
649         return true;
650 }
651
652
653 /* Show domain info */
654
655 static bool wbinfo_domain_info(const char *domain)
656 {
657         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
658         struct wbcDomainInfo *dinfo = NULL;
659         char sid_str[WBC_SID_STRING_BUFLEN];
660
661         if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')){
662                 domain = get_winbind_domain();
663         }
664
665         /* Send request */
666
667         wbc_status = wbcDomainInfo(domain, &dinfo);
668         if (!WBC_ERROR_IS_OK(wbc_status)) {
669                 d_fprintf(stderr, "failed to call wbcDomainInfo: %s\n",
670                           wbcErrorString(wbc_status));
671                 return false;
672         }
673
674         wbcSidToStringBuf(&dinfo->sid, sid_str, sizeof(sid_str));
675
676         /* Display response */
677
678         d_printf("Name              : %s\n", dinfo->short_name);
679         d_printf("Alt_Name          : %s\n", dinfo->dns_name);
680
681         d_printf("SID               : %s\n", sid_str);
682
683         d_printf("Active Directory  : %s\n",
684                  (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_AD) ? "Yes" : "No");
685         d_printf("Native            : %s\n",
686                  (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_NATIVE) ?
687                  "Yes" : "No");
688
689         d_printf("Primary           : %s\n",
690                  (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_PRIMARY) ?
691                  "Yes" : "No");
692
693         wbcFreeMemory(dinfo);
694
695         return true;
696 }
697
698 /* Get a foreign DC's name */
699 static bool wbinfo_getdcname(const char *domain_name)
700 {
701         struct winbindd_request request;
702         struct winbindd_response response;
703
704         ZERO_STRUCT(request);
705         ZERO_STRUCT(response);
706
707         fstrcpy(request.domain_name, domain_name);
708
709         /* Send request */
710
711         if (winbindd_request_response(NULL, WINBINDD_GETDCNAME, &request,
712                                       &response) != NSS_STATUS_SUCCESS) {
713                 d_fprintf(stderr, "Could not get dc name for %s\n",domain_name);
714                 return false;
715         }
716
717         /* Display response */
718
719         d_printf("%s\n", response.data.dc_name);
720
721         return true;
722 }
723
724 /* Find a DC */
725 static bool wbinfo_dsgetdcname(const char *domain_name, uint32_t flags)
726 {
727         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
728         struct wbcDomainControllerInfoEx *dc_info;
729         char *str = NULL;
730
731         wbc_status = wbcLookupDomainControllerEx(domain_name, NULL, NULL,
732                                                  flags | DS_DIRECTORY_SERVICE_REQUIRED,
733                                                  &dc_info);
734         if (!WBC_ERROR_IS_OK(wbc_status)) {
735                 printf("Could not find dc for %s\n", domain_name);
736                 return false;
737         }
738
739         wbcGuidToString(dc_info->domain_guid, &str);
740
741         d_printf("%s\n", dc_info->dc_unc);
742         d_printf("%s\n", dc_info->dc_address);
743         d_printf("%d\n", dc_info->dc_address_type);
744         d_printf("%s\n", str);
745         d_printf("%s\n", dc_info->domain_name);
746         d_printf("%s\n", dc_info->forest_name);
747         d_printf("0x%08x\n", dc_info->dc_flags);
748         d_printf("%s\n", dc_info->dc_site_name);
749         d_printf("%s\n", dc_info->client_site_name);
750
751         wbcFreeMemory(str);
752         wbcFreeMemory(dc_info);
753
754         return true;
755 }
756
757 /* Check trust account password */
758
759 static bool wbinfo_check_secret(const char *domain)
760 {
761         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
762         struct wbcAuthErrorInfo *error = NULL;
763         const char *domain_name;
764
765         if (domain) {
766                 domain_name = domain;
767         } else {
768                 domain_name = get_winbind_domain();
769         }
770
771         wbc_status = wbcCheckTrustCredentials(domain_name, &error);
772
773         d_printf("checking the trust secret for domain %s via RPC calls %s\n",
774                 domain_name,
775                 WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
776
777         if (wbc_status == WBC_ERR_AUTH_ERROR) {
778                 d_fprintf(stderr, "wbcCheckTrustCredentials(%s): error code was %s (0x%x)\n",
779                           domain_name, error->nt_string, error->nt_status);
780                 wbcFreeMemory(error);
781         }
782         if (!WBC_ERROR_IS_OK(wbc_status)) {
783                 d_fprintf(stderr, "failed to call wbcCheckTrustCredentials: "
784                           "%s\n", wbcErrorString(wbc_status));
785                 return false;
786         }
787
788         return true;
789 }
790
791 /* Find the currently connected DCs */
792
793 static bool wbinfo_dc_info(const char *domain_name)
794 {
795         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
796         size_t i, num_dcs;
797         const char **dc_names, **dc_ips;
798
799         wbc_status = wbcDcInfo(domain_name, &num_dcs,
800                                &dc_names, &dc_ips);
801         if (!WBC_ERROR_IS_OK(wbc_status)) {
802                 printf("Could not find dc info %s\n",
803                        domain_name ? domain_name : "our domain");
804                 return false;
805         }
806
807         for (i=0; i<num_dcs; i++) {
808                 printf("%s (%s)\n", dc_names[i], dc_ips[i]);
809         }
810         wbcFreeMemory(dc_names);
811         wbcFreeMemory(dc_ips);
812
813         return true;
814 }
815
816 /* Change trust account password */
817
818 static bool wbinfo_change_secret(const char *domain)
819 {
820         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
821         struct wbcAuthErrorInfo *error = NULL;
822         const char *domain_name;
823
824         if (domain) {
825                 domain_name = domain;
826         } else {
827                 domain_name = get_winbind_domain();
828         }
829
830         wbc_status = wbcChangeTrustCredentials(domain_name, &error);
831
832         d_printf("changing the trust secret for domain %s via RPC calls %s\n",
833                 domain_name,
834                 WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
835
836         if (wbc_status == WBC_ERR_AUTH_ERROR) {
837                 d_fprintf(stderr, "wbcChangeTrustCredentials(%s): error code was %s (0x%x)\n",
838                           domain_name, error->nt_string, error->nt_status);
839                 wbcFreeMemory(error);
840         }
841         if (!WBC_ERROR_IS_OK(wbc_status)) {
842                 d_fprintf(stderr, "failed to call wbcChangeTrustCredentials: "
843                           "%s\n", wbcErrorString(wbc_status));
844                 return false;
845         }
846
847         return true;
848 }
849
850 /* Check DC connection */
851
852 static bool wbinfo_ping_dc(const char *domain)
853 {
854         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
855         struct wbcAuthErrorInfo *error = NULL;
856         char *dcname = NULL;
857
858         const char *domain_name;
859
860         if (domain) {
861                 domain_name = domain;
862         } else {
863                 domain_name = get_winbind_domain();
864         }
865
866         wbc_status = wbcPingDc2(domain_name, &error, &dcname);
867
868         d_printf("checking the NETLOGON for domain[%s] dc connection to \"%s\" %s\n",
869                  domain_name ? domain_name : "",
870                  dcname ? dcname : "",
871                  WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
872
873         wbcFreeMemory(dcname);
874         if (wbc_status == WBC_ERR_AUTH_ERROR) {
875                 d_fprintf(stderr, "wbcPingDc2(%s): error code was %s (0x%x)\n",
876                           domain_name, error->nt_string, error->nt_status);
877                 wbcFreeMemory(error);
878                 return false;
879         }
880         if (!WBC_ERROR_IS_OK(wbc_status)) {
881                 d_fprintf(stderr, "failed to call wbcPingDc: %s\n",
882                           wbcErrorString(wbc_status));
883                 return false;
884         }
885
886         return true;
887 }
888
889 /* Convert uid to sid */
890
891 static bool wbinfo_uid_to_sid(uid_t uid)
892 {
893         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
894         struct wbcDomainSid sid;
895         char sid_str[WBC_SID_STRING_BUFLEN];
896
897         /* Send request */
898
899         wbc_status = wbcUidToSid(uid, &sid);
900         if (!WBC_ERROR_IS_OK(wbc_status)) {
901                 d_fprintf(stderr, "failed to call wbcUidToSid: %s\n",
902                           wbcErrorString(wbc_status));
903                 return false;
904         }
905
906         wbcSidToStringBuf(&sid, sid_str, sizeof(sid_str));
907
908         /* Display response */
909
910         d_printf("%s\n", sid_str);
911
912         return true;
913 }
914
915 /* Convert gid to sid */
916
917 static bool wbinfo_gid_to_sid(gid_t gid)
918 {
919         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
920         struct wbcDomainSid sid;
921         char sid_str[WBC_SID_STRING_BUFLEN];
922
923         /* Send request */
924
925         wbc_status = wbcGidToSid(gid, &sid);
926         if (!WBC_ERROR_IS_OK(wbc_status)) {
927                 d_fprintf(stderr, "failed to call wbcGidToSid: %s\n",
928                           wbcErrorString(wbc_status));
929                 return false;
930         }
931
932         wbcSidToStringBuf(&sid, sid_str, sizeof(sid_str));
933
934         /* Display response */
935
936         d_printf("%s\n", sid_str);
937
938         return true;
939 }
940
941 /* Convert sid to uid */
942
943 static bool wbinfo_sid_to_uid(const char *sid_str)
944 {
945         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
946         struct wbcDomainSid sid;
947         uid_t uid;
948
949         /* Send request */
950
951         wbc_status = wbcStringToSid(sid_str, &sid);
952         if (!WBC_ERROR_IS_OK(wbc_status)) {
953                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
954                           wbcErrorString(wbc_status));
955                 return false;
956         }
957
958         wbc_status = wbcSidToUid(&sid, &uid);
959         if (!WBC_ERROR_IS_OK(wbc_status)) {
960                 d_fprintf(stderr, "failed to call wbcSidToUid: %s\n",
961                           wbcErrorString(wbc_status));
962                 return false;
963         }
964
965         /* Display response */
966
967         d_printf("%d\n", (int)uid);
968
969         return true;
970 }
971
972 static bool wbinfo_sid_to_gid(const char *sid_str)
973 {
974         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
975         struct wbcDomainSid sid;
976         gid_t gid;
977
978         /* Send request */
979
980         wbc_status = wbcStringToSid(sid_str, &sid);
981         if (!WBC_ERROR_IS_OK(wbc_status)) {
982                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
983                           wbcErrorString(wbc_status));
984                 return false;
985         }
986
987         wbc_status = wbcSidToGid(&sid, &gid);
988         if (!WBC_ERROR_IS_OK(wbc_status)) {
989                 d_fprintf(stderr, "failed to call wbcSidToGid: %s\n",
990                           wbcErrorString(wbc_status));
991                 return false;
992         }
993
994         /* Display response */
995
996         d_printf("%d\n", (int)gid);
997
998         return true;
999 }
1000
1001 static bool wbinfo_sids_to_unix_ids(const char *arg)
1002 {
1003         char sidstr[WBC_SID_STRING_BUFLEN];
1004         struct wbcDomainSid *sids;
1005         struct wbcUnixId *unix_ids;
1006         int i, num_sids;
1007         const char *p;
1008         wbcErr wbc_status;
1009
1010
1011         num_sids = 0;
1012         sids = NULL;
1013         p = arg;
1014
1015         while (next_token(&p, sidstr, LIST_SEP, sizeof(sidstr))) {
1016                 sids = talloc_realloc(talloc_tos(), sids, struct wbcDomainSid,
1017                                       num_sids+1);
1018                 if (sids == NULL) {
1019                         d_fprintf(stderr, "talloc failed\n");
1020                         return false;
1021                 }
1022                 wbc_status = wbcStringToSid(sidstr, &sids[num_sids]);
1023                 if (!WBC_ERROR_IS_OK(wbc_status)) {
1024                         d_fprintf(stderr, "wbcSidToString(%s) failed: %s\n",
1025                                   sidstr, wbcErrorString(wbc_status));
1026                         TALLOC_FREE(sids);
1027                         return false;
1028                 }
1029                 num_sids += 1;
1030         }
1031
1032         unix_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_sids);
1033         if (unix_ids == NULL) {
1034                 TALLOC_FREE(sids);
1035                 return false;
1036         }
1037
1038         wbc_status = wbcSidsToUnixIds(sids, num_sids, unix_ids);
1039         if (!WBC_ERROR_IS_OK(wbc_status)) {
1040                 d_fprintf(stderr, "wbcSidsToUnixIds failed: %s\n",
1041                           wbcErrorString(wbc_status));
1042                 TALLOC_FREE(sids);
1043                 return false;
1044         }
1045
1046         for (i=0; i<num_sids; i++) {
1047
1048                 wbcSidToStringBuf(&sids[i], sidstr, sizeof(sidstr));
1049
1050                 switch(unix_ids[i].type) {
1051                 case WBC_ID_TYPE_UID:
1052                         d_printf("%s -> uid %d\n", sidstr, unix_ids[i].id.uid);
1053                         break;
1054                 case WBC_ID_TYPE_GID:
1055                         d_printf("%s -> gid %d\n", sidstr, unix_ids[i].id.gid);
1056                         break;
1057                 case WBC_ID_TYPE_BOTH:
1058                         d_printf("%s -> uid/gid %d\n", sidstr, unix_ids[i].id.uid);
1059                         break;
1060                 default:
1061                         d_printf("%s -> unmapped\n", sidstr);
1062                         break;
1063                 }
1064         }
1065
1066         TALLOC_FREE(sids);
1067         TALLOC_FREE(unix_ids);
1068
1069         return true;
1070 }
1071
1072 static bool wbinfo_xids_to_sids(const char *arg)
1073 {
1074         fstring idstr;
1075         struct wbcUnixId *xids = NULL;
1076         struct wbcDomainSid *sids;
1077         wbcErr wbc_status;
1078         int num_xids = 0;
1079         const char *p;
1080         int i;
1081
1082         p = arg;
1083
1084         while (next_token(&p, idstr, LIST_SEP, sizeof(idstr))) {
1085                 xids = talloc_realloc(talloc_tos(), xids, struct wbcUnixId,
1086                                       num_xids+1);
1087                 if (xids == NULL) {
1088                         d_fprintf(stderr, "talloc failed\n");
1089                         return false;
1090                 }
1091
1092                 switch (idstr[0]) {
1093                 case 'u':
1094                         xids[num_xids] = (struct wbcUnixId) {
1095                                 .type = WBC_ID_TYPE_UID,
1096                                 .id.uid = atoi(&idstr[1])
1097                         };
1098                         break;
1099                 case 'g':
1100                         xids[num_xids] = (struct wbcUnixId) {
1101                                 .type = WBC_ID_TYPE_GID,
1102                                 .id.gid = atoi(&idstr[1])
1103                         };
1104                         break;
1105                 default:
1106                         d_fprintf(stderr, "%s is an invalid id\n", idstr);
1107                         TALLOC_FREE(xids);
1108                         return false;
1109                 }
1110                 num_xids += 1;
1111         }
1112
1113         sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_xids);
1114         if (sids == NULL) {
1115                 d_fprintf(stderr, "talloc failed\n");
1116                 TALLOC_FREE(xids);
1117                 return false;
1118         }
1119
1120         wbc_status = wbcUnixIdsToSids(xids, num_xids, sids);
1121         if (!WBC_ERROR_IS_OK(wbc_status)) {
1122                 d_fprintf(stderr, "wbcUnixIdsToSids failed: %s\n",
1123                           wbcErrorString(wbc_status));
1124                 TALLOC_FREE(sids);
1125                 TALLOC_FREE(xids);
1126                 return false;
1127         }
1128
1129         for (i=0; i<num_xids; i++) {
1130                 char str[WBC_SID_STRING_BUFLEN];
1131                 struct wbcDomainSid null_sid = { 0 };
1132
1133                 if (memcmp(&null_sid, &sids[i], sizeof(struct wbcDomainSid)) == 0) {
1134                         d_printf("NOT MAPPED\n");
1135                         continue;
1136                 }
1137                 wbcSidToStringBuf(&sids[i], str, sizeof(str));
1138                 d_printf("%s\n", str);
1139         }
1140
1141         return true;
1142 }
1143
1144 static bool wbinfo_allocate_uid(void)
1145 {
1146         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1147         uid_t uid;
1148
1149         /* Send request */
1150
1151         wbc_status = wbcAllocateUid(&uid);
1152         if (!WBC_ERROR_IS_OK(wbc_status)) {
1153                 d_fprintf(stderr, "failed to call wbcAllocateUid: %s\n",
1154                           wbcErrorString(wbc_status));
1155                 return false;
1156         }
1157
1158         /* Display response */
1159
1160         d_printf("New uid: %u\n", (unsigned int)uid);
1161
1162         return true;
1163 }
1164
1165 static bool wbinfo_allocate_gid(void)
1166 {
1167         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1168         gid_t gid;
1169
1170         /* Send request */
1171
1172         wbc_status = wbcAllocateGid(&gid);
1173         if (!WBC_ERROR_IS_OK(wbc_status)) {
1174                 d_fprintf(stderr, "failed to call wbcAllocateGid: %s\n",
1175                           wbcErrorString(wbc_status));
1176                 return false;
1177         }
1178
1179         /* Display response */
1180
1181         d_printf("New gid: %u\n", (unsigned int)gid);
1182
1183         return true;
1184 }
1185
1186 static bool wbinfo_set_uid_mapping(uid_t uid, const char *sid_str)
1187 {
1188         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1189         struct wbcDomainSid sid;
1190
1191         /* Send request */
1192
1193         wbc_status = wbcStringToSid(sid_str, &sid);
1194         if (!WBC_ERROR_IS_OK(wbc_status)) {
1195                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
1196                           wbcErrorString(wbc_status));
1197                 return false;
1198         }
1199
1200         wbc_status = wbcSetUidMapping(uid, &sid);
1201         if (!WBC_ERROR_IS_OK(wbc_status)) {
1202                 d_fprintf(stderr, "failed to call wbcSetUidMapping: %s\n",
1203                           wbcErrorString(wbc_status));
1204                 return false;
1205         }
1206
1207         /* Display response */
1208
1209         d_printf("uid %u now mapped to sid %s\n",
1210                 (unsigned int)uid, sid_str);
1211
1212         return true;
1213 }
1214
1215 static bool wbinfo_set_gid_mapping(gid_t gid, const char *sid_str)
1216 {
1217         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1218         struct wbcDomainSid sid;
1219
1220         /* Send request */
1221
1222         wbc_status = wbcStringToSid(sid_str, &sid);
1223         if (!WBC_ERROR_IS_OK(wbc_status)) {
1224                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
1225                           wbcErrorString(wbc_status));
1226                 return false;
1227         }
1228
1229         wbc_status = wbcSetGidMapping(gid, &sid);
1230         if (!WBC_ERROR_IS_OK(wbc_status)) {
1231                 d_fprintf(stderr, "failed to call wbcSetGidMapping: %s\n",
1232                           wbcErrorString(wbc_status));
1233                 return false;
1234         }
1235
1236         /* Display response */
1237
1238         d_printf("gid %u now mapped to sid %s\n",
1239                 (unsigned int)gid, sid_str);
1240
1241         return true;
1242 }
1243
1244 static bool wbinfo_remove_uid_mapping(uid_t uid, const char *sid_str)
1245 {
1246         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1247         struct wbcDomainSid sid;
1248
1249         /* Send request */
1250
1251         wbc_status = wbcStringToSid(sid_str, &sid);
1252         if (!WBC_ERROR_IS_OK(wbc_status)) {
1253                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
1254                           wbcErrorString(wbc_status));
1255                 return false;
1256         }
1257
1258         wbc_status = wbcRemoveUidMapping(uid, &sid);
1259         if (!WBC_ERROR_IS_OK(wbc_status)) {
1260                 d_fprintf(stderr, "failed to call wbcRemoveUidMapping: %s\n",
1261                           wbcErrorString(wbc_status));
1262                 return false;
1263         }
1264
1265         /* Display response */
1266
1267         d_printf("Removed uid %u to sid %s mapping\n",
1268                 (unsigned int)uid, sid_str);
1269
1270         return true;
1271 }
1272
1273 static bool wbinfo_remove_gid_mapping(gid_t gid, const char *sid_str)
1274 {
1275         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1276         struct wbcDomainSid sid;
1277
1278         /* Send request */
1279
1280         wbc_status = wbcStringToSid(sid_str, &sid);
1281         if (!WBC_ERROR_IS_OK(wbc_status)) {
1282                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
1283                           wbcErrorString(wbc_status));
1284                 return false;
1285         }
1286
1287         wbc_status = wbcRemoveGidMapping(gid, &sid);
1288         if (!WBC_ERROR_IS_OK(wbc_status)) {
1289                 d_fprintf(stderr, "failed to call wbcRemoveGidMapping: %s\n",
1290                           wbcErrorString(wbc_status));
1291                 return false;
1292         }
1293
1294         /* Display response */
1295
1296         d_printf("Removed gid %u to sid %s mapping\n",
1297                 (unsigned int)gid, sid_str);
1298
1299         return true;
1300 }
1301
1302 /* Convert sid to string */
1303
1304 static bool wbinfo_lookupsid(const char *sid_str)
1305 {
1306         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1307         struct wbcDomainSid sid;
1308         char *domain;
1309         char *name;
1310         enum wbcSidType type;
1311
1312         /* Send off request */
1313
1314         wbc_status = wbcStringToSid(sid_str, &sid);
1315         if (!WBC_ERROR_IS_OK(wbc_status)) {
1316                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
1317                           wbcErrorString(wbc_status));
1318                 return false;
1319         }
1320
1321         wbc_status = wbcLookupSid(&sid, &domain, &name, &type);
1322         if (!WBC_ERROR_IS_OK(wbc_status)) {
1323                 d_fprintf(stderr, "failed to call wbcLookupSid: %s\n",
1324                           wbcErrorString(wbc_status));
1325                 return false;
1326         }
1327
1328         /* Display response */
1329
1330         if (type == WBC_SID_NAME_DOMAIN) {
1331                 d_printf("%s %d\n", domain, type);
1332         } else {
1333                 d_printf("%s%c%s %d\n",
1334                          domain, winbind_separator(), name, type);
1335         }
1336
1337         wbcFreeMemory(domain);
1338         wbcFreeMemory(name);
1339
1340         return true;
1341 }
1342
1343 /* Convert sid to fullname */
1344
1345 static bool wbinfo_lookupsid_fullname(const char *sid_str)
1346 {
1347         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1348         struct wbcDomainSid sid;
1349         char *domain;
1350         char *name;
1351         enum wbcSidType type;
1352
1353         /* Send off request */
1354
1355         wbc_status = wbcStringToSid(sid_str, &sid);
1356         if (!WBC_ERROR_IS_OK(wbc_status)) {
1357                 d_fprintf(stderr, "failed to call wbcStringToSid: %s\n",
1358                           wbcErrorString(wbc_status));
1359                 return false;
1360         }
1361
1362         wbc_status = wbcGetDisplayName(&sid, &domain, &name, &type);
1363         if (!WBC_ERROR_IS_OK(wbc_status)) {
1364                 d_fprintf(stderr, "failed to call wbcGetDisplayName: %s\n",
1365                           wbcErrorString(wbc_status));
1366                 return false;
1367         }
1368
1369         /* Display response */
1370
1371         d_printf("%s%c%s %d\n",
1372                  domain, winbind_separator(), name, type);
1373
1374         wbcFreeMemory(domain);
1375         wbcFreeMemory(name);
1376
1377         return true;
1378 }
1379
1380 /* Lookup a list of RIDs */
1381
1382 static bool wbinfo_lookuprids(const char *domain, const char *arg)
1383 {
1384         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1385         struct wbcDomainInfo *dinfo = NULL;
1386         char *domain_name = NULL;
1387         const char **names = NULL;
1388         enum wbcSidType *types = NULL;
1389         size_t i;
1390         int num_rids;
1391         uint32_t *rids = NULL;
1392         const char *p;
1393         char *ridstr;
1394         TALLOC_CTX *mem_ctx = NULL;
1395         bool ret = false;
1396
1397         if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')){
1398                 domain = get_winbind_domain();
1399         }
1400
1401         /* Send request */
1402
1403         wbc_status = wbcDomainInfo(domain, &dinfo);
1404         if (!WBC_ERROR_IS_OK(wbc_status)) {
1405                 d_printf("wbcDomainInfo(%s) failed: %s\n", domain,
1406                          wbcErrorString(wbc_status));
1407                 goto done;
1408         }
1409
1410         mem_ctx = talloc_new(NULL);
1411         if (mem_ctx == NULL) {
1412                 d_printf("talloc_new failed\n");
1413                 goto done;
1414         }
1415
1416         num_rids = 0;
1417         rids = NULL;
1418         p = arg;
1419
1420         while (next_token_talloc(mem_ctx, &p, &ridstr, " ,\n")) {
1421                 int error = 0;
1422                 uint32_t rid;
1423
1424                 rid = strtoul_err(ridstr, NULL, 10, &error);
1425                 if (error != 0) {
1426                         d_printf("failed to convert rid\n");
1427                         goto done;
1428                 }
1429                 rids = talloc_realloc(mem_ctx, rids, uint32_t, num_rids + 1);
1430                 if (rids == NULL) {
1431                         d_printf("talloc_realloc failed\n");
1432                 }
1433                 rids[num_rids] = rid;
1434                 num_rids += 1;
1435         }
1436
1437         if (rids == NULL) {
1438                 d_printf("no rids\n");
1439                 goto done;
1440         }
1441
1442         wbc_status = wbcLookupRids(&dinfo->sid, num_rids, rids,
1443                                    &p, &names, &types);
1444         if (!WBC_ERROR_IS_OK(wbc_status)) {
1445                 d_printf("winbind_lookup_rids failed: %s\n",
1446                          wbcErrorString(wbc_status));
1447                 goto done;
1448         }
1449
1450         domain_name = discard_const_p(char, p);
1451         d_printf("Domain: %s\n", domain_name);
1452
1453         for (i=0; i<num_rids; i++) {
1454                 d_printf("%8d: %s (%s)\n", rids[i], names[i],
1455                          wbcSidTypeString(types[i]));
1456         }
1457
1458         ret = true;
1459 done:
1460         wbcFreeMemory(dinfo);
1461         wbcFreeMemory(domain_name);
1462         wbcFreeMemory(names);
1463         wbcFreeMemory(types);
1464         TALLOC_FREE(mem_ctx);
1465         return ret;
1466 }
1467
1468 static bool wbinfo_lookup_sids(const char *arg)
1469 {
1470         char sidstr[WBC_SID_STRING_BUFLEN];
1471         struct wbcDomainSid *sids;
1472         struct wbcDomainInfo *domains;
1473         struct wbcTranslatedName *names;
1474         int num_domains;
1475         int i, num_sids;
1476         const char *p;
1477         wbcErr wbc_status;
1478
1479
1480         num_sids = 0;
1481         sids = NULL;
1482         p = arg;
1483
1484         while (next_token(&p, sidstr, LIST_SEP, sizeof(sidstr))) {
1485                 sids = talloc_realloc(talloc_tos(), sids, struct wbcDomainSid,
1486                                       num_sids+1);
1487                 if (sids == NULL) {
1488                         d_fprintf(stderr, "talloc failed\n");
1489                         return false;
1490                 }
1491                 wbc_status = wbcStringToSid(sidstr, &sids[num_sids]);
1492                 if (!WBC_ERROR_IS_OK(wbc_status)) {
1493                         d_fprintf(stderr, "wbcSidToString(%s) failed: %s\n",
1494                                   sidstr, wbcErrorString(wbc_status));
1495                         TALLOC_FREE(sids);
1496                         return false;
1497                 }
1498                 num_sids += 1;
1499         }
1500
1501         wbc_status = wbcLookupSids(sids, num_sids, &domains, &num_domains,
1502                                    &names);
1503         if (!WBC_ERROR_IS_OK(wbc_status)) {
1504                 d_fprintf(stderr, "wbcLookupSids failed: %s\n",
1505                           wbcErrorString(wbc_status));
1506                 TALLOC_FREE(sids);
1507                 return false;
1508         }
1509
1510         for (i=0; i<num_sids; i++) {
1511                 const char *domain = NULL;
1512
1513                 wbcSidToStringBuf(&sids[i], sidstr, sizeof(sidstr));
1514
1515                 if (names[i].domain_index >= num_domains) {
1516                         domain = "<none>";
1517                 } else if (names[i].domain_index < 0) {
1518                         domain = "<none>";
1519                 } else {
1520                         domain = domains[names[i].domain_index].short_name;
1521                 }
1522
1523                 if (names[i].type == WBC_SID_NAME_DOMAIN) {
1524                         d_printf("%s -> %s %d\n", sidstr,
1525                                  domain,
1526                                  names[i].type);
1527                 } else {
1528                         d_printf("%s -> %s%c%s %d\n", sidstr,
1529                                  domain,
1530                                  winbind_separator(),
1531                                  names[i].name, names[i].type);
1532                 }
1533         }
1534         wbcFreeMemory(names);
1535         wbcFreeMemory(domains);
1536         return true;
1537 }
1538
1539 /* Convert string to sid */
1540
1541 static bool wbinfo_lookupname(const char *full_name)
1542 {
1543         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1544         struct wbcDomainSid sid;
1545         char sid_str[WBC_SID_STRING_BUFLEN];
1546         enum wbcSidType type;
1547         fstring domain_name;
1548         fstring account_name;
1549
1550         /* Send off request */
1551
1552         parse_wbinfo_domain_user(full_name, domain_name,
1553                                  account_name);
1554
1555         wbc_status = wbcLookupName(domain_name, account_name,
1556                                    &sid, &type);
1557         if (!WBC_ERROR_IS_OK(wbc_status)) {
1558                 d_fprintf(stderr, "failed to call wbcLookupName: %s\n",
1559                           wbcErrorString(wbc_status));
1560                 return false;
1561         }
1562
1563         wbcSidToStringBuf(&sid, sid_str, sizeof(sid_str));
1564
1565         /* Display response */
1566
1567         d_printf("%s %s (%d)\n", sid_str, wbcSidTypeString(type), type);
1568
1569         return true;
1570 }
1571
1572 static char *wbinfo_prompt_pass(TALLOC_CTX *mem_ctx,
1573                                 const char *prefix,
1574                                 const char *username)
1575 {
1576         char *prompt;
1577         char buf[1024] = {0};
1578         int rc;
1579
1580         prompt = talloc_asprintf(mem_ctx, "Enter %s's ", username);
1581         if (!prompt) {
1582                 return NULL;
1583         }
1584         if (prefix) {
1585                 prompt = talloc_asprintf_append(prompt, "%s ", prefix);
1586                 if (!prompt) {
1587                         return NULL;
1588                 }
1589         }
1590         prompt = talloc_asprintf_append(prompt, "password: ");
1591         if (!prompt) {
1592                 return NULL;
1593         }
1594
1595         rc = samba_getpass(prompt, buf, sizeof(buf), false, false);
1596         TALLOC_FREE(prompt);
1597         if (rc < 0) {
1598                 return NULL;
1599         }
1600
1601         return talloc_strdup(mem_ctx, buf);
1602 }
1603
1604 /* Authenticate a user with a plaintext password */
1605
1606 static bool wbinfo_auth_krb5(char *username, const char *cctype, uint32_t flags)
1607 {
1608         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1609         char *s = NULL;
1610         char *p = NULL;
1611         char *password = NULL;
1612         char *name = NULL;
1613         char *local_cctype = NULL;
1614         uid_t uid;
1615         struct wbcLogonUserParams params;
1616         struct wbcLogonUserInfo *info;
1617         struct wbcAuthErrorInfo *error;
1618         struct wbcUserPasswordPolicyInfo *policy;
1619         TALLOC_CTX *frame = talloc_tos();
1620
1621         if ((s = talloc_strdup(frame, username)) == NULL) {
1622                 return false;
1623         }
1624
1625         if ((p = strchr(s, '%')) != NULL) {
1626                 *p = 0;
1627                 p++;
1628                 password = talloc_strdup(frame, p);
1629         } else {
1630                 password = wbinfo_prompt_pass(frame, NULL, username);
1631         }
1632
1633         local_cctype = talloc_strdup(frame, cctype);
1634
1635         name = s;
1636
1637         uid = geteuid();
1638
1639         params.username = name;
1640         params.password = password;
1641         params.num_blobs = 0;
1642         params.blobs = NULL;
1643
1644         wbc_status = wbcAddNamedBlob(&params.num_blobs,
1645                                      &params.blobs,
1646                                      "flags",
1647                                      0,
1648                                      (uint8_t *)&flags,
1649                                      sizeof(flags));
1650         if (!WBC_ERROR_IS_OK(wbc_status)) {
1651                 d_fprintf(stderr, "failed to call wbcAddNamedBlob: %s\n",
1652                           wbcErrorString(wbc_status));
1653                 goto done;
1654         }
1655
1656         wbc_status = wbcAddNamedBlob(&params.num_blobs,
1657                                      &params.blobs,
1658                                      "user_uid",
1659                                      0,
1660                                      (uint8_t *)&uid,
1661                                      sizeof(uid));
1662         if (!WBC_ERROR_IS_OK(wbc_status)) {
1663                 d_fprintf(stderr, "failed to call wbcAddNamedBlob: %s\n",
1664                           wbcErrorString(wbc_status));
1665                 goto done;
1666         }
1667
1668         wbc_status = wbcAddNamedBlob(&params.num_blobs,
1669                                      &params.blobs,
1670                                      "krb5_cc_type",
1671                                      0,
1672                                      (uint8_t *)local_cctype,
1673                                      strlen(cctype)+1);
1674         if (!WBC_ERROR_IS_OK(wbc_status)) {
1675                 d_fprintf(stderr, "failed to call wbcAddNamedBlob: %s\n",
1676                           wbcErrorString(wbc_status));
1677                 goto done;
1678         }
1679
1680         wbc_status = wbcLogonUser(&params, &info, &error, &policy);
1681
1682         d_printf("plaintext kerberos password authentication for [%s] %s "
1683                  "(requesting cctype: %s)\n",
1684                  username, WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed",
1685                  cctype);
1686
1687         if (error) {
1688                 d_fprintf(stderr,
1689                          "wbcLogonUser(%s): error code was %s (0x%x)\n"
1690                          "error message was: %s\n",
1691                          params.username, error->nt_string,
1692                          error->nt_status,
1693                          error->display_string);
1694         }
1695
1696         if (WBC_ERROR_IS_OK(wbc_status)) {
1697                 if (flags & WBFLAG_PAM_INFO3_TEXT) {
1698                         if (info && info->info && info->info->user_flags &
1699                             NETLOGON_CACHED_ACCOUNT) {
1700                                 d_printf("user_flgs: "
1701                                          "NETLOGON_CACHED_ACCOUNT\n");
1702                         }
1703                 }
1704
1705                 if (info) {
1706                         int i;
1707                         for (i=0; i < info->num_blobs; i++) {
1708                                 if (strequal(info->blobs[i].name,
1709                                              "krb5ccname")) {
1710                                         d_printf("credentials were put "
1711                                                  "in: %s\n",
1712                                                 (const char *)
1713                                                       info->blobs[i].blob.data);
1714                                         break;
1715                                 }
1716                         }
1717                 } else {
1718                         d_printf("no credentials cached\n");
1719                 }
1720         }
1721  done:
1722
1723         wbcFreeMemory(params.blobs);
1724
1725         return WBC_ERROR_IS_OK(wbc_status);
1726 }
1727
1728 /* Authenticate a user with a plaintext password */
1729
1730 static bool wbinfo_auth(char *username)
1731 {
1732         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1733         char *s = NULL;
1734         char *p = NULL;
1735         char *password = NULL;
1736         char *name = NULL;
1737         TALLOC_CTX *frame = talloc_tos();
1738
1739         if ((s = talloc_strdup(frame, username)) == NULL) {
1740                 return false;
1741         }
1742
1743         if ((p = strchr(s, '%')) != NULL) {
1744                 *p = 0;
1745                 p++;
1746                 password = talloc_strdup(frame, p);
1747         } else {
1748                 password = wbinfo_prompt_pass(frame, NULL, username);
1749         }
1750
1751         name = s;
1752
1753         wbc_status = wbcAuthenticateUser(name, password);
1754
1755         d_printf("plaintext password authentication %s\n",
1756                  WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
1757
1758 #if 0
1759         if (response.data.auth.nt_status)
1760                 d_fprintf(stderr,
1761                          "error code was %s (0x%x)\nerror message was: %s\n",
1762                          response.data.auth.nt_status_string,
1763                          response.data.auth.nt_status,
1764                          response.data.auth.error_string);
1765 #endif
1766
1767         return WBC_ERROR_IS_OK(wbc_status);
1768 }
1769
1770 /* Authenticate a user with a challenge/response */
1771
1772 static bool wbinfo_auth_crap(char *username, bool use_ntlmv2, bool use_lanman)
1773 {
1774         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1775         struct wbcAuthUserParams params;
1776         struct wbcAuthUserInfo *info = NULL;
1777         struct wbcAuthErrorInfo *err = NULL;
1778         DATA_BLOB lm = data_blob_null;
1779         DATA_BLOB nt = data_blob_null;
1780         fstring name_user;
1781         fstring name_domain;
1782         char *pass;
1783         char *p;
1784         TALLOC_CTX *frame = talloc_tos();
1785
1786         p = strchr(username, '%');
1787
1788         if (p) {
1789                 *p = 0;
1790                 pass = talloc_strdup(frame, p + 1);
1791         } else {
1792                 pass = wbinfo_prompt_pass(frame, NULL, username);
1793         }
1794
1795         parse_wbinfo_domain_user(username, name_domain, name_user);
1796
1797         params.account_name     = name_user;
1798         params.domain_name      = name_domain;
1799         params.workstation_name = NULL;
1800
1801         params.flags            = 0;
1802         params.parameter_control= WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT |
1803                                   WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
1804
1805         params.level            = WBC_AUTH_USER_LEVEL_RESPONSE;
1806
1807         generate_random_buffer(params.password.response.challenge, 8);
1808
1809         if (use_ntlmv2) {
1810                 DATA_BLOB server_chal;
1811                 DATA_BLOB names_blob;
1812                 const char *netbios_name = NULL;
1813                 const char *domain = NULL;
1814
1815                 netbios_name = get_winbind_netbios_name(),
1816                 domain = get_winbind_domain();
1817                 if (domain == NULL) {
1818                         d_fprintf(stderr, "Failed to get domain from winbindd\n");
1819                         return false;
1820                 }
1821
1822                 server_chal = data_blob(params.password.response.challenge, 8);
1823
1824                 /* Pretend this is a login to 'us', for blob purposes */
1825                 names_blob = NTLMv2_generate_names_blob(NULL,
1826                                                         netbios_name,
1827                                                         domain);
1828
1829                 if (pass != NULL &&
1830                     !SMBNTLMv2encrypt(NULL, name_user, name_domain, pass,
1831                                       &server_chal,
1832                                       &names_blob,
1833                                       &lm, &nt, NULL, NULL)) {
1834                         data_blob_free(&names_blob);
1835                         data_blob_free(&server_chal);
1836                         TALLOC_FREE(pass);
1837                         return false;
1838                 }
1839                 data_blob_free(&names_blob);
1840                 data_blob_free(&server_chal);
1841
1842         } else {
1843                 if (use_lanman) {
1844                         bool ok;
1845                         lm = data_blob(NULL, 24);
1846                         ok = SMBencrypt(pass,
1847                                         params.password.response.challenge,
1848                                         lm.data);
1849                         if (!ok) {
1850                                 data_blob_free(&lm);
1851                         }
1852                 }
1853                 nt = data_blob(NULL, 24);
1854                 SMBNTencrypt(pass, params.password.response.challenge,
1855                              nt.data);
1856         }
1857
1858         params.password.response.nt_length      = nt.length;
1859         params.password.response.nt_data        = nt.data;
1860         params.password.response.lm_length      = lm.length;
1861         params.password.response.lm_data        = lm.data;
1862
1863         wbc_status = wbcAuthenticateUserEx(&params, &info, &err);
1864
1865         /* Display response */
1866
1867         d_printf("challenge/response password authentication %s\n",
1868                  WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
1869
1870         if (wbc_status == WBC_ERR_AUTH_ERROR) {
1871                 d_fprintf(stderr,
1872                          "wbcAuthenticateUserEx(%s%c%s): error code was "
1873                           "%s (0x%x, authoritative=%"PRIu8")\n"
1874                          "error message was: %s\n",
1875                          name_domain,
1876                          winbind_separator(),
1877                          name_user,
1878                          err->nt_string,
1879                          err->nt_status,
1880                          err->authoritative,
1881                          err->display_string);
1882                 wbcFreeMemory(err);
1883         } else if (WBC_ERROR_IS_OK(wbc_status)) {
1884                 wbcFreeMemory(info);
1885         }
1886
1887         data_blob_free(&nt);
1888         data_blob_free(&lm);
1889
1890         return WBC_ERROR_IS_OK(wbc_status);
1891 }
1892
1893 /* Authenticate a user with a plaintext password */
1894
1895 static bool wbinfo_pam_logon(char *username, bool verbose)
1896 {
1897         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1898         struct wbcLogonUserParams params;
1899         struct wbcLogonUserInfo *info = NULL;
1900         struct wbcAuthErrorInfo *error = NULL;
1901         char *s = NULL;
1902         char *p = NULL;
1903         TALLOC_CTX *frame = talloc_tos();
1904         uint32_t flags;
1905         uint32_t uid;
1906
1907         ZERO_STRUCT(params);
1908
1909         if ((s = talloc_strdup(frame, username)) == NULL) {
1910                 return false;
1911         }
1912
1913         if ((p = strchr(s, '%')) != NULL) {
1914                 *p = 0;
1915                 p++;
1916                 params.password = talloc_strdup(frame, p);
1917         } else {
1918                 params.password = wbinfo_prompt_pass(frame, NULL, username);
1919         }
1920         params.username = s;
1921
1922         flags = WBFLAG_PAM_CACHED_LOGIN;
1923
1924         wbc_status = wbcAddNamedBlob(&params.num_blobs, &params.blobs,
1925                                      "flags", 0,
1926                                      (uint8_t *)&flags, sizeof(flags));
1927         if (!WBC_ERROR_IS_OK(wbc_status)) {
1928                 d_printf("wbcAddNamedBlob failed: %s\n",
1929                          wbcErrorString(wbc_status));
1930                 return false;
1931         }
1932
1933         uid = getuid();
1934
1935         wbc_status = wbcAddNamedBlob(&params.num_blobs, &params.blobs,
1936                                      "user_uid", 0,
1937                                      (uint8_t *)&uid, sizeof(uid));
1938         if (!WBC_ERROR_IS_OK(wbc_status)) {
1939                 d_printf("wbcAddNamedBlob failed: %s\n",
1940                          wbcErrorString(wbc_status));
1941                 return false;
1942         }
1943
1944         wbc_status = wbcLogonUser(&params, &info, &error, NULL);
1945
1946         if (verbose && (info != NULL)) {
1947                 struct wbcAuthUserInfo *i = info->info;
1948                 uint32_t j;
1949
1950                 if (i->account_name != NULL) {
1951                         d_printf("account_name: %s\n", i->account_name);
1952                 }
1953                 if (i->user_principal != NULL) {
1954                         d_printf("user_principal: %s\n", i->user_principal);
1955                 }
1956                 if (i->full_name != NULL) {
1957                         d_printf("full_name: %s\n", i->full_name);
1958                 }
1959                 if (i->domain_name != NULL) {
1960                         d_printf("domain_name: %s\n", i->domain_name);
1961                 }
1962                 if (i->dns_domain_name != NULL) {
1963                         d_printf("dns_domain_name: %s\n", i->dns_domain_name);
1964                 }
1965                 if (i->logon_server != NULL) {
1966                         d_printf("logon_server: %s\n", i->logon_server);
1967                 }
1968                 if (i->logon_script != NULL) {
1969                         d_printf("logon_script: %s\n", i->logon_script);
1970                 }
1971                 if (i->profile_path != NULL) {
1972                         d_printf("profile_path: %s\n", i->profile_path);
1973                 }
1974                 if (i->home_directory != NULL) {
1975                         d_printf("home_directory: %s\n", i->home_directory);
1976                 }
1977                 if (i->home_drive != NULL) {
1978                         d_printf("home_drive: %s\n", i->home_drive);
1979                 }
1980
1981                 d_printf("sids:");
1982
1983                 for (j=0; j<i->num_sids; j++) {
1984                         char buf[WBC_SID_STRING_BUFLEN];
1985                         wbcSidToStringBuf(&i->sids[j].sid, buf, sizeof(buf));
1986                         d_printf(" %s", buf);
1987                 }
1988                 d_printf("\n");
1989
1990                 wbcFreeMemory(info);
1991                 info = NULL;
1992         }
1993
1994         wbcFreeMemory(params.blobs);
1995
1996         d_printf("plaintext password authentication %s\n",
1997                  WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
1998
1999         if (!WBC_ERROR_IS_OK(wbc_status) && (error != NULL)) {
2000                 d_fprintf(stderr,
2001                           "wbcLogonUser(%s): error code was %s (0x%x)\n"
2002                           "error message was: %s\n",
2003                           params.username,
2004                           error->nt_string,
2005                           (int)error->nt_status,
2006                           error->display_string);
2007                 wbcFreeMemory(error);
2008         }
2009         return WBC_ERROR_IS_OK(wbc_status);
2010 }
2011
2012 /* Save creds with winbind */
2013
2014 static bool wbinfo_ccache_save(char *username)
2015 {
2016         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
2017         char *s = NULL;
2018         char *p = NULL;
2019         char *password = NULL;
2020         char *name = NULL;
2021         TALLOC_CTX *frame = talloc_stackframe();
2022
2023         s = talloc_strdup(frame, username);
2024         if (s == NULL) {
2025                 return false;
2026         }
2027
2028         p = strchr(s, '%');
2029         if (p != NULL) {
2030                 *p = 0;
2031                 p++;
2032                 password = talloc_strdup(frame, p);
2033         } else {
2034                 password = wbinfo_prompt_pass(frame, NULL, username);
2035         }
2036
2037         name = s;
2038
2039         wbc_status = wbcCredentialSave(name, password);
2040
2041         d_printf("saving creds %s\n",
2042                  WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
2043
2044         TALLOC_FREE(frame);
2045
2046         return WBC_ERROR_IS_OK(wbc_status);
2047 }
2048
2049 #ifdef WITH_FAKE_KASERVER
2050 /* Authenticate a user with a plaintext password and set a token */
2051
2052 static bool wbinfo_klog(char *username)
2053 {
2054         struct winbindd_request request;
2055         struct winbindd_response response;
2056         NSS_STATUS result;
2057         char *p;
2058
2059         /* Send off request */
2060
2061         ZERO_STRUCT(request);
2062         ZERO_STRUCT(response);
2063
2064         p = strchr(username, '%');
2065
2066         if (p) {
2067                 *p = 0;
2068                 fstrcpy(request.data.auth.user, username);
2069                 fstrcpy(request.data.auth.pass, p + 1);
2070                 *p = '%';
2071         } else {
2072                 fstrcpy(request.data.auth.user, username);
2073                 (void) samba_getpass("Password: ",
2074                                      request.data.auth.pass,
2075                                      sizeof(request.data.auth.pass),
2076                                      false, false);
2077         }
2078
2079         request.flags |= WBFLAG_PAM_AFS_TOKEN;
2080
2081         result = winbindd_request_response(NULL, WINBINDD_PAM_AUTH, &request,
2082                                            &response);
2083
2084         /* Display response */
2085
2086         d_printf("plaintext password authentication %s\n",
2087                  (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
2088
2089         if (response.data.auth.nt_status)
2090                 d_fprintf(stderr,
2091                          "error code was %s (0x%x)\nerror message was: %s\n",
2092                          response.data.auth.nt_status_string,
2093                          response.data.auth.nt_status,
2094                          response.data.auth.error_string);
2095
2096         if (result != NSS_STATUS_SUCCESS)
2097                 return false;
2098
2099         if (response.extra_data.data == NULL) {
2100                 d_fprintf(stderr, "Did not get token data\n");
2101                 return false;
2102         }
2103
2104         if (!afs_settoken_str((char *)response.extra_data.data)) {
2105                 d_fprintf(stderr, "Could not set token\n");
2106                 return false;
2107         }
2108
2109         d_printf("Successfully created AFS token\n");
2110         return true;
2111 }
2112 #else
2113 static bool wbinfo_klog(char *username)
2114 {
2115         d_fprintf(stderr, "No AFS support compiled in.\n");
2116         return false;
2117 }
2118 #endif
2119
2120 /* Print domain users */
2121
2122 static bool print_domain_users(const char *domain)
2123 {
2124         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
2125         uint32_t i;
2126         uint32_t num_users = 0;
2127         const char **users = NULL;
2128
2129         /* Send request to winbind daemon */
2130
2131         if (domain == NULL) {
2132                 domain = get_winbind_domain();
2133         } else {
2134                 /* '.' is the special sign for our own domain */
2135                 if ((domain[0] == '\0') || strcmp(domain, ".") == 0) {
2136                         domain = get_winbind_domain();
2137                 /* '*' is the special sign for all domains */
2138                 } else if (strcmp(domain, "*") == 0) {
2139                         domain = NULL;
2140                 }
2141         }
2142
2143         wbc_status = wbcListUsers(domain, &num_users, &users);
2144         if (!WBC_ERROR_IS_OK(wbc_status)) {
2145                 return false;
2146         }
2147
2148         for (i=0; i < num_users; i++) {
2149                 d_printf("%s\n", users[i]);
2150         }
2151
2152         wbcFreeMemory(users);
2153
2154         return true;
2155 }
2156
2157 /* Print domain groups */
2158
2159 static bool print_domain_groups(const char *domain)
2160 {
2161         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
2162         uint32_t i;
2163         uint32_t num_groups = 0;
2164         const char **groups = NULL;
2165
2166         /* Send request to winbind daemon */
2167
2168         if (domain == NULL) {
2169                 domain = get_winbind_domain();
2170         } else {
2171                 /* '.' is the special sign for our own domain */
2172                 if ((domain[0] == '\0') || strcmp(domain, ".") == 0) {
2173                         domain = get_winbind_domain();
2174                 /* '*' is the special sign for all domains */
2175                 } else if (strcmp(domain, "*") == 0) {
2176                         domain = NULL;
2177                 }
2178         }
2179
2180         wbc_status = wbcListGroups(domain, &num_groups, &groups);
2181         if (!WBC_ERROR_IS_OK(wbc_status)) {
2182                 d_fprintf(stderr, "failed to call wbcListGroups: %s\n",
2183                           wbcErrorString(wbc_status));
2184                 return false;
2185         }
2186
2187         for (i=0; i < num_groups; i++) {
2188                 d_printf("%s\n", groups[i]);
2189         }
2190
2191         wbcFreeMemory(groups);
2192
2193         return true;
2194 }
2195
2196 /* Set the authorised user for winbindd access in secrets.tdb */
2197
2198 static bool wbinfo_set_auth_user(char *username)
2199 {
2200         d_fprintf(stderr, "This functionality was moved to the 'net' utility.\n"
2201                           "See 'net help setauthuser' for details.\n");
2202         return false;
2203 }
2204
2205 static void wbinfo_get_auth_user(void)
2206 {
2207         d_fprintf(stderr, "This functionality was moved to the 'net' utility.\n"
2208                           "See 'net help getauthuser' for details.\n");
2209 }
2210
2211 static bool wbinfo_ping(void)
2212 {
2213         wbcErr wbc_status;
2214
2215         wbc_status = wbcPing();
2216
2217         /* Display response */
2218
2219         d_printf("Ping to winbindd %s\n",
2220                  WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
2221
2222         return WBC_ERROR_IS_OK(wbc_status);
2223 }
2224
2225 static bool wbinfo_change_user_password(const char *username)
2226 {
2227         wbcErr wbc_status;
2228         char *old_password = NULL;
2229         char *new_password = NULL;
2230         TALLOC_CTX *frame = talloc_tos();
2231
2232         old_password = wbinfo_prompt_pass(frame, "old", username);
2233         new_password = wbinfo_prompt_pass(frame, "new", username);
2234
2235         wbc_status = wbcChangeUserPassword(username, old_password,new_password);
2236
2237         /* Display response */
2238
2239         d_printf("Password change for user %s %s\n", username,
2240                 WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
2241
2242         return WBC_ERROR_IS_OK(wbc_status);
2243 }
2244
2245 /* Main program */
2246
2247 enum {
2248         OPT_SET_AUTH_USER = 1000,
2249         OPT_GET_AUTH_USER,
2250         OPT_DOMAIN_NAME,
2251         OPT_SEQUENCE,
2252         OPT_GETDCNAME,
2253         OPT_DSGETDCNAME,
2254         OPT_DC_INFO,
2255         OPT_USERDOMGROUPS,
2256         OPT_SIDALIASES,
2257         OPT_USERSIDS,
2258         OPT_LOOKUP_SIDS,
2259         OPT_ALLOCATE_UID,
2260         OPT_ALLOCATE_GID,
2261         OPT_SET_UID_MAPPING,
2262         OPT_SET_GID_MAPPING,
2263         OPT_REMOVE_UID_MAPPING,
2264         OPT_REMOVE_GID_MAPPING,
2265         OPT_SIDS_TO_XIDS,
2266         OPT_XIDS_TO_SIDS,
2267         OPT_SEPARATOR,
2268         OPT_LIST_ALL_DOMAINS,
2269         OPT_LIST_OWN_DOMAIN,
2270         OPT_UID_INFO,
2271         OPT_USER_SIDINFO,
2272         OPT_GROUP_INFO,
2273         OPT_GID_INFO,
2274         OPT_VERBOSE,
2275         OPT_ONLINESTATUS,
2276         OPT_CHANGE_USER_PASSWORD,
2277         OPT_CCACHE_SAVE,
2278         OPT_SID_TO_FULLNAME,
2279         OPT_NTLMV1,
2280         OPT_NTLMV2,
2281         OPT_PAM_LOGON,
2282         OPT_LOGOFF,
2283         OPT_LOGOFF_USER,
2284         OPT_LOGOFF_UID,
2285         OPT_LANMAN,
2286         OPT_KRB5CCNAME
2287 };
2288
2289 int main(int argc, const char **argv, char **envp)
2290 {
2291         int opt;
2292         TALLOC_CTX *frame = talloc_stackframe();
2293         poptContext pc;
2294         static char *string_arg;
2295         char *string_subarg = NULL;
2296         static char *opt_domain_name;
2297         static int int_arg;
2298         int int_subarg = -1;
2299         int result = 1;
2300         bool verbose = false;
2301         bool use_ntlmv2 = true;
2302         bool use_lanman = false;
2303         char *logoff_user = getenv("USER");
2304         int logoff_uid = geteuid();
2305         const char *opt_krb5ccname = "FILE";
2306
2307         struct poptOption long_options[] = {
2308                 POPT_AUTOHELP
2309
2310                 /* longName, shortName, argInfo, argPtr, value, descrip,
2311                    argDesc */
2312
2313                 {
2314                         .longName   = "domain-users",
2315                         .shortName  = 'u',
2316                         .argInfo    = POPT_ARG_NONE,
2317                         .val        = 'u',
2318                         .descrip    = "Lists all domain users",
2319                         .argDescrip = "domain"
2320                 },
2321                 {
2322                         .longName   = "domain-groups",
2323                         .shortName  = 'g',
2324                         .argInfo    = POPT_ARG_NONE,
2325                         .val        = 'g',
2326                         .descrip    = "Lists all domain groups",
2327                         .argDescrip = "domain"
2328                 },
2329                 {
2330                         .longName   = "WINS-by-name",
2331                         .shortName  = 'N',
2332                         .argInfo    = POPT_ARG_STRING,
2333                         .arg        = &string_arg,
2334                         .val        = 'N',
2335                         .descrip    = "Converts NetBIOS name to IP",
2336                         .argDescrip = "NETBIOS-NAME"
2337                 },
2338                 {
2339                         .longName   = "WINS-by-ip",
2340                         .shortName  = 'I',
2341                         .argInfo    = POPT_ARG_STRING,
2342                         .arg        = &string_arg,
2343                         .val        = 'I',
2344                         .descrip    = "Converts IP address to NetBIOS name",
2345                         .argDescrip = "IP"
2346                 },
2347                 {
2348                         .longName   = "name-to-sid",
2349                         .shortName  = 'n',
2350                         .argInfo    = POPT_ARG_STRING,
2351                         .arg        = &string_arg,
2352                         .val        = 'n',
2353                         .descrip    = "Converts name to sid",
2354                         .argDescrip = "NAME"
2355                 },
2356                 {
2357                         .longName   = "sid-to-name",
2358                         .shortName  = 's',
2359                         .argInfo    = POPT_ARG_STRING,
2360                         .arg        = &string_arg,
2361                         .val        = 's',
2362                         .descrip    = "Converts sid to name",
2363                         .argDescrip = "SID"
2364                 },
2365                 {
2366                         .longName   = "sid-to-fullname",
2367                         .argInfo    = POPT_ARG_STRING,
2368                         .arg        = &string_arg,
2369                         .val        = OPT_SID_TO_FULLNAME,
2370                         .descrip    = "Converts sid to fullname",
2371                         .argDescrip = "SID"
2372                 },
2373                 {
2374                         .longName   = "lookup-rids",
2375                         .shortName  = 'R',
2376                         .argInfo    = POPT_ARG_STRING,
2377                         .arg        = &string_arg,
2378                         .val        = 'R',
2379                         .descrip    = "Converts RIDs to names",
2380                         .argDescrip = "RIDs"
2381                 },
2382                 {
2383                         .longName   = "lookup-sids",
2384                         .argInfo    = POPT_ARG_STRING,
2385                         .arg        = &string_arg,
2386                         .val        = OPT_LOOKUP_SIDS,
2387                         .descrip    = "Converts SIDs to types and names",
2388                         .argDescrip = "Sid-List"
2389                 },
2390                 {
2391                         .longName   = "uid-to-sid",
2392                         .shortName  = 'U',
2393                         .argInfo    = POPT_ARG_INT,
2394                         .arg        = &int_arg,
2395                         .val        = 'U',
2396                         .descrip    = "Converts uid to sid",
2397                         .argDescrip = "UID"
2398                 },
2399                 {
2400                         .longName   = "gid-to-sid",
2401                         .shortName  = 'G',
2402                         .argInfo    = POPT_ARG_INT,
2403                         .arg        = &int_arg,
2404                         .val        = 'G',
2405                         .descrip    = "Converts gid to sid",
2406                         .argDescrip = "GID"
2407                 },
2408                 {
2409                         .longName   = "sid-to-uid",
2410                         .shortName  = 'S',
2411                         .argInfo    = POPT_ARG_STRING,
2412                         .arg        = &string_arg,
2413                         .val        = 'S',
2414                         .descrip    = "Converts sid to uid",
2415                         .argDescrip = "SID"
2416                 },
2417                 {
2418                         .longName   = "sid-to-gid",
2419                         .shortName  = 'Y',
2420                         .argInfo    = POPT_ARG_STRING,
2421                         .arg        = &string_arg,
2422                         .val        = 'Y',
2423                         .descrip    = "Converts sid to gid",
2424                         .argDescrip = "SID"
2425                 },
2426                 {
2427                         .longName   = "allocate-uid",
2428                         .argInfo    = POPT_ARG_NONE,
2429                         .val        = OPT_ALLOCATE_UID,
2430                         .descrip    = "Get a new UID out of idmap"
2431                 },
2432                 {
2433                         .longName   = "allocate-gid",
2434                         .argInfo    = POPT_ARG_NONE,
2435                         .val        = OPT_ALLOCATE_GID,
2436                         .descrip    = "Get a new GID out of idmap"
2437                 },
2438                 {
2439                         .longName   = "set-uid-mapping",
2440                         .argInfo    = POPT_ARG_STRING,
2441                         .arg        = &string_arg,
2442                         .val        = OPT_SET_UID_MAPPING,
2443                         .descrip    = "Create or modify uid to sid mapping in "
2444                                       "idmap",
2445                         .argDescrip = "UID,SID"
2446                 },
2447                 {
2448                         .longName   = "set-gid-mapping",
2449                         .argInfo    = POPT_ARG_STRING,
2450                         .arg        = &string_arg,
2451                         .val        = OPT_SET_GID_MAPPING,
2452                         .descrip    = "Create or modify gid to sid mapping in "
2453                                       "idmap",
2454                         .argDescrip = "GID,SID"
2455                 },
2456                 {
2457                         .longName   = "remove-uid-mapping",
2458                         .argInfo    = POPT_ARG_STRING,
2459                         .arg        = &string_arg,
2460                         .val        = OPT_REMOVE_UID_MAPPING,
2461                         .descrip    = "Remove uid to sid mapping in idmap",
2462                         .argDescrip = "UID,SID"
2463                 },
2464                 {
2465                         .longName   = "remove-gid-mapping",
2466                         .argInfo    = POPT_ARG_STRING,
2467                         .arg        = &string_arg,
2468                         .val        = OPT_REMOVE_GID_MAPPING,
2469                         .descrip    = "Remove gid to sid mapping in idmap",
2470                         .argDescrip = "GID,SID",
2471                 },
2472                 {
2473                         .longName   = "sids-to-unix-ids",
2474                         .argInfo    = POPT_ARG_STRING,
2475                         .arg        = &string_arg,
2476                         .val        = OPT_SIDS_TO_XIDS,
2477                         .descrip    = "Translate SIDs to Unix IDs",
2478                         .argDescrip = "Sid-List",
2479                 },
2480                 {
2481                         .longName   = "unix-ids-to-sids",
2482                         .argInfo    = POPT_ARG_STRING,
2483                         .arg        = &string_arg,
2484                         .val        = OPT_XIDS_TO_SIDS,
2485                         .descrip    = "Translate Unix IDs to SIDs",
2486                         .argDescrip = "ID-List (u<num> g<num>)",
2487                 },
2488                 {
2489                         .longName   = "check-secret",
2490                         .shortName  = 't',
2491                         .argInfo    = POPT_ARG_NONE,
2492                         .val        = 't',
2493                         .descrip    = "Check shared secret",
2494                 },
2495                 {
2496                         .longName   = "change-secret",
2497                         .shortName  = 'c',
2498                         .argInfo    = POPT_ARG_NONE,
2499                         .val        = 'c',
2500                         .descrip    = "Change shared secret",
2501                 },
2502                 {
2503                         .longName   = "ping-dc",
2504                         .shortName  = 'P',
2505                         .argInfo    = POPT_ARG_NONE,
2506                         .val        = 'P',
2507                         .descrip    = "Check the NETLOGON connection",
2508                 },
2509                 {
2510                         .longName   = "trusted-domains",
2511                         .shortName  = 'm',
2512                         .argInfo    = POPT_ARG_NONE,
2513                         .val        = 'm',
2514                         .descrip    = "List trusted domains",
2515                 },
2516                 {
2517                         .longName   = "all-domains",
2518                         .argInfo    = POPT_ARG_NONE,
2519                         .val        = OPT_LIST_ALL_DOMAINS,
2520                         .descrip    = "List all domains (trusted and own "
2521                                       "domain)",
2522                 },
2523                 {
2524                         .longName   = "own-domain",
2525                         .argInfo    = POPT_ARG_NONE,
2526                         .val        = OPT_LIST_OWN_DOMAIN,
2527                         .descrip    = "List own domain",
2528                 },
2529                 {
2530                         .longName   = "sequence",
2531                         .argInfo    = POPT_ARG_NONE,
2532                         .val        = OPT_SEQUENCE,
2533                         .descrip    = "Deprecated command, see --online-status",
2534                 },
2535                 {
2536                         .longName   = "online-status",
2537                         .argInfo    = POPT_ARG_NONE,
2538                         .val        = OPT_ONLINESTATUS,
2539                         .descrip    = "Show whether domains maintain an active "
2540                                       "connection",
2541                 },
2542                 {
2543                         .longName   = "domain-info",
2544                         .shortName  = 'D',
2545                         .argInfo    = POPT_ARG_STRING,
2546                         .arg        = &string_arg,
2547                         .val        = 'D',
2548                         .descrip    = "Show most of the info we have about the "
2549                                       "domain",
2550                 },
2551                 {
2552                         .longName   = "user-info",
2553                         .shortName  = 'i',
2554                         .argInfo    = POPT_ARG_STRING,
2555                         .arg        = &string_arg,
2556                         .val        = 'i',
2557                         .descrip    = "Get user info",
2558                         .argDescrip = "USER",
2559                 },
2560                 {
2561                         .longName   = "uid-info",
2562                         .argInfo    = POPT_ARG_INT,
2563                         .arg        = &int_arg,
2564                         .val        = OPT_UID_INFO,
2565                         .descrip    = "Get user info from uid",
2566                         .argDescrip = "UID",
2567                 },
2568                 {
2569                         .longName   = "group-info",
2570                         .argInfo    = POPT_ARG_STRING,
2571                         .arg        = &string_arg,
2572                         .val        = OPT_GROUP_INFO,
2573                         .descrip    = "Get group info",
2574                         .argDescrip = "GROUP",
2575                 },
2576                 {
2577                         .longName   = "user-sidinfo",
2578                         .argInfo    = POPT_ARG_STRING,
2579                         .arg        = &string_arg,
2580                         .val        = OPT_USER_SIDINFO,
2581                         .descrip    = "Get user info from sid",
2582                         .argDescrip = "SID",
2583                 },
2584                 {
2585                         .longName   = "gid-info",
2586                         .argInfo    = POPT_ARG_INT,
2587                         .arg        = &int_arg,
2588                         .val        = OPT_GID_INFO,
2589                         .descrip    = "Get group info from gid",
2590                         .argDescrip = "GID",
2591                 },
2592                 {
2593                         .longName   = "user-groups",
2594                         .shortName  = 'r',
2595                         .argInfo    = POPT_ARG_STRING,
2596                         .arg        = &string_arg,
2597                         .val        = 'r',
2598                         .descrip    = "Get user groups",
2599                         .argDescrip = "USER",
2600                 },
2601                 {
2602                         .longName   = "user-domgroups",
2603                         .argInfo    = POPT_ARG_STRING,
2604                         .arg        = &string_arg,
2605                         .val        = OPT_USERDOMGROUPS,
2606                         .descrip    = "Get user domain groups",
2607                         .argDescrip = "SID",
2608                 },
2609                 {
2610                         .longName   = "sid-aliases",
2611                         .argInfo    = POPT_ARG_STRING,
2612                         .arg        = &string_arg,
2613                         .val        = OPT_SIDALIASES,
2614                         .descrip    = "Get sid aliases",
2615                         .argDescrip = "SID",
2616                 },
2617                 {
2618                         .longName   = "user-sids",
2619                         .argInfo    = POPT_ARG_STRING,
2620                         .arg        = &string_arg,
2621                         .val        = OPT_USERSIDS,
2622                         .descrip    = "Get user group sids for user SID",
2623                         .argDescrip = "SID",
2624                 },
2625                 {
2626                         .longName   = "authenticate",
2627                         .shortName  = 'a',
2628                         .argInfo    = POPT_ARG_STRING,
2629                         .arg        = &string_arg,
2630                         .val        = 'a',
2631                         .descrip    = "authenticate user",
2632                         .argDescrip = "user%password",
2633                 },
2634                 {
2635                         .longName   = "pam-logon",
2636                         .argInfo    = POPT_ARG_STRING,
2637                         .arg        = &string_arg,
2638                         .val        = OPT_PAM_LOGON,
2639                         .descrip    = "do a pam logon equivalent",
2640                         .argDescrip = "user%password",
2641                 },
2642                 {
2643                         .longName   = "logoff",
2644                         .argInfo    = POPT_ARG_NONE,
2645                         .val        = OPT_LOGOFF,
2646                         .descrip    = "log off user",
2647                         .argDescrip = "uid",
2648                 },
2649                 {
2650                         .longName   = "logoff-user",
2651                         .argInfo    = POPT_ARG_STRING,
2652                         .arg        = &logoff_user,
2653                         .val        = OPT_LOGOFF_USER,
2654                         .descrip    = "username to log off"
2655                 },
2656                 {
2657                         .longName   = "logoff-uid",
2658                         .argInfo    = POPT_ARG_INT,
2659                         .arg        = &logoff_uid,
2660                         .val        = OPT_LOGOFF_UID,
2661                         .descrip    = "uid to log off",
2662                 },
2663                 {
2664                         .longName   = "set-auth-user",
2665                         .argInfo    = POPT_ARG_STRING,
2666                         .arg        = &string_arg,
2667                         .val        = OPT_SET_AUTH_USER,
2668                         .descrip    = "Store user and password used by "
2669                                       "winbindd (root only)",
2670                         .argDescrip = "user%password",
2671                 },
2672                 {
2673                         .longName   = "ccache-save",
2674                         .shortName  = 0,
2675                         .argInfo    = POPT_ARG_STRING,
2676                         .arg        = &string_arg,
2677                         .val        = OPT_CCACHE_SAVE,
2678                         .descrip    = "Store user and password for ccache "
2679                                       "operation",
2680                         .argDescrip = "user%password",
2681                 },
2682                 {
2683                         .longName   = "getdcname",
2684                         .argInfo    = POPT_ARG_STRING,
2685                         .arg        = &string_arg,
2686                         .val        = OPT_GETDCNAME,
2687                         .descrip    = "Get a DC name for a foreign domain",
2688                         .argDescrip = "domainname",
2689                 },
2690                 {
2691                         .longName   = "dsgetdcname",
2692                         .argInfo    = POPT_ARG_STRING,
2693                         .arg        = &string_arg,
2694                         .val        = OPT_DSGETDCNAME,
2695                         .descrip    = "Find a DC for a domain",
2696                         .argDescrip = "domainname",
2697                 },
2698                 {
2699                         .longName   = "dc-info",
2700                         .argInfo    = POPT_ARG_STRING,
2701                         .arg        = &string_arg,
2702                         .val        = OPT_DC_INFO,
2703                         .descrip    = "Find the currently known DCs",
2704                         .argDescrip = "domainname",
2705                 },
2706                 {
2707                         .longName   = "get-auth-user",
2708                         .argInfo    = POPT_ARG_NONE,
2709                         .val        = OPT_GET_AUTH_USER,
2710                         .descrip    = "Retrieve user and password used by "
2711                                       "winbindd (root only)",
2712                 },
2713                 {
2714                         .longName   = "ping",
2715                         .shortName  = 'p',
2716                         .argInfo    = POPT_ARG_NONE,
2717                         .arg        = 0,
2718                         .val        = 'p',
2719                         .descrip    = "Ping winbindd to see if it is alive",
2720                 },
2721                 {
2722                         .longName   = "domain",
2723                         .shortName  = 0,
2724                         .argInfo    = POPT_ARG_STRING,
2725                         .arg        = &opt_domain_name,
2726                         .val        = OPT_DOMAIN_NAME,
2727                         .descrip    = "Define to the domain to restrict "
2728                                       "operation",
2729                         .argDescrip = "domain",
2730                 },
2731 #ifdef WITH_FAKE_KASERVER
2732                 {
2733                         .longName   = "klog",
2734                         .shortName  = 'k',
2735                         .argInfo    = POPT_ARG_STRING,
2736                         .arg        = &string_arg,
2737                         .val        = 'k',
2738                         .descrip    = "set an AFS token from winbind",
2739                         .argDescrip = "user%password",
2740                 },
2741 #endif
2742 #ifdef HAVE_KRB5
2743                 {
2744                         .longName   = "krb5auth",
2745                         .shortName  = 'K',
2746                         .argInfo    = POPT_ARG_STRING,
2747                         .arg        = &string_arg,
2748                         .val        = 'K',
2749                         .descrip    = "authenticate user using Kerberos",
2750                         .argDescrip = "user%password",
2751                 },
2752                         /* destroys wbinfo --help output */
2753                         /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" },
2754                         */
2755                 {
2756                         .longName   = "krb5ccname",
2757                         .argInfo    = POPT_ARG_STRING,
2758                         .arg        = &opt_krb5ccname,
2759                         .val        = OPT_KRB5CCNAME,
2760                         .descrip    = "authenticate user using Kerberos and "
2761                                       "specific credential cache type",
2762                         .argDescrip = "krb5ccname",
2763                 },
2764 #endif
2765                 {
2766                         .longName   = "separator",
2767                         .argInfo    = POPT_ARG_NONE,
2768                         .val        = OPT_SEPARATOR,
2769                         .descrip    = "Get the active winbind separator",
2770                 },
2771                 {
2772                         .longName   = "verbose",
2773                         .argInfo    = POPT_ARG_NONE,
2774                         .val        = OPT_VERBOSE,
2775                         .descrip    = "Print additional information per command",
2776                 },
2777                 {
2778                         .longName   = "change-user-password",
2779                         .argInfo    = POPT_ARG_STRING,
2780                         .arg        = &string_arg,
2781                         .val        = OPT_CHANGE_USER_PASSWORD,
2782                         .descrip    = "Change the password for a user",
2783                 },
2784                 {
2785                         .longName   = "ntlmv1",
2786                         .argInfo    = POPT_ARG_NONE,
2787                         .val        = OPT_NTLMV1,
2788                         .descrip    = "Use NTLMv1 cryptography for user authentication",
2789                 },
2790                 {
2791                         .longName   = "ntlmv2",
2792                         .argInfo    = POPT_ARG_NONE,
2793                         .val        = OPT_NTLMV2,
2794                         .descrip    = "Use NTLMv2 cryptography for user authentication",
2795                 },
2796                 {
2797                         .longName   = "lanman",
2798                         .argInfo    = POPT_ARG_NONE,
2799                         .val        = OPT_LANMAN,
2800                         .descrip    = "Use lanman cryptography for user authentication",
2801                 },
2802                 POPT_COMMON_VERSION
2803                 POPT_TABLEEND
2804         };
2805
2806         /* Samba client initialisation */
2807         smb_init_locale();
2808
2809
2810         /* Parse options */
2811
2812         pc = poptGetContext("wbinfo", argc, argv,
2813                             long_options, 0);
2814
2815         /* Parse command line options */
2816
2817         if (argc == 1) {
2818                 poptPrintHelp(pc, stderr, 0);
2819                 return 1;
2820         }
2821
2822         while((opt = poptGetNextOpt(pc)) != -1) {
2823                 /* get the generic configuration parameters like --domain */
2824                 switch (opt) {
2825                 case OPT_VERBOSE:
2826                         verbose = true;
2827                         break;
2828                 case OPT_NTLMV1:
2829                         use_ntlmv2 = false;
2830                         break;
2831                 case OPT_LANMAN:
2832                         use_lanman = true;
2833                         break;
2834                 }
2835         }
2836
2837         poptFreeContext(pc);
2838
2839         pc = poptGetContext(NULL, argc, (const char **)argv, long_options,
2840                             POPT_CONTEXT_KEEP_FIRST);
2841
2842         while((opt = poptGetNextOpt(pc)) != -1) {
2843                 switch (opt) {
2844                 case 'u':
2845                         if (!print_domain_users(opt_domain_name)) {
2846                                 d_fprintf(stderr,
2847                                           "Error looking up domain users\n");
2848                                 goto done;
2849                         }
2850                         break;
2851                 case 'g':
2852                         if (!print_domain_groups(opt_domain_name)) {
2853                                 d_fprintf(stderr,
2854                                           "Error looking up domain groups\n");
2855                                 goto done;
2856                         }
2857                         break;
2858                 case 's':
2859                         if (!wbinfo_lookupsid(string_arg)) {
2860                                 d_fprintf(stderr,
2861                                           "Could not lookup sid %s\n",
2862                                           string_arg);
2863                                 goto done;
2864                         }
2865                         break;
2866                 case OPT_SID_TO_FULLNAME:
2867                         if (!wbinfo_lookupsid_fullname(string_arg)) {
2868                                 d_fprintf(stderr, "Could not lookup sid %s\n",
2869                                           string_arg);
2870                                 goto done;
2871                         }
2872                         break;
2873                 case 'R':
2874                         if (!wbinfo_lookuprids(opt_domain_name, string_arg)) {
2875                                 d_fprintf(stderr, "Could not lookup RIDs %s\n",
2876                                           string_arg);
2877                                 goto done;
2878                         }
2879                         break;
2880                 case OPT_LOOKUP_SIDS:
2881                         if (!wbinfo_lookup_sids(string_arg)) {
2882                                 d_fprintf(stderr, "Could not lookup SIDs %s\n",
2883                                           string_arg);
2884                                 goto done;
2885                         }
2886                         break;
2887                 case 'n':
2888                         if (!wbinfo_lookupname(string_arg)) {
2889                                 d_fprintf(stderr, "Could not lookup name %s\n",
2890                                           string_arg);
2891                                 goto done;
2892                         }
2893                         break;
2894                 case 'N':
2895                         if (!wbinfo_wins_byname(string_arg)) {
2896                                 d_fprintf(stderr,
2897                                           "Could not lookup WINS by name %s\n",
2898                                           string_arg);
2899                                 goto done;
2900                         }
2901                         break;
2902                 case 'I':
2903                         if (!wbinfo_wins_byip(string_arg)) {
2904                                 d_fprintf(stderr,
2905                                           "Could not lookup WINS by IP %s\n",
2906                                           string_arg);
2907                                 goto done;
2908                         }
2909                         break;
2910                 case 'U':
2911                         if (!wbinfo_uid_to_sid(int_arg)) {
2912                                 d_fprintf(stderr,
2913                                           "Could not convert uid %d to sid\n",
2914                                           int_arg);
2915                                 goto done;
2916                         }
2917                         break;
2918                 case 'G':
2919                         if (!wbinfo_gid_to_sid(int_arg)) {
2920                                 d_fprintf(stderr,
2921                                           "Could not convert gid %d to sid\n",
2922                                           int_arg);
2923                                 goto done;
2924                         }
2925                         break;
2926                 case 'S':
2927                         if (!wbinfo_sid_to_uid(string_arg)) {
2928                                 d_fprintf(stderr,
2929                                           "Could not convert sid %s to uid\n",
2930                                           string_arg);
2931                                 goto done;
2932                         }
2933                         break;
2934                 case 'Y':
2935                         if (!wbinfo_sid_to_gid(string_arg)) {
2936                                 d_fprintf(stderr,
2937                                           "Could not convert sid %s to gid\n",
2938                                           string_arg);
2939                                 goto done;
2940                         }
2941                         break;
2942                 case OPT_ALLOCATE_UID:
2943                         if (!wbinfo_allocate_uid()) {
2944                                 d_fprintf(stderr, "Could not allocate a uid\n");
2945                                 goto done;
2946                         }
2947                         break;
2948                 case OPT_ALLOCATE_GID:
2949                         if (!wbinfo_allocate_gid()) {
2950                                 d_fprintf(stderr, "Could not allocate a gid\n");
2951                                 goto done;
2952                         }
2953                         break;
2954                 case OPT_SET_UID_MAPPING:
2955                         if (!parse_mapping_arg(string_arg, &int_subarg,
2956                                 &string_subarg) ||
2957                             !wbinfo_set_uid_mapping(int_subarg, string_subarg))
2958                         {
2959                                 d_fprintf(stderr, "Could not create or modify "
2960                                           "uid to sid mapping\n");
2961                                 goto done;
2962                         }
2963                         break;
2964                 case OPT_SET_GID_MAPPING:
2965                         if (!parse_mapping_arg(string_arg, &int_subarg,
2966                                 &string_subarg) ||
2967                             !wbinfo_set_gid_mapping(int_subarg, string_subarg))
2968                         {
2969                                 d_fprintf(stderr, "Could not create or modify "
2970                                           "gid to sid mapping\n");
2971                                 goto done;
2972                         }
2973                         break;
2974                 case OPT_REMOVE_UID_MAPPING:
2975                         if (!parse_mapping_arg(string_arg, &int_subarg,
2976                                 &string_subarg) ||
2977                             !wbinfo_remove_uid_mapping(int_subarg,
2978                                 string_subarg))
2979                         {
2980                                 d_fprintf(stderr, "Could not remove uid to sid "
2981                                     "mapping\n");
2982                                 goto done;
2983                         }
2984                         break;
2985                 case OPT_REMOVE_GID_MAPPING:
2986                         if (!parse_mapping_arg(string_arg, &int_subarg,
2987                                 &string_subarg) ||
2988                             !wbinfo_remove_gid_mapping(int_subarg,
2989                                 string_subarg))
2990                         {
2991                                 d_fprintf(stderr, "Could not remove gid to sid "
2992                                     "mapping\n");
2993                                 goto done;
2994                         }
2995                         break;
2996                 case OPT_SIDS_TO_XIDS:
2997                         if (!wbinfo_sids_to_unix_ids(string_arg)) {
2998                                 d_fprintf(stderr, "wbinfo_sids_to_unix_ids "
2999                                           "failed\n");
3000                                 goto done;
3001                         }
3002                         break;
3003                 case OPT_XIDS_TO_SIDS:
3004                         if (!wbinfo_xids_to_sids(string_arg)) {
3005                                 d_fprintf(stderr, "wbinfo_xids_to_sids "
3006                                           "failed\n");
3007                                 goto done;
3008                         }
3009                         break;
3010                 case 't':
3011                         if (!wbinfo_check_secret(opt_domain_name)) {
3012                                 d_fprintf(stderr, "Could not check secret\n");
3013                                 goto done;
3014                         }
3015                         break;
3016                 case 'c':
3017                         if (!wbinfo_change_secret(opt_domain_name)) {
3018                                 d_fprintf(stderr, "Could not change secret\n");
3019                                 goto done;
3020                         }
3021                         break;
3022                 case 'P':
3023                         if (!wbinfo_ping_dc(opt_domain_name)) {
3024                                 goto done;
3025                         }
3026                         break;
3027                 case 'm':
3028                         if (!wbinfo_list_domains(false, verbose)) {
3029                                 d_fprintf(stderr,
3030                                           "Could not list trusted domains\n");
3031                                 goto done;
3032                         }
3033                         break;
3034                 case OPT_SEQUENCE:
3035                         if (!wbinfo_show_sequence(opt_domain_name)) {
3036                                 d_fprintf(stderr,
3037                                           "Could not show sequence numbers\n");
3038                                 goto done;
3039                         }
3040                         break;
3041                 case OPT_ONLINESTATUS:
3042                         if (!wbinfo_show_onlinestatus(opt_domain_name)) {
3043                                 d_fprintf(stderr,
3044                                           "Could not show online-status\n");
3045                                 goto done;
3046                         }
3047                         break;
3048                 case 'D':
3049                         if (!wbinfo_domain_info(string_arg)) {
3050                                 d_fprintf(stderr,
3051                                           "Could not get domain info\n");
3052                                 goto done;
3053                         }
3054                         break;
3055                 case 'i':
3056                         if (!wbinfo_get_userinfo(string_arg)) {
3057                                 d_fprintf(stderr,
3058                                           "Could not get info for user %s\n",
3059                                           string_arg);
3060                                 goto done;
3061                         }
3062                         break;
3063                 case OPT_USER_SIDINFO:
3064                         if ( !wbinfo_get_user_sidinfo(string_arg)) {
3065                                 d_fprintf(stderr,
3066                                           "Could not get info for user "
3067                                           "sid %s\n", string_arg);
3068                                 goto done;
3069                         }
3070                         break;
3071                 case OPT_UID_INFO:
3072                         if ( !wbinfo_get_uidinfo(int_arg)) {
3073                                 d_fprintf(stderr, "Could not get info for uid "
3074                                                 "%d\n", int_arg);
3075                                 goto done;
3076                         }
3077                         break;
3078                 case OPT_GROUP_INFO:
3079                         if ( !wbinfo_get_groupinfo(string_arg)) {
3080                                 d_fprintf(stderr, "Could not get info for "
3081                                           "group %s\n", string_arg);
3082                                 goto done;
3083                         }
3084                         break;
3085                 case OPT_GID_INFO:
3086                         if ( !wbinfo_get_gidinfo(int_arg)) {
3087                                 d_fprintf(stderr, "Could not get info for gid "
3088                                                 "%d\n", int_arg);
3089                                 goto done;
3090                         }
3091                         break;
3092                 case 'r':
3093                         if (!wbinfo_get_usergroups(string_arg)) {
3094                                 d_fprintf(stderr,
3095                                           "Could not get groups for user %s\n",
3096                                           string_arg);
3097                                 goto done;
3098                         }
3099                         break;
3100                 case OPT_USERSIDS:
3101                         if (!wbinfo_get_usersids(string_arg)) {
3102                                 d_fprintf(stderr, "Could not get group SIDs "
3103                                           "for user SID %s\n",
3104                                           string_arg);
3105                                 goto done;
3106                         }
3107                         break;
3108                 case OPT_USERDOMGROUPS:
3109                         if (!wbinfo_get_userdomgroups(string_arg)) {
3110                                 d_fprintf(stderr, "Could not get user's domain "
3111                                          "groups for user SID %s\n",
3112                                          string_arg);
3113                                 goto done;
3114                         }
3115                         break;
3116                 case OPT_SIDALIASES:
3117                         if (!wbinfo_get_sidaliases(opt_domain_name,
3118                                                    string_arg)) {
3119                                 d_fprintf(stderr, "Could not get sid aliases "
3120                                          "for user SID %s\n", string_arg);
3121                                 goto done;
3122                         }
3123                         break;
3124                 case 'a': {
3125                                 bool got_error = false;
3126
3127                                 if (!wbinfo_auth(string_arg)) {
3128                                         d_fprintf(stderr,
3129                                                   "Could not authenticate user "
3130                                                   "%s with plaintext "
3131                                                   "password\n", string_arg);
3132                                         got_error = true;
3133                                 }
3134
3135                                 if (!wbinfo_auth_crap(string_arg, use_ntlmv2,
3136                                                       use_lanman)) {
3137                                         d_fprintf(stderr,
3138                                                 "Could not authenticate user "
3139                                                 "%s with challenge/response\n",
3140                                                 string_arg);
3141                                         got_error = true;
3142                                 }
3143
3144                                 if (got_error)
3145                                         goto done;
3146                                 break;
3147                         }
3148                 case OPT_PAM_LOGON:
3149                         if (!wbinfo_pam_logon(string_arg, verbose)) {
3150                                 d_fprintf(stderr, "pam_logon failed for %s\n",
3151                                           string_arg);
3152                                 goto done;
3153                         }
3154                         break;
3155                 case OPT_LOGOFF:
3156                 {
3157                         wbcErr wbc_status;
3158
3159                         wbc_status = wbcLogoffUser(logoff_user, logoff_uid,
3160                                                    "");
3161                         d_printf("Logoff %s (%d): %s\n", logoff_user,
3162                                  logoff_uid, wbcErrorString(wbc_status));
3163                         break;
3164                 }
3165                 case 'K': {
3166                                 uint32_t flags = WBFLAG_PAM_KRB5 |
3167                                                  WBFLAG_PAM_CACHED_LOGIN |
3168                                                 WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
3169                                                  WBFLAG_PAM_INFO3_TEXT |
3170                                                  WBFLAG_PAM_CONTACT_TRUSTDOM;
3171
3172                                 if (!wbinfo_auth_krb5(string_arg, opt_krb5ccname,
3173                                                       flags)) {
3174                                         d_fprintf(stderr,
3175                                                 "Could not authenticate user "
3176                                                 "[%s] with Kerberos "
3177                                                 "(ccache: %s)\n", string_arg,
3178                                                 opt_krb5ccname);
3179                                         goto done;
3180                                 }
3181                                 break;
3182                         }
3183                 case 'k':
3184                         if (!wbinfo_klog(string_arg)) {
3185                                 d_fprintf(stderr, "Could not klog user\n");
3186                                 goto done;
3187                         }
3188                         break;
3189                 case 'p':
3190                         if (!wbinfo_ping()) {
3191                                 d_fprintf(stderr, "could not ping winbindd!\n");
3192                                 goto done;
3193                         }
3194                         break;
3195                 case OPT_SET_AUTH_USER:
3196                         if (!wbinfo_set_auth_user(string_arg)) {
3197                                 goto done;
3198                         }
3199                         break;
3200                 case OPT_GET_AUTH_USER:
3201                         wbinfo_get_auth_user();
3202                         goto done;
3203                         break;
3204                 case OPT_CCACHE_SAVE:
3205                         if (!wbinfo_ccache_save(string_arg)) {
3206                                 goto done;
3207                         }
3208                         break;
3209                 case OPT_GETDCNAME:
3210                         if (!wbinfo_getdcname(string_arg)) {
3211                                 goto done;
3212                         }
3213                         break;
3214                 case OPT_DSGETDCNAME:
3215                         if (!wbinfo_dsgetdcname(string_arg, 0)) {
3216                                 goto done;
3217                         }
3218                         break;
3219                 case OPT_DC_INFO:
3220                         if (!wbinfo_dc_info(string_arg)) {
3221                                 goto done;
3222                         }
3223                         break;
3224                 case OPT_SEPARATOR: {
3225                         const char sep = winbind_separator();
3226                         if ( !sep ) {
3227                                 goto done;
3228                         }
3229                         d_printf("%c\n", sep);
3230                         break;
3231                 }
3232                 case OPT_LIST_ALL_DOMAINS:
3233                         if (!wbinfo_list_domains(true, verbose)) {
3234                                 goto done;
3235                         }
3236                         break;
3237                 case OPT_LIST_OWN_DOMAIN:
3238                         if (!wbinfo_list_own_domain()) {
3239                                 goto done;
3240                         }
3241                         break;
3242                 case OPT_CHANGE_USER_PASSWORD:
3243                         if (!wbinfo_change_user_password(string_arg)) {
3244                                 d_fprintf(stderr,
3245                                         "Could not change user password "
3246                                          "for user %s\n", string_arg);
3247                                 goto done;
3248                         }
3249                         break;
3250
3251                 /* generic configuration options */
3252                 case OPT_DOMAIN_NAME:
3253                 case OPT_VERBOSE:
3254                 case OPT_NTLMV1:
3255                 case OPT_NTLMV2:
3256                 case OPT_LANMAN:
3257                 case OPT_LOGOFF_USER:
3258                 case OPT_LOGOFF_UID:
3259                 case OPT_KRB5CCNAME:
3260                         break;
3261                 default:
3262                         d_fprintf(stderr, "Invalid option\n");
3263                         poptPrintHelp(pc, stderr, 0);
3264                         goto done;
3265                 }
3266         }
3267
3268         result = 0;
3269
3270         /* Exit code */
3271
3272  done:
3273         talloc_free(frame);
3274
3275         poptFreeContext(pc);
3276         return result;
3277 }