r25242: remove sequence_number out of WINBINDD_DOMAIN_INFO call
[kai/samba.git] / source / 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();
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();
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();
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         }
657         return "Invalid sid type\n";
658 }
659
660 /* Convert string to sid */
661
662 static BOOL wbinfo_lookupname(char *name)
663 {
664         struct winbindd_request request;
665         struct winbindd_response response;
666
667         /* Send off request */
668
669         ZERO_STRUCT(request);
670         ZERO_STRUCT(response);
671
672         parse_wbinfo_domain_user(name, request.data.name.dom_name, 
673                                  request.data.name.name);
674
675         if (winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response) !=
676             NSS_STATUS_SUCCESS)
677                 return False;
678
679         /* Display response */
680
681         d_printf("%s %s (%d)\n", response.data.sid.sid, sid_type_lookup(response.data.sid.type), response.data.sid.type);
682
683         return True;
684 }
685
686 /* Authenticate a user with a plaintext password */
687
688 static BOOL wbinfo_auth_krb5(char *username, const char *cctype, uint32_t flags)
689 {
690         struct winbindd_request request;
691         struct winbindd_response response;
692         NSS_STATUS result;
693         char *p;
694
695         /* Send off request */
696
697         ZERO_STRUCT(request);
698         ZERO_STRUCT(response);
699
700         p = strchr(username, '%');
701
702         if (p) {
703                 *p = 0;
704                 fstrcpy(request.data.auth.user, username);
705                 fstrcpy(request.data.auth.pass, p + 1);
706                 *p = '%';
707         } else
708                 fstrcpy(request.data.auth.user, username);
709
710         request.flags = flags;
711
712         fstrcpy(request.data.auth.krb5_cc_type, cctype);
713
714         request.data.auth.uid = geteuid();
715
716         result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
717
718         /* Display response */
719
720         d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n", 
721                 username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype);
722
723         if (response.data.auth.nt_status)
724                 d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
725                          response.data.auth.nt_status_string, 
726                          response.data.auth.nt_status,
727                          response.data.auth.error_string);
728
729         if (result == NSS_STATUS_SUCCESS) {
730
731                 if (request.flags & WBFLAG_PAM_INFO3_TEXT) {
732                         if (response.data.auth.info3.user_flgs & NETLOGON_CACHED_ACCOUNT) {
733                                 d_printf("user_flgs: NETLOGON_CACHED_ACCOUNT\n");
734                         }
735                 }
736
737                 if (response.data.auth.krb5ccname[0] != '\0') {
738                         d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname);
739                 } else {
740                         d_printf("no credentials cached\n");
741                 }
742         }
743
744         return result == NSS_STATUS_SUCCESS;
745 }
746
747 /* Authenticate a user with a plaintext password */
748
749 static BOOL wbinfo_auth(char *username)
750 {
751         struct winbindd_request request;
752         struct winbindd_response response;
753         NSS_STATUS result;
754         char *p;
755
756         /* Send off request */
757
758         ZERO_STRUCT(request);
759         ZERO_STRUCT(response);
760
761         p = strchr(username, '%');
762
763         if (p) {
764                 *p = 0;
765                 fstrcpy(request.data.auth.user, username);
766                 fstrcpy(request.data.auth.pass, p + 1);
767                 *p = '%';
768         } else
769                 fstrcpy(request.data.auth.user, username);
770
771         result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
772
773         /* Display response */
774
775         d_printf("plaintext password authentication %s\n", 
776                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
777
778         if (response.data.auth.nt_status)
779                 d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
780                          response.data.auth.nt_status_string, 
781                          response.data.auth.nt_status,
782                          response.data.auth.error_string);
783
784         return result == NSS_STATUS_SUCCESS;
785 }
786
787 /* Authenticate a user with a challenge/response */
788
789 static BOOL wbinfo_auth_crap(char *username)
790 {
791         struct winbindd_request request;
792         struct winbindd_response response;
793         NSS_STATUS result;
794         fstring name_user;
795         fstring name_domain;
796         fstring pass;
797         char *p;
798
799         /* Send off request */
800
801         ZERO_STRUCT(request);
802         ZERO_STRUCT(response);
803
804         p = strchr(username, '%');
805
806         if (p) {
807                 *p = 0;
808                 fstrcpy(pass, p + 1);
809         }
810                 
811         parse_wbinfo_domain_user(username, name_domain, name_user);
812
813         request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
814
815         fstrcpy(request.data.auth_crap.user, name_user);
816
817         fstrcpy(request.data.auth_crap.domain, 
818                               name_domain);
819
820         generate_random_buffer(request.data.auth_crap.chal, 8);
821         
822         if (lp_client_ntlmv2_auth()) {
823                 DATA_BLOB server_chal;
824                 DATA_BLOB names_blob;   
825
826                 DATA_BLOB lm_response;
827                 DATA_BLOB nt_response;
828
829                 TALLOC_CTX *mem_ctx;
830                 mem_ctx = talloc_new(NULL);
831                 if (mem_ctx == NULL) {
832                         d_printf("talloc_new failed\n");
833                         return False;
834                 }
835
836                 server_chal = data_blob(request.data.auth_crap.chal, 8); 
837                 
838                 /* Pretend this is a login to 'us', for blob purposes */
839                 names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(), lp_workgroup());
840                 
841                 if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, pass, &server_chal, 
842                                       &names_blob,
843                                       &lm_response, &nt_response, NULL, NULL)) {
844                         data_blob_free(&names_blob);
845                         data_blob_free(&server_chal);
846                         return False;
847                 }
848                 data_blob_free(&names_blob);
849                 data_blob_free(&server_chal);
850
851                 memcpy(request.data.auth_crap.nt_resp, nt_response.data, 
852                        MIN(nt_response.length, 
853                            sizeof(request.data.auth_crap.nt_resp)));
854                 request.data.auth_crap.nt_resp_len = nt_response.length;
855
856                 memcpy(request.data.auth_crap.lm_resp, lm_response.data, 
857                        MIN(lm_response.length, 
858                            sizeof(request.data.auth_crap.lm_resp)));
859                 request.data.auth_crap.lm_resp_len = lm_response.length;
860                        
861                 data_blob_free(&nt_response);
862                 data_blob_free(&lm_response);
863
864         } else {
865                 if (lp_client_lanman_auth() 
866                     && SMBencrypt(pass, request.data.auth_crap.chal, 
867                                (unsigned char *)request.data.auth_crap.lm_resp)) {
868                         request.data.auth_crap.lm_resp_len = 24;
869                 } else {
870                         request.data.auth_crap.lm_resp_len = 0;
871                 }
872                 SMBNTencrypt(pass, request.data.auth_crap.chal,
873                              (unsigned char *)request.data.auth_crap.nt_resp);
874
875                 request.data.auth_crap.nt_resp_len = 24;
876         }
877
878         result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);
879
880         /* Display response */
881
882         d_printf("challenge/response password authentication %s\n", 
883                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
884
885         if (response.data.auth.nt_status)
886                 d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
887                          response.data.auth.nt_status_string, 
888                          response.data.auth.nt_status,
889                          response.data.auth.error_string);
890
891         return result == NSS_STATUS_SUCCESS;
892 }
893
894 /* Print domain users */
895
896 static BOOL print_domain_users(const char *domain)
897 {
898         struct winbindd_request request;
899         struct winbindd_response response;
900         const char *extra_data;
901         fstring name;
902
903         /* Send request to winbind daemon */
904
905         ZERO_STRUCT(request);
906         ZERO_STRUCT(response);
907         
908         if (domain) {
909                 /* '.' is the special sign for our own domain */
910                 if ( strequal(domain, ".") )
911                         fstrcpy( request.domain_name, get_winbind_domain() );
912                 else
913                         fstrcpy( request.domain_name, domain );
914         }
915
916         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
917             NSS_STATUS_SUCCESS)
918                 return False;
919
920         /* Look through extra data */
921
922         if (!response.extra_data.data)
923                 return False;
924
925         extra_data = (const char *)response.extra_data.data;
926
927         while(next_token(&extra_data, name, ",", sizeof(fstring)))
928                 d_printf("%s\n", name);
929         
930         SAFE_FREE(response.extra_data.data);
931
932         return True;
933 }
934
935 /* Print domain groups */
936
937 static BOOL print_domain_groups(const char *domain)
938 {
939         struct winbindd_request  request;
940         struct winbindd_response response;
941         const char *extra_data;
942         fstring name;
943
944         ZERO_STRUCT(request);
945         ZERO_STRUCT(response);
946
947         if (domain) {
948                 if ( strequal(domain, ".") )
949                         fstrcpy( request.domain_name, get_winbind_domain() );
950                 else
951                         fstrcpy( request.domain_name, domain );
952         }
953
954         if (winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response) !=
955             NSS_STATUS_SUCCESS)
956                 return False;
957
958         /* Look through extra data */
959
960         if (!response.extra_data.data)
961                 return False;
962
963         extra_data = (const char *)response.extra_data.data;
964
965         while(next_token(&extra_data, name, ",", sizeof(fstring)))
966                 d_printf("%s\n", name);
967
968         SAFE_FREE(response.extra_data.data);
969         
970         return True;
971 }
972
973 static BOOL wbinfo_ping(void)
974 {
975         NSS_STATUS result;
976
977         result = winbindd_request_response(WINBINDD_PING, NULL, NULL);
978
979         /* Display response */
980
981         d_printf("Ping to winbindd %s on fd %d\n", 
982                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd);
983
984         return result == NSS_STATUS_SUCCESS;
985 }
986
987 /* Main program */
988
989 enum {
990         OPT_SET_AUTH_USER = 1000,
991         OPT_GET_AUTH_USER,
992         OPT_DOMAIN_NAME,
993         OPT_SEQUENCE,
994         OPT_GETDCNAME,
995         OPT_USERDOMGROUPS,
996         OPT_USERSIDS,
997         OPT_ALLOCATE_UID,
998         OPT_ALLOCATE_GID,
999         OPT_SEPARATOR,
1000         OPT_LIST_ALL_DOMAINS,
1001         OPT_LIST_OWN_DOMAIN,
1002         OPT_UID_INFO,
1003         OPT_GROUP_INFO,
1004 };
1005
1006 int main(int argc, char **argv, char **envp)
1007 {
1008         int opt;
1009
1010         poptContext pc;
1011         static char *string_arg;
1012         static char *opt_domain_name;
1013         static int int_arg;
1014         int result = 1;
1015
1016         struct poptOption long_options[] = {
1017                 POPT_AUTOHELP
1018
1019                 /* longName, shortName, argInfo, argPtr, value, descrip, 
1020                    argDesc */
1021
1022                 { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users", "domain"},
1023                 { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups", "domain" },
1024                 { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP", "NETBIOS-NAME" },
1025                 { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" },
1026                 { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" },
1027                 { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" },
1028                 { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" },
1029                 { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
1030                 { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
1031                 { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
1032                 { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
1033                 { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
1034                 { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
1035                 { "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" },
1036                 { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
1037                 { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" },
1038                 { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" },
1039                 { "uid-info", 0, POPT_ARG_INT, &int_arg, OPT_UID_INFO, "Get user info from uid", "UID" },
1040                 { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" },
1041                 { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
1042                 { "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
1043                   OPT_USERDOMGROUPS, "Get user domain groups", "SID" },
1044                 { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" },
1045                 { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" },
1046                 { "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME,
1047                   "Get a DC name for a foreign domain", "domainname" },
1048                 { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" },
1049                 { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
1050 #ifdef HAVE_KRB5
1051                 { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" },
1052                         /* destroys wbinfo --help output */
1053                         /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */
1054 #endif
1055                 { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
1056                 POPT_COMMON_VERSION
1057                 POPT_COMMON_SAMBA
1058                 POPT_TABLEEND
1059         };
1060
1061         /* Parse options */
1062
1063         pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0);
1064
1065         /* Parse command line options */
1066
1067         if (argc == 1) {
1068                 poptPrintHelp(pc, stderr, 0);
1069                 return 1;
1070         }
1071
1072         while((opt = poptGetNextOpt(pc)) != -1) {
1073                 /* get the generic configuration parameters like --domain */
1074         }
1075
1076         poptFreeContext(pc);
1077
1078         pc = poptGetContext(NULL, argc, (const char **)argv, long_options, 
1079                             POPT_CONTEXT_KEEP_FIRST);
1080
1081         while((opt = poptGetNextOpt(pc)) != -1) {
1082                 switch (opt) {
1083                 case 'u':
1084                         if (!print_domain_users(opt_domain_name)) {
1085                                 d_fprintf(stderr, "Error looking up domain users\n");
1086                                 goto done;
1087                         }
1088                         break;
1089                 case 'g':
1090                         if (!print_domain_groups(opt_domain_name)) {
1091                                 d_fprintf(stderr, "Error looking up domain groups\n");
1092                                 goto done;
1093                         }
1094                         break;
1095                 case 's':
1096                         if (!wbinfo_lookupsid(string_arg)) {
1097                                 d_fprintf(stderr, "Could not lookup sid %s\n", string_arg);
1098                                 goto done;
1099                         }
1100                         break;
1101                 case 'n':
1102                         if (!wbinfo_lookupname(string_arg)) {
1103                                 d_fprintf(stderr, "Could not lookup name %s\n", string_arg);
1104                                 goto done;
1105                         }
1106                         break;
1107                 case 'N':
1108                         if (!wbinfo_wins_byname(string_arg)) {
1109                                 d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg);
1110                                 goto done;
1111                         }
1112                         break;
1113                 case 'I':
1114                         if (!wbinfo_wins_byip(string_arg)) {
1115                                 d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg);
1116                                 goto done;
1117                         }
1118                         break;
1119                 case 'U':
1120                         if (!wbinfo_uid_to_sid(int_arg)) {
1121                                 d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg);
1122                                 goto done;
1123                         }
1124                         break;
1125                 case 'G':
1126                         if (!wbinfo_gid_to_sid(int_arg)) {
1127                                 d_fprintf(stderr, "Could not convert gid %d to sid\n",
1128                                        int_arg);
1129                                 goto done;
1130                         }
1131                         break;
1132                 case 'S':
1133                         if (!wbinfo_sid_to_uid(string_arg)) {
1134                                 d_fprintf(stderr, "Could not convert sid %s to uid\n",
1135                                        string_arg);
1136                                 goto done;
1137                         }
1138                         break;
1139                 case 'Y':
1140                         if (!wbinfo_sid_to_gid(string_arg)) {
1141                                 d_fprintf(stderr, "Could not convert sid %s to gid\n",
1142                                        string_arg);
1143                                 goto done;
1144                         }
1145                         break;
1146                 case 't':
1147                         if (!wbinfo_check_secret()) {
1148                                 d_fprintf(stderr, "Could not check secret\n");
1149                                 goto done;
1150                         }
1151                         break;
1152                 case 'm':
1153                         if (!wbinfo_list_domains(False)) {
1154                                 d_fprintf(stderr, "Could not list trusted domains\n");
1155                                 goto done;
1156                         }
1157                         break;
1158                 case OPT_SEQUENCE:
1159                         if (!wbinfo_show_sequence(opt_domain_name)) {
1160                                 d_fprintf(stderr, "Could not show sequence numbers\n");
1161                                 goto done;
1162                         }
1163                         break;
1164                 case 'D':
1165                         if (!wbinfo_domain_info(string_arg)) {
1166                                 d_fprintf(stderr, "Could not get domain info\n");
1167                                 goto done;
1168                         }
1169                         break;
1170                 case 'i':
1171                         if (!wbinfo_get_userinfo(string_arg)) {
1172                                 d_fprintf(stderr, "Could not get info for user %s\n",
1173                                                   string_arg);
1174                                 goto done;
1175                         }
1176                         break;
1177                 case OPT_UID_INFO:
1178                         if ( !wbinfo_get_uidinfo(int_arg)) {
1179                                 d_fprintf(stderr, "Could not get info for uid "
1180                                                 "%d\n", int_arg);
1181                                 goto done;
1182                         }
1183                         break;
1184                 case OPT_GROUP_INFO:
1185                         if ( !wbinfo_get_groupinfo(string_arg)) {
1186                                 d_fprintf(stderr, "Could not get info for "
1187                                           "group %s\n", string_arg);
1188                                 goto done;
1189                         }
1190                         break;
1191                 case 'r':
1192                         if (!wbinfo_get_usergroups(string_arg)) {
1193                                 d_fprintf(stderr, "Could not get groups for user %s\n", 
1194                                        string_arg);
1195                                 goto done;
1196                         }
1197                         break;
1198                 case OPT_USERSIDS:
1199                         if (!wbinfo_get_usersids(string_arg)) {
1200                                 d_fprintf(stderr, "Could not get group SIDs for user SID %s\n", 
1201                                        string_arg);
1202                                 goto done;
1203                         }
1204                         break;
1205                 case OPT_USERDOMGROUPS:
1206                         if (!wbinfo_get_userdomgroups(string_arg)) {
1207                                 d_fprintf(stderr, "Could not get user's domain groups "
1208                                          "for user SID %s\n", string_arg);
1209                                 goto done;
1210                         }
1211                         break;
1212                 case 'a': {
1213                                 BOOL got_error = False;
1214
1215                                 if (!wbinfo_auth(string_arg)) {
1216                                         d_fprintf(stderr, "Could not authenticate user %s with "
1217                                                 "plaintext password\n", string_arg);
1218                                         got_error = True;
1219                                 }
1220
1221                                 if (!wbinfo_auth_crap(string_arg)) {
1222                                         d_fprintf(stderr, "Could not authenticate user %s with "
1223                                                 "challenge/response\n", string_arg);
1224                                         got_error = True;
1225                                 }
1226
1227                                 if (got_error)
1228                                         goto done;
1229                                 break;
1230                         }
1231                 case 'K': {
1232                                 uint32_t flags =  WBFLAG_PAM_KRB5 |
1233                                                 WBFLAG_PAM_CACHED_LOGIN |
1234                                                 WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
1235                                                 WBFLAG_PAM_INFO3_TEXT;
1236
1237                                 if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) {
1238                                         d_fprintf(stderr, "Could not authenticate user [%s] with "
1239                                                 "Kerberos (ccache: %s)\n", string_arg, "FILE");
1240                                         goto done;
1241                                 }
1242                                 break;
1243                         }
1244                 case 'p':
1245                         if (!wbinfo_ping()) {
1246                                 d_fprintf(stderr, "could not ping winbindd!\n");
1247                                 goto done;
1248                         }
1249                         break;
1250                 case OPT_GETDCNAME:
1251                         if (!wbinfo_getdcname(string_arg)) {
1252                                 goto done;
1253                         }
1254                         break;
1255                 case OPT_SEPARATOR: {
1256                         const char sep = winbind_separator_int(True);
1257                         if ( !sep ) {
1258                                 goto done;
1259                         }
1260                         d_printf("%c\n", sep);
1261                         break;
1262                 }
1263                 case OPT_LIST_ALL_DOMAINS:
1264                         if (!wbinfo_list_domains(True)) {
1265                                 goto done;
1266                         }
1267                         break;
1268                 case OPT_LIST_OWN_DOMAIN:
1269                         if (!wbinfo_list_own_domain()) {
1270                                 goto done;
1271                         }
1272                         break;
1273                 /* generic configuration options */
1274                 case OPT_DOMAIN_NAME:
1275                         break;
1276                 default:
1277                         d_fprintf(stderr, "Invalid option\n");
1278                         poptPrintHelp(pc, stderr, 0);
1279                         goto done;
1280                 }
1281         }
1282
1283         result = 0;
1284
1285         /* Exit code */
1286
1287  done:
1288         poptFreeContext(pc);
1289         return result;
1290 }