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",
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",
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
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;
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
;
168 struct rpc_pipe_client
*netlogon_pipe
;
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
,
188 if (!NT_STATUS_IS_OK(result
)) {
189 DEBUG(5, ("Error requesting DCname: %s\n", nt_errstr(result
)));
190 return WINBINDD_ERROR
;
201 fstrcpy(state
->response
.data
.dc_name
, p
);
205 struct sequence_state
{
207 struct winbindd_cli_state
*cli_state
;
208 struct winbindd_domain
*domain
;
209 struct winbindd_request
*request
;
210 struct winbindd_response
*response
;
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
);
231 sendto_domain(state
, domain
);
235 /* Ask all domains in sequence, collect the results in sequence_recv */
237 seq
= TALLOC_P(state
->mem_ctx
, struct sequence_state
);
239 DEBUG(0, ("talloc failed\n"));
240 request_error(state
);
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
);
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
);
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
,
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",
286 state
->domain
->name
);
288 state
->extra_data
= talloc_asprintf(state
->mem_ctx
,
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
);
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
;
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
);
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
);
368 istate
->cli_state
= state
;
369 istate
->domain
= domain
;
371 init_child_connection(domain
, domain_info_init_recv
, istate
);
376 fstrcpy(state
->response
.data
.domain_info
.name
,
378 fstrcpy(state
->response
.data
.domain_info
.alt_name
,
380 fstrcpy(state
->response
.data
.domain_info
.sid
,
381 sid_string_static(&domain
->sid
));
383 state
->response
.data
.domain_info
.native_mode
=
385 state
->response
.data
.domain_info
.active_directory
=
386 domain
->active_directory
;
387 state
->response
.data
.domain_info
.primary
=
389 state
->response
.data
.domain_info
.sequence_number
=
390 domain
->sequence_number
;
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",
406 request_error(state
);
410 fstrcpy(state
->response
.data
.domain_info
.name
,
412 fstrcpy(state
->response
.data
.domain_info
.alt_name
,
414 fstrcpy(state
->response
.data
.domain_info
.sid
,
415 sid_string_static(&domain
->sid
));
417 state
->response
.data
.domain_info
.native_mode
=
419 state
->response
.data
.domain_info
.active_directory
=
420 domain
->active_directory
;
421 state
->response
.data
.domain_info
.primary
=
423 state
->response
.data
.domain_info
.sequence_number
=
424 domain
->sequence_number
;
429 void winbindd_ping(struct winbindd_cli_state
*state
)
431 DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state
->pid
));
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
);
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
;
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());
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());
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
);
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;