2 Unix SMB/CIFS implementation.
4 Winbind daemon - miscellaneous other functions
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Bartlett 2002
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.
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.
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/>.
27 #define DBGC_CLASS DBGC_WINBIND
29 /* Check the machine account password is valid */
31 void winbindd_check_machine_acct(struct winbindd_cli_state *state)
33 DEBUG(3, ("[%5lu]: check machine account\n",
34 (unsigned long)state->pid));
36 sendto_domain(state, find_our_domain());
39 enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain,
40 struct winbindd_cli_state *state)
42 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
44 struct winbindd_domain *contact_domain;
46 DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
48 /* Get trust account password */
52 contact_domain = find_our_domain();
54 /* This call does a cli_nt_setup_creds() which implicitly checks
55 the trust account password. */
57 invalidate_cm_connection(&contact_domain->conn);
60 struct rpc_pipe_client *netlogon_pipe;
61 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
64 if (!NT_STATUS_IS_OK(result)) {
65 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
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. */
76 if ((num_retries < MAX_RETRIES) &&
77 NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
82 /* Pass back result code - zero for success, other values for
85 DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ?
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);
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));
97 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
100 /* Constants and helper functions for determining domain trust types */
109 const char *trust_type_strings[] = {"External",
114 static enum trust_type get_trust_type(struct winbindd_tdc_domain *domain)
116 if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)
118 else if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)
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))
126 static const char *get_trust_type_string(struct winbindd_tdc_domain *domain)
128 return trust_type_strings[get_trust_type(domain)];
131 static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
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);
140 static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
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);
149 static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
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))
158 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
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;
167 DEBUG(3, ("[%5lu]: list trusted domains\n",
168 (unsigned long)state->pid));
170 if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) {
171 request_error(state);
175 for ( i = 0; i < num_domains; i++ ) {
176 struct winbindd_domain *domain;
177 bool is_online = true;
180 domain = find_domain_from_name_noinit(d->domain_name);
182 is_online = domain->online;
186 extra_data = talloc_asprintf(state->mem_ctx,
187 "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
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" );
197 extra_data = talloc_asprintf(state->mem_ctx,
198 "%s\n%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
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" );
212 if (extra_data != NULL) {
213 extra_data_len = strlen(extra_data);
216 if (extra_data_len > 0) {
217 state->response.extra_data.data = SMB_STRDUP(extra_data);
218 state->response.length += extra_data_len+1;
223 TALLOC_FREE( dom_list );
224 TALLOC_FREE( extra_data );
227 enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
228 struct winbindd_cli_state *state)
230 uint32 i, num_domains;
231 char **names, **alt_names;
233 int extra_data_len = 0;
236 bool have_own_domain = False;
238 DEBUG(3, ("[%5lu]: list trusted domains\n",
239 (unsigned long)state->pid));
241 result = domain->methods->trusted_domains(domain, state->mem_ctx,
242 &num_domains, &names,
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;
251 extra_data = talloc_strdup(state->mem_ctx, "");
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]));
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]));
266 /* add our primary domain */
268 for (i=0; i<num_domains; i++) {
269 if (strequal(names[i], domain->name)) {
270 have_own_domain = True;
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));
283 /* This is a bit excessive, but the extra data sooner or later will be
287 if (extra_data != NULL) {
288 extra_data_len = strlen(extra_data);
291 if (extra_data_len > 0) {
292 state->response.extra_data.data = SMB_STRDUP(extra_data);
293 state->response.length += extra_data_len+1;
299 static void winbindd_getdcname_recv(void *private_data,
301 struct winbind_get_dc_info *r)
303 struct winbindd_cli_state *state =
304 talloc_get_type_abort(private_data, struct winbindd_cli_state);
307 request_error(state);
311 fstrcpy(state->response.data.dc_name, r->out.dc_info->name);
316 void winbindd_getdcname(struct winbindd_cli_state *state)
318 struct winbindd_domain *domain;
319 struct winbind_get_dc_info *r;
321 state->request.domain_name
322 [sizeof(state->request.domain_name)-1] = '\0';
324 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
325 state->request.domain_name));
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());
334 r = TALLOC_P(state->mem_ctx, struct winbind_get_dc_info);
336 r->in.level = TALLOC_P(r, enum winbind_dc_info_level);
337 if (!r->in.level) goto nomem;
339 *r->in.level = WINBIND_DC_INFO_LEVEL_COMPAT_NT4;
340 r->in.domain_name = state->request.domain_name;
342 winbindd_get_dc_info_async_domain(state->mem_ctx, find_our_domain(),
343 r, winbindd_getdcname_recv, state);
346 request_error(state);
350 static void winbindd_get_dc_info_recv(TALLOC_CTX *mem_ctx, bool success,
351 struct winbindd_ndr_call *c,
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);
362 DEBUG(5, ("Could not get dc_info\n"));
363 cont(private_data, False, r);
367 if (r->out.result != WINBIND_STATUS_OK) {
368 DEBUG(5, ("get_dc_info returned an error:0x%08X\n",
370 cont(private_data, False, r);
374 cont(private_data, True, r);
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,
382 struct winbind_get_dc_info *r),
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);
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,
396 struct winbind_get_dc_info *r),
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);
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)
409 const char *dcname_slash;
411 struct rpc_pipe_client *netlogon_pipe;
414 unsigned int orig_timeout;
415 struct winbindd_domain *req_domain;
417 DEBUG(3, ("Get DC name for '%s'\n", r->in.domain_name));
419 result = cm_connect_netlogon(domain, &netlogon_pipe);
421 if (!NT_STATUS_IS_OK(result)) {
422 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
423 r->out.result = WINBIND_STATUS_FOOBAR;
427 /* This call can take a long time - allow the server to time out.
428 35 seconds should do it. */
430 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
433 * if the requested domain name matches the current one
434 * we need to use GetDCName(), because GetAnyDCName() only
435 * works for trusted domains
437 req_domain = find_domain_from_name_noinit(r->in.domain_name);
438 if (req_domain == domain) {
439 result = rpccli_netr_GetDcName(netlogon_pipe,
446 result = rpccli_netr_GetAnyDCName(netlogon_pipe,
453 /* And restore our original timeout. */
454 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
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;
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;
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;
483 r->out.result = WINBIND_STATUS_OK;
486 void winbindd_ndr_domain_child_get_dc_info(struct winbindd_domain *domain,
487 struct winbindd_cli_state *state)
489 struct winbind_get_dc_info *r;
491 r = talloc_get_type_abort(state->c.ndr.r,
492 struct winbind_get_dc_info);
494 switch (*r->in.level) {
495 case WINBIND_DC_INFO_LEVEL_COMPAT_NT4:
496 ndr_child_get_dc_info_comapt_nt4(domain, state, r);
499 case WINBIND_DC_INFO_LEVEL_COMPAT_DS:
500 r->out.result = WINBIND_STATUS_INVALID_LEVEL;
504 r->out.result = WINBIND_STATUS_UNKNOWN_LEVEL;
508 static void winbindd_get_domain_info_recv(TALLOC_CTX *mem_ctx, bool success,
509 struct winbindd_ndr_call *c,
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);
520 DEBUG(5, ("Could not get domain_info\n"));
521 cont(private_data, False, r);
525 if (r->out.result != WINBIND_STATUS_OK) {
526 DEBUG(5, ("get_domain_info returned an error:0x%08X\n",
528 cont(private_data, False, r);
532 cont(private_data, True, r);
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,
540 struct winbind_get_domain_info *r),
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);
549 struct sequence_state {
550 struct winbindd_cli_state *cli_state;
551 struct winbindd_domain *domain;
552 struct winbind_get_domain_info *r;
554 void (*recv_fn)(void *priv, bool succ,
555 struct winbind_get_domain_info *r);
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);
563 void winbindd_show_sequence(struct winbindd_cli_state *state)
565 struct sequence_state *seq;
567 /* Ensure null termination */
568 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
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;
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);
589 seq->recv_fn = sequence_one_recv;
591 seq->domain = domain_list();
592 if (seq->domain == NULL) {
593 DEBUG(0, ("domain list empty\n"));
594 request_error(state);
597 seq->recv_fn = sequence_next_recv;
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;
604 winbindd_get_domain_info_async(seq, seq->domain, seq->r,
608 request_error(state);
612 static void sequence_one_recv(void *private_data, bool success,
613 struct winbind_get_domain_info *r)
615 struct sequence_state *state = talloc_get_type_abort(private_data,
616 struct sequence_state);
619 request_error(state->cli_state);
623 state->cli_state->response.data.sequence_number =
624 state->r->out.domain_info->seqnum;
626 request_ok(state->cli_state);
629 static void sequence_next_recv(void *private_data, bool success,
630 struct winbind_get_domain_info *r)
632 struct sequence_state *state = talloc_get_type_abort(private_data,
633 struct sequence_state);
634 uint64_t seq = DOM_SEQUENCE_NONE;
637 seq = state->r->out.domain_info->seqnum;
640 if (seq == DOM_SEQUENCE_NONE) {
641 state->extra_data = talloc_asprintf(state,
642 "%s%s : DISCONNECTED\n",
644 state->domain->name);
646 state->extra_data = talloc_asprintf(state,
650 (unsigned long long)seq);
653 state->domain->sequence_number = seq;
655 state->domain = state->domain->next;
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);
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;
673 winbindd_get_domain_info_async(state, state->domain, state->r,
674 state->recv_fn, state);
677 /* This is the child-only version of --sequence. It only allows for a single
678 * domain (ie "our" one) to be displayed. */
680 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
681 struct winbindd_cli_state *state)
683 DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
685 /* Ensure null termination */
686 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
688 domain->methods->sequence_number(domain, &domain->sequence_number);
690 state->response.data.sequence_number =
691 domain->sequence_number;
696 struct domain_info_state {
697 struct winbindd_domain *domain;
698 struct winbindd_cli_state *cli_state;
701 static void domain_info_init_recv(void *private_data, bool success);
703 void winbindd_domain_info(struct winbindd_cli_state *state)
705 struct winbindd_domain *domain;
707 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
708 state->request.domain_name));
710 domain = find_domain_from_name_noinit(state->request.domain_name);
712 if (domain == NULL) {
713 DEBUG(3, ("Did not find domain [%s]\n",
714 state->request.domain_name));
715 request_error(state);
719 if (!domain->initialized) {
720 struct domain_info_state *istate;
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);
729 istate->cli_state = state;
730 istate->domain = domain;
732 init_child_connection(domain, domain_info_init_recv, istate);
737 fstrcpy(state->response.data.domain_info.name,
739 fstrcpy(state->response.data.domain_info.alt_name,
741 sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
743 state->response.data.domain_info.native_mode =
745 state->response.data.domain_info.active_directory =
746 domain->active_directory;
747 state->response.data.domain_info.primary =
753 static void domain_info_init_recv(void *private_data, bool success)
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;
760 DEBUG(10, ("Got back from child init: %d\n", success));
762 if ((!success) || (!domain->initialized)) {
763 DEBUG(5, ("Could not init child for domain %s\n",
765 request_error(state);
769 fstrcpy(state->response.data.domain_info.name,
771 fstrcpy(state->response.data.domain_info.alt_name,
773 sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
775 state->response.data.domain_info.native_mode =
777 state->response.data.domain_info.active_directory =
778 domain->active_directory;
779 state->response.data.domain_info.primary =
785 void winbindd_ping(struct winbindd_cli_state *state)
787 if (lp_parm_bool(-1, "winbindd", "ping_our_domain", False)) {
788 sendto_domain(state, find_our_domain());
792 DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
796 enum winbindd_result winbindd_dual_ping(struct winbindd_domain *domain,
797 struct winbindd_cli_state *state)
799 DEBUG(3, ("[%5lu]: (dual) ping\n", (unsigned long)state->pid));
803 /* List various tidbits of information */
805 void winbindd_info(struct winbindd_cli_state *state)
808 DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
810 state->response.data.info.winbind_separator = *lp_winbind_separator();
811 fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
815 /* Tell the client the current interface version */
817 void winbindd_interface_version(struct winbindd_cli_state *state)
819 DEBUG(3, ("[%5lu]: request interface version\n",
820 (unsigned long)state->pid));
822 state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
826 /* What domain are we a member of? */
828 void winbindd_domain_name(struct winbindd_cli_state *state)
830 DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
832 fstrcpy(state->response.data.domain_name, lp_workgroup());
836 /* What's my name again? */
838 void winbindd_netbios_name(struct winbindd_cli_state *state)
840 DEBUG(3, ("[%5lu]: request netbios name\n",
841 (unsigned long)state->pid));
843 fstrcpy(state->response.data.netbios_name, global_myname());
847 /* Where can I find the privilaged pipe? */
849 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
852 DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
853 (unsigned long)state->pid));
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);
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;