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