use WINBIND_DOMAIN_INFO_LEVEL_SEQNUM to get the seqnumber from the domain childs...
[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 static void winbindd_get_domain_info_recv(TALLOC_CTX *mem_ctx, bool success,
509                                           struct winbindd_ndr_call *c,
510                                           void *_r,
511                                           void *_cont,
512                                           void *private_data)
513 {
514         void (*cont)(void *priv, bool succ, struct winbind_get_domain_info *r) =
515                 (void (*)(void *, bool, struct winbind_get_domain_info*))_cont;
516         struct winbind_get_domain_info *r =
517                 talloc_get_type_abort(_r, struct winbind_get_domain_info);
518
519         if (!success) {
520                 DEBUG(5, ("Could not get domain_info\n"));
521                 cont(private_data, False, r);
522                 return;
523         }
524
525         if (r->out.result != WINBIND_STATUS_OK) {
526                 DEBUG(5, ("get_domain_info returned an error:0x%08X\n",
527                         r->out.result));
528                 cont(private_data, False, r);
529                 return;
530         }
531
532         cont(private_data, True, r);
533 }
534
535 void winbindd_get_domain_info_async(TALLOC_CTX *mem_ctx,
536                                     struct winbindd_domain *domain,
537                                     struct winbind_get_domain_info *r,
538                                     void (*cont)(void *private_data,
539                                                  bool success,
540                                                  struct winbind_get_domain_info *r),
541                                     void *private_data)
542 {
543         do_async_ndr_domain(mem_ctx, domain,
544                             NDR_WINBIND_GET_DOMAIN_INFO, r,
545                             winbindd_get_domain_info_recv, r,
546                             (void *)cont, private_data);
547 }
548
549 struct sequence_state {
550         struct winbindd_cli_state *cli_state;
551         struct winbindd_domain *domain;
552         struct winbind_get_domain_info *r;
553         char *extra_data;
554         void (*recv_fn)(void *priv, bool succ,
555                         struct winbind_get_domain_info *r);
556 };
557
558 static void sequence_one_recv(void *private_data, bool success,
559                               struct winbind_get_domain_info *r);
560 static void sequence_next_recv(void *private_data, bool success,
561                                struct winbind_get_domain_info *r);
562
563 void winbindd_show_sequence(struct winbindd_cli_state *state)
564 {
565         struct sequence_state *seq;
566
567         /* Ensure null termination */
568         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
569
570         seq = TALLOC_P(state->mem_ctx, struct sequence_state);
571         if (!seq) goto nomem;
572         seq->cli_state = state;
573         seq->extra_data = talloc_strdup(state->mem_ctx, "");
574         if (!seq->extra_data) goto nomem;
575         seq->r = TALLOC_P(seq, struct winbind_get_domain_info);
576         if (!seq->r) goto nomem;
577         seq->r->in.level = TALLOC_P(seq->r, enum winbind_domain_info_level);
578         if (!seq->r->in.level) goto nomem;
579
580         if (strlen(state->request.domain_name) > 0) {
581                 seq->domain = find_domain_from_name_noinit(
582                         state->request.domain_name);
583                 if (seq->domain == NULL) {
584                         DEBUG(0,("domain '%s' not found\n",
585                                  state->request.domain_name));
586                         request_error(state);
587                         return;
588                 }
589                 seq->recv_fn = sequence_one_recv;
590         } else {
591                 seq->domain = domain_list();
592                 if (seq->domain == NULL) {
593                         DEBUG(0, ("domain list empty\n"));
594                         request_error(state);
595                         return;
596                 }
597                 seq->recv_fn = sequence_next_recv;
598         }
599
600         *seq->r->in.level       = WINBIND_DOMAIN_INFO_LEVEL_SEQNUM;
601         seq->r->in.domain_name  = seq->domain->name;
602         seq->r->in.dc_name      = NULL;
603
604         winbindd_get_domain_info_async(seq, seq->domain, seq->r,
605                                        seq->recv_fn, seq);
606         return;
607 nomem:
608         request_error(state);
609         return;
610 }
611
612 static void sequence_one_recv(void *private_data, bool success,
613                               struct winbind_get_domain_info *r)
614 {
615         struct sequence_state *state = talloc_get_type_abort(private_data,
616                                        struct sequence_state);
617
618         if (!success) {
619                 request_error(state->cli_state);
620                 return;
621         }
622
623         state->cli_state->response.data.sequence_number =
624                 state->r->out.domain_info->seqnum;
625
626         request_ok(state->cli_state);
627 }
628
629 static void sequence_next_recv(void *private_data, bool success,
630                                struct winbind_get_domain_info *r)
631 {
632         struct sequence_state *state = talloc_get_type_abort(private_data,
633                                        struct sequence_state);
634         uint64_t seq = DOM_SEQUENCE_NONE;
635
636         if (success) {
637                 seq = state->r->out.domain_info->seqnum;
638         }
639
640         if (seq == DOM_SEQUENCE_NONE) {
641                 state->extra_data = talloc_asprintf(state,
642                                                     "%s%s : DISCONNECTED\n",
643                                                     state->extra_data,
644                                                     state->domain->name);
645         } else {
646                 state->extra_data = talloc_asprintf(state,
647                                                     "%s%s : %lld\n",
648                                                     state->extra_data,
649                                                     state->domain->name,
650                                                     (unsigned long long)seq);
651         }
652
653         state->domain->sequence_number = seq;
654
655         state->domain = state->domain->next;
656
657         if (state->domain == NULL) {
658                 struct winbindd_cli_state *cli_state = state->cli_state;
659                 cli_state->response.length =
660                         sizeof(cli_state->response) +
661                         strlen(state->extra_data) + 1;
662                 cli_state->response.extra_data.data =
663                         SMB_STRDUP(state->extra_data);
664                 request_ok(cli_state);
665                 return;
666         }
667
668         /* Ask the next domain */
669         *state->r->in.level     = WINBIND_DOMAIN_INFO_LEVEL_SEQNUM;
670         state->r->in.domain_name= state->domain->name;
671         state->r->in.dc_name    = NULL;
672
673         winbindd_get_domain_info_async(state, state->domain, state->r,
674                                        state->recv_fn, state);
675 }
676
677 /* This is the child-only version of --sequence. It only allows for a single
678  * domain (ie "our" one) to be displayed. */
679
680 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
681                                                  struct winbindd_cli_state *state)
682 {
683         DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
684
685         /* Ensure null termination */
686         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
687
688         domain->methods->sequence_number(domain, &domain->sequence_number);
689
690         state->response.data.sequence_number =
691                 domain->sequence_number;
692
693         return WINBINDD_OK;
694 }
695
696 struct domain_info_state {
697         struct winbindd_domain *domain;
698         struct winbindd_cli_state *cli_state;
699 };
700
701 static void domain_info_init_recv(void *private_data, bool success);
702
703 void winbindd_domain_info(struct winbindd_cli_state *state)
704 {
705         struct winbindd_domain *domain;
706
707         DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
708                   state->request.domain_name));
709
710         domain = find_domain_from_name_noinit(state->request.domain_name);
711
712         if (domain == NULL) {
713                 DEBUG(3, ("Did not find domain [%s]\n",
714                           state->request.domain_name));
715                 request_error(state);
716                 return;
717         }
718
719         if (!domain->initialized) {
720                 struct domain_info_state *istate;
721
722                 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
723                 if (istate == NULL) {
724                         DEBUG(0, ("talloc failed\n"));
725                         request_error(state);
726                         return;
727                 }
728
729                 istate->cli_state = state;
730                 istate->domain = domain;
731
732                 init_child_connection(domain, domain_info_init_recv, istate);
733                                       
734                 return;
735         }
736
737         fstrcpy(state->response.data.domain_info.name,
738                 domain->name);
739         fstrcpy(state->response.data.domain_info.alt_name,
740                 domain->alt_name);
741         sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
742         
743         state->response.data.domain_info.native_mode =
744                 domain->native_mode;
745         state->response.data.domain_info.active_directory =
746                 domain->active_directory;
747         state->response.data.domain_info.primary =
748                 domain->primary;
749
750         request_ok(state);
751 }
752
753 static void domain_info_init_recv(void *private_data, bool success)
754 {
755         struct domain_info_state *istate =
756                 (struct domain_info_state *)private_data;
757         struct winbindd_cli_state *state = istate->cli_state;
758         struct winbindd_domain *domain = istate->domain;
759
760         DEBUG(10, ("Got back from child init: %d\n", success));
761
762         if ((!success) || (!domain->initialized)) {
763                 DEBUG(5, ("Could not init child for domain %s\n",
764                           domain->name));
765                 request_error(state);
766                 return;
767         }
768
769         fstrcpy(state->response.data.domain_info.name,
770                 domain->name);
771         fstrcpy(state->response.data.domain_info.alt_name,
772                 domain->alt_name);
773         sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
774         
775         state->response.data.domain_info.native_mode =
776                 domain->native_mode;
777         state->response.data.domain_info.active_directory =
778                 domain->active_directory;
779         state->response.data.domain_info.primary =
780                 domain->primary;
781
782         request_ok(state);
783 }
784
785 void winbindd_ping(struct winbindd_cli_state *state)
786 {
787         if (lp_parm_bool(-1, "winbindd", "ping_our_domain", False)) {
788                 sendto_domain(state, find_our_domain());
789                 return;
790         }
791
792         DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
793         request_ok(state);
794 }
795
796 enum winbindd_result winbindd_dual_ping(struct winbindd_domain *domain,
797                                         struct winbindd_cli_state *state)
798 {
799         DEBUG(3, ("[%5lu]: (dual) ping\n", (unsigned long)state->pid));
800         return WINBINDD_OK;
801 }
802
803 /* List various tidbits of information */
804
805 void winbindd_info(struct winbindd_cli_state *state)
806 {
807
808         DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
809
810         state->response.data.info.winbind_separator = *lp_winbind_separator();
811         fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
812         request_ok(state);
813 }
814
815 /* Tell the client the current interface version */
816
817 void winbindd_interface_version(struct winbindd_cli_state *state)
818 {
819         DEBUG(3, ("[%5lu]: request interface version\n",
820                   (unsigned long)state->pid));
821         
822         state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
823         request_ok(state);
824 }
825
826 /* What domain are we a member of? */
827
828 void winbindd_domain_name(struct winbindd_cli_state *state)
829 {
830         DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
831         
832         fstrcpy(state->response.data.domain_name, lp_workgroup());
833         request_ok(state);
834 }
835
836 /* What's my name again? */
837
838 void winbindd_netbios_name(struct winbindd_cli_state *state)
839 {
840         DEBUG(3, ("[%5lu]: request netbios name\n",
841                   (unsigned long)state->pid));
842         
843         fstrcpy(state->response.data.netbios_name, global_myname());
844         request_ok(state);
845 }
846
847 /* Where can I find the privilaged pipe? */
848
849 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
850 {
851
852         DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
853                   (unsigned long)state->pid));
854         
855         state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir());
856         if (!state->response.extra_data.data) {
857                 DEBUG(0, ("malloc failed\n"));
858                 request_error(state);
859                 return;
860         }
861
862         /* must add one to length to copy the 0 for string termination */
863         state->response.length +=
864                 strlen((char *)state->response.extra_data.data) + 1;
865
866         request_ok(state);
867 }
868