Don't fill in the secrets DB unless we make the entries.
[samba.git] / source4 / nsswitch / wbinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind status program.
5
6    Copyright (C) Tim Potter      2000-2003
7    Copyright (C) Andrew Bartlett 2002-2007
8    
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 "pstring.h"
25 #include "winbind_client.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "libcli/auth/libcli_auth.h"
28 #include "libcli/security/security.h"
29 #include "lib/cmdline/popt_common.h"
30 #include "dynconfig.h"
31 #include "param/param.h"
32
33 extern int winbindd_fd;
34
35 static char winbind_separator_int(bool strict)
36 {
37         struct winbindd_response response;
38         static bool got_sep;
39         static char sep;
40
41         if (got_sep)
42                 return sep;
43
44         ZERO_STRUCT(response);
45
46         /* Send off request */
47
48         if (winbindd_request_response(WINBINDD_INFO, NULL, &response) !=
49             NSS_STATUS_SUCCESS) {
50                 d_fprintf(stderr, "could not obtain winbind separator!\n");
51                 if (strict) {
52                         return 0;
53                 }
54                 /* HACK: (this module should not call lp_ funtions) */
55                 return *lp_winbind_separator(cmdline_lp_ctx);
56         }
57
58         sep = response.data.info.winbind_separator;
59         got_sep = true;
60
61         if (!sep) {
62                 d_fprintf(stderr, "winbind separator was NULL!\n");
63                 if (strict) {
64                         return 0;
65                 }
66                 /* HACK: (this module should not call lp_ funtions) */
67                 sep = *lp_winbind_separator(cmdline_lp_ctx);
68         }
69         
70         return sep;
71 }
72
73 static char winbind_separator(void)
74 {
75         return winbind_separator_int(false);
76 }
77
78 static const char *get_winbind_domain(void)
79 {
80         struct winbindd_response response;
81         static fstring winbind_domain;
82
83         ZERO_STRUCT(response);
84
85         /* Send off request */
86
87         if (winbindd_request_response(WINBINDD_DOMAIN_NAME, NULL, &response) !=
88             NSS_STATUS_SUCCESS) {
89                 d_fprintf(stderr, "could not obtain winbind domain name!\n");
90                 
91                 /* HACK: (this module should not call lp_ funtions) */
92                 return lp_workgroup(cmdline_lp_ctx);
93         }
94
95         fstrcpy(winbind_domain, response.data.domain_name);
96
97         return winbind_domain;
98
99 }
100
101 /* Copy of parse_domain_user from winbindd_util.c.  Parse a string of the
102    form DOMAIN/user into a domain and a user */
103
104 static bool parse_wbinfo_domain_user(const char *domuser, fstring domain, 
105                                      fstring user)
106 {
107
108         char *p = strchr(domuser,winbind_separator());
109
110         if (!p) {
111                 fstrcpy(user, domuser);
112                 fstrcpy(domain, get_winbind_domain());
113                 return true;
114         }
115         
116         fstrcpy(user, p+1);
117         fstrcpy(domain, domuser);
118         domain[PTR_DIFF(p, domuser)] = 0;
119         strupper_m(domain);
120
121         return true;
122 }
123
124 /* pull pwent info for a given user */
125
126 static bool wbinfo_get_userinfo(char *user)
127 {
128         struct winbindd_request request;
129         struct winbindd_response response;
130         NSS_STATUS result;
131         
132         ZERO_STRUCT(request);
133         ZERO_STRUCT(response);
134
135         /* Send request */
136         
137         fstrcpy(request.data.username, user);
138
139         result = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
140         
141         if (result != NSS_STATUS_SUCCESS)
142                 return false;
143         
144         d_printf( "%s:%s:%d:%d:%s:%s:%s\n",
145                           response.data.pw.pw_name,
146                           response.data.pw.pw_passwd,
147                           response.data.pw.pw_uid,
148                           response.data.pw.pw_gid,
149                           response.data.pw.pw_gecos,
150                           response.data.pw.pw_dir,
151                           response.data.pw.pw_shell );
152         
153         return true;
154 }
155
156 /* pull pwent info for a given uid */
157 static bool wbinfo_get_uidinfo(int uid)
158 {
159         struct winbindd_request request;
160         struct winbindd_response response;
161         NSS_STATUS result;
162
163         ZERO_STRUCT(request);
164         ZERO_STRUCT(response);
165
166         request.data.uid = uid;
167
168         result = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
169
170         if (result != NSS_STATUS_SUCCESS)
171                 return false;
172
173         d_printf( "%s:%s:%d:%d:%s:%s:%s\n",
174                 response.data.pw.pw_name,
175                 response.data.pw.pw_passwd,
176                 response.data.pw.pw_uid,
177                 response.data.pw.pw_gid,
178                 response.data.pw.pw_gecos,
179                 response.data.pw.pw_dir,
180                 response.data.pw.pw_shell );
181
182         return true;
183 }
184
185 /* pull grent for a given group */
186 static bool wbinfo_get_groupinfo(char *group)
187 {
188         struct winbindd_request request;
189         struct winbindd_response response;
190         NSS_STATUS result;
191
192         ZERO_STRUCT(request);
193         ZERO_STRUCT(response);
194
195         /* Send request */
196
197         fstrcpy(request.data.groupname, group);
198
199         result = winbindd_request_response(WINBINDD_GETGRNAM, &request,
200                                   &response);
201
202         if ( result != NSS_STATUS_SUCCESS)
203                 return false;
204
205         d_printf( "%s:%s:%d\n",
206                   response.data.gr.gr_name,
207                   response.data.gr.gr_passwd,
208                   response.data.gr.gr_gid );
209         
210         return true;
211 }
212
213 /* List groups a user is a member of */
214
215 static bool wbinfo_get_usergroups(char *user)
216 {
217         struct winbindd_request request;
218         struct winbindd_response response;
219         NSS_STATUS result;
220         int i;
221         
222         ZERO_STRUCT(request);
223         ZERO_STRUCT(response);
224
225         /* Send request */
226
227         fstrcpy(request.data.username, user);
228
229         result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
230
231         if (result != NSS_STATUS_SUCCESS)
232                 return false;
233
234         for (i = 0; i < response.data.num_entries; i++)
235                 d_printf("%d\n", (int)((gid_t *)response.extra_data.data)[i]);
236
237         SAFE_FREE(response.extra_data.data);
238
239         return true;
240 }
241
242
243 /* List group SIDs a user SID is a member of */
244 static bool wbinfo_get_usersids(char *user_sid)
245 {
246         struct winbindd_request request;
247         struct winbindd_response response;
248         NSS_STATUS result;
249         int i;
250         const char *s;
251
252         ZERO_STRUCT(request);
253         ZERO_STRUCT(response);
254
255         /* Send request */
256         fstrcpy(request.data.sid, user_sid);
257
258         result = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response);
259
260         if (result != NSS_STATUS_SUCCESS)
261                 return false;
262
263         s = (const char *)response.extra_data.data;
264         for (i = 0; i < response.data.num_entries; i++) {
265                 d_printf("%s\n", s);
266                 s += strlen(s) + 1;
267         }
268
269         SAFE_FREE(response.extra_data.data);
270
271         return true;
272 }
273
274 static bool wbinfo_get_userdomgroups(const char *user_sid)
275 {
276         struct winbindd_request request;
277         struct winbindd_response response;
278         NSS_STATUS result;
279
280         ZERO_STRUCT(request);
281         ZERO_STRUCT(response);
282
283         /* Send request */
284         fstrcpy(request.data.sid, user_sid);
285
286         result = winbindd_request_response(WINBINDD_GETUSERDOMGROUPS, &request,
287                                   &response);
288
289         if (result != NSS_STATUS_SUCCESS)
290                 return false;
291
292         if (response.data.num_entries != 0)
293                 printf("%s", (char *)response.extra_data.data);
294         
295         SAFE_FREE(response.extra_data.data);
296
297         return true;
298 }
299
300 /* Convert NetBIOS name to IP */
301
302 static bool wbinfo_wins_byname(char *name)
303 {
304         struct winbindd_request request;
305         struct winbindd_response response;
306
307         ZERO_STRUCT(request);
308         ZERO_STRUCT(response);
309
310         /* Send request */
311
312         fstrcpy(request.data.winsreq, name);
313
314         if (winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response) !=
315             NSS_STATUS_SUCCESS) {
316                 return false;
317         }
318
319         /* Display response */
320
321         d_printf("%s\n", response.data.winsresp);
322
323         return true;
324 }
325
326 /* Convert IP to NetBIOS name */
327
328 static bool wbinfo_wins_byip(char *ip)
329 {
330         struct winbindd_request request;
331         struct winbindd_response response;
332
333         ZERO_STRUCT(request);
334         ZERO_STRUCT(response);
335
336         /* Send request */
337
338         fstrcpy(request.data.winsreq, ip);
339
340         if (winbindd_request_response(WINBINDD_WINS_BYIP, &request, &response) !=
341             NSS_STATUS_SUCCESS) {
342                 return false;
343         }
344
345         /* Display response */
346
347         d_printf("%s\n", response.data.winsresp);
348
349         return true;
350 }
351
352 /* List trusted domains */
353
354 static bool wbinfo_list_domains(bool list_all_domains)
355 {
356         struct winbindd_request request;
357         struct winbindd_response response;
358
359         ZERO_STRUCT(request);
360         ZERO_STRUCT(response);
361
362         /* Send request */
363
364         request.data.list_all_domains = list_all_domains;
365
366         if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, &request, &response) !=
367             NSS_STATUS_SUCCESS)
368                 return false;
369
370         /* Display response */
371
372         if (response.extra_data.data) {
373                 const char *extra_data = (char *)response.extra_data.data;
374                 fstring name;
375                 char *p;
376
377                 while(next_token(&extra_data, name, "\n", sizeof(fstring))) {
378                         p = strchr(name, '\\');
379                         if (p == 0) {
380                                 d_fprintf(stderr, "Got invalid response: %s\n",
381                                          extra_data);
382                                 return false;
383                         }
384                         *p = 0;
385                         d_printf("%s\n", name);
386                 }
387
388                 SAFE_FREE(response.extra_data.data);
389         }
390
391         return true;
392 }
393
394 /* List own domain */
395
396 static bool wbinfo_list_own_domain(void)
397 {
398         d_printf("%s\n", get_winbind_domain());
399
400         return true;
401 }
402
403 /* show sequence numbers */
404 static bool wbinfo_show_sequence(const char *domain)
405 {
406         struct winbindd_request  request;
407         struct winbindd_response response;
408
409         ZERO_STRUCT(response);
410         ZERO_STRUCT(request);
411
412         if ( domain )
413                 fstrcpy( request.domain_name, domain );
414
415         /* Send request */
416
417         if (winbindd_request_response(WINBINDD_SHOW_SEQUENCE, &request, &response) !=
418             NSS_STATUS_SUCCESS)
419                 return false;
420
421         /* Display response */
422
423         if (response.extra_data.data) {
424                 char *extra_data = (char *)response.extra_data.data;
425                 d_printf("%s", extra_data);
426                 SAFE_FREE(response.extra_data.data);
427         }
428
429         return true;
430 }
431
432 /* Show domain info */
433
434 static bool wbinfo_domain_info(const char *domain_name)
435 {
436         struct winbindd_request request;
437         struct winbindd_response response;
438
439         ZERO_STRUCT(request);
440         ZERO_STRUCT(response);
441
442         if ((strequal(domain_name, ".")) || (domain_name[0] == '\0'))
443                 fstrcpy(request.domain_name, get_winbind_domain());
444         else
445                 fstrcpy(request.domain_name, domain_name);
446
447         /* Send request */
448
449         if (winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response) !=
450             NSS_STATUS_SUCCESS)
451                 return false;
452
453         /* Display response */
454
455         d_printf("Name              : %s\n", response.data.domain_info.name);
456         d_printf("Alt_Name          : %s\n", response.data.domain_info.alt_name);
457
458         d_printf("SID               : %s\n", response.data.domain_info.sid);
459
460         d_printf("Active Directory  : %s\n",
461                  response.data.domain_info.active_directory ? "Yes" : "No");
462         d_printf("Native            : %s\n",
463                  response.data.domain_info.native_mode ? "Yes" : "No");
464
465         d_printf("Primary           : %s\n",
466                  response.data.domain_info.primary ? "Yes" : "No");
467
468         return true;
469 }
470
471 /* Get a foreign DC's name */
472 static bool wbinfo_getdcname(const char *domain_name)
473 {
474         struct winbindd_request request;
475         struct winbindd_response response;
476
477         ZERO_STRUCT(request);
478         ZERO_STRUCT(response);
479
480         fstrcpy(request.domain_name, domain_name);
481
482         /* Send request */
483
484         if (winbindd_request_response(WINBINDD_GETDCNAME, &request, &response) !=
485             NSS_STATUS_SUCCESS) {
486                 d_fprintf(stderr, "Could not get dc name for %s\n", domain_name);
487                 return false;
488         }
489
490         /* Display response */
491
492         d_printf("%s\n", response.data.dc_name);
493
494         return true;
495 }
496
497 /* Check trust account password */
498
499 static bool wbinfo_check_secret(void)
500 {
501         struct winbindd_response response;
502         NSS_STATUS result;
503
504         ZERO_STRUCT(response);
505
506         result = winbindd_request_response(WINBINDD_CHECK_MACHACC, NULL, &response);
507                 
508         d_printf("checking the trust secret via RPC calls %s\n", 
509                  (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
510
511         if (result != NSS_STATUS_SUCCESS)       
512                 d_fprintf(stderr, "error code was %s (0x%x)\n", 
513                          response.data.auth.nt_status_string, 
514                          response.data.auth.nt_status);
515         
516         return result == NSS_STATUS_SUCCESS;    
517 }
518
519 /* Convert uid to sid */
520
521 static bool wbinfo_uid_to_sid(uid_t uid)
522 {
523         struct winbindd_request request;
524         struct winbindd_response response;
525
526         ZERO_STRUCT(request);
527         ZERO_STRUCT(response);
528
529         /* Send request */
530
531         request.data.uid = uid;
532
533         if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) !=
534             NSS_STATUS_SUCCESS)
535                 return false;
536
537         /* Display response */
538
539         d_printf("%s\n", response.data.sid.sid);
540
541         return true;
542 }
543
544 /* Convert gid to sid */
545
546 static bool wbinfo_gid_to_sid(gid_t gid)
547 {
548         struct winbindd_request request;
549         struct winbindd_response response;
550
551         ZERO_STRUCT(request);
552         ZERO_STRUCT(response);
553
554         /* Send request */
555
556         request.data.gid = gid;
557
558         if (winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response) !=
559             NSS_STATUS_SUCCESS)
560                 return false;
561
562         /* Display response */
563
564         d_printf("%s\n", response.data.sid.sid);
565
566         return true;
567 }
568
569 /* Convert sid to uid */
570
571 static bool wbinfo_sid_to_uid(char *sid)
572 {
573         struct winbindd_request request;
574         struct winbindd_response response;
575
576         ZERO_STRUCT(request);
577         ZERO_STRUCT(response);
578
579         /* Send request */
580
581         fstrcpy(request.data.sid, sid);
582
583         if (winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response) !=
584             NSS_STATUS_SUCCESS)
585                 return false;
586
587         /* Display response */
588
589         d_printf("%d\n", (int)response.data.uid);
590
591         return true;
592 }
593
594 static bool wbinfo_sid_to_gid(char *sid)
595 {
596         struct winbindd_request request;
597         struct winbindd_response response;
598
599         ZERO_STRUCT(request);
600         ZERO_STRUCT(response);
601
602         /* Send request */
603
604         fstrcpy(request.data.sid, sid);
605
606         if (winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response) !=
607             NSS_STATUS_SUCCESS)
608                 return false;
609
610         /* Display response */
611
612         d_printf("%d\n", (int)response.data.gid);
613
614         return true;
615 }
616
617 /* Convert sid to string */
618
619 static bool wbinfo_lookupsid(char *sid)
620 {
621         struct winbindd_request request;
622         struct winbindd_response response;
623
624         ZERO_STRUCT(request);
625         ZERO_STRUCT(response);
626
627         /* Send off request */
628
629         fstrcpy(request.data.sid, sid);
630
631         if (winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response) !=
632             NSS_STATUS_SUCCESS)
633                 return false;
634
635         /* Display response */
636
637         d_printf("%s%c%s %d\n", response.data.name.dom_name, 
638                  winbind_separator(), response.data.name.name, 
639                  response.data.name.type);
640
641         return true;
642 }
643
644 static const char *sid_type_lookup(enum lsa_SidType r)
645 {
646         switch (r) {
647                 case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break;
648                 case SID_NAME_USER: return "SID_NAME_USER"; break;
649                 case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break;
650                 case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break;
651                 case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break;
652                 case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break;
653                 case SID_NAME_DELETED: return "SID_NAME_DELETED"; break;
654                 case SID_NAME_INVALID: return "SID_NAME_INVALID"; break;
655                 case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break;
656                 case SID_NAME_COMPUTER: return "SID_NAME_COMPUTER"; break;
657         }
658         return "Invalid sid type\n";
659 }
660
661 /* Convert string to sid */
662
663 static bool wbinfo_lookupname(char *name)
664 {
665         struct winbindd_request request;
666         struct winbindd_response response;
667
668         /* Send off request */
669
670         ZERO_STRUCT(request);
671         ZERO_STRUCT(response);
672
673         parse_wbinfo_domain_user(name, request.data.name.dom_name, 
674                                  request.data.name.name);
675
676         if (winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response) !=
677             NSS_STATUS_SUCCESS)
678                 return false;
679
680         /* Display response */
681
682         d_printf("%s %s (%d)\n", response.data.sid.sid, sid_type_lookup(response.data.sid.type), response.data.sid.type);
683
684         return true;
685 }
686
687 /* Authenticate a user with a plaintext password */
688
689 static bool wbinfo_auth_krb5(char *username, const char *cctype, uint32_t flags)
690 {
691         struct winbindd_request request;
692         struct winbindd_response response;
693         NSS_STATUS result;
694         char *p;
695
696         /* Send off request */
697
698         ZERO_STRUCT(request);
699         ZERO_STRUCT(response);
700
701         p = strchr(username, '%');
702
703         if (p) {
704                 *p = 0;
705                 fstrcpy(request.data.auth.user, username);
706                 fstrcpy(request.data.auth.pass, p + 1);
707                 *p = '%';
708         } else
709                 fstrcpy(request.data.auth.user, username);
710
711         request.flags = flags;
712
713         fstrcpy(request.data.auth.krb5_cc_type, cctype);
714
715         request.data.auth.uid = geteuid();
716
717         result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
718
719         /* Display response */
720
721         d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n", 
722                 username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype);
723
724         if (response.data.auth.nt_status)
725                 d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
726                          response.data.auth.nt_status_string, 
727                          response.data.auth.nt_status,
728                          response.data.auth.error_string);
729
730         if (result == NSS_STATUS_SUCCESS) {
731
732                 if (request.flags & WBFLAG_PAM_INFO3_TEXT) {
733                         if (response.data.auth.info3.user_flgs & NETLOGON_CACHED_ACCOUNT) {
734                                 d_printf("user_flgs: NETLOGON_CACHED_ACCOUNT\n");
735                         }
736                 }
737
738                 if (response.data.auth.krb5ccname[0] != '\0') {
739                         d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname);
740                 } else {
741                         d_printf("no credentials cached\n");
742                 }
743         }
744
745         return result == NSS_STATUS_SUCCESS;
746 }
747
748 /* Authenticate a user with a plaintext password */
749
750 static bool wbinfo_auth(char *username)
751 {
752         struct winbindd_request request;
753         struct winbindd_response response;
754         NSS_STATUS result;
755         char *p;
756
757         /* Send off request */
758
759         ZERO_STRUCT(request);
760         ZERO_STRUCT(response);
761
762         p = strchr(username, '%');
763
764         if (p) {
765                 *p = 0;
766                 fstrcpy(request.data.auth.user, username);
767                 fstrcpy(request.data.auth.pass, p + 1);
768                 *p = '%';
769         } else
770                 fstrcpy(request.data.auth.user, username);
771
772         result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
773
774         /* Display response */
775
776         d_printf("plaintext password authentication %s\n", 
777                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
778
779         if (response.data.auth.nt_status)
780                 d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
781                          response.data.auth.nt_status_string, 
782                          response.data.auth.nt_status,
783                          response.data.auth.error_string);
784
785         return result == NSS_STATUS_SUCCESS;
786 }
787
788 /* Authenticate a user with a challenge/response */
789
790 static bool wbinfo_auth_crap(struct loadparm_context *lp_ctx, char *username)
791 {
792         struct winbindd_request request;
793         struct winbindd_response response;
794         NSS_STATUS result;
795         fstring name_user;
796         fstring name_domain;
797         fstring pass;
798         char *p;
799
800         /* Send off request */
801
802         ZERO_STRUCT(request);
803         ZERO_STRUCT(response);
804
805         p = strchr(username, '%');
806
807         if (p) {
808                 *p = 0;
809                 fstrcpy(pass, p + 1);
810         }
811                 
812         parse_wbinfo_domain_user(username, name_domain, name_user);
813
814         request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
815
816         fstrcpy(request.data.auth_crap.user, name_user);
817
818         fstrcpy(request.data.auth_crap.domain, 
819                               name_domain);
820
821         generate_random_buffer(request.data.auth_crap.chal, 8);
822         
823         if (lp_client_ntlmv2_auth(lp_ctx)) {
824                 DATA_BLOB server_chal;
825                 DATA_BLOB names_blob;   
826
827                 DATA_BLOB lm_response;
828                 DATA_BLOB nt_response;
829
830                 TALLOC_CTX *mem_ctx;
831                 mem_ctx = talloc_new(NULL);
832                 if (mem_ctx == NULL) {
833                         d_printf("talloc_new failed\n");
834                         return false;
835                 }
836
837                 server_chal = data_blob(request.data.auth_crap.chal, 8); 
838                 
839                 /* Pretend this is a login to 'us', for blob purposes */
840                 names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_iconv_convenience(lp_ctx), lp_netbios_name(lp_ctx), lp_workgroup(lp_ctx));
841                 
842                 if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, pass, &server_chal, 
843                                       &names_blob,
844                                       &lm_response, &nt_response, NULL, NULL)) {
845                         data_blob_free(&names_blob);
846                         data_blob_free(&server_chal);
847                         return false;
848                 }
849                 data_blob_free(&names_blob);
850                 data_blob_free(&server_chal);
851
852                 memcpy(request.data.auth_crap.nt_resp, nt_response.data, 
853                        MIN(nt_response.length, 
854                            sizeof(request.data.auth_crap.nt_resp)));
855                 request.data.auth_crap.nt_resp_len = nt_response.length;
856
857                 memcpy(request.data.auth_crap.lm_resp, lm_response.data, 
858                        MIN(lm_response.length, 
859                            sizeof(request.data.auth_crap.lm_resp)));
860                 request.data.auth_crap.lm_resp_len = lm_response.length;
861                        
862                 data_blob_free(&nt_response);
863                 data_blob_free(&lm_response);
864
865         } else {
866                 if (lp_client_lanman_auth(lp_ctx) 
867                     && SMBencrypt(pass, request.data.auth_crap.chal, 
868                                (unsigned char *)request.data.auth_crap.lm_resp)) {
869                         request.data.auth_crap.lm_resp_len = 24;
870                 } else {
871                         request.data.auth_crap.lm_resp_len = 0;
872                 }
873                 SMBNTencrypt(pass, request.data.auth_crap.chal,
874                              (unsigned char *)request.data.auth_crap.nt_resp);
875
876                 request.data.auth_crap.nt_resp_len = 24;
877         }
878
879         result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);
880
881         /* Display response */
882
883         d_printf("challenge/response password authentication %s\n", 
884                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
885
886         if (response.data.auth.nt_status)
887                 d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
888                          response.data.auth.nt_status_string, 
889                          response.data.auth.nt_status,
890                          response.data.auth.error_string);
891
892         return result == NSS_STATUS_SUCCESS;
893 }
894
895 /* Print domain users */
896
897 static bool print_domain_users(const char *domain)
898 {
899         struct winbindd_request request;
900         struct winbindd_response response;
901         const char *extra_data;
902         fstring name;
903
904         /* Send request to winbind daemon */
905
906         ZERO_STRUCT(request);
907         ZERO_STRUCT(response);
908         
909         if (domain) {
910                 /* '.' is the special sign for our own domain */
911                 if ( strequal(domain, ".") )
912                         fstrcpy( request.domain_name, get_winbind_domain() );
913                 else
914                         fstrcpy( request.domain_name, domain );
915         }
916
917         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
918             NSS_STATUS_SUCCESS)
919                 return false;
920
921         /* Look through extra data */
922
923         if (!response.extra_data.data)
924                 return false;
925
926         extra_data = (const char *)response.extra_data.data;
927
928         while(next_token(&extra_data, name, ",", sizeof(fstring)))
929                 d_printf("%s\n", name);
930         
931         SAFE_FREE(response.extra_data.data);
932
933         return true;
934 }
935
936 /* Print domain groups */
937
938 static bool print_domain_groups(const char *domain)
939 {
940         struct winbindd_request  request;
941         struct winbindd_response response;
942         const char *extra_data;
943         fstring name;
944
945         ZERO_STRUCT(request);
946         ZERO_STRUCT(response);
947
948         if (domain) {
949                 if ( strequal(domain, ".") )
950                         fstrcpy( request.domain_name, get_winbind_domain() );
951                 else
952                         fstrcpy( request.domain_name, domain );
953         }
954
955         if (winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response) !=
956             NSS_STATUS_SUCCESS)
957                 return false;
958
959         /* Look through extra data */
960
961         if (!response.extra_data.data)
962                 return false;
963
964         extra_data = (const char *)response.extra_data.data;
965
966         while(next_token(&extra_data, name, ",", sizeof(fstring)))
967                 d_printf("%s\n", name);
968
969         SAFE_FREE(response.extra_data.data);
970         
971         return true;
972 }
973
974 static bool wbinfo_ping(void)
975 {
976         NSS_STATUS result;
977
978         result = winbindd_request_response(WINBINDD_PING, NULL, NULL);
979
980         /* Display response */
981
982         d_printf("Ping to winbindd %s on fd %d\n", 
983                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd);
984
985         return result == NSS_STATUS_SUCCESS;
986 }
987
988 /* Main program */
989
990 enum {
991         OPT_SET_AUTH_USER = 1000,
992         OPT_GET_AUTH_USER,
993         OPT_DOMAIN_NAME,
994         OPT_SEQUENCE,
995         OPT_GETDCNAME,
996         OPT_USERDOMGROUPS,
997         OPT_USERSIDS,
998         OPT_ALLOCATE_UID,
999         OPT_ALLOCATE_GID,
1000         OPT_SEPARATOR,
1001         OPT_LIST_ALL_DOMAINS,
1002         OPT_LIST_OWN_DOMAIN,
1003         OPT_UID_INFO,
1004         OPT_GROUP_INFO,
1005 };
1006
1007 int main(int argc, char **argv, char **envp)
1008 {
1009         int opt;
1010
1011         poptContext pc;
1012         static char *string_arg;
1013         static char *opt_domain_name;
1014         static int int_arg;
1015         int result = 1;
1016
1017         struct poptOption long_options[] = {
1018                 POPT_AUTOHELP
1019
1020                 /* longName, shortName, argInfo, argPtr, value, descrip, 
1021                    argDesc */
1022
1023                 { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users", "domain"},
1024                 { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups", "domain" },
1025                 { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP", "NETBIOS-NAME" },
1026                 { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" },
1027                 { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" },
1028                 { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" },
1029                 { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" },
1030                 { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
1031                 { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
1032                 { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
1033                 { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
1034                 { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
1035                 { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
1036                 { "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" },
1037                 { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
1038                 { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" },
1039                 { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" },
1040                 { "uid-info", 0, POPT_ARG_INT, &int_arg, OPT_UID_INFO, "Get user info from uid", "UID" },
1041                 { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" },
1042                 { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
1043                 { "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
1044                   OPT_USERDOMGROUPS, "Get user domain groups", "SID" },
1045                 { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" },
1046                 { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" },
1047                 { "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME,
1048                   "Get a DC name for a foreign domain", "domainname" },
1049                 { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" },
1050                 { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
1051 #ifdef HAVE_KRB5
1052                 { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" },
1053                         /* destroys wbinfo --help output */
1054                         /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */
1055 #endif
1056                 { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
1057                 POPT_COMMON_VERSION
1058                 POPT_COMMON_SAMBA
1059                 POPT_TABLEEND
1060         };
1061
1062         /* Parse options */
1063
1064         pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0);
1065
1066         /* Parse command line options */
1067
1068         if (argc == 1) {
1069                 poptPrintHelp(pc, stderr, 0);
1070                 return 1;
1071         }
1072
1073         while((opt = poptGetNextOpt(pc)) != -1) {
1074                 /* get the generic configuration parameters like --domain */
1075         }
1076
1077         poptFreeContext(pc);
1078
1079         pc = poptGetContext(NULL, argc, (const char **)argv, long_options, 
1080                             POPT_CONTEXT_KEEP_FIRST);
1081
1082         while((opt = poptGetNextOpt(pc)) != -1) {
1083                 switch (opt) {
1084                 case 'u':
1085                         if (!print_domain_users(opt_domain_name)) {
1086                                 d_fprintf(stderr, "Error looking up domain users\n");
1087                                 goto done;
1088                         }
1089                         break;
1090                 case 'g':
1091                         if (!print_domain_groups(opt_domain_name)) {
1092                                 d_fprintf(stderr, "Error looking up domain groups\n");
1093                                 goto done;
1094                         }
1095                         break;
1096                 case 's':
1097                         if (!wbinfo_lookupsid(string_arg)) {
1098                                 d_fprintf(stderr, "Could not lookup sid %s\n", string_arg);
1099                                 goto done;
1100                         }
1101                         break;
1102                 case 'n':
1103                         if (!wbinfo_lookupname(string_arg)) {
1104                                 d_fprintf(stderr, "Could not lookup name %s\n", string_arg);
1105                                 goto done;
1106                         }
1107                         break;
1108                 case 'N':
1109                         if (!wbinfo_wins_byname(string_arg)) {
1110                                 d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg);
1111                                 goto done;
1112                         }
1113                         break;
1114                 case 'I':
1115                         if (!wbinfo_wins_byip(string_arg)) {
1116                                 d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg);
1117                                 goto done;
1118                         }
1119                         break;
1120                 case 'U':
1121                         if (!wbinfo_uid_to_sid(int_arg)) {
1122                                 d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg);
1123                                 goto done;
1124                         }
1125                         break;
1126                 case 'G':
1127                         if (!wbinfo_gid_to_sid(int_arg)) {
1128                                 d_fprintf(stderr, "Could not convert gid %d to sid\n",
1129                                        int_arg);
1130                                 goto done;
1131                         }
1132                         break;
1133                 case 'S':
1134                         if (!wbinfo_sid_to_uid(string_arg)) {
1135                                 d_fprintf(stderr, "Could not convert sid %s to uid\n",
1136                                        string_arg);
1137                                 goto done;
1138                         }
1139                         break;
1140                 case 'Y':
1141                         if (!wbinfo_sid_to_gid(string_arg)) {
1142                                 d_fprintf(stderr, "Could not convert sid %s to gid\n",
1143                                        string_arg);
1144                                 goto done;
1145                         }
1146                         break;
1147                 case 't':
1148                         if (!wbinfo_check_secret()) {
1149                                 d_fprintf(stderr, "Could not check secret\n");
1150                                 goto done;
1151                         }
1152                         break;
1153                 case 'm':
1154                         if (!wbinfo_list_domains(false)) {
1155                                 d_fprintf(stderr, "Could not list trusted domains\n");
1156                                 goto done;
1157                         }
1158                         break;
1159                 case OPT_SEQUENCE:
1160                         if (!wbinfo_show_sequence(opt_domain_name)) {
1161                                 d_fprintf(stderr, "Could not show sequence numbers\n");
1162                                 goto done;
1163                         }
1164                         break;
1165                 case 'D':
1166                         if (!wbinfo_domain_info(string_arg)) {
1167                                 d_fprintf(stderr, "Could not get domain info\n");
1168                                 goto done;
1169                         }
1170                         break;
1171                 case 'i':
1172                         if (!wbinfo_get_userinfo(string_arg)) {
1173                                 d_fprintf(stderr, "Could not get info for user %s\n",
1174                                                   string_arg);
1175                                 goto done;
1176                         }
1177                         break;
1178                 case OPT_UID_INFO:
1179                         if ( !wbinfo_get_uidinfo(int_arg)) {
1180                                 d_fprintf(stderr, "Could not get info for uid "
1181                                                 "%d\n", int_arg);
1182                                 goto done;
1183                         }
1184                         break;
1185                 case OPT_GROUP_INFO:
1186                         if ( !wbinfo_get_groupinfo(string_arg)) {
1187                                 d_fprintf(stderr, "Could not get info for "
1188                                           "group %s\n", string_arg);
1189                                 goto done;
1190                         }
1191                         break;
1192                 case 'r':
1193                         if (!wbinfo_get_usergroups(string_arg)) {
1194                                 d_fprintf(stderr, "Could not get groups for user %s\n", 
1195                                        string_arg);
1196                                 goto done;
1197                         }
1198                         break;
1199                 case OPT_USERSIDS:
1200                         if (!wbinfo_get_usersids(string_arg)) {
1201                                 d_fprintf(stderr, "Could not get group SIDs for user SID %s\n", 
1202                                        string_arg);
1203                                 goto done;
1204                         }
1205                         break;
1206                 case OPT_USERDOMGROUPS:
1207                         if (!wbinfo_get_userdomgroups(string_arg)) {
1208                                 d_fprintf(stderr, "Could not get user's domain groups "
1209                                          "for user SID %s\n", string_arg);
1210                                 goto done;
1211                         }
1212                         break;
1213                 case 'a': {
1214                                 bool got_error = false;
1215
1216                                 if (!wbinfo_auth(string_arg)) {
1217                                         d_fprintf(stderr, "Could not authenticate user %s with "
1218                                                 "plaintext password\n", string_arg);
1219                                         got_error = true;
1220                                 }
1221
1222                                 if (!wbinfo_auth_crap(cmdline_lp_ctx, string_arg)) {
1223                                         d_fprintf(stderr, "Could not authenticate user %s with "
1224                                                 "challenge/response\n", string_arg);
1225                                         got_error = true;
1226                                 }
1227
1228                                 if (got_error)
1229                                         goto done;
1230                                 break;
1231                         }
1232                 case 'K': {
1233                                 uint32_t flags =  WBFLAG_PAM_KRB5 |
1234                                                 WBFLAG_PAM_CACHED_LOGIN |
1235                                                 WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
1236                                                 WBFLAG_PAM_INFO3_TEXT;
1237
1238                                 if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) {
1239                                         d_fprintf(stderr, "Could not authenticate user [%s] with "
1240                                                 "Kerberos (ccache: %s)\n", string_arg, "FILE");
1241                                         goto done;
1242                                 }
1243                                 break;
1244                         }
1245                 case 'p':
1246                         if (!wbinfo_ping()) {
1247                                 d_fprintf(stderr, "could not ping winbindd!\n");
1248                                 goto done;
1249                         }
1250                         break;
1251                 case OPT_GETDCNAME:
1252                         if (!wbinfo_getdcname(string_arg)) {
1253                                 goto done;
1254                         }
1255                         break;
1256                 case OPT_SEPARATOR: {
1257                         const char sep = winbind_separator_int(true);
1258                         if ( !sep ) {
1259                                 goto done;
1260                         }
1261                         d_printf("%c\n", sep);
1262                         break;
1263                 }
1264                 case OPT_LIST_ALL_DOMAINS:
1265                         if (!wbinfo_list_domains(true)) {
1266                                 goto done;
1267                         }
1268                         break;
1269                 case OPT_LIST_OWN_DOMAIN:
1270                         if (!wbinfo_list_own_domain()) {
1271                                 goto done;
1272                         }
1273                         break;
1274                 /* generic configuration options */
1275                 case OPT_DOMAIN_NAME:
1276                         break;
1277                 default:
1278                         d_fprintf(stderr, "Invalid option\n");
1279                         poptPrintHelp(pc, stderr, 0);
1280                         goto done;
1281                 }
1282         }
1283
1284         result = 0;
1285
1286         /* Exit code */
1287
1288  done:
1289         poptFreeContext(pc);
1290         return result;
1291 }