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