Fix bogus uninitialized variable warnings
[Samba/gbeck.git] / source3 / winbindd / winbindd_misc.c
blob76f2554122b476482e8c80a4d49af7b9a0db0fbb
1 /*
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/>.
23 #include "includes.h"
24 #include "winbindd.h"
26 #undef DBGC_CLASS
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;
43 int num_retries = 0;
44 struct winbindd_domain *contact_domain;
46 DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
48 /* Get trust account password */
50 again:
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"));
66 goto done;
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. */
74 #define MAX_RETRIES 8
76 if ((num_retries < MAX_RETRIES) &&
77 NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
78 num_retries++;
79 goto again;
82 /* Pass back result code - zero for success, other values for
83 specific failures. */
85 DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ?
86 "good" : "bad"));
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);
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 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
102 struct winbindd_domain *d = NULL;
103 int extra_data_len = 0;
104 char *extra_data = NULL;
106 DEBUG(3, ("[%5lu]: list trusted domains\n",
107 (unsigned long)state->pid));
109 for ( d=domain_list(); d; d=d->next ) {
110 if ( !extra_data ) {
111 extra_data = talloc_asprintf(
112 state->mem_ctx, "%s\\%s\\%s",
113 d->name, d->alt_name ? d->alt_name : d->name,
114 sid_string_talloc(state->mem_ctx, &d->sid));
115 } else {
116 extra_data = talloc_asprintf(
117 state->mem_ctx, "%s\n%s\\%s\\%s",
118 extra_data, d->name,
119 d->alt_name ? d->alt_name : d->name,
120 sid_string_talloc(state->mem_ctx, &d->sid));
124 extra_data_len = 0;
125 if (extra_data != NULL) {
126 extra_data_len = strlen(extra_data);
129 if (extra_data_len > 0) {
130 state->response.extra_data.data = SMB_STRDUP(extra_data);
131 state->response.length += extra_data_len+1;
134 TALLOC_FREE( extra_data );
136 request_ok(state);
139 enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
140 struct winbindd_cli_state *state)
142 uint32 i, num_domains;
143 char **names, **alt_names;
144 DOM_SID *sids;
145 int extra_data_len = 0;
146 char *extra_data;
147 NTSTATUS result;
148 bool have_own_domain = False;
150 DEBUG(3, ("[%5lu]: list trusted domains\n",
151 (unsigned long)state->pid));
153 result = domain->methods->trusted_domains(domain, state->mem_ctx,
154 &num_domains, &names,
155 &alt_names, &sids);
157 if (!NT_STATUS_IS_OK(result)) {
158 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
159 nt_errstr(result) ));
160 return WINBINDD_ERROR;
163 extra_data = talloc_strdup(state->mem_ctx, "");
165 if (num_domains > 0)
166 extra_data = talloc_asprintf(
167 state->mem_ctx, "%s\\%s\\%s",
168 names[0], alt_names[0] ? alt_names[0] : names[0],
169 sid_string_talloc(state->mem_ctx, &sids[0]));
171 for (i=1; i<num_domains; i++)
172 extra_data = talloc_asprintf(
173 state->mem_ctx, "%s\n%s\\%s\\%s",
174 extra_data, names[i],
175 alt_names[i] ? alt_names[i] : names[i],
176 sid_string_talloc(state->mem_ctx, &sids[i]));
178 /* add our primary domain */
180 for (i=0; i<num_domains; i++) {
181 if (strequal(names[i], domain->name)) {
182 have_own_domain = True;
183 break;
187 if (state->request.data.list_all_domains && !have_own_domain) {
188 extra_data = talloc_asprintf(
189 state->mem_ctx, "%s\n%s\\%s\\%s",
190 extra_data, domain->name,
191 domain->alt_name ? domain->alt_name : domain->name,
192 sid_string_talloc(state->mem_ctx, &domain->sid));
195 /* This is a bit excessive, but the extra data sooner or later will be
196 talloc'ed */
198 extra_data_len = 0;
199 if (extra_data != NULL) {
200 extra_data_len = strlen(extra_data);
203 if (extra_data_len > 0) {
204 state->response.extra_data.data = SMB_STRDUP(extra_data);
205 state->response.length += extra_data_len+1;
208 return WINBINDD_OK;
211 void winbindd_getdcname(struct winbindd_cli_state *state)
213 struct winbindd_domain *domain;
215 state->request.domain_name
216 [sizeof(state->request.domain_name)-1] = '\0';
218 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
219 state->request.domain_name));
221 domain = find_domain_from_name_noinit(state->request.domain_name);
222 if (domain && domain->internal) {
223 fstrcpy(state->response.data.dc_name, global_myname());
224 request_ok(state);
225 return;
228 sendto_domain(state, find_our_domain());
231 enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
232 struct winbindd_cli_state *state)
234 char *dcname_slash = NULL;
235 char *p;
236 struct rpc_pipe_client *netlogon_pipe;
237 NTSTATUS result;
238 WERROR werr;
239 unsigned int orig_timeout;
240 struct winbindd_domain *req_domain;
242 state->request.domain_name
243 [sizeof(state->request.domain_name)-1] = '\0';
245 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
246 state->request.domain_name));
248 result = cm_connect_netlogon(domain, &netlogon_pipe);
250 if (!NT_STATUS_IS_OK(result)) {
251 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
252 return WINBINDD_ERROR;
255 /* This call can take a long time - allow the server to time out.
256 35 seconds should do it. */
258 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
260 req_domain = find_domain_from_name_noinit(state->request.domain_name);
261 if (req_domain == domain) {
262 werr = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx,
263 domain->dcname,
264 state->request.domain_name,
265 &dcname_slash);
266 } else {
267 werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx,
268 domain->dcname,
269 state->request.domain_name,
270 &dcname_slash);
272 /* And restore our original timeout. */
273 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
275 if (!W_ERROR_IS_OK(werr)) {
276 DEBUG(5, ("Error requesting DCname for domain %s: %s\n",
277 state->request.domain_name, dos_errstr(werr)));
278 return WINBINDD_ERROR;
281 p = dcname_slash;
282 if (*p == '\\') {
283 p+=1;
285 if (*p == '\\') {
286 p+=1;
289 fstrcpy(state->response.data.dc_name, p);
290 return WINBINDD_OK;
293 struct sequence_state {
294 TALLOC_CTX *mem_ctx;
295 struct winbindd_cli_state *cli_state;
296 struct winbindd_domain *domain;
297 struct winbindd_request *request;
298 struct winbindd_response *response;
299 char *extra_data;
302 static void sequence_recv(void *private_data, bool success);
304 void winbindd_show_sequence(struct winbindd_cli_state *state)
306 struct sequence_state *seq;
308 /* Ensure null termination */
309 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
311 if (strlen(state->request.domain_name) > 0) {
312 struct winbindd_domain *domain;
313 domain = find_domain_from_name_noinit(
314 state->request.domain_name);
315 if (domain == NULL) {
316 request_error(state);
317 return;
319 sendto_domain(state, domain);
320 return;
323 /* Ask all domains in sequence, collect the results in sequence_recv */
325 seq = TALLOC_P(state->mem_ctx, struct sequence_state);
326 if (seq == NULL) {
327 DEBUG(0, ("talloc failed\n"));
328 request_error(state);
329 return;
332 seq->mem_ctx = state->mem_ctx;
333 seq->cli_state = state;
334 seq->domain = domain_list();
335 if (seq->domain == NULL) {
336 DEBUG(0, ("domain list empty\n"));
337 request_error(state);
338 return;
340 seq->request = TALLOC_ZERO_P(state->mem_ctx,
341 struct winbindd_request);
342 seq->response = TALLOC_ZERO_P(state->mem_ctx,
343 struct winbindd_response);
344 seq->extra_data = talloc_strdup(state->mem_ctx, "");
346 if ((seq->request == NULL) || (seq->response == NULL) ||
347 (seq->extra_data == NULL)) {
348 DEBUG(0, ("talloc failed\n"));
349 request_error(state);
350 return;
353 seq->request->length = sizeof(*seq->request);
354 seq->request->cmd = WINBINDD_SHOW_SEQUENCE;
355 fstrcpy(seq->request->domain_name, seq->domain->name);
357 async_domain_request(state->mem_ctx, seq->domain,
358 seq->request, seq->response,
359 sequence_recv, seq);
362 static void sequence_recv(void *private_data, bool success)
364 struct sequence_state *state =
365 (struct sequence_state *)private_data;
366 uint32 seq = DOM_SEQUENCE_NONE;
368 if ((success) && (state->response->result == WINBINDD_OK))
369 seq = state->response->data.sequence_number;
371 if (seq == DOM_SEQUENCE_NONE) {
372 state->extra_data = talloc_asprintf(state->mem_ctx,
373 "%s%s : DISCONNECTED\n",
374 state->extra_data,
375 state->domain->name);
376 } else {
377 state->extra_data = talloc_asprintf(state->mem_ctx,
378 "%s%s : %d\n",
379 state->extra_data,
380 state->domain->name, seq);
383 state->domain->sequence_number = seq;
385 state->domain = state->domain->next;
387 if (state->domain == NULL) {
388 struct winbindd_cli_state *cli_state = state->cli_state;
389 cli_state->response.length =
390 sizeof(cli_state->response) +
391 strlen(state->extra_data) + 1;
392 cli_state->response.extra_data.data =
393 SMB_STRDUP(state->extra_data);
394 request_ok(cli_state);
395 return;
398 /* Ask the next domain */
399 fstrcpy(state->request->domain_name, state->domain->name);
400 async_domain_request(state->mem_ctx, state->domain,
401 state->request, state->response,
402 sequence_recv, state);
405 /* This is the child-only version of --sequence. It only allows for a single
406 * domain (ie "our" one) to be displayed. */
408 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
409 struct winbindd_cli_state *state)
411 DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
413 /* Ensure null termination */
414 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
416 domain->methods->sequence_number(domain, &domain->sequence_number);
418 state->response.data.sequence_number =
419 domain->sequence_number;
421 return WINBINDD_OK;
424 struct domain_info_state {
425 struct winbindd_domain *domain;
426 struct winbindd_cli_state *cli_state;
429 static void domain_info_init_recv(void *private_data, bool success);
431 void winbindd_domain_info(struct winbindd_cli_state *state)
433 struct winbindd_domain *domain;
435 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
436 state->request.domain_name));
438 domain = find_domain_from_name_noinit(state->request.domain_name);
440 if (domain == NULL) {
441 DEBUG(3, ("Did not find domain [%s]\n",
442 state->request.domain_name));
443 request_error(state);
444 return;
447 if (!domain->initialized) {
448 struct domain_info_state *istate;
450 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
451 if (istate == NULL) {
452 DEBUG(0, ("talloc failed\n"));
453 request_error(state);
454 return;
457 istate->cli_state = state;
458 istate->domain = domain;
460 init_child_connection(domain, domain_info_init_recv, istate);
462 return;
465 fstrcpy(state->response.data.domain_info.name,
466 domain->name);
467 fstrcpy(state->response.data.domain_info.alt_name,
468 domain->alt_name);
469 sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
471 state->response.data.domain_info.native_mode =
472 domain->native_mode;
473 state->response.data.domain_info.active_directory =
474 domain->active_directory;
475 state->response.data.domain_info.primary =
476 domain->primary;
478 request_ok(state);
481 static void domain_info_init_recv(void *private_data, bool success)
483 struct domain_info_state *istate =
484 (struct domain_info_state *)private_data;
485 struct winbindd_cli_state *state = istate->cli_state;
486 struct winbindd_domain *domain = istate->domain;
488 DEBUG(10, ("Got back from child init: %d\n", success));
490 if ((!success) || (!domain->initialized)) {
491 DEBUG(5, ("Could not init child for domain %s\n",
492 domain->name));
493 request_error(state);
494 return;
497 fstrcpy(state->response.data.domain_info.name,
498 domain->name);
499 fstrcpy(state->response.data.domain_info.alt_name,
500 domain->alt_name);
501 sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
503 state->response.data.domain_info.native_mode =
504 domain->native_mode;
505 state->response.data.domain_info.active_directory =
506 domain->active_directory;
507 state->response.data.domain_info.primary =
508 domain->primary;
510 request_ok(state);
513 void winbindd_ping(struct winbindd_cli_state *state)
515 DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
516 request_ok(state);
519 /* List various tidbits of information */
521 void winbindd_info(struct winbindd_cli_state *state)
524 DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
526 state->response.data.info.winbind_separator = *lp_winbind_separator();
527 fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
528 request_ok(state);
531 /* Tell the client the current interface version */
533 void winbindd_interface_version(struct winbindd_cli_state *state)
535 DEBUG(3, ("[%5lu]: request interface version\n",
536 (unsigned long)state->pid));
538 state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
539 request_ok(state);
542 /* What domain are we a member of? */
544 void winbindd_domain_name(struct winbindd_cli_state *state)
546 DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
548 fstrcpy(state->response.data.domain_name, lp_workgroup());
549 request_ok(state);
552 /* What's my name again? */
554 void winbindd_netbios_name(struct winbindd_cli_state *state)
556 DEBUG(3, ("[%5lu]: request netbios name\n",
557 (unsigned long)state->pid));
559 fstrcpy(state->response.data.netbios_name, global_myname());
560 request_ok(state);
563 /* Where can I find the privilaged pipe? */
565 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
568 DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
569 (unsigned long)state->pid));
571 state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir());
572 if (!state->response.extra_data.data) {
573 DEBUG(0, ("malloc failed\n"));
574 request_error(state);
575 return;
578 /* must add one to length to copy the 0 for string termination */
579 state->response.length +=
580 strlen((char *)state->response.extra_data.data) + 1;
582 request_ok(state);