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