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