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