source: trunk-3.0/source/nsswitch/winbindd_misc.c@ 101

Last change on this file since 101 was 44, checked in by Paul Smedley, 18 years ago

Update source to 3.0.25b

File size: 15.0 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Winbind daemon - miscellaneous other functions
5
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Bartlett 2002
8
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.
13
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.
18
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.
22*/
23
24#include "includes.h"
25#include "winbindd.h"
26
27#undef DBGC_CLASS
28#define DBGC_CLASS DBGC_WINBIND
29
30/* Check the machine account password is valid */
31
32void winbindd_check_machine_acct(struct winbindd_cli_state *state)
33{
34 DEBUG(3, ("[%5lu]: check machine account\n",
35 (unsigned long)state->pid));
36
37 sendto_domain(state, find_our_domain());
38}
39
40enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain,
41 struct winbindd_cli_state *state)
42{
43 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
44 int num_retries = 0;
45 struct winbindd_domain *contact_domain;
46
47 DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
48
49 /* Get trust account password */
50
51 again:
52
53 contact_domain = find_our_domain();
54
55 /* This call does a cli_nt_setup_creds() which implicitly checks
56 the trust account password. */
57
58 invalidate_cm_connection(&contact_domain->conn);
59
60 {
61 struct rpc_pipe_client *netlogon_pipe;
62 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
63 }
64
65 if (!NT_STATUS_IS_OK(result)) {
66 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
67 goto done;
68 }
69
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. */
74
75#define MAX_RETRIES 8
76
77 if ((num_retries < MAX_RETRIES) &&
78 NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
79 num_retries++;
80 goto again;
81 }
82
83 /* Pass back result code - zero for success, other values for
84 specific failures. */
85
86 DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ?
87 "good" : "bad"));
88
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);
94
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));
97
98 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
99}
100
101void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
102{
103 DEBUG(3, ("[%5lu]: list trusted domains\n",
104 (unsigned long)state->pid));
105
106 sendto_domain(state, find_our_domain());
107}
108
109enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
110 struct winbindd_cli_state *state)
111{
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;
118 BOOL have_own_domain = False;
119
120 DEBUG(3, ("[%5lu]: list trusted domains\n",
121 (unsigned long)state->pid));
122
123 result = domain->methods->trusted_domains(domain, state->mem_ctx,
124 &num_domains, &names,
125 &alt_names, &sids);
126
127 if (!NT_STATUS_IS_OK(result)) {
128 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
129 nt_errstr(result) ));
130 return WINBINDD_ERROR;
131 }
132
133 extra_data = talloc_strdup(state->mem_ctx, "");
134
135 if (num_domains > 0)
136 extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s",
137 names[0],
138 alt_names[0] ? alt_names[0] : names[0],
139 sid_string_static(&sids[0]));
140
141 for (i=1; i<num_domains; i++)
142 extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
143 extra_data,
144 names[i],
145 alt_names[i] ? alt_names[i] : names[i],
146 sid_string_static(&sids[i]));
147 /* add our primary domain */
148
149 for (i=0; i<num_domains; i++) {
150 if (strequal(names[i], domain->name)) {
151 have_own_domain = True;
152 break;
153 }
154 }
155
156 if (state->request.data.list_all_domains && !have_own_domain) {
157 extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
158 extra_data,
159 domain->name,
160 domain->alt_name ? domain->alt_name : domain->name,
161 sid_string_static(&domain->sid));
162 }
163
164 /* This is a bit excessive, but the extra data sooner or later will be
165 talloc'ed */
166
167 extra_data_len = 0;
168 if (extra_data != NULL) {
169 extra_data_len = strlen(extra_data);
170 }
171
172 if (extra_data_len > 0) {
173 state->response.extra_data.data = SMB_STRDUP(extra_data);
174 state->response.length += extra_data_len+1;
175 }
176
177 return WINBINDD_OK;
178}
179
180void winbindd_getdcname(struct winbindd_cli_state *state)
181{
182 state->request.domain_name
183 [sizeof(state->request.domain_name)-1] = '\0';
184
185 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
186 state->request.domain_name));
187
188 sendto_domain(state, find_our_domain());
189}
190
191enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
192 struct winbindd_cli_state *state)
193{
194 fstring dcname_slash;
195 char *p;
196 struct rpc_pipe_client *netlogon_pipe;
197 NTSTATUS result;
198 WERROR werr;
199 unsigned int orig_timeout;
200
201 state->request.domain_name
202 [sizeof(state->request.domain_name)-1] = '\0';
203
204 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
205 state->request.domain_name));
206
207 result = cm_connect_netlogon(domain, &netlogon_pipe);
208
209 if (!NT_STATUS_IS_OK(result)) {
210 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
211 return WINBINDD_ERROR;
212 }
213
214 /* This call can take a long time - allow the server to time out.
215 35 seconds should do it. */
216
217 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
218
219 werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx, domain->dcname,
220 state->request.domain_name,
221 dcname_slash);
222 /* And restore our original timeout. */
223 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
224
225 if (!W_ERROR_IS_OK(werr)) {
226 DEBUG(5, ("Error requesting DCname: %s\n", dos_errstr(werr)));
227 return WINBINDD_ERROR;
228 }
229
230 p = dcname_slash;
231 if (*p == '\\') {
232 p+=1;
233 }
234 if (*p == '\\') {
235 p+=1;
236 }
237
238 fstrcpy(state->response.data.dc_name, p);
239 return WINBINDD_OK;
240}
241
242struct sequence_state {
243 TALLOC_CTX *mem_ctx;
244 struct winbindd_cli_state *cli_state;
245 struct winbindd_domain *domain;
246 struct winbindd_request *request;
247 struct winbindd_response *response;
248 char *extra_data;
249};
250
251static void sequence_recv(void *private_data, BOOL success);
252
253void winbindd_show_sequence(struct winbindd_cli_state *state)
254{
255 struct sequence_state *seq;
256
257 /* Ensure null termination */
258 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
259
260 if (strlen(state->request.domain_name) > 0) {
261 struct winbindd_domain *domain;
262 domain = find_domain_from_name_noinit(
263 state->request.domain_name);
264 if (domain == NULL) {
265 request_error(state);
266 return;
267 }
268 sendto_domain(state, domain);
269 return;
270 }
271
272 /* Ask all domains in sequence, collect the results in sequence_recv */
273
274 seq = TALLOC_P(state->mem_ctx, struct sequence_state);
275 if (seq == NULL) {
276 DEBUG(0, ("talloc failed\n"));
277 request_error(state);
278 return;
279 }
280
281 seq->mem_ctx = state->mem_ctx;
282 seq->cli_state = state;
283 seq->domain = domain_list();
284 if (seq->domain == NULL) {
285 DEBUG(0, ("domain list empty\n"));
286 request_error(state);
287 return;
288 }
289 seq->request = TALLOC_ZERO_P(state->mem_ctx,
290 struct winbindd_request);
291 seq->response = TALLOC_ZERO_P(state->mem_ctx,
292 struct winbindd_response);
293 seq->extra_data = talloc_strdup(state->mem_ctx, "");
294
295 if ((seq->request == NULL) || (seq->response == NULL) ||
296 (seq->extra_data == NULL)) {
297 DEBUG(0, ("talloc failed\n"));
298 request_error(state);
299 return;
300 }
301
302 seq->request->length = sizeof(*seq->request);
303 seq->request->cmd = WINBINDD_SHOW_SEQUENCE;
304 fstrcpy(seq->request->domain_name, seq->domain->name);
305
306 async_domain_request(state->mem_ctx, seq->domain,
307 seq->request, seq->response,
308 sequence_recv, seq);
309}
310
311static void sequence_recv(void *private_data, BOOL success)
312{
313 struct sequence_state *state =
314 (struct sequence_state *)private_data;
315 uint32 seq = DOM_SEQUENCE_NONE;
316
317 if ((success) && (state->response->result == WINBINDD_OK))
318 seq = state->response->data.domain_info.sequence_number;
319
320 if (seq == DOM_SEQUENCE_NONE) {
321 state->extra_data = talloc_asprintf(state->mem_ctx,
322 "%s%s : DISCONNECTED\n",
323 state->extra_data,
324 state->domain->name);
325 } else {
326 state->extra_data = talloc_asprintf(state->mem_ctx,
327 "%s%s : %d\n",
328 state->extra_data,
329 state->domain->name, seq);
330 }
331
332 state->domain->sequence_number = seq;
333
334 state->domain = state->domain->next;
335
336 if (state->domain == NULL) {
337 struct winbindd_cli_state *cli_state = state->cli_state;
338 cli_state->response.length =
339 sizeof(cli_state->response) +
340 strlen(state->extra_data) + 1;
341 cli_state->response.extra_data.data =
342 SMB_STRDUP(state->extra_data);
343 request_ok(cli_state);
344 return;
345 }
346
347 /* Ask the next domain */
348 fstrcpy(state->request->domain_name, state->domain->name);
349 async_domain_request(state->mem_ctx, state->domain,
350 state->request, state->response,
351 sequence_recv, state);
352}
353
354/* This is the child-only version of --sequence. It only allows for a single
355 * domain (ie "our" one) to be displayed. */
356
357enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
358 struct winbindd_cli_state *state)
359{
360 DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
361
362 /* Ensure null termination */
363 state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
364
365 domain->methods->sequence_number(domain, &domain->sequence_number);
366
367 state->response.data.domain_info.sequence_number =
368 domain->sequence_number;
369
370 return WINBINDD_OK;
371}
372
373struct domain_info_state {
374 struct winbindd_domain *domain;
375 struct winbindd_cli_state *cli_state;
376};
377
378static void domain_info_init_recv(void *private_data, BOOL success);
379
380void winbindd_domain_info(struct winbindd_cli_state *state)
381{
382 struct winbindd_domain *domain;
383
384 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
385 state->request.domain_name));
386
387 domain = find_domain_from_name_noinit(state->request.domain_name);
388
389 if (domain == NULL) {
390 DEBUG(3, ("Did not find domain [%s]\n",
391 state->request.domain_name));
392 request_error(state);
393 return;
394 }
395
396 if (!domain->initialized) {
397 struct domain_info_state *istate;
398
399 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
400 if (istate == NULL) {
401 DEBUG(0, ("talloc failed\n"));
402 request_error(state);
403 return;
404 }
405
406 istate->cli_state = state;
407 istate->domain = domain;
408
409 init_child_connection(domain, domain_info_init_recv, istate);
410
411 return;
412 }
413
414 fstrcpy(state->response.data.domain_info.name,
415 domain->name);
416 fstrcpy(state->response.data.domain_info.alt_name,
417 domain->alt_name);
418 fstrcpy(state->response.data.domain_info.sid,
419 sid_string_static(&domain->sid));
420
421 state->response.data.domain_info.native_mode =
422 domain->native_mode;
423 state->response.data.domain_info.active_directory =
424 domain->active_directory;
425 state->response.data.domain_info.primary =
426 domain->primary;
427 state->response.data.domain_info.sequence_number =
428 domain->sequence_number;
429
430 request_ok(state);
431}
432
433static void domain_info_init_recv(void *private_data, BOOL success)
434{
435 struct domain_info_state *istate =
436 (struct domain_info_state *)private_data;
437 struct winbindd_cli_state *state = istate->cli_state;
438 struct winbindd_domain *domain = istate->domain;
439
440 DEBUG(10, ("Got back from child init: %d\n", success));
441
442 if ((!success) || (!domain->initialized)) {
443 DEBUG(5, ("Could not init child for domain %s\n",
444 domain->name));
445 request_error(state);
446 return;
447 }
448
449 fstrcpy(state->response.data.domain_info.name,
450 domain->name);
451 fstrcpy(state->response.data.domain_info.alt_name,
452 domain->alt_name);
453 fstrcpy(state->response.data.domain_info.sid,
454 sid_string_static(&domain->sid));
455
456 state->response.data.domain_info.native_mode =
457 domain->native_mode;
458 state->response.data.domain_info.active_directory =
459 domain->active_directory;
460 state->response.data.domain_info.primary =
461 domain->primary;
462 state->response.data.domain_info.sequence_number =
463 domain->sequence_number;
464
465 request_ok(state);
466}
467
468void winbindd_ping(struct winbindd_cli_state *state)
469{
470 DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
471 request_ok(state);
472}
473
474/* List various tidbits of information */
475
476void winbindd_info(struct winbindd_cli_state *state)
477{
478
479 DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
480
481 state->response.data.info.winbind_separator = *lp_winbind_separator();
482 fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
483 request_ok(state);
484}
485
486/* Tell the client the current interface version */
487
488void winbindd_interface_version(struct winbindd_cli_state *state)
489{
490 DEBUG(3, ("[%5lu]: request interface version\n",
491 (unsigned long)state->pid));
492
493 state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
494 request_ok(state);
495}
496
497/* What domain are we a member of? */
498
499void winbindd_domain_name(struct winbindd_cli_state *state)
500{
501 DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
502
503 fstrcpy(state->response.data.domain_name, lp_workgroup());
504 request_ok(state);
505}
506
507/* What's my name again? */
508
509void winbindd_netbios_name(struct winbindd_cli_state *state)
510{
511 DEBUG(3, ("[%5lu]: request netbios name\n",
512 (unsigned long)state->pid));
513
514 fstrcpy(state->response.data.netbios_name, global_myname());
515 request_ok(state);
516}
517
518/* Where can I find the privilaged pipe? */
519
520void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
521{
522
523 DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
524 (unsigned long)state->pid));
525
526 state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir());
527 if (!state->response.extra_data.data) {
528 DEBUG(0, ("malloc failed\n"));
529 request_error(state);
530 return;
531 }
532
533 /* must add one to length to copy the 0 for string termination */
534 state->response.length +=
535 strlen((char *)state->response.extra_data.data) + 1;
536
537 request_ok(state);
538}
Note: See TracBrowser for help on using the repository browser.