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