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