e511c34ca013fac199c44f3edf1a5ad1eadd2ccb
[metze/samba/wb-ndr.git] / source / winbindd / winbindd_misc.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon - miscellaneous other functions
5
6    Copyright (C) Tim Potter      2000
7    Copyright (C) Andrew Bartlett 2002
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "winbindd.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_WINBIND
28
29 /* Check the machine account password is valid */
30
31 void winbindd_check_machine_acct(struct winbindd_cli_state *state)
32 {
33         DEBUG(3, ("[%5lu]: check machine account\n",
34                   (unsigned long)state->pid));
35
36         sendto_domain(state, find_our_domain());
37 }
38
39 enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain,
40                                                       struct winbindd_cli_state *state)
41 {
42         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
43         int num_retries = 0;
44         struct winbindd_domain *contact_domain;
45
46         DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
47
48         /* Get trust account password */
49
50  again:
51
52         contact_domain = find_our_domain();
53         
54         /* This call does a cli_nt_setup_creds() which implicitly checks
55            the trust account password. */
56
57         invalidate_cm_connection(&contact_domain->conn);
58
59         {
60                 struct rpc_pipe_client *netlogon_pipe;
61                 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
62         }
63
64         if (!NT_STATUS_IS_OK(result)) {
65                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
66                 goto done;
67         }
68
69         /* There is a race condition between fetching the trust account
70            password and the periodic machine password change.  So it's 
71            possible that the trust account password has been changed on us.  
72            We are returned NT_STATUS_ACCESS_DENIED if this happens. */
73
74 #define MAX_RETRIES 8
75
76         if ((num_retries < MAX_RETRIES) && 
77             NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
78                 num_retries++;
79                 goto again;
80         }
81
82         /* Pass back result code - zero for success, other values for
83            specific failures. */
84
85         DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ?  
86                   "good" : "bad"));
87
88  done:
89         state->response.data.auth.nt_status = NT_STATUS_V(result);
90         fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
91         fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
92         state->response.data.auth.pam_error = nt_status_to_pam(result);
93
94         DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", 
95                                                 state->response.data.auth.nt_status_string));
96
97         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
98 }
99
100 /* Constants and helper functions for determining domain trust types */
101
102 enum trust_type {
103         EXTERNAL = 0,
104         FOREST,
105         IN_FOREST,
106         NONE,
107 };
108
109 const char *trust_type_strings[] = {"External", 
110                                     "Forest", 
111                                     "In Forest",
112                                     "None"};
113
114 static enum trust_type get_trust_type(struct winbindd_tdc_domain *domain)
115 {
116         if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)   
117                 return EXTERNAL;
118         else if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)
119                 return FOREST;
120         else if (((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) == NETR_TRUST_FLAG_IN_FOREST) &&
121             ((domain->trust_flags & NETR_TRUST_FLAG_PRIMARY) == 0x0))
122                 return IN_FOREST;
123         return NONE;    
124 }
125
126 static const char *get_trust_type_string(struct winbindd_tdc_domain *domain)
127 {
128         return trust_type_strings[get_trust_type(domain)];
129 }
130
131 static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
132 {
133         return (domain->trust_flags == 0x0) ||
134             ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) ==
135             NETR_TRUST_FLAG_IN_FOREST) ||                       
136             ((domain->trust_flags & NETR_TRUST_FLAG_INBOUND) ==
137             NETR_TRUST_FLAG_INBOUND);           
138 }
139
140 static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
141 {
142         return (domain->trust_flags == 0x0) ||
143             ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) ==
144             NETR_TRUST_FLAG_IN_FOREST) ||                       
145             ((domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) ==
146             NETR_TRUST_FLAG_OUTBOUND);          
147 }
148
149 static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
150 {
151         if ((domain->trust_attribs == NETR_TRUST_ATTRIBUTE_NON_TRANSITIVE) ||         
152             (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) ||
153             (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL))
154                 return False;
155         return True;
156 }
157
158 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
159 {
160         struct winbindd_tdc_domain *dom_list = NULL;
161         struct winbindd_tdc_domain *d = NULL;
162         size_t num_domains = 0;
163         int extra_data_len = 0;
164         char *extra_data = NULL;
165         int i = 0;
166         
167         DEBUG(3, ("[%5lu]: list trusted domains\n",
168                   (unsigned long)state->pid));
169
170         if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) {
171                 request_error(state);   
172                 goto done;
173         }
174
175         for ( i = 0; i < num_domains; i++ ) {
176                 struct winbindd_domain *domain;
177                 bool is_online = true;          
178
179                 d = &dom_list[i];
180                 domain = find_domain_from_name_noinit(d->domain_name);
181                 if (domain) {
182                         is_online = domain->online;
183                 }
184
185                 if ( !extra_data ) {
186                         extra_data = talloc_asprintf(state->mem_ctx, 
187                                                      "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
188                                                      d->domain_name,
189                                                      d->dns_name ? d->dns_name : d->domain_name,
190                                                      sid_string_talloc(state->mem_ctx, &d->sid),
191                                                      get_trust_type_string(d),
192                                                      trust_is_transitive(d) ? "Yes" : "No",
193                                                      trust_is_inbound(d) ? "Yes" : "No",
194                                                      trust_is_outbound(d) ? "Yes" : "No",
195                                                      is_online ? "Online" : "Offline" );
196                 } else {
197                         extra_data = talloc_asprintf(state->mem_ctx, 
198                                                      "%s\n%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
199                                                      extra_data,
200                                                      d->domain_name,
201                                                      d->dns_name ? d->dns_name : d->domain_name,
202                                                      sid_string_talloc(state->mem_ctx, &d->sid),
203                                                      get_trust_type_string(d),
204                                                      trust_is_transitive(d) ? "Yes" : "No",
205                                                      trust_is_inbound(d) ? "Yes" : "No",
206                                                      trust_is_outbound(d) ? "Yes" : "No",
207                                                      is_online ? "Online" : "Offline" );
208                 }
209         }
210         
211         extra_data_len = 0;
212         if (extra_data != NULL) {
213                 extra_data_len = strlen(extra_data);
214         }
215
216         if (extra_data_len > 0) {
217                 state->response.extra_data.data = SMB_STRDUP(extra_data);
218                 state->response.length += extra_data_len+1;
219         }
220
221         request_ok(state);      
222 done:
223         TALLOC_FREE( dom_list );
224         TALLOC_FREE( extra_data );      
225 }
226
227 enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
228                                                         struct winbindd_cli_state *state)
229 {
230         uint32 i, num_domains;
231         char **names, **alt_names;
232         DOM_SID *sids;
233         int extra_data_len = 0;
234         char *extra_data;
235         NTSTATUS result;
236         bool have_own_domain = False;
237
238         DEBUG(3, ("[%5lu]: list trusted domains\n",
239                   (unsigned long)state->pid));
240
241         result = domain->methods->trusted_domains(domain, state->mem_ctx,
242                                                   &num_domains, &names,
243                                                   &alt_names, &sids);
244
245         if (!NT_STATUS_IS_OK(result)) {
246                 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
247                         nt_errstr(result) ));
248                 return WINBINDD_ERROR;
249         }
250
251         extra_data = talloc_strdup(state->mem_ctx, "");
252
253         if (num_domains > 0)
254                 extra_data = talloc_asprintf(
255                         state->mem_ctx, "%s\\%s\\%s",
256                         names[0], alt_names[0] ? alt_names[0] : names[0],
257                         sid_string_talloc(state->mem_ctx, &sids[0]));
258
259         for (i=1; i<num_domains; i++)
260                 extra_data = talloc_asprintf(
261                         state->mem_ctx, "%s\n%s\\%s\\%s",
262                         extra_data, names[i],
263                         alt_names[i] ? alt_names[i] : names[i],
264                         sid_string_talloc(state->mem_ctx, &sids[i]));
265
266         /* add our primary domain */
267         
268         for (i=0; i<num_domains; i++) {
269                 if (strequal(names[i], domain->name)) {
270                         have_own_domain = True;
271                         break;
272                 }
273         }
274
275         if (state->request.data.list_all_domains && !have_own_domain) {
276                 extra_data = talloc_asprintf(
277                         state->mem_ctx, "%s\n%s\\%s\\%s",
278                         extra_data, domain->name,
279                         domain->alt_name ? domain->alt_name : domain->name,
280                         sid_string_talloc(state->mem_ctx, &domain->sid));
281         }
282
283         /* This is a bit excessive, but the extra data sooner or later will be
284            talloc'ed */
285
286         extra_data_len = 0;
287         if (extra_data != NULL) {
288                 extra_data_len = strlen(extra_data);
289         }
290
291         if (extra_data_len > 0) {
292                 state->response.extra_data.data = SMB_STRDUP(extra_data);
293                 state->response.length += extra_data_len+1;
294         }
295
296         return WINBINDD_OK;
297 }
298
299 static void winbindd_getdcname_recv(void *private_data,
300                                     bool success,
301                                     struct winbind_get_dc_info *r)
302 {
303         struct winbindd_cli_state *state =
304                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
305
306         if (!success) {
307                 request_error(state);
308                 return;
309         }
310
311         fstrcpy(state->response.data.dc_name, r->out.dc_info->name);
312
313         request_ok(state);
314 }
315
316 void winbindd_getdcname(struct winbindd_cli_state *state)
317 {
318         struct winbindd_domain *domain;
319         struct winbind_get_dc_info *r;
320
321         state->request.domain_name
322                 [sizeof(state->request.domain_name)-1] = '\0';
323
324         DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
325                   state->request.domain_name));
326
327         domain = find_domain_from_name_noinit(state->request.domain_name);
328         if (domain && domain->internal) {
329                 fstrcpy(state->response.data.dc_name, global_myname());
330                 request_ok(state);      
331                 return;
332         }
333
334         r = TALLOC_P(state->mem_ctx, struct winbind_get_dc_info);
335         if (!r) goto nomem;
336         r->in.level = TALLOC_P(r, enum winbind_dc_info_level);
337         if (!r->in.level) goto nomem;
338
339         *r->in.level            = WINBIND_DC_INFO_LEVEL_COMPAT_NT4;
340         r->in.domain_name       = state->request.domain_name;
341
342         winbindd_get_dc_info_async_domain(state->mem_ctx, find_our_domain(),
343                                           r, winbindd_getdcname_recv, state);
344         return;
345 nomem:
346         request_error(state);
347         return;
348 }
349
350 static void winbindd_get_dc_info_recv(TALLOC_CTX *mem_ctx, bool success,
351                                       struct winbindd_ndr_call *c,
352                                       void *_r,
353                                       void *_cont,
354                                       void *private_data)
355 {
356         void (*cont)(void *priv, bool succ, struct winbind_get_dc_info *r) =
357                 (void (*)(void *, bool, struct winbind_get_dc_info*))_cont;
358         struct winbind_get_dc_info *r =
359                 talloc_get_type_abort(_r, struct winbind_get_dc_info);
360
361         if (!success) {
362                 DEBUG(5, ("Could not get dc_info\n"));
363                 cont(private_data, False, r);
364                 return;
365         }
366
367         if (r->out.result != WINBIND_STATUS_OK) {
368                 DEBUG(5, ("get_dc_info returned an error:0x%08X\n",
369                         r->out.result));
370                 cont(private_data, False, r);
371                 return;
372         }
373
374         cont(private_data, True, r);
375 }
376
377 void winbindd_get_dc_info_async_domain(TALLOC_CTX *mem_ctx,
378                                        struct winbindd_domain *domain,
379                                        struct winbind_get_dc_info *r,
380                                        void (*cont)(void *private_data,
381                                                     bool success,
382                                                     struct winbind_get_dc_info *r),
383                                        void *private_data)
384 {
385         do_async_ndr_domain(mem_ctx, domain,
386                             NDR_WINBIND_GET_DC_INFO, r,
387                             winbindd_get_dc_info_recv, r,
388                             (void *)cont, private_data);
389 }
390
391 void winbindd_get_dc_info_async_child(TALLOC_CTX *mem_ctx,
392                                       struct winbindd_child *child,
393                                       struct winbind_get_dc_info *r,
394                                       void (*cont)(void *private_data,
395                                                    bool success,
396                                                    struct winbind_get_dc_info *r),
397                                       void *private_data)
398 {
399         do_async_ndr(mem_ctx, child,
400                      NDR_WINBIND_GET_DC_INFO, r,
401                      winbindd_get_dc_info_recv, r,
402                      (void *)cont, private_data);
403 }
404
405 static void ndr_child_get_dc_info_comapt_nt4(struct winbindd_domain *domain,
406                                              struct winbindd_cli_state *state,
407                                              struct winbind_get_dc_info *r)
408 {
409         const char *dcname_slash;
410         const char *p;
411         struct rpc_pipe_client *netlogon_pipe;
412         NTSTATUS result;
413         WERROR werr;
414         unsigned int orig_timeout;
415         struct winbindd_domain *req_domain;
416
417         DEBUG(3, ("Get DC name for '%s'\n", r->in.domain_name));
418
419         result = cm_connect_netlogon(domain, &netlogon_pipe);
420
421         if (!NT_STATUS_IS_OK(result)) {
422                 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
423                 r->out.result = WINBIND_STATUS_FOOBAR;
424                 return;
425         }
426
427         /* This call can take a long time - allow the server to time out.
428            35 seconds should do it. */
429
430         orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
431
432         /*
433          * if the requested domain name matches the current one
434          * we need to use GetDCName(), because GetAnyDCName() only
435          * works for trusted domains
436          */
437         req_domain = find_domain_from_name_noinit(r->in.domain_name);
438         if (req_domain == domain) {
439                 result = rpccli_netr_GetDcName(netlogon_pipe,
440                                                r,
441                                                domain->dcname,
442                                                r->in.domain_name,
443                                                &dcname_slash,
444                                                &werr);
445         } else {
446                 result = rpccli_netr_GetAnyDCName(netlogon_pipe,
447                                                   r,
448                                                   domain->dcname,
449                                                   r->in.domain_name,
450                                                   &dcname_slash,
451                                                   &werr);
452         }
453         /* And restore our original timeout. */
454         cli_set_timeout(netlogon_pipe->cli, orig_timeout);
455
456         if (!NT_STATUS_IS_OK(result)) {
457                 DEBUG(5,("Error requesting DCname for domain %s: %s\n",
458                         r->in.domain_name, nt_errstr(result)));
459                 r->out.result = WINBIND_STATUS_FOOBAR;
460                 return;
461         }
462
463         if (!W_ERROR_IS_OK(werr)) {
464                 DEBUG(5, ("Error requesting DCname for domain %s: %s\n",
465                         r->in.domain_name, dos_errstr(werr)));
466                 r->out.result = WINBIND_STATUS_FOOBAR;
467                 return;
468         }
469
470         p = dcname_slash;
471         if (*p == '\\') {
472                 p+=1;
473         }
474         if (*p == '\\') {
475                 p+=1;
476         }
477
478         r->out.dc_info->name = talloc_strdup(r, p);
479         if (!r->out.dc_info->name) {
480                 r->out.result = WINBIND_STATUS_NO_MEMORY;
481                 return;
482         }
483         r->out.result = WINBIND_STATUS_OK;
484 }
485
486 void winbindd_ndr_domain_child_get_dc_info(struct winbindd_domain *domain,
487                                            struct winbindd_cli_state *state)
488 {
489         struct winbind_get_dc_info *r;
490
491         r = talloc_get_type_abort(state->c.ndr.r,
492                                   struct winbind_get_dc_info);
493
494         switch (*r->in.level) {
495         case WINBIND_DC_INFO_LEVEL_COMPAT_NT4:
496                 ndr_child_get_dc_info_comapt_nt4(domain, state, r);
497                 return;
498
499         case WINBIND_DC_INFO_LEVEL_COMPAT_DS:
500                 r->out.result = WINBIND_STATUS_INVALID_LEVEL;
501                 return;
502         }
503
504         r->out.result = WINBIND_STATUS_UNKNOWN_LEVEL;
505         return;
506 }
507
508 struct sequence_state {
509         TALLOC_CTX *mem_ctx;
510         struct winbindd_cli_state *cli_state;
511         struct winbindd_domain *domain;
512         struct winbindd_request *request;
513         struct winbindd_response *response;
514         char *extra_data;
515 };
516
517 static void sequence_recv(void *private_data, bool success);
518
519 void winbindd_show_sequence(struct winbindd_cli_state *state)
520 {
521         struct sequence_state *seq;
522
523         /* Ensure null termination */
524         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
525
526         if (strlen(state->request.domain_name) > 0) {
527                 struct winbindd_domain *domain;
528                 domain = find_domain_from_name_noinit(
529                         state->request.domain_name);
530                 if (domain == NULL) {
531                         request_error(state);
532                         return;
533                 }
534                 sendto_domain(state, domain);
535                 return;
536         }
537
538         /* Ask all domains in sequence, collect the results in sequence_recv */
539
540         seq = TALLOC_P(state->mem_ctx, struct sequence_state);
541         if (seq == NULL) {
542                 DEBUG(0, ("talloc failed\n"));
543                 request_error(state);
544                 return;
545         }
546
547         seq->mem_ctx = state->mem_ctx;
548         seq->cli_state = state;
549         seq->domain = domain_list();
550         if (seq->domain == NULL) {
551                 DEBUG(0, ("domain list empty\n"));
552                 request_error(state);
553                 return;
554         }
555         seq->request = TALLOC_ZERO_P(state->mem_ctx,
556                                      struct winbindd_request);
557         seq->response = TALLOC_ZERO_P(state->mem_ctx,
558                                       struct winbindd_response);
559         seq->extra_data = talloc_strdup(state->mem_ctx, "");
560
561         if ((seq->request == NULL) || (seq->response == NULL) ||
562             (seq->extra_data == NULL)) {
563                 DEBUG(0, ("talloc failed\n"));
564                 request_error(state);
565                 return;
566         }
567
568         seq->request->length = sizeof(*seq->request);
569         seq->request->cmd = WINBINDD_SHOW_SEQUENCE;
570         fstrcpy(seq->request->domain_name, seq->domain->name);
571
572         async_domain_request(state->mem_ctx, seq->domain,
573                              seq->request, seq->response,
574                              sequence_recv, seq);
575 }
576
577 static void sequence_recv(void *private_data, bool success)
578 {
579         struct sequence_state *state =
580                 (struct sequence_state *)private_data;
581         uint32 seq = DOM_SEQUENCE_NONE;
582
583         if ((success) && (state->response->result == WINBINDD_OK))
584                 seq = state->response->data.sequence_number;
585
586         if (seq == DOM_SEQUENCE_NONE) {
587                 state->extra_data = talloc_asprintf(state->mem_ctx,
588                                                     "%s%s : DISCONNECTED\n",
589                                                     state->extra_data,
590                                                     state->domain->name);
591         } else {
592                 state->extra_data = talloc_asprintf(state->mem_ctx,
593                                                     "%s%s : %d\n",
594                                                     state->extra_data,
595                                                     state->domain->name, seq);
596         }
597
598         state->domain->sequence_number = seq;
599
600         state->domain = state->domain->next;
601
602         if (state->domain == NULL) {
603                 struct winbindd_cli_state *cli_state = state->cli_state;
604                 cli_state->response.length =
605                         sizeof(cli_state->response) +
606                         strlen(state->extra_data) + 1;
607                 cli_state->response.extra_data.data =
608                         SMB_STRDUP(state->extra_data);
609                 request_ok(cli_state);
610                 return;
611         }
612
613         /* Ask the next domain */
614         fstrcpy(state->request->domain_name, state->domain->name);
615         async_domain_request(state->mem_ctx, state->domain,
616                              state->request, state->response,
617                              sequence_recv, state);
618 }
619
620 /* This is the child-only version of --sequence. It only allows for a single
621  * domain (ie "our" one) to be displayed. */
622
623 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
624                                                  struct winbindd_cli_state *state)
625 {
626         DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
627
628         /* Ensure null termination */
629         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
630
631         domain->methods->sequence_number(domain, &domain->sequence_number);
632
633         state->response.data.sequence_number =
634                 domain->sequence_number;
635
636         return WINBINDD_OK;
637 }
638
639 struct domain_info_state {
640         struct winbindd_domain *domain;
641         struct winbindd_cli_state *cli_state;
642 };
643
644 static void domain_info_init_recv(void *private_data, bool success);
645
646 void winbindd_domain_info(struct winbindd_cli_state *state)
647 {
648         struct winbindd_domain *domain;
649
650         DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
651                   state->request.domain_name));
652
653         domain = find_domain_from_name_noinit(state->request.domain_name);
654
655         if (domain == NULL) {
656                 DEBUG(3, ("Did not find domain [%s]\n",
657                           state->request.domain_name));
658                 request_error(state);
659                 return;
660         }
661
662         if (!domain->initialized) {
663                 struct domain_info_state *istate;
664
665                 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
666                 if (istate == NULL) {
667                         DEBUG(0, ("talloc failed\n"));
668                         request_error(state);
669                         return;
670                 }
671
672                 istate->cli_state = state;
673                 istate->domain = domain;
674
675                 init_child_connection(domain, domain_info_init_recv, istate);
676                                       
677                 return;
678         }
679
680         fstrcpy(state->response.data.domain_info.name,
681                 domain->name);
682         fstrcpy(state->response.data.domain_info.alt_name,
683                 domain->alt_name);
684         sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
685         
686         state->response.data.domain_info.native_mode =
687                 domain->native_mode;
688         state->response.data.domain_info.active_directory =
689                 domain->active_directory;
690         state->response.data.domain_info.primary =
691                 domain->primary;
692
693         request_ok(state);
694 }
695
696 static void domain_info_init_recv(void *private_data, bool success)
697 {
698         struct domain_info_state *istate =
699                 (struct domain_info_state *)private_data;
700         struct winbindd_cli_state *state = istate->cli_state;
701         struct winbindd_domain *domain = istate->domain;
702
703         DEBUG(10, ("Got back from child init: %d\n", success));
704
705         if ((!success) || (!domain->initialized)) {
706                 DEBUG(5, ("Could not init child for domain %s\n",
707                           domain->name));
708                 request_error(state);
709                 return;
710         }
711
712         fstrcpy(state->response.data.domain_info.name,
713                 domain->name);
714         fstrcpy(state->response.data.domain_info.alt_name,
715                 domain->alt_name);
716         sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
717         
718         state->response.data.domain_info.native_mode =
719                 domain->native_mode;
720         state->response.data.domain_info.active_directory =
721                 domain->active_directory;
722         state->response.data.domain_info.primary =
723                 domain->primary;
724
725         request_ok(state);
726 }
727
728 void winbindd_ping(struct winbindd_cli_state *state)
729 {
730         if (lp_parm_bool(-1, "winbindd", "ping_our_domain", False)) {
731                 sendto_domain(state, find_our_domain());
732                 return;
733         }
734
735         DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
736         request_ok(state);
737 }
738
739 enum winbindd_result winbindd_dual_ping(struct winbindd_domain *domain,
740                                         struct winbindd_cli_state *state)
741 {
742         DEBUG(3, ("[%5lu]: (dual) ping\n", (unsigned long)state->pid));
743         return WINBINDD_OK;
744 }
745
746 /* List various tidbits of information */
747
748 void winbindd_info(struct winbindd_cli_state *state)
749 {
750
751         DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
752
753         state->response.data.info.winbind_separator = *lp_winbind_separator();
754         fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
755         request_ok(state);
756 }
757
758 /* Tell the client the current interface version */
759
760 void winbindd_interface_version(struct winbindd_cli_state *state)
761 {
762         DEBUG(3, ("[%5lu]: request interface version\n",
763                   (unsigned long)state->pid));
764         
765         state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
766         request_ok(state);
767 }
768
769 /* What domain are we a member of? */
770
771 void winbindd_domain_name(struct winbindd_cli_state *state)
772 {
773         DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
774         
775         fstrcpy(state->response.data.domain_name, lp_workgroup());
776         request_ok(state);
777 }
778
779 /* What's my name again? */
780
781 void winbindd_netbios_name(struct winbindd_cli_state *state)
782 {
783         DEBUG(3, ("[%5lu]: request netbios name\n",
784                   (unsigned long)state->pid));
785         
786         fstrcpy(state->response.data.netbios_name, global_myname());
787         request_ok(state);
788 }
789
790 /* Where can I find the privilaged pipe? */
791
792 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
793 {
794
795         DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
796                   (unsigned long)state->pid));
797         
798         state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir());
799         if (!state->response.extra_data.data) {
800                 DEBUG(0, ("malloc failed\n"));
801                 request_error(state);
802                 return;
803         }
804
805         /* must add one to length to copy the 0 for string termination */
806         state->response.length +=
807                 strlen((char *)state->response.extra_data.data) + 1;
808
809         request_ok(state);
810 }
811