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