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