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