r10656: BIG merge from trunk. Features not copied over
[Samba/nascimento.git] / source3 / nsswitch / winbindd_misc.c
blob83c4c0f6ee5e5b391d1b68bfcae2b5c1c1721959
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
25 #include "winbindd.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_WINBIND
30 /* Check the machine account password is valid */
32 void winbindd_check_machine_acct(struct winbindd_cli_state *state)
34 DEBUG(3, ("[%5lu]: check machine account\n",
35 (unsigned long)state->pid));
37 sendto_domain(state, find_our_domain());
40 enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain,
41 struct winbindd_cli_state *state)
43 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
44 int num_retries = 0;
45 struct winbindd_domain *contact_domain;
47 DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
49 /* Get trust account password */
51 again:
53 contact_domain = find_our_domain();
55 /* This call does a cli_nt_setup_creds() which implicitly checks
56 the trust account password. */
58 invalidate_cm_connection(&contact_domain->conn);
61 struct rpc_pipe_client *netlogon_pipe;
62 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
65 if (!NT_STATUS_IS_OK(result)) {
66 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
67 goto done;
70 /* There is a race condition between fetching the trust account
71 password and the periodic machine password change. So it's
72 possible that the trust account password has been changed on us.
73 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
75 #define MAX_RETRIES 8
77 if ((num_retries < MAX_RETRIES) &&
78 NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
79 num_retries++;
80 goto again;
83 /* Pass back result code - zero for success, other values for
84 specific failures. */
86 DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ?
87 "good" : "bad"));
89 done:
90 state->response.data.auth.nt_status = NT_STATUS_V(result);
91 fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
92 fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
93 state->response.data.auth.pam_error = nt_status_to_pam(result);
95 DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n",
96 state->response.data.auth.nt_status_string));
98 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
101 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
103 DEBUG(3, ("[%5lu]: list trusted domains\n",
104 (unsigned long)state->pid));
106 sendto_domain(state, find_our_domain());
109 enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
110 struct winbindd_cli_state *state)
112 uint32 i, num_domains;
113 char **names, **alt_names;
114 DOM_SID *sids;
115 int extra_data_len = 0;
116 char *extra_data;
117 NTSTATUS result;
119 DEBUG(3, ("[%5lu]: list trusted domains\n",
120 (unsigned long)state->pid));
122 result = domain->methods->trusted_domains(domain, state->mem_ctx,
123 &num_domains, &names,
124 &alt_names, &sids);
126 extra_data = talloc_strdup(state->mem_ctx, "");
128 if (num_domains > 0)
129 extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s",
130 names[0], alt_names[0],
131 sid_string_static(&sids[0]));
133 for (i=1; i<num_domains; i++)
134 extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
135 extra_data,
136 names[i], alt_names[i],
137 sid_string_static(&sids[i]));
139 /* This is a bit excessive, but the extra data sooner or later will be
140 talloc'ed */
142 extra_data_len = strlen(extra_data);
144 if (extra_data_len > 0) {
145 state->response.extra_data = SMB_STRDUP(extra_data);
146 state->response.length += extra_data_len+1;
149 return WINBINDD_OK;
152 void winbindd_getdcname(struct winbindd_cli_state *state)
154 state->request.domain_name
155 [sizeof(state->request.domain_name)-1] = '\0';
157 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
158 state->request.domain_name));
160 sendto_domain(state, find_our_domain());
163 enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
164 struct winbindd_cli_state *state)
166 fstring dcname_slash;
167 char *p;
168 struct rpc_pipe_client *netlogon_pipe;
169 NTSTATUS result;
171 state->request.domain_name
172 [sizeof(state->request.domain_name)-1] = '\0';
174 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
175 state->request.domain_name));
177 result = cm_connect_netlogon(domain, &netlogon_pipe);
179 if (!NT_STATUS_IS_OK(result)) {
180 DEBUG(1, ("Can't contact our the NETLOGON pipe\n"));
181 return WINBINDD_ERROR;
184 result = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx, domain->dcname,
185 state->request.domain_name,
186 dcname_slash);
188 if (!NT_STATUS_IS_OK(result)) {
189 DEBUG(5, ("Error requesting DCname: %s\n", nt_errstr(result)));
190 return WINBINDD_ERROR;
193 p = dcname_slash;
194 if (*p == '\\') {
195 p+=1;
197 if (*p == '\\') {
198 p+=1;
201 fstrcpy(state->response.data.dc_name, p);
202 return WINBINDD_OK;
205 struct sequence_state {
206 TALLOC_CTX *mem_ctx;
207 struct winbindd_cli_state *cli_state;
208 struct winbindd_domain *domain;
209 struct winbindd_request *request;
210 struct winbindd_response *response;
211 char *extra_data;
214 static void sequence_recv(void *private_data, BOOL success);
216 void winbindd_show_sequence(struct winbindd_cli_state *state)
218 struct sequence_state *seq;
220 /* Ensure null termination */
221 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
223 if (strlen(state->request.domain_name) > 0) {
224 struct winbindd_domain *domain;
225 domain = find_domain_from_name_noinit(
226 state->request.domain_name);
227 if (domain == NULL) {
228 request_error(state);
229 return;
231 sendto_domain(state, domain);
232 return;
235 /* Ask all domains in sequence, collect the results in sequence_recv */
237 seq = TALLOC_P(state->mem_ctx, struct sequence_state);
238 if (seq == NULL) {
239 DEBUG(0, ("talloc failed\n"));
240 request_error(state);
241 return;
244 seq->mem_ctx = state->mem_ctx;
245 seq->cli_state = state;
246 seq->domain = domain_list();
247 if (seq->domain == NULL) {
248 DEBUG(0, ("domain list empty\n"));
249 request_error(state);
250 return;
252 seq->request = TALLOC_ZERO_P(state->mem_ctx,
253 struct winbindd_request);
254 seq->response = TALLOC_ZERO_P(state->mem_ctx,
255 struct winbindd_response);
256 seq->extra_data = talloc_strdup(state->mem_ctx, "");
258 if ((seq->request == NULL) || (seq->response == NULL) ||
259 (seq->extra_data == NULL)) {
260 DEBUG(0, ("talloc failed\n"));
261 request_error(state);
262 return;
265 seq->request->length = sizeof(*seq->request);
266 seq->request->cmd = WINBINDD_SHOW_SEQUENCE;
267 fstrcpy(seq->request->domain_name, seq->domain->name);
269 async_domain_request(state->mem_ctx, seq->domain,
270 seq->request, seq->response,
271 sequence_recv, seq);
274 static void sequence_recv(void *private_data, BOOL success)
276 struct sequence_state *state = private_data;
277 uint32 seq = DOM_SEQUENCE_NONE;
279 if ((success) && (state->response->result == WINBINDD_OK))
280 seq = state->response->data.domain_info.sequence_number;
282 if (seq == DOM_SEQUENCE_NONE) {
283 state->extra_data = talloc_asprintf(state->mem_ctx,
284 "%s%s : DISCONNECTED\n",
285 state->extra_data,
286 state->domain->name);
287 } else {
288 state->extra_data = talloc_asprintf(state->mem_ctx,
289 "%s%s : %d\n",
290 state->extra_data,
291 state->domain->name, seq);
294 state->domain->sequence_number = seq;
296 state->domain = state->domain->next;
298 if (state->domain == NULL) {
299 struct winbindd_cli_state *cli_state = state->cli_state;
300 cli_state->response.length =
301 sizeof(cli_state->response) +
302 strlen(state->extra_data) + 1;
303 cli_state->response.extra_data =
304 SMB_STRDUP(state->extra_data);
305 request_ok(cli_state);
306 return;
309 /* Ask the next domain */
310 fstrcpy(state->request->domain_name, state->domain->name);
311 async_domain_request(state->mem_ctx, state->domain,
312 state->request, state->response,
313 sequence_recv, state);
316 /* This is the child-only version of --sequence. It only allows for a single
317 * domain (ie "our" one) to be displayed. */
319 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
320 struct winbindd_cli_state *state)
322 DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
324 /* Ensure null termination */
325 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
327 domain->methods->sequence_number(domain, &domain->sequence_number);
329 state->response.data.domain_info.sequence_number =
330 domain->sequence_number;
332 return WINBINDD_OK;
335 struct domain_info_state {
336 struct winbindd_domain *domain;
337 struct winbindd_cli_state *cli_state;
340 static void domain_info_init_recv(void *private_data, BOOL success);
342 void winbindd_domain_info(struct winbindd_cli_state *state)
344 struct winbindd_domain *domain;
346 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
347 state->request.domain_name));
349 domain = find_domain_from_name_noinit(state->request.domain_name);
351 if (domain == NULL) {
352 DEBUG(3, ("Did not find domain [%s]\n",
353 state->request.domain_name));
354 request_error(state);
355 return;
358 if (!domain->initialized) {
359 struct domain_info_state *istate;
361 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
362 if (istate == NULL) {
363 DEBUG(0, ("talloc failed\n"));
364 request_error(state);
365 return;
368 istate->cli_state = state;
369 istate->domain = domain;
371 init_child_connection(domain, domain_info_init_recv, istate);
373 return;
376 fstrcpy(state->response.data.domain_info.name,
377 domain->name);
378 fstrcpy(state->response.data.domain_info.alt_name,
379 domain->alt_name);
380 fstrcpy(state->response.data.domain_info.sid,
381 sid_string_static(&domain->sid));
383 state->response.data.domain_info.native_mode =
384 domain->native_mode;
385 state->response.data.domain_info.active_directory =
386 domain->active_directory;
387 state->response.data.domain_info.primary =
388 domain->primary;
389 state->response.data.domain_info.sequence_number =
390 domain->sequence_number;
392 request_ok(state);
395 static void domain_info_init_recv(void *private_data, BOOL success)
397 struct domain_info_state *istate = private_data;
398 struct winbindd_cli_state *state = istate->cli_state;
399 struct winbindd_domain *domain = istate->domain;
401 DEBUG(10, ("Got back from child init: %d\n", success));
403 if ((!success) || (!domain->initialized)) {
404 DEBUG(5, ("Could not init child for domain %s\n",
405 domain->name));
406 request_error(state);
407 return;
410 fstrcpy(state->response.data.domain_info.name,
411 domain->name);
412 fstrcpy(state->response.data.domain_info.alt_name,
413 domain->alt_name);
414 fstrcpy(state->response.data.domain_info.sid,
415 sid_string_static(&domain->sid));
417 state->response.data.domain_info.native_mode =
418 domain->native_mode;
419 state->response.data.domain_info.active_directory =
420 domain->active_directory;
421 state->response.data.domain_info.primary =
422 domain->primary;
423 state->response.data.domain_info.sequence_number =
424 domain->sequence_number;
426 request_ok(state);
429 void winbindd_ping(struct winbindd_cli_state *state)
431 DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
432 request_ok(state);
435 /* List various tidbits of information */
437 void winbindd_info(struct winbindd_cli_state *state)
440 DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
442 state->response.data.info.winbind_separator = *lp_winbind_separator();
443 fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
444 request_ok(state);
447 /* Tell the client the current interface version */
449 void winbindd_interface_version(struct winbindd_cli_state *state)
451 DEBUG(3, ("[%5lu]: request interface version\n",
452 (unsigned long)state->pid));
454 state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
455 request_ok(state);
458 /* What domain are we a member of? */
460 void winbindd_domain_name(struct winbindd_cli_state *state)
462 DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
464 fstrcpy(state->response.data.domain_name, lp_workgroup());
465 request_ok(state);
468 /* What's my name again? */
470 void winbindd_netbios_name(struct winbindd_cli_state *state)
472 DEBUG(3, ("[%5lu]: request netbios name\n",
473 (unsigned long)state->pid));
475 fstrcpy(state->response.data.netbios_name, global_myname());
476 request_ok(state);
479 /* Where can I find the privilaged pipe? */
481 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
484 DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
485 (unsigned long)state->pid));
487 state->response.extra_data = SMB_STRDUP(get_winbind_priv_pipe_dir());
488 if (!state->response.extra_data) {
489 DEBUG(0, ("malloc failed\n"));
490 request_error(state);
491 return;
494 /* must add one to length to copy the 0 for string termination */
495 state->response.length +=
496 strlen((char *)state->response.extra_data) + 1;
498 request_ok(state);