Merge branch 'v3-devel' of ssh://git.samba.org/data/git/samba into v3-devel
[ira/wip.git] / source3 / 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         set_auth_errors(&state->response, result);
90
91         DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", 
92                                                 state->response.data.auth.nt_status_string));
93
94         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
95 }
96
97 /* Helpers for listing user and group names */
98
99 const char *ent_type_strings[] = {"users", 
100                                   "groups"};
101
102 static const char *get_ent_type_string(enum ent_type type)
103 {
104         return ent_type_strings[type];
105 }
106
107 struct listent_state {
108         TALLOC_CTX *mem_ctx;
109         struct winbindd_cli_state *cli_state;
110         enum ent_type type;
111         int domain_count;
112         char *extra_data;
113         uint32_t extra_data_len;
114 };
115
116 static void listent_recv(void *private_data, bool success, fstring dom_name,
117                          char *extra_data);
118
119 /* List domain users/groups without mapping to unix ids */
120 void winbindd_list_ent(struct winbindd_cli_state *state, enum ent_type type)
121 {
122         struct winbindd_domain *domain;
123         const char *which_domain;
124         struct listent_state *ent_state;
125
126         DEBUG(3, ("[%5lu]: list %s\n", (unsigned long)state->pid, 
127               get_ent_type_string(type)));
128
129         /* Ensure null termination */
130         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';  
131         which_domain = state->request.domain_name;
132         
133         /* Initialize listent_state */
134         ent_state = TALLOC_P(state->mem_ctx, struct listent_state);
135         if (ent_state == NULL) {
136                 DEBUG(0, ("talloc failed\n"));
137                 request_error(state);
138                 return;
139         }
140
141         ent_state->mem_ctx = state->mem_ctx;
142         ent_state->cli_state = state;
143         ent_state->type = type;
144         ent_state->domain_count = 0;
145         ent_state->extra_data = NULL;
146         ent_state->extra_data_len = 0;
147
148         /* Must count the full list of expected domains before we request data
149          * from any of them.  Otherwise it's possible for a connection to the
150          * first domain to fail, call listent_recv(), and return to the
151          * client without checking any other domains. */
152         for (domain = domain_list(); domain; domain = domain->next) {
153                 /* if we have a domain name restricting the request and this
154                    one in the list doesn't match, then just bypass the remainder
155                    of the loop */
156                 if ( *which_domain && !strequal(which_domain, domain->name) )
157                         continue;
158
159                 ent_state->domain_count++;
160         }
161
162         /* Make sure we're enumerating at least one domain */
163         if (!ent_state->domain_count) {
164                 request_ok(state);
165                 return;
166         }
167
168         /* Enumerate list of trusted domains and request user/group list from
169          * each */
170         for (domain = domain_list(); domain; domain = domain->next) {
171                 if ( *which_domain && !strequal(which_domain, domain->name) )
172                         continue;
173
174                 winbindd_listent_async(state->mem_ctx, domain, 
175                                           listent_recv, ent_state, type);
176         }
177 }
178
179 static void listent_recv(void *private_data, bool success, fstring dom_name,
180                          char *extra_data)
181 {
182         /* extra_data comes to us as a '\0' terminated string of comma
183            separated users or groups */
184         struct listent_state *state = talloc_get_type_abort(
185                 private_data, struct listent_state);
186
187         /* Append users/groups from one domain onto the whole list */
188         if (extra_data) {
189                 DEBUG(5, ("listent_recv: %s returned %s.\n", 
190                       dom_name, get_ent_type_string(state->type)));
191                 if (!state->extra_data)
192                         state->extra_data = talloc_asprintf(state->mem_ctx,
193                                                             "%s", extra_data);
194                 else
195                         state->extra_data = talloc_asprintf_append(
196                                                             state->extra_data,
197                                                             ",%s", extra_data);
198                 /* Add one for the '\0' and each additional ',' */
199                 state->extra_data_len += strlen(extra_data) + 1;
200         }
201         else {
202                 DEBUG(5, ("listent_recv: %s returned no %s.\n", 
203                       dom_name, get_ent_type_string(state->type)));
204         }
205
206         if (--state->domain_count)
207                 /* Still waiting for some child domains to return */
208                 return;
209
210         /* Return list of all users/groups to the client */
211         if (state->extra_data) {
212                 state->cli_state->response.extra_data.data = 
213                         SMB_STRDUP(state->extra_data);
214                 state->cli_state->response.length += state->extra_data_len;
215         }
216
217         request_ok(state->cli_state);
218 }       
219
220 /* Constants and helper functions for determining domain trust types */
221
222 enum trust_type {
223         EXTERNAL = 0,
224         FOREST,
225         IN_FOREST,
226         NONE,
227 };
228
229 const char *trust_type_strings[] = {"External", 
230                                     "Forest", 
231                                     "In Forest",
232                                     "None"};
233
234 static enum trust_type get_trust_type(struct winbindd_tdc_domain *domain)
235 {
236         if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)   
237                 return EXTERNAL;
238         else if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)
239                 return FOREST;
240         else if (((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) == NETR_TRUST_FLAG_IN_FOREST) &&
241             ((domain->trust_flags & NETR_TRUST_FLAG_PRIMARY) == 0x0))
242                 return IN_FOREST;
243         return NONE;    
244 }
245
246 static const char *get_trust_type_string(struct winbindd_tdc_domain *domain)
247 {
248         return trust_type_strings[get_trust_type(domain)];
249 }
250
251 static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
252 {
253         return (domain->trust_flags == 0x0) ||
254             ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) ==
255             NETR_TRUST_FLAG_IN_FOREST) ||                       
256             ((domain->trust_flags & NETR_TRUST_FLAG_INBOUND) ==
257             NETR_TRUST_FLAG_INBOUND);           
258 }
259
260 static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
261 {
262         return (domain->trust_flags == 0x0) ||
263             ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) ==
264             NETR_TRUST_FLAG_IN_FOREST) ||                       
265             ((domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) ==
266             NETR_TRUST_FLAG_OUTBOUND);          
267 }
268
269 static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
270 {
271         if ((domain->trust_attribs == NETR_TRUST_ATTRIBUTE_NON_TRANSITIVE) ||         
272             (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) ||
273             (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL))
274                 return False;
275         return True;
276 }
277
278 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
279 {
280         struct winbindd_tdc_domain *dom_list = NULL;
281         struct winbindd_tdc_domain *d = NULL;
282         size_t num_domains = 0;
283         int extra_data_len = 0;
284         char *extra_data = NULL;
285         int i = 0;
286         
287         DEBUG(3, ("[%5lu]: list trusted domains\n",
288                   (unsigned long)state->pid));
289
290         if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) {
291                 request_error(state);   
292                 goto done;
293         }
294
295         for ( i = 0; i < num_domains; i++ ) {
296                 struct winbindd_domain *domain;
297                 bool is_online = true;          
298
299                 d = &dom_list[i];
300                 domain = find_domain_from_name_noinit(d->domain_name);
301                 if (domain) {
302                         is_online = domain->online;
303                 }
304
305                 if ( !extra_data ) {
306                         extra_data = talloc_asprintf(state->mem_ctx, 
307                                                      "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
308                                                      d->domain_name,
309                                                      d->dns_name ? d->dns_name : d->domain_name,
310                                                      sid_string_talloc(state->mem_ctx, &d->sid),
311                                                      get_trust_type_string(d),
312                                                      trust_is_transitive(d) ? "Yes" : "No",
313                                                      trust_is_inbound(d) ? "Yes" : "No",
314                                                      trust_is_outbound(d) ? "Yes" : "No",
315                                                      is_online ? "Online" : "Offline" );
316                 } else {
317                         extra_data = talloc_asprintf(state->mem_ctx, 
318                                                      "%s\n%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
319                                                      extra_data,
320                                                      d->domain_name,
321                                                      d->dns_name ? d->dns_name : d->domain_name,
322                                                      sid_string_talloc(state->mem_ctx, &d->sid),
323                                                      get_trust_type_string(d),
324                                                      trust_is_transitive(d) ? "Yes" : "No",
325                                                      trust_is_inbound(d) ? "Yes" : "No",
326                                                      trust_is_outbound(d) ? "Yes" : "No",
327                                                      is_online ? "Online" : "Offline" );
328                 }
329         }
330         
331         extra_data_len = 0;
332         if (extra_data != NULL) {
333                 extra_data_len = strlen(extra_data);
334         }
335
336         if (extra_data_len > 0) {
337                 state->response.extra_data.data = SMB_STRDUP(extra_data);
338                 state->response.length += extra_data_len+1;
339         }
340
341         request_ok(state);      
342 done:
343         TALLOC_FREE( dom_list );
344         TALLOC_FREE( extra_data );      
345 }
346
347 enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
348                                                         struct winbindd_cli_state *state)
349 {
350         uint32 i, num_domains;
351         char **names, **alt_names;
352         DOM_SID *sids;
353         int extra_data_len = 0;
354         char *extra_data;
355         NTSTATUS result;
356         bool have_own_domain = False;
357
358         DEBUG(3, ("[%5lu]: list trusted domains\n",
359                   (unsigned long)state->pid));
360
361         result = domain->methods->trusted_domains(domain, state->mem_ctx,
362                                                   &num_domains, &names,
363                                                   &alt_names, &sids);
364
365         if (!NT_STATUS_IS_OK(result)) {
366                 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
367                         nt_errstr(result) ));
368                 return WINBINDD_ERROR;
369         }
370
371         extra_data = talloc_strdup(state->mem_ctx, "");
372
373         if (num_domains > 0)
374                 extra_data = talloc_asprintf(
375                         state->mem_ctx, "%s\\%s\\%s",
376                         names[0], alt_names[0] ? alt_names[0] : names[0],
377                         sid_string_talloc(state->mem_ctx, &sids[0]));
378
379         for (i=1; i<num_domains; i++)
380                 extra_data = talloc_asprintf(
381                         state->mem_ctx, "%s\n%s\\%s\\%s",
382                         extra_data, names[i],
383                         alt_names[i] ? alt_names[i] : names[i],
384                         sid_string_talloc(state->mem_ctx, &sids[i]));
385
386         /* add our primary domain */
387         
388         for (i=0; i<num_domains; i++) {
389                 if (strequal(names[i], domain->name)) {
390                         have_own_domain = True;
391                         break;
392                 }
393         }
394
395         if (state->request.data.list_all_domains && !have_own_domain) {
396                 extra_data = talloc_asprintf(
397                         state->mem_ctx, "%s\n%s\\%s\\%s",
398                         extra_data, domain->name,
399                         domain->alt_name ? domain->alt_name : domain->name,
400                         sid_string_talloc(state->mem_ctx, &domain->sid));
401         }
402
403         /* This is a bit excessive, but the extra data sooner or later will be
404            talloc'ed */
405
406         extra_data_len = 0;
407         if (extra_data != NULL) {
408                 extra_data_len = strlen(extra_data);
409         }
410
411         if (extra_data_len > 0) {
412                 state->response.extra_data.data = SMB_STRDUP(extra_data);
413                 state->response.length += extra_data_len+1;
414         }
415
416         return WINBINDD_OK;
417 }
418
419 void winbindd_getdcname(struct winbindd_cli_state *state)
420 {
421         struct winbindd_domain *domain;
422
423         state->request.domain_name
424                 [sizeof(state->request.domain_name)-1] = '\0';
425
426         DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
427                   state->request.domain_name));
428
429         domain = find_domain_from_name_noinit(state->request.domain_name);
430         if (domain && domain->internal) {
431                 fstrcpy(state->response.data.dc_name, global_myname());
432                 request_ok(state);      
433                 return;
434         }
435
436         sendto_domain(state, find_our_domain());
437 }
438
439 enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
440                                              struct winbindd_cli_state *state)
441 {
442         const char *dcname_slash = NULL;
443         const char *p;
444         struct rpc_pipe_client *netlogon_pipe;
445         NTSTATUS result;
446         WERROR werr;
447         unsigned int orig_timeout;
448         struct winbindd_domain *req_domain;
449
450         state->request.domain_name
451                 [sizeof(state->request.domain_name)-1] = '\0';
452
453         DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
454                   state->request.domain_name));
455
456         result = cm_connect_netlogon(domain, &netlogon_pipe);
457
458         if (!NT_STATUS_IS_OK(result)) {
459                 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
460                 return WINBINDD_ERROR;
461         }
462
463         /* This call can take a long time - allow the server to time out.
464            35 seconds should do it. */
465
466         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
467
468         req_domain = find_domain_from_name_noinit(state->request.domain_name);
469         if (req_domain == domain) {
470                 result = rpccli_netr_GetDcName(netlogon_pipe,
471                                                state->mem_ctx,
472                                                domain->dcname,
473                                                state->request.domain_name,
474                                                &dcname_slash,
475                                                &werr);
476         } else {
477                 result = rpccli_netr_GetAnyDCName(netlogon_pipe,
478                                                   state->mem_ctx,
479                                                   domain->dcname,
480                                                   state->request.domain_name,
481                                                   &dcname_slash,
482                                                   &werr);
483         }
484         /* And restore our original timeout. */
485         rpccli_set_timeout(netlogon_pipe, orig_timeout);
486
487         if (!NT_STATUS_IS_OK(result)) {
488                 DEBUG(5,("Error requesting DCname for domain %s: %s\n",
489                         state->request.domain_name, nt_errstr(result)));
490                 return WINBINDD_ERROR;
491         }
492
493         if (!W_ERROR_IS_OK(werr)) {
494                 DEBUG(5, ("Error requesting DCname for domain %s: %s\n",
495                         state->request.domain_name, dos_errstr(werr)));
496                 return WINBINDD_ERROR;
497         }
498
499         p = dcname_slash;
500         if (*p == '\\') {
501                 p+=1;
502         }
503         if (*p == '\\') {
504                 p+=1;
505         }
506
507         fstrcpy(state->response.data.dc_name, p);
508         return WINBINDD_OK;
509 }
510
511 struct sequence_state {
512         TALLOC_CTX *mem_ctx;
513         struct winbindd_cli_state *cli_state;
514         struct winbindd_domain *domain;
515         struct winbindd_request *request;
516         struct winbindd_response *response;
517         char *extra_data;
518 };
519
520 static void sequence_recv(void *private_data, bool success);
521
522 void winbindd_show_sequence(struct winbindd_cli_state *state)
523 {
524         struct sequence_state *seq;
525
526         /* Ensure null termination */
527         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
528
529         if (strlen(state->request.domain_name) > 0) {
530                 struct winbindd_domain *domain;
531                 domain = find_domain_from_name_noinit(
532                         state->request.domain_name);
533                 if (domain == NULL) {
534                         request_error(state);
535                         return;
536                 }
537                 sendto_domain(state, domain);
538                 return;
539         }
540
541         /* Ask all domains in sequence, collect the results in sequence_recv */
542
543         seq = TALLOC_P(state->mem_ctx, struct sequence_state);
544         if (seq == NULL) {
545                 DEBUG(0, ("talloc failed\n"));
546                 request_error(state);
547                 return;
548         }
549
550         seq->mem_ctx = state->mem_ctx;
551         seq->cli_state = state;
552         seq->domain = domain_list();
553         if (seq->domain == NULL) {
554                 DEBUG(0, ("domain list empty\n"));
555                 request_error(state);
556                 return;
557         }
558         seq->request = TALLOC_ZERO_P(state->mem_ctx,
559                                      struct winbindd_request);
560         seq->response = TALLOC_ZERO_P(state->mem_ctx,
561                                       struct winbindd_response);
562         seq->extra_data = talloc_strdup(state->mem_ctx, "");
563
564         if ((seq->request == NULL) || (seq->response == NULL) ||
565             (seq->extra_data == NULL)) {
566                 DEBUG(0, ("talloc failed\n"));
567                 request_error(state);
568                 return;
569         }
570
571         seq->request->length = sizeof(*seq->request);
572         seq->request->cmd = WINBINDD_SHOW_SEQUENCE;
573         fstrcpy(seq->request->domain_name, seq->domain->name);
574
575         async_domain_request(state->mem_ctx, seq->domain,
576                              seq->request, seq->response,
577                              sequence_recv, seq);
578 }
579
580 static void sequence_recv(void *private_data, bool success)
581 {
582         struct sequence_state *state =
583                 (struct sequence_state *)private_data;
584         uint32 seq = DOM_SEQUENCE_NONE;
585
586         if ((success) && (state->response->result == WINBINDD_OK))
587                 seq = state->response->data.sequence_number;
588
589         if (seq == DOM_SEQUENCE_NONE) {
590                 state->extra_data = talloc_asprintf(state->mem_ctx,
591                                                     "%s%s : DISCONNECTED\n",
592                                                     state->extra_data,
593                                                     state->domain->name);
594         } else {
595                 state->extra_data = talloc_asprintf(state->mem_ctx,
596                                                     "%s%s : %d\n",
597                                                     state->extra_data,
598                                                     state->domain->name, seq);
599         }
600
601         state->domain->sequence_number = seq;
602
603         state->domain = state->domain->next;
604
605         if (state->domain == NULL) {
606                 struct winbindd_cli_state *cli_state = state->cli_state;
607                 cli_state->response.length =
608                         sizeof(cli_state->response) +
609                         strlen(state->extra_data) + 1;
610                 cli_state->response.extra_data.data =
611                         SMB_STRDUP(state->extra_data);
612                 request_ok(cli_state);
613                 return;
614         }
615
616         /* Ask the next domain */
617         fstrcpy(state->request->domain_name, state->domain->name);
618         async_domain_request(state->mem_ctx, state->domain,
619                              state->request, state->response,
620                              sequence_recv, state);
621 }
622
623 /* This is the child-only version of --sequence. It only allows for a single
624  * domain (ie "our" one) to be displayed. */
625
626 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
627                                                  struct winbindd_cli_state *state)
628 {
629         DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
630
631         /* Ensure null termination */
632         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
633
634         domain->methods->sequence_number(domain, &domain->sequence_number);
635
636         state->response.data.sequence_number =
637                 domain->sequence_number;
638
639         return WINBINDD_OK;
640 }
641
642 struct domain_info_state {
643         struct winbindd_domain *domain;
644         struct winbindd_cli_state *cli_state;
645 };
646
647 static void domain_info_init_recv(void *private_data, bool success);
648
649 void winbindd_domain_info(struct winbindd_cli_state *state)
650 {
651         struct winbindd_domain *domain;
652
653         DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
654                   state->request.domain_name));
655
656         domain = find_domain_from_name_noinit(state->request.domain_name);
657
658         if (domain == NULL) {
659                 DEBUG(3, ("Did not find domain [%s]\n",
660                           state->request.domain_name));
661                 request_error(state);
662                 return;
663         }
664
665         if (!domain->initialized) {
666                 struct domain_info_state *istate;
667
668                 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
669                 if (istate == NULL) {
670                         DEBUG(0, ("talloc failed\n"));
671                         request_error(state);
672                         return;
673                 }
674
675                 istate->cli_state = state;
676                 istate->domain = domain;
677
678                 init_child_connection(domain, domain_info_init_recv, istate);
679                                       
680                 return;
681         }
682
683         fstrcpy(state->response.data.domain_info.name,
684                 domain->name);
685         fstrcpy(state->response.data.domain_info.alt_name,
686                 domain->alt_name);
687         sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
688         
689         state->response.data.domain_info.native_mode =
690                 domain->native_mode;
691         state->response.data.domain_info.active_directory =
692                 domain->active_directory;
693         state->response.data.domain_info.primary =
694                 domain->primary;
695
696         request_ok(state);
697 }
698
699 static void domain_info_init_recv(void *private_data, bool success)
700 {
701         struct domain_info_state *istate =
702                 (struct domain_info_state *)private_data;
703         struct winbindd_cli_state *state = istate->cli_state;
704         struct winbindd_domain *domain = istate->domain;
705
706         DEBUG(10, ("Got back from child init: %d\n", success));
707
708         if ((!success) || (!domain->initialized)) {
709                 DEBUG(5, ("Could not init child for domain %s\n",
710                           domain->name));
711                 request_error(state);
712                 return;
713         }
714
715         fstrcpy(state->response.data.domain_info.name,
716                 domain->name);
717         fstrcpy(state->response.data.domain_info.alt_name,
718                 domain->alt_name);
719         sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
720         
721         state->response.data.domain_info.native_mode =
722                 domain->native_mode;
723         state->response.data.domain_info.active_directory =
724                 domain->active_directory;
725         state->response.data.domain_info.primary =
726                 domain->primary;
727
728         request_ok(state);
729 }
730
731 void winbindd_ping(struct winbindd_cli_state *state)
732 {
733         DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
734         request_ok(state);
735 }
736
737 /* List various tidbits of information */
738
739 void winbindd_info(struct winbindd_cli_state *state)
740 {
741
742         DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
743
744         state->response.data.info.winbind_separator = *lp_winbind_separator();
745         fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
746         request_ok(state);
747 }
748
749 /* Tell the client the current interface version */
750
751 void winbindd_interface_version(struct winbindd_cli_state *state)
752 {
753         DEBUG(3, ("[%5lu]: request interface version\n",
754                   (unsigned long)state->pid));
755         
756         state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
757         request_ok(state);
758 }
759
760 /* What domain are we a member of? */
761
762 void winbindd_domain_name(struct winbindd_cli_state *state)
763 {
764         DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
765         
766         fstrcpy(state->response.data.domain_name, lp_workgroup());
767         request_ok(state);
768 }
769
770 /* What's my name again? */
771
772 void winbindd_netbios_name(struct winbindd_cli_state *state)
773 {
774         DEBUG(3, ("[%5lu]: request netbios name\n",
775                   (unsigned long)state->pid));
776         
777         fstrcpy(state->response.data.netbios_name, global_myname());
778         request_ok(state);
779 }
780
781 /* Where can I find the privilaged pipe? */
782
783 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
784 {
785
786         DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
787                   (unsigned long)state->pid));
788         
789         state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir());
790         if (!state->response.extra_data.data) {
791                 DEBUG(0, ("malloc failed\n"));
792                 request_error(state);
793                 return;
794         }
795
796         /* must add one to length to copy the 0 for string termination */
797         state->response.length +=
798                 strlen((char *)state->response.extra_data.data) + 1;
799
800         request_ok(state);
801 }
802