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.
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;
45 struct winbindd_domain *contact_domain;
47 DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
49 /* Get trust account password */
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"));
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. */
77 if ((num_retries < MAX_RETRIES) &&
78 NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
83 /* Pass back result code - zero for success, other values for
86 DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ?
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;
115 int extra_data_len = 0;
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,
126 extra_data = talloc_strdup(state->mem_ctx, "");
129 extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s",
131 alt_names[0] ? alt_names[0] : names[0],
132 sid_string_static(&sids[0]));
134 for (i=1; i<num_domains; i++)
135 extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
138 alt_names[i] ? alt_names[i] : names[i],
139 sid_string_static(&sids[i]));
141 /* This is a bit excessive, but the extra data sooner or later will be
144 extra_data_len = strlen(extra_data);
146 if (extra_data_len > 0) {
147 state->response.extra_data = SMB_STRDUP(extra_data);
148 state->response.length += extra_data_len+1;
154 void winbindd_getdcname(struct winbindd_cli_state *state)
156 state->request.domain_name
157 [sizeof(state->request.domain_name)-1] = '\0';
159 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
160 state->request.domain_name));
162 sendto_domain(state, find_our_domain());
165 enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
166 struct winbindd_cli_state *state)
168 fstring dcname_slash;
170 struct rpc_pipe_client *netlogon_pipe;
173 state->request.domain_name
174 [sizeof(state->request.domain_name)-1] = '\0';
176 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
177 state->request.domain_name));
179 result = cm_connect_netlogon(domain, &netlogon_pipe);
181 if (!NT_STATUS_IS_OK(result)) {
182 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
183 return WINBINDD_ERROR;
186 result = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx, domain->dcname,
187 state->request.domain_name,
190 if (!NT_STATUS_IS_OK(result)) {
191 DEBUG(5, ("Error requesting DCname: %s\n", nt_errstr(result)));
192 return WINBINDD_ERROR;
203 fstrcpy(state->response.data.dc_name, p);
207 struct sequence_state {
209 struct winbindd_cli_state *cli_state;
210 struct winbindd_domain *domain;
211 struct winbindd_request *request;
212 struct winbindd_response *response;
216 static void sequence_recv(void *private_data, BOOL success);
218 void winbindd_show_sequence(struct winbindd_cli_state *state)
220 struct sequence_state *seq;
222 /* Ensure null termination */
223 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
225 if (strlen(state->request.domain_name) > 0) {
226 struct winbindd_domain *domain;
227 domain = find_domain_from_name_noinit(
228 state->request.domain_name);
229 if (domain == NULL) {
230 request_error(state);
233 sendto_domain(state, domain);
237 /* Ask all domains in sequence, collect the results in sequence_recv */
239 seq = TALLOC_P(state->mem_ctx, struct sequence_state);
241 DEBUG(0, ("talloc failed\n"));
242 request_error(state);
246 seq->mem_ctx = state->mem_ctx;
247 seq->cli_state = state;
248 seq->domain = domain_list();
249 if (seq->domain == NULL) {
250 DEBUG(0, ("domain list empty\n"));
251 request_error(state);
254 seq->request = TALLOC_ZERO_P(state->mem_ctx,
255 struct winbindd_request);
256 seq->response = TALLOC_ZERO_P(state->mem_ctx,
257 struct winbindd_response);
258 seq->extra_data = talloc_strdup(state->mem_ctx, "");
260 if ((seq->request == NULL) || (seq->response == NULL) ||
261 (seq->extra_data == NULL)) {
262 DEBUG(0, ("talloc failed\n"));
263 request_error(state);
267 seq->request->length = sizeof(*seq->request);
268 seq->request->cmd = WINBINDD_SHOW_SEQUENCE;
269 fstrcpy(seq->request->domain_name, seq->domain->name);
271 async_domain_request(state->mem_ctx, seq->domain,
272 seq->request, seq->response,
276 static void sequence_recv(void *private_data, BOOL success)
278 struct sequence_state *state = private_data;
279 uint32 seq = DOM_SEQUENCE_NONE;
281 if ((success) && (state->response->result == WINBINDD_OK))
282 seq = state->response->data.domain_info.sequence_number;
284 if (seq == DOM_SEQUENCE_NONE) {
285 state->extra_data = talloc_asprintf(state->mem_ctx,
286 "%s%s : DISCONNECTED\n",
288 state->domain->name);
290 state->extra_data = talloc_asprintf(state->mem_ctx,
293 state->domain->name, seq);
296 state->domain->sequence_number = seq;
298 state->domain = state->domain->next;
300 if (state->domain == NULL) {
301 struct winbindd_cli_state *cli_state = state->cli_state;
302 cli_state->response.length =
303 sizeof(cli_state->response) +
304 strlen(state->extra_data) + 1;
305 cli_state->response.extra_data =
306 SMB_STRDUP(state->extra_data);
307 request_ok(cli_state);
311 /* Ask the next domain */
312 fstrcpy(state->request->domain_name, state->domain->name);
313 async_domain_request(state->mem_ctx, state->domain,
314 state->request, state->response,
315 sequence_recv, state);
318 /* This is the child-only version of --sequence. It only allows for a single
319 * domain (ie "our" one) to be displayed. */
321 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
322 struct winbindd_cli_state *state)
324 DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
326 /* Ensure null termination */
327 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
329 domain->methods->sequence_number(domain, &domain->sequence_number);
331 state->response.data.domain_info.sequence_number =
332 domain->sequence_number;
337 struct domain_info_state {
338 struct winbindd_domain *domain;
339 struct winbindd_cli_state *cli_state;
342 static void domain_info_init_recv(void *private_data, BOOL success);
344 void winbindd_domain_info(struct winbindd_cli_state *state)
346 struct winbindd_domain *domain;
348 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
349 state->request.domain_name));
351 domain = find_domain_from_name_noinit(state->request.domain_name);
353 if (domain == NULL) {
354 DEBUG(3, ("Did not find domain [%s]\n",
355 state->request.domain_name));
356 request_error(state);
360 if (!domain->initialized) {
361 struct domain_info_state *istate;
363 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
364 if (istate == NULL) {
365 DEBUG(0, ("talloc failed\n"));
366 request_error(state);
370 istate->cli_state = state;
371 istate->domain = domain;
373 init_child_connection(domain, domain_info_init_recv, istate);
378 fstrcpy(state->response.data.domain_info.name,
380 fstrcpy(state->response.data.domain_info.alt_name,
382 fstrcpy(state->response.data.domain_info.sid,
383 sid_string_static(&domain->sid));
385 state->response.data.domain_info.native_mode =
387 state->response.data.domain_info.active_directory =
388 domain->active_directory;
389 state->response.data.domain_info.primary =
391 state->response.data.domain_info.sequence_number =
392 domain->sequence_number;
397 static void domain_info_init_recv(void *private_data, BOOL success)
399 struct domain_info_state *istate = private_data;
400 struct winbindd_cli_state *state = istate->cli_state;
401 struct winbindd_domain *domain = istate->domain;
403 DEBUG(10, ("Got back from child init: %d\n", success));
405 if ((!success) || (!domain->initialized)) {
406 DEBUG(5, ("Could not init child for domain %s\n",
408 request_error(state);
412 fstrcpy(state->response.data.domain_info.name,
414 fstrcpy(state->response.data.domain_info.alt_name,
416 fstrcpy(state->response.data.domain_info.sid,
417 sid_string_static(&domain->sid));
419 state->response.data.domain_info.native_mode =
421 state->response.data.domain_info.active_directory =
422 domain->active_directory;
423 state->response.data.domain_info.primary =
425 state->response.data.domain_info.sequence_number =
426 domain->sequence_number;
431 void winbindd_ping(struct winbindd_cli_state *state)
433 DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
437 /* List various tidbits of information */
439 void winbindd_info(struct winbindd_cli_state *state)
442 DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
444 state->response.data.info.winbind_separator = *lp_winbind_separator();
445 fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
449 /* Tell the client the current interface version */
451 void winbindd_interface_version(struct winbindd_cli_state *state)
453 DEBUG(3, ("[%5lu]: request interface version\n",
454 (unsigned long)state->pid));
456 state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
460 /* What domain are we a member of? */
462 void winbindd_domain_name(struct winbindd_cli_state *state)
464 DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
466 fstrcpy(state->response.data.domain_name, lp_workgroup());
470 /* What's my name again? */
472 void winbindd_netbios_name(struct winbindd_cli_state *state)
474 DEBUG(3, ("[%5lu]: request netbios name\n",
475 (unsigned long)state->pid));
477 fstrcpy(state->response.data.netbios_name, global_myname());
481 /* Where can I find the privilaged pipe? */
483 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
486 DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
487 (unsigned long)state->pid));
489 state->response.extra_data = SMB_STRDUP(get_winbind_priv_pipe_dir());
490 if (!state->response.extra_data) {
491 DEBUG(0, ("malloc failed\n"));
492 request_error(state);
496 /* must add one to length to copy the 0 for string termination */
497 state->response.length +=
498 strlen((char *)state->response.extra_data) + 1;