Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Winbind child daemons
5 :
6 : Copyright (C) Andrew Tridgell 2002
7 : Copyright (C) Volker Lendecke 2004,2005
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 3 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, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : /*
24 : * We fork a child per domain to be able to act non-blocking in the main
25 : * winbind daemon. A domain controller thousands of miles away being being
26 : * slow replying with a 10.000 user list should not hold up netlogon calls
27 : * that can be handled locally.
28 : */
29 :
30 : #include "includes.h"
31 : #include "winbindd.h"
32 : #include "rpc_client/rpc_client.h"
33 : #include "nsswitch/wb_reqtrans.h"
34 : #include "secrets.h"
35 : #include "../lib/util/select.h"
36 : #include "winbindd_traceid.h"
37 : #include "../libcli/security/security.h"
38 : #include "system/select.h"
39 : #include "messages.h"
40 : #include "../lib/util/tevent_unix.h"
41 : #include "lib/param/loadparm.h"
42 : #include "lib/util/sys_rw.h"
43 : #include "lib/util/sys_rw_data.h"
44 : #include "passdb.h"
45 : #include "lib/util/string_wrappers.h"
46 : #include "lib/global_contexts.h"
47 : #include "idmap.h"
48 : #include "libcli/auth/netlogon_creds_cli.h"
49 : #include "../lib/util/pidfile.h"
50 : #include "librpc/gen_ndr/ndr_winbind_c.h"
51 : #include "lib/util/util_process.h"
52 :
53 : #undef DBGC_CLASS
54 : #define DBGC_CLASS DBGC_WINBIND
55 :
56 15 : static void forall_domain_children(bool (*fn)(struct winbindd_child *c,
57 : void *private_data),
58 : void *private_data)
59 : {
60 : struct winbindd_domain *d;
61 :
62 65 : for (d = domain_list(); d != NULL; d = d->next) {
63 : int i;
64 :
65 100 : for (i = 0; i < lp_winbind_max_domain_connections(); i++) {
66 50 : struct winbindd_child *c = &d->children[i];
67 : bool ok;
68 :
69 50 : if (c->pid == 0) {
70 20 : continue;
71 : }
72 :
73 30 : ok = fn(c, private_data);
74 30 : if (!ok) {
75 0 : return;
76 : }
77 : }
78 : }
79 : }
80 :
81 11 : static void forall_children(bool (*fn)(struct winbindd_child *c,
82 : void *private_data),
83 : void *private_data)
84 : {
85 : struct winbindd_child *c;
86 : bool ok;
87 :
88 11 : c = idmap_child();
89 11 : if (c->pid != 0) {
90 11 : ok = fn(c, private_data);
91 11 : if (!ok) {
92 0 : return;
93 : }
94 : }
95 :
96 11 : c = locator_child();
97 11 : if (c->pid != 0) {
98 0 : ok = fn(c, private_data);
99 0 : if (!ok) {
100 0 : return;
101 : }
102 : }
103 :
104 11 : forall_domain_children(fn, private_data);
105 : }
106 :
107 : /* Read some data from a client connection */
108 :
109 0 : static NTSTATUS child_read_request(int sock, struct winbindd_request *wreq)
110 : {
111 : NTSTATUS status;
112 :
113 0 : status = read_data_ntstatus(sock, (char *)wreq, sizeof(*wreq));
114 0 : if (!NT_STATUS_IS_OK(status)) {
115 0 : DEBUG(3, ("child_read_request: read_data failed: %s\n",
116 : nt_errstr(status)));
117 0 : return status;
118 : }
119 :
120 0 : if (wreq->extra_len == 0) {
121 0 : wreq->extra_data.data = NULL;
122 0 : return NT_STATUS_OK;
123 : }
124 :
125 0 : DEBUG(10, ("Need to read %d extra bytes\n", (int)wreq->extra_len));
126 :
127 0 : wreq->extra_data.data = SMB_MALLOC_ARRAY(char, wreq->extra_len + 1);
128 0 : if (wreq->extra_data.data == NULL) {
129 0 : DEBUG(0, ("malloc failed\n"));
130 0 : return NT_STATUS_NO_MEMORY;
131 : }
132 :
133 : /* Ensure null termination */
134 0 : wreq->extra_data.data[wreq->extra_len] = '\0';
135 :
136 0 : status = read_data_ntstatus(sock, wreq->extra_data.data,
137 0 : wreq->extra_len);
138 0 : if (!NT_STATUS_IS_OK(status)) {
139 0 : DEBUG(0, ("Could not read extra data: %s\n",
140 : nt_errstr(status)));
141 : }
142 0 : return status;
143 : }
144 :
145 0 : static NTSTATUS child_write_response(int sock, struct winbindd_response *wrsp)
146 : {
147 : struct iovec iov[2];
148 : int iov_count;
149 :
150 0 : iov[0].iov_base = (void *)wrsp;
151 0 : iov[0].iov_len = sizeof(struct winbindd_response);
152 0 : iov_count = 1;
153 :
154 0 : if (wrsp->length > sizeof(struct winbindd_response)) {
155 0 : iov[1].iov_base = (void *)wrsp->extra_data.data;
156 0 : iov[1].iov_len = wrsp->length-iov[0].iov_len;
157 0 : iov_count = 2;
158 : }
159 :
160 0 : DEBUG(10, ("Writing %d bytes to parent\n", (int)wrsp->length));
161 :
162 0 : if (write_data_iov(sock, iov, iov_count) != wrsp->length) {
163 0 : DEBUG(0, ("Could not write result\n"));
164 0 : return NT_STATUS_INVALID_HANDLE;
165 : }
166 :
167 0 : return NT_STATUS_OK;
168 : }
169 :
170 : /*
171 : * Do winbind child async request. This is not simply wb_simple_trans. We have
172 : * to do the queueing ourselves because while a request is queued, the child
173 : * might have crashed, and we have to re-fork it in the _trigger function.
174 : */
175 :
176 : struct wb_child_request_state {
177 : struct tevent_context *ev;
178 : struct tevent_req *queue_subreq;
179 : struct tevent_req *subreq;
180 : struct winbindd_child *child;
181 : struct winbindd_request *request;
182 : struct winbindd_response *response;
183 : };
184 :
185 : static bool fork_domain_child(struct winbindd_child *child);
186 :
187 : static void wb_child_request_waited(struct tevent_req *subreq);
188 : static void wb_child_request_done(struct tevent_req *subreq);
189 : static void wb_child_request_orphaned(struct tevent_req *subreq);
190 :
191 : static void wb_child_request_cleanup(struct tevent_req *req,
192 : enum tevent_req_state req_state);
193 :
194 6644 : struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx,
195 : struct tevent_context *ev,
196 : struct winbindd_child *child,
197 : struct winbindd_request *request)
198 : {
199 : struct tevent_req *req;
200 : struct wb_child_request_state *state;
201 : struct tevent_req *subreq;
202 :
203 6644 : req = tevent_req_create(mem_ctx, &state,
204 : struct wb_child_request_state);
205 6644 : if (req == NULL) {
206 0 : return NULL;
207 : }
208 :
209 6644 : state->ev = ev;
210 6644 : state->child = child;
211 :
212 : /*
213 : * We have to make a copy of "request", because our caller
214 : * might drop us via talloc_free().
215 : *
216 : * The talloc_move() magic in wb_child_request_cleanup() keeps
217 : * all the requests, but if we are sitting deep within
218 : * writev_send() down to the client, we have given it the
219 : * pointer to "request". As our caller lost interest, it will
220 : * just free "request", while writev_send still references it.
221 : */
222 :
223 6644 : state->request = talloc_memdup(state, request, sizeof(*request));
224 6644 : if (tevent_req_nomem(state->request, req)) {
225 0 : return tevent_req_post(req, ev);
226 : }
227 :
228 6644 : state->request->traceid = debug_traceid_get();
229 :
230 6644 : if (request->extra_data.data != NULL) {
231 6644 : state->request->extra_data.data = talloc_memdup(
232 : state->request,
233 : request->extra_data.data,
234 : request->extra_len);
235 6644 : if (tevent_req_nomem(state->request->extra_data.data, req)) {
236 0 : return tevent_req_post(req, ev);
237 : }
238 : }
239 :
240 6644 : subreq = tevent_queue_wait_send(state, ev, child->queue);
241 6644 : if (tevent_req_nomem(subreq, req)) {
242 0 : return tevent_req_post(req, ev);
243 : }
244 6644 : tevent_req_set_callback(subreq, wb_child_request_waited, req);
245 6644 : state->queue_subreq = subreq;
246 :
247 6644 : tevent_req_set_cleanup_fn(req, wb_child_request_cleanup);
248 :
249 6644 : return req;
250 : }
251 :
252 6644 : static void wb_child_request_waited(struct tevent_req *subreq)
253 : {
254 6644 : struct tevent_req *req = tevent_req_callback_data(
255 : subreq, struct tevent_req);
256 6644 : struct wb_child_request_state *state = tevent_req_data(
257 : req, struct wb_child_request_state);
258 : bool ok;
259 :
260 6644 : ok = tevent_queue_wait_recv(subreq);
261 6644 : if (!ok) {
262 0 : tevent_req_oom(req);
263 0 : return;
264 : }
265 : /*
266 : * We need to keep state->queue_subreq
267 : * in order to block the queue.
268 : */
269 6644 : subreq = NULL;
270 :
271 6644 : if ((state->child->sock == -1) && (!fork_domain_child(state->child))) {
272 0 : tevent_req_error(req, errno);
273 0 : return;
274 : }
275 :
276 6644 : tevent_fd_set_flags(state->child->monitor_fde, 0);
277 :
278 6644 : subreq = wb_simple_trans_send(state, global_event_context(), NULL,
279 6644 : state->child->sock, state->request);
280 6644 : if (tevent_req_nomem(subreq, req)) {
281 0 : return;
282 : }
283 :
284 6644 : state->subreq = subreq;
285 6644 : tevent_req_set_callback(subreq, wb_child_request_done, req);
286 6644 : tevent_req_set_endtime(req, state->ev, timeval_current_ofs(300, 0));
287 : }
288 :
289 6644 : static void wb_child_request_done(struct tevent_req *subreq)
290 : {
291 6644 : struct tevent_req *req = tevent_req_callback_data(
292 : subreq, struct tevent_req);
293 6644 : struct wb_child_request_state *state = tevent_req_data(
294 : req, struct wb_child_request_state);
295 : int ret, err;
296 :
297 6644 : ret = wb_simple_trans_recv(subreq, state, &state->response, &err);
298 : /* Freeing the subrequest is deferred until the cleanup function,
299 : * which has to know whether a subrequest exists, and consequently
300 : * decide whether to shut down the pipe to the child process.
301 : */
302 6644 : if (ret == -1) {
303 0 : tevent_req_error(req, err);
304 0 : return;
305 : }
306 6644 : tevent_req_done(req);
307 : }
308 :
309 0 : static void wb_child_request_orphaned(struct tevent_req *subreq)
310 : {
311 : struct winbindd_child *child =
312 0 : (struct winbindd_child *)tevent_req_callback_data_void(subreq);
313 :
314 0 : DBG_WARNING("cleanup orphaned subreq[%p]\n", subreq);
315 0 : TALLOC_FREE(subreq);
316 :
317 0 : if (child->domain != NULL) {
318 : /*
319 : * If the child is attached to a domain,
320 : * we need to make sure the domain queue
321 : * can move forward, after the orphaned
322 : * request is done.
323 : */
324 0 : tevent_queue_start(child->domain->queue);
325 : }
326 0 : }
327 :
328 6644 : int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
329 : struct winbindd_response **presponse, int *err)
330 : {
331 6644 : struct wb_child_request_state *state = tevent_req_data(
332 : req, struct wb_child_request_state);
333 :
334 6644 : if (tevent_req_is_unix_error(req, err)) {
335 0 : return -1;
336 : }
337 6644 : *presponse = talloc_move(mem_ctx, &state->response);
338 6644 : return 0;
339 : }
340 :
341 13288 : static void wb_child_request_cleanup(struct tevent_req *req,
342 : enum tevent_req_state req_state)
343 : {
344 : struct wb_child_request_state *state =
345 13288 : tevent_req_data(req, struct wb_child_request_state);
346 :
347 13288 : if (state->subreq == NULL) {
348 : /* nothing to cleanup */
349 6644 : return;
350 : }
351 :
352 6644 : if (req_state == TEVENT_REQ_RECEIVED) {
353 0 : struct tevent_req *subreq = NULL;
354 :
355 : /*
356 : * Our caller gave up, but we need to keep
357 : * the low level request (wb_simple_trans)
358 : * in order to maintain the parent child protocol.
359 : *
360 : * We also need to keep the child queue blocked
361 : * until we got the response from the child.
362 : */
363 :
364 0 : subreq = talloc_move(state->child->queue, &state->subreq);
365 0 : talloc_move(subreq, &state->queue_subreq);
366 0 : talloc_move(subreq, &state->request);
367 0 : tevent_req_set_callback(subreq,
368 : wb_child_request_orphaned,
369 0 : state->child);
370 :
371 0 : DBG_WARNING("keep orphaned subreq[%p]\n", subreq);
372 0 : return;
373 : }
374 :
375 6644 : TALLOC_FREE(state->subreq);
376 6644 : TALLOC_FREE(state->queue_subreq);
377 :
378 6644 : tevent_fd_set_flags(state->child->monitor_fde, TEVENT_FD_READ);
379 :
380 6644 : if (state->child->domain != NULL) {
381 : /*
382 : * If the child is attached to a domain,
383 : * we need to make sure the domain queue
384 : * can move forward, after the request
385 : * is done.
386 : */
387 3123 : tevent_queue_start(state->child->domain->queue);
388 : }
389 :
390 6644 : if (req_state == TEVENT_REQ_DONE) {
391 : /* transmitted request and got response */
392 6644 : return;
393 : }
394 :
395 : /*
396 : * Failed to transmit and receive response, or request
397 : * cancelled while being serviced.
398 : * The basic parent/child communication broke, close
399 : * our socket
400 : */
401 0 : TALLOC_FREE(state->child->monitor_fde);
402 0 : close(state->child->sock);
403 0 : state->child->sock = -1;
404 : }
405 :
406 0 : static void child_socket_readable(struct tevent_context *ev,
407 : struct tevent_fd *fde,
408 : uint16_t flags,
409 : void *private_data)
410 : {
411 0 : struct winbindd_child *child = private_data;
412 :
413 0 : if ((flags & TEVENT_FD_READ) == 0) {
414 0 : return;
415 : }
416 :
417 0 : TALLOC_FREE(child->monitor_fde);
418 :
419 : /*
420 : * We're only active when there is no outstanding child
421 : * request. Arriving here means the child closed its socket,
422 : * it died. Do the same here.
423 : */
424 :
425 0 : SMB_ASSERT(child->sock != -1);
426 :
427 0 : close(child->sock);
428 0 : child->sock = -1;
429 : }
430 :
431 3057 : static struct winbindd_child *choose_domain_child(struct winbindd_domain *domain)
432 : {
433 3057 : struct winbindd_child *shortest = &domain->children[0];
434 : struct winbindd_child *current;
435 : int i;
436 :
437 3060 : for (i=0; i<lp_winbind_max_domain_connections(); i++) {
438 : size_t shortest_len, current_len;
439 :
440 3057 : current = &domain->children[i];
441 3057 : current_len = tevent_queue_length(current->queue);
442 :
443 3057 : if (current_len == 0) {
444 : /* idle child */
445 3054 : return current;
446 : }
447 :
448 3 : shortest_len = tevent_queue_length(shortest->queue);
449 :
450 3 : if (current_len < shortest_len) {
451 0 : shortest = current;
452 : }
453 : }
454 :
455 3 : return shortest;
456 : }
457 :
458 9623 : struct dcerpc_binding_handle *dom_child_handle(struct winbindd_domain *domain)
459 : {
460 9623 : return domain->binding_handle;
461 : }
462 :
463 : struct wb_domain_request_state {
464 : struct tevent_context *ev;
465 : struct tevent_queue_entry *queue_entry;
466 : struct winbindd_domain *domain;
467 : struct winbindd_child *child;
468 : struct winbindd_request *request;
469 : struct winbindd_request *init_req;
470 : struct winbindd_response *response;
471 : struct tevent_req *pending_subreq;
472 : struct wbint_InitConnection r;
473 : };
474 :
475 6108 : static void wb_domain_request_cleanup(struct tevent_req *req,
476 : enum tevent_req_state req_state)
477 : {
478 6108 : struct wb_domain_request_state *state = tevent_req_data(
479 : req, struct wb_domain_request_state);
480 :
481 : /*
482 : * If we're completely done or got a failure.
483 : * we should remove ourself from the domain queue,
484 : * after removing the child subreq from the child queue
485 : * and give the next one in the queue the chance
486 : * to check for an idle child.
487 : */
488 6108 : TALLOC_FREE(state->pending_subreq);
489 6108 : TALLOC_FREE(state->queue_entry);
490 6108 : tevent_queue_start(state->domain->queue);
491 6108 : }
492 :
493 : static void wb_domain_request_trigger(struct tevent_req *req,
494 : void *private_data);
495 : static void wb_domain_request_gotdc(struct tevent_req *subreq);
496 : static void wb_domain_request_initialized(struct tevent_req *subreq);
497 : static void wb_domain_request_done(struct tevent_req *subreq);
498 :
499 3054 : struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
500 : struct tevent_context *ev,
501 : struct winbindd_domain *domain,
502 : struct winbindd_request *request)
503 : {
504 : struct tevent_req *req;
505 : struct wb_domain_request_state *state;
506 :
507 3054 : req = tevent_req_create(mem_ctx, &state,
508 : struct wb_domain_request_state);
509 3054 : if (req == NULL) {
510 0 : return NULL;
511 : }
512 :
513 3054 : state->domain = domain;
514 3054 : state->ev = ev;
515 3054 : state->request = request;
516 :
517 3054 : tevent_req_set_cleanup_fn(req, wb_domain_request_cleanup);
518 :
519 6108 : state->queue_entry = tevent_queue_add_entry(
520 3054 : domain->queue, state->ev, req,
521 : wb_domain_request_trigger, NULL);
522 3054 : if (tevent_req_nomem(state->queue_entry, req)) {
523 0 : return tevent_req_post(req, ev);
524 : }
525 :
526 3054 : return req;
527 : }
528 :
529 3057 : static void wb_domain_request_trigger(struct tevent_req *req,
530 : void *private_data)
531 : {
532 3057 : struct wb_domain_request_state *state = tevent_req_data(
533 : req, struct wb_domain_request_state);
534 3057 : struct winbindd_domain *domain = state->domain;
535 3057 : struct tevent_req *subreq = NULL;
536 : size_t shortest_queue_length;
537 :
538 3057 : state->child = choose_domain_child(domain);
539 3057 : shortest_queue_length = tevent_queue_length(state->child->queue);
540 3057 : if (shortest_queue_length > 0) {
541 : /*
542 : * All children are busy, we need to stop
543 : * the queue and untrigger our own queue
544 : * entry. Once a pending request
545 : * is done it calls tevent_queue_start
546 : * and we get retriggered.
547 : */
548 3 : state->child = NULL;
549 3 : tevent_queue_stop(state->domain->queue);
550 3 : tevent_queue_entry_untrigger(state->queue_entry);
551 3 : return;
552 : }
553 :
554 3054 : if (domain->initialized) {
555 2985 : subreq = wb_child_request_send(state, state->ev, state->child,
556 : state->request);
557 2985 : if (tevent_req_nomem(subreq, req)) {
558 0 : return;
559 : }
560 2985 : tevent_req_set_callback(subreq, wb_domain_request_done, req);
561 2985 : state->pending_subreq = subreq;
562 :
563 : /*
564 : * Once the domain is initialized and
565 : * once we placed our real request into the child queue,
566 : * we can remove ourself from the domain queue
567 : * and give the next one in the queue the chance
568 : * to check for an idle child.
569 : */
570 2985 : TALLOC_FREE(state->queue_entry);
571 2985 : return;
572 : }
573 :
574 69 : state->init_req = talloc_zero(state, struct winbindd_request);
575 69 : if (tevent_req_nomem(state->init_req, req)) {
576 0 : return;
577 : }
578 :
579 69 : if (IS_DC || domain->primary || domain->internal) {
580 : /* The primary domain has to find the DC name itself */
581 65 : state->r.in.dcname = talloc_strdup(state, "");
582 65 : if (tevent_req_nomem(state->r.in.dcname, req)) {
583 0 : return;
584 : }
585 :
586 65 : subreq = dcerpc_wbint_InitConnection_r_send(state,
587 : state->ev,
588 65 : state->child->binding_handle,
589 : &state->r);
590 65 : if (tevent_req_nomem(subreq, req)) {
591 0 : return;
592 : }
593 65 : tevent_req_set_callback(subreq, wb_domain_request_initialized,
594 : req);
595 65 : state->pending_subreq = subreq;
596 65 : return;
597 : }
598 :
599 : /*
600 : * This is *not* the primary domain,
601 : * let's ask our DC about a DC name.
602 : *
603 : * We prefer getting a dns name in dc_unc,
604 : * which is indicated by DS_RETURN_DNS_NAME.
605 : * For NT4 domains we still get the netbios name.
606 : */
607 4 : subreq = wb_dsgetdcname_send(state, state->ev,
608 4 : state->domain->name,
609 : NULL, /* domain_guid */
610 : NULL, /* site_name */
611 : DS_RETURN_DNS_NAME); /* flags */
612 4 : if (tevent_req_nomem(subreq, req)) {
613 0 : return;
614 : }
615 4 : tevent_req_set_callback(subreq, wb_domain_request_gotdc, req);
616 4 : state->pending_subreq = subreq;
617 4 : return;
618 : }
619 :
620 4 : static void wb_domain_request_gotdc(struct tevent_req *subreq)
621 : {
622 4 : struct tevent_req *req = tevent_req_callback_data(
623 : subreq, struct tevent_req);
624 4 : struct wb_domain_request_state *state = tevent_req_data(
625 : req, struct wb_domain_request_state);
626 4 : struct netr_DsRGetDCNameInfo *dcinfo = NULL;
627 : NTSTATUS status;
628 4 : const char *dcname = NULL;
629 :
630 4 : state->pending_subreq = NULL;
631 :
632 4 : status = wb_dsgetdcname_recv(subreq, state, &dcinfo);
633 4 : TALLOC_FREE(subreq);
634 4 : if (tevent_req_nterror(req, status)) {
635 0 : return;
636 : }
637 4 : dcname = dcinfo->dc_unc;
638 12 : while (dcname != NULL && *dcname == '\\') {
639 8 : dcname++;
640 : }
641 :
642 4 : state->r.in.dcname = talloc_strdup(state, dcname);
643 4 : if (tevent_req_nomem(state->r.in.dcname, req)) {
644 0 : return;
645 : }
646 :
647 4 : TALLOC_FREE(dcinfo);
648 :
649 4 : subreq = dcerpc_wbint_InitConnection_r_send(state,
650 : state->ev,
651 4 : state->child->binding_handle,
652 : &state->r);
653 4 : if (tevent_req_nomem(subreq, req)) {
654 0 : return;
655 : }
656 4 : tevent_req_set_callback(subreq, wb_domain_request_initialized, req);
657 4 : state->pending_subreq = subreq;
658 : }
659 :
660 69 : static void wb_domain_request_initialized(struct tevent_req *subreq)
661 : {
662 69 : struct tevent_req *req = tevent_req_callback_data(
663 : subreq, struct tevent_req);
664 69 : struct wb_domain_request_state *state = tevent_req_data(
665 : req, struct wb_domain_request_state);
666 : NTSTATUS status;
667 :
668 69 : state->pending_subreq = NULL;
669 :
670 69 : status = dcerpc_wbint_InitConnection_r_recv(subreq, state);
671 69 : TALLOC_FREE(subreq);
672 69 : if (NT_STATUS_IS_ERR(status)) {
673 0 : tevent_req_error(req, map_errno_from_nt_status(status));
674 0 : return;
675 : }
676 :
677 69 : status = state->r.out.result;
678 69 : if (NT_STATUS_IS_ERR(status)) {
679 0 : tevent_req_error(req, map_errno_from_nt_status(status));
680 0 : return;
681 : }
682 :
683 69 : state->domain->sid = *state->r.out.sid;
684 :
685 69 : talloc_free(state->domain->name);
686 69 : state->domain->name = talloc_strdup(state->domain, *state->r.out.name);
687 69 : if (state->domain->name == NULL) {
688 0 : tevent_req_error(req, ENOMEM);
689 0 : return;
690 : }
691 :
692 69 : if (*state->r.out.alt_name != NULL &&
693 32 : strlen(*state->r.out.alt_name) > 0) {
694 31 : talloc_free(state->domain->alt_name);
695 :
696 62 : state->domain->alt_name = talloc_strdup(state->domain,
697 31 : *state->r.out.alt_name);
698 31 : if (state->domain->alt_name == NULL) {
699 0 : tevent_req_error(req, ENOMEM);
700 0 : return;
701 : }
702 : }
703 :
704 69 : state->domain->native_mode =
705 69 : (*state->r.out.flags & WB_DOMINFO_DOMAIN_NATIVE);
706 69 : state->domain->active_directory =
707 69 : (*state->r.out.flags & WB_DOMINFO_DOMAIN_AD);
708 69 : state->domain->initialized = true;
709 :
710 69 : subreq = wb_child_request_send(state, state->ev, state->child,
711 : state->request);
712 69 : if (tevent_req_nomem(subreq, req)) {
713 0 : return;
714 : }
715 69 : tevent_req_set_callback(subreq, wb_domain_request_done, req);
716 69 : state->pending_subreq = subreq;
717 :
718 : /*
719 : * Once the domain is initialized and
720 : * once we placed our real request into the child queue,
721 : * we can remove ourself from the domain queue
722 : * and give the next one in the queue the chance
723 : * to check for an idle child.
724 : */
725 69 : TALLOC_FREE(state->queue_entry);
726 : }
727 :
728 3054 : static void wb_domain_request_done(struct tevent_req *subreq)
729 : {
730 3054 : struct tevent_req *req = tevent_req_callback_data(
731 : subreq, struct tevent_req);
732 3054 : struct wb_domain_request_state *state = tevent_req_data(
733 : req, struct wb_domain_request_state);
734 : int ret, err;
735 :
736 3054 : state->pending_subreq = NULL;
737 :
738 3054 : ret = wb_child_request_recv(subreq, talloc_tos(), &state->response,
739 : &err);
740 3054 : TALLOC_FREE(subreq);
741 3054 : if (ret == -1) {
742 0 : tevent_req_error(req, err);
743 0 : return;
744 : }
745 3054 : tevent_req_done(req);
746 : }
747 :
748 3054 : int wb_domain_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
749 : struct winbindd_response **presponse, int *err)
750 : {
751 3054 : struct wb_domain_request_state *state = tevent_req_data(
752 : req, struct wb_domain_request_state);
753 :
754 3054 : if (tevent_req_is_unix_error(req, err)) {
755 0 : return -1;
756 : }
757 3054 : *presponse = talloc_move(mem_ctx, &state->response);
758 3054 : return 0;
759 : }
760 :
761 0 : static void child_process_request(struct winbindd_child *child,
762 : struct winbindd_cli_state *state)
763 : {
764 0 : struct winbindd_domain *domain = child->domain;
765 :
766 : /* Free response data - we may be interrupted and receive another
767 : command before being able to send this data off. */
768 :
769 0 : state->response->result = WINBINDD_ERROR;
770 0 : state->response->length = sizeof(struct winbindd_response);
771 :
772 : /* as all requests in the child are sync, we can use talloc_tos() */
773 0 : state->mem_ctx = talloc_tos();
774 :
775 : /* Process command */
776 0 : state->response->result = winbindd_dual_ndrcmd(domain, state);
777 0 : }
778 :
779 156 : void setup_child(struct winbindd_domain *domain, struct winbindd_child *child,
780 : const char *logprefix,
781 : const char *logname)
782 : {
783 : const struct loadparm_substitution *lp_sub =
784 156 : loadparm_s3_global_substitution();
785 :
786 312 : if (logprefix && logname) {
787 156 : char *logbase = NULL;
788 :
789 156 : if (*lp_logfile(talloc_tos(), lp_sub)) {
790 156 : char *end = NULL;
791 :
792 156 : if (asprintf(&logbase, "%s", lp_logfile(talloc_tos(), lp_sub)) < 0) {
793 0 : smb_panic("Internal error: asprintf failed");
794 : }
795 :
796 156 : if ((end = strrchr_m(logbase, '/'))) {
797 156 : *end = '\0';
798 : }
799 : } else {
800 0 : if (asprintf(&logbase, "%s", get_dyn_LOGFILEBASE()) < 0) {
801 0 : smb_panic("Internal error: asprintf failed");
802 : }
803 : }
804 :
805 156 : if (asprintf(&child->logfilename, "%s/%s-%s",
806 : logbase, logprefix, logname) < 0) {
807 0 : SAFE_FREE(logbase);
808 0 : smb_panic("Internal error: asprintf failed");
809 : }
810 :
811 156 : SAFE_FREE(logbase);
812 : } else {
813 0 : smb_panic("Internal error: logprefix == NULL && "
814 : "logname == NULL");
815 : }
816 :
817 156 : child->pid = 0;
818 156 : child->sock = -1;
819 156 : child->domain = domain;
820 156 : child->queue = tevent_queue_create(NULL, "winbind_child");
821 156 : SMB_ASSERT(child->queue != NULL);
822 :
823 156 : child->binding_handle = wbint_binding_handle(NULL, NULL, child);
824 156 : SMB_ASSERT(child->binding_handle != NULL);
825 156 : }
826 :
827 : struct winbind_child_died_state {
828 : pid_t pid;
829 : struct winbindd_child *child;
830 : };
831 :
832 15 : static bool winbind_child_died_fn(struct winbindd_child *child,
833 : void *private_data)
834 : {
835 15 : struct winbind_child_died_state *state = private_data;
836 :
837 15 : if (child->pid == state->pid) {
838 0 : state->child = child;
839 0 : return false;
840 : }
841 15 : return true;
842 : }
843 :
844 5 : void winbind_child_died(pid_t pid)
845 : {
846 5 : struct winbind_child_died_state state = { .pid = pid };
847 :
848 5 : forall_children(winbind_child_died_fn, &state);
849 :
850 5 : if (state.child == NULL) {
851 5 : DEBUG(5, ("Already reaped child %u died\n", (unsigned int)pid));
852 5 : return;
853 : }
854 :
855 0 : state.child->pid = 0;
856 : }
857 :
858 : /* Ensure any negative cache entries with the netbios or realm names are removed. */
859 :
860 32 : void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
861 : {
862 32 : flush_negative_conn_cache_for_domain(domain->name);
863 32 : if (domain->alt_name != NULL) {
864 32 : flush_negative_conn_cache_for_domain(domain->alt_name);
865 : }
866 32 : }
867 :
868 : /*
869 : * Parent winbindd process sets its own debug level first and then
870 : * sends a message to all the winbindd children to adjust their debug
871 : * level to that of parents.
872 : */
873 :
874 : struct winbind_msg_relay_state {
875 : struct messaging_context *msg_ctx;
876 : uint32_t msg_type;
877 : DATA_BLOB *data;
878 : };
879 :
880 18 : static bool winbind_msg_relay_fn(struct winbindd_child *child,
881 : void *private_data)
882 : {
883 18 : struct winbind_msg_relay_state *state = private_data;
884 :
885 18 : DBG_DEBUG("sending message to pid %u.\n",
886 : (unsigned int)child->pid);
887 :
888 18 : messaging_send(state->msg_ctx, pid_to_procid(child->pid),
889 18 : state->msg_type, state->data);
890 18 : return true;
891 : }
892 :
893 0 : void winbind_msg_debug(struct messaging_context *msg_ctx,
894 : void *private_data,
895 : uint32_t msg_type,
896 : struct server_id server_id,
897 : DATA_BLOB *data)
898 : {
899 0 : struct winbind_msg_relay_state state = {
900 : .msg_ctx = msg_ctx, .msg_type = msg_type, .data = data
901 : };
902 :
903 0 : DEBUG(10,("winbind_msg_debug: got debug message.\n"));
904 :
905 0 : debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data);
906 :
907 0 : forall_children(winbind_msg_relay_fn, &state);
908 0 : }
909 :
910 0 : void winbind_disconnect_dc_parent(struct messaging_context *msg_ctx,
911 : void *private_data,
912 : uint32_t msg_type,
913 : struct server_id server_id,
914 : DATA_BLOB *data)
915 : {
916 0 : struct winbind_msg_relay_state state = {
917 : .msg_ctx = msg_ctx, .msg_type = msg_type, .data = data
918 : };
919 :
920 0 : DBG_DEBUG("Got disconnect_dc message\n");
921 :
922 0 : forall_children(winbind_msg_relay_fn, &state);
923 0 : }
924 :
925 0 : static void winbindd_msg_reload_services_child(struct messaging_context *msg,
926 : void *private_data,
927 : uint32_t msg_type,
928 : struct server_id server_id,
929 : DATA_BLOB *data)
930 : {
931 0 : DBG_DEBUG("Got reload-config message\n");
932 0 : winbindd_reload_services_file((const char *)private_data);
933 0 : }
934 :
935 : /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
936 6 : void winbindd_msg_reload_services_parent(struct messaging_context *msg,
937 : void *private_data,
938 : uint32_t msg_type,
939 : struct server_id server_id,
940 : DATA_BLOB *data)
941 : {
942 6 : struct winbind_msg_relay_state state = {
943 : .msg_ctx = msg,
944 : .msg_type = msg_type,
945 : .data = data,
946 : };
947 :
948 6 : DBG_DEBUG("Got reload-config message\n");
949 :
950 : /* Flush various caches */
951 6 : winbindd_flush_caches();
952 :
953 6 : winbindd_reload_services_file((const char *)private_data);
954 :
955 6 : forall_children(winbind_msg_relay_fn, &state);
956 6 : }
957 :
958 : /* Set our domains as offline and forward the offline message to our children. */
959 :
960 : struct winbind_msg_on_offline_state {
961 : struct messaging_context *msg_ctx;
962 : uint32_t msg_type;
963 : };
964 :
965 8 : static bool winbind_msg_on_offline_fn(struct winbindd_child *child,
966 : void *private_data)
967 : {
968 8 : struct winbind_msg_on_offline_state *state = private_data;
969 :
970 8 : if (child->domain->internal) {
971 4 : return true;
972 : }
973 :
974 : /*
975 : * Each winbindd child should only process requests for one
976 : * domain - make sure we only set it online / offline for that
977 : * domain.
978 : */
979 4 : DBG_DEBUG("sending message to pid %u for domain %s.\n",
980 : (unsigned int)child->pid, child->domain->name);
981 :
982 4 : messaging_send_buf(state->msg_ctx,
983 : pid_to_procid(child->pid),
984 : state->msg_type,
985 4 : (const uint8_t *)child->domain->name,
986 4 : strlen(child->domain->name)+1);
987 :
988 4 : return true;
989 : }
990 :
991 4 : void winbind_msg_offline(struct messaging_context *msg_ctx,
992 : void *private_data,
993 : uint32_t msg_type,
994 : struct server_id server_id,
995 : DATA_BLOB *data)
996 : {
997 4 : struct winbind_msg_on_offline_state state = {
998 : .msg_ctx = msg_ctx,
999 : .msg_type = MSG_WINBIND_OFFLINE,
1000 : };
1001 : struct winbindd_domain *domain;
1002 :
1003 4 : DEBUG(10,("winbind_msg_offline: got offline message.\n"));
1004 :
1005 4 : if (!lp_winbind_offline_logon()) {
1006 0 : DEBUG(10,("winbind_msg_offline: rejecting offline message.\n"));
1007 0 : return;
1008 : }
1009 :
1010 : /* Set our global state as offline. */
1011 4 : if (!set_global_winbindd_state_offline()) {
1012 0 : DEBUG(10,("winbind_msg_offline: offline request failed.\n"));
1013 0 : return;
1014 : }
1015 :
1016 : /* Set all our domains as offline. */
1017 16 : for (domain = domain_list(); domain; domain = domain->next) {
1018 12 : if (domain->internal) {
1019 8 : continue;
1020 : }
1021 4 : DEBUG(5,("winbind_msg_offline: marking %s offline.\n", domain->name));
1022 4 : domain->online = false;
1023 : }
1024 :
1025 4 : forall_domain_children(winbind_msg_on_offline_fn, &state);
1026 : }
1027 :
1028 : /* Set our domains as online and forward the online message to our children. */
1029 :
1030 0 : void winbind_msg_online(struct messaging_context *msg_ctx,
1031 : void *private_data,
1032 : uint32_t msg_type,
1033 : struct server_id server_id,
1034 : DATA_BLOB *data)
1035 : {
1036 0 : struct winbind_msg_on_offline_state state = {
1037 : .msg_ctx = msg_ctx,
1038 : .msg_type = MSG_WINBIND_ONLINE,
1039 : };
1040 :
1041 0 : DEBUG(10,("winbind_msg_online: got online message.\n"));
1042 :
1043 0 : if (!lp_winbind_offline_logon()) {
1044 0 : DEBUG(10,("winbind_msg_online: rejecting online message.\n"));
1045 0 : return;
1046 : }
1047 :
1048 : /* Set our global state as online. */
1049 0 : set_global_winbindd_state_online();
1050 :
1051 0 : smb_nscd_flush_user_cache();
1052 0 : smb_nscd_flush_group_cache();
1053 :
1054 : /* Tell all our child domains to go online online. */
1055 0 : forall_domain_children(winbind_msg_on_offline_fn, &state);
1056 : }
1057 :
1058 0 : static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx)
1059 : {
1060 : struct winbindd_domain *domain;
1061 0 : char *buf = NULL;
1062 :
1063 0 : if ((buf = talloc_asprintf(mem_ctx, "global:%s ",
1064 0 : get_global_winbindd_state_offline() ?
1065 : "Offline":"Online")) == NULL) {
1066 0 : return NULL;
1067 : }
1068 :
1069 0 : for (domain = domain_list(); domain; domain = domain->next) {
1070 0 : if ((buf = talloc_asprintf_append_buffer(buf, "%s:%s ",
1071 : domain->name,
1072 0 : domain->online ?
1073 : "Online":"Offline")) == NULL) {
1074 0 : return NULL;
1075 : }
1076 : }
1077 :
1078 0 : buf = talloc_asprintf_append_buffer(buf, "\n");
1079 :
1080 0 : DEBUG(5,("collect_onlinestatus: %s", buf));
1081 :
1082 0 : return buf;
1083 : }
1084 :
1085 0 : void winbind_msg_onlinestatus(struct messaging_context *msg_ctx,
1086 : void *private_data,
1087 : uint32_t msg_type,
1088 : struct server_id server_id,
1089 : DATA_BLOB *data)
1090 : {
1091 : TALLOC_CTX *mem_ctx;
1092 : const char *message;
1093 :
1094 0 : DEBUG(5,("winbind_msg_onlinestatus received.\n"));
1095 :
1096 0 : mem_ctx = talloc_init("winbind_msg_onlinestatus");
1097 0 : if (mem_ctx == NULL) {
1098 0 : return;
1099 : }
1100 :
1101 0 : message = collect_onlinestatus(mem_ctx);
1102 0 : if (message == NULL) {
1103 0 : talloc_destroy(mem_ctx);
1104 0 : return;
1105 : }
1106 :
1107 0 : messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_ONLINESTATUS,
1108 0 : (const uint8_t *)message, strlen(message) + 1);
1109 :
1110 0 : talloc_destroy(mem_ctx);
1111 : }
1112 :
1113 0 : void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx,
1114 : void *private_data,
1115 : uint32_t msg_type,
1116 : struct server_id server_id,
1117 : DATA_BLOB *data)
1118 : {
1119 : TALLOC_CTX *mem_ctx;
1120 0 : const char *message = NULL;
1121 0 : const char *domain = NULL;
1122 0 : char *s = NULL;
1123 : NTSTATUS status;
1124 0 : struct winbindd_domain *dom = NULL;
1125 :
1126 0 : DEBUG(5,("winbind_msg_dump_domain_list received.\n"));
1127 :
1128 0 : mem_ctx = talloc_init("winbind_msg_dump_domain_list");
1129 0 : if (!mem_ctx) {
1130 0 : return;
1131 : }
1132 :
1133 0 : if (data->length > 0) {
1134 0 : domain = (const char *)data->data;
1135 : }
1136 :
1137 0 : if (domain) {
1138 :
1139 0 : DEBUG(5,("winbind_msg_dump_domain_list for domain: %s\n",
1140 : domain));
1141 :
1142 0 : message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain,
1143 : find_domain_from_name_noinit(domain));
1144 0 : if (!message) {
1145 0 : talloc_destroy(mem_ctx);
1146 0 : return;
1147 : }
1148 :
1149 0 : messaging_send_buf(msg_ctx, server_id,
1150 : MSG_WINBIND_DUMP_DOMAIN_LIST,
1151 0 : (const uint8_t *)message, strlen(message) + 1);
1152 :
1153 0 : talloc_destroy(mem_ctx);
1154 :
1155 0 : return;
1156 : }
1157 :
1158 0 : DEBUG(5,("winbind_msg_dump_domain_list all domains\n"));
1159 :
1160 0 : for (dom = domain_list(); dom; dom=dom->next) {
1161 0 : message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, dom);
1162 0 : if (!message) {
1163 0 : talloc_destroy(mem_ctx);
1164 0 : return;
1165 : }
1166 :
1167 0 : s = talloc_asprintf_append(s, "%s\n", message);
1168 0 : if (!s) {
1169 0 : talloc_destroy(mem_ctx);
1170 0 : return;
1171 : }
1172 : }
1173 :
1174 0 : status = messaging_send_buf(msg_ctx, server_id,
1175 : MSG_WINBIND_DUMP_DOMAIN_LIST,
1176 0 : (uint8_t *)s, strlen(s) + 1);
1177 0 : if (!NT_STATUS_IS_OK(status)) {
1178 0 : DEBUG(0,("failed to send message: %s\n",
1179 : nt_errstr(status)));
1180 : }
1181 :
1182 0 : talloc_destroy(mem_ctx);
1183 : }
1184 :
1185 0 : static void account_lockout_policy_handler(struct tevent_context *ctx,
1186 : struct tevent_timer *te,
1187 : struct timeval now,
1188 : void *private_data)
1189 : {
1190 0 : struct winbindd_child *child =
1191 : (struct winbindd_child *)private_data;
1192 0 : TALLOC_CTX *mem_ctx = NULL;
1193 : struct samr_DomInfo12 lockout_policy;
1194 : NTSTATUS result;
1195 :
1196 0 : DEBUG(10,("account_lockout_policy_handler called\n"));
1197 :
1198 0 : TALLOC_FREE(child->lockout_policy_event);
1199 :
1200 0 : if ( !winbindd_can_contact_domain( child->domain ) ) {
1201 0 : DEBUG(10,("account_lockout_policy_handler: Removing myself since I "
1202 : "do not have an incoming trust to domain %s\n",
1203 : child->domain->name));
1204 :
1205 0 : return;
1206 : }
1207 :
1208 0 : mem_ctx = talloc_init("account_lockout_policy_handler ctx");
1209 0 : if (!mem_ctx) {
1210 0 : result = NT_STATUS_NO_MEMORY;
1211 : } else {
1212 0 : result = wb_cache_lockout_policy(child->domain, mem_ctx,
1213 : &lockout_policy);
1214 : }
1215 0 : TALLOC_FREE(mem_ctx);
1216 :
1217 0 : if (!NT_STATUS_IS_OK(result)) {
1218 0 : DEBUG(10,("account_lockout_policy_handler: lockout_policy failed error %s\n",
1219 : nt_errstr(result)));
1220 : }
1221 :
1222 0 : child->lockout_policy_event = tevent_add_timer(global_event_context(), NULL,
1223 : timeval_current_ofs(3600, 0),
1224 : account_lockout_policy_handler,
1225 : child);
1226 : }
1227 :
1228 0 : static time_t get_machine_password_timeout(void)
1229 : {
1230 : /* until we have gpo support use lp setting */
1231 0 : return lp_machine_password_timeout();
1232 : }
1233 :
1234 0 : static bool calculate_next_machine_pwd_change(const char *domain,
1235 : struct timeval *t)
1236 : {
1237 : time_t pass_last_set_time;
1238 : time_t timeout;
1239 : time_t next_change;
1240 : struct timeval tv;
1241 : char *pw;
1242 :
1243 0 : pw = secrets_fetch_machine_password(domain,
1244 : &pass_last_set_time,
1245 : NULL);
1246 :
1247 0 : if (pw == NULL) {
1248 0 : DEBUG(0,("cannot fetch own machine password ????"));
1249 0 : return false;
1250 : }
1251 :
1252 0 : SAFE_FREE(pw);
1253 :
1254 0 : timeout = get_machine_password_timeout();
1255 0 : if (timeout == 0) {
1256 0 : DEBUG(10,("machine password never expires\n"));
1257 0 : return false;
1258 : }
1259 :
1260 0 : tv.tv_sec = pass_last_set_time;
1261 0 : DEBUG(10, ("password last changed %s\n",
1262 : timeval_string(talloc_tos(), &tv, false)));
1263 0 : tv.tv_sec += timeout;
1264 0 : DEBUGADD(10, ("password valid until %s\n",
1265 : timeval_string(talloc_tos(), &tv, false)));
1266 :
1267 0 : if (time(NULL) < (pass_last_set_time + timeout)) {
1268 0 : next_change = pass_last_set_time + timeout;
1269 0 : DEBUG(10,("machine password still valid until: %s\n",
1270 : http_timestring(talloc_tos(), next_change)));
1271 0 : *t = timeval_set(next_change, 0);
1272 :
1273 0 : if (lp_clustering()) {
1274 : uint8_t randbuf;
1275 : /*
1276 : * When having a cluster, we have several
1277 : * winbinds racing for the password change. In
1278 : * the machine_password_change_handler()
1279 : * function we check if someone else was
1280 : * faster when the event triggers. We add a
1281 : * 255-second random delay here, so that we
1282 : * don't run to change the password at the
1283 : * exact same moment.
1284 : */
1285 0 : generate_random_buffer(&randbuf, sizeof(randbuf));
1286 0 : DEBUG(10, ("adding %d seconds randomness\n",
1287 : (int)randbuf));
1288 0 : t->tv_sec += randbuf;
1289 : }
1290 0 : return true;
1291 : }
1292 :
1293 0 : DEBUG(10,("machine password expired, needs immediate change\n"));
1294 :
1295 0 : *t = timeval_zero();
1296 :
1297 0 : return true;
1298 : }
1299 :
1300 0 : static void machine_password_change_handler(struct tevent_context *ctx,
1301 : struct tevent_timer *te,
1302 : struct timeval now,
1303 : void *private_data)
1304 : {
1305 0 : struct messaging_context *msg_ctx = global_messaging_context();
1306 0 : struct winbindd_child *child =
1307 : (struct winbindd_child *)private_data;
1308 0 : struct rpc_pipe_client *netlogon_pipe = NULL;
1309 0 : struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
1310 : NTSTATUS result;
1311 : struct timeval next_change;
1312 :
1313 0 : DEBUG(10,("machine_password_change_handler called\n"));
1314 :
1315 0 : TALLOC_FREE(child->machine_password_change_event);
1316 :
1317 0 : if (!calculate_next_machine_pwd_change(child->domain->name,
1318 : &next_change)) {
1319 0 : DEBUG(10, ("calculate_next_machine_pwd_change failed\n"));
1320 0 : return;
1321 : }
1322 :
1323 0 : DEBUG(10, ("calculate_next_machine_pwd_change returned %s\n",
1324 : timeval_string(talloc_tos(), &next_change, false)));
1325 :
1326 0 : if (!timeval_expired(&next_change)) {
1327 0 : DEBUG(10, ("Someone else has already changed the pw\n"));
1328 0 : goto done;
1329 : }
1330 :
1331 0 : if (!winbindd_can_contact_domain(child->domain)) {
1332 0 : DEBUG(10,("machine_password_change_handler: Removing myself since I "
1333 : "do not have an incoming trust to domain %s\n",
1334 : child->domain->name));
1335 0 : return;
1336 : }
1337 :
1338 0 : result = cm_connect_netlogon_secure(child->domain,
1339 : &netlogon_pipe,
1340 : &netlogon_creds_ctx);
1341 0 : if (!NT_STATUS_IS_OK(result)) {
1342 0 : DEBUG(10,("machine_password_change_handler: "
1343 : "failed to connect netlogon pipe: %s\n",
1344 : nt_errstr(result)));
1345 0 : return;
1346 : }
1347 :
1348 0 : result = trust_pw_change(netlogon_creds_ctx,
1349 : msg_ctx,
1350 0 : netlogon_pipe->binding_handle,
1351 0 : child->domain->name,
1352 0 : child->domain->dcname,
1353 : false); /* force */
1354 :
1355 0 : DEBUG(10, ("machine_password_change_handler: "
1356 : "trust_pw_change returned %s\n",
1357 : nt_errstr(result)));
1358 :
1359 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) {
1360 0 : DEBUG(3,("machine_password_change_handler: password set returned "
1361 : "ACCESS_DENIED. Maybe the trust account "
1362 : "password was changed and we didn't know it. "
1363 : "Killing connections to domain %s\n",
1364 : child->domain->name));
1365 0 : invalidate_cm_connection(child->domain);
1366 : }
1367 :
1368 0 : if (!calculate_next_machine_pwd_change(child->domain->name,
1369 : &next_change)) {
1370 0 : DEBUG(10, ("calculate_next_machine_pwd_change failed\n"));
1371 0 : return;
1372 : }
1373 :
1374 0 : DEBUG(10, ("calculate_next_machine_pwd_change returned %s\n",
1375 : timeval_string(talloc_tos(), &next_change, false)));
1376 :
1377 0 : if (!NT_STATUS_IS_OK(result)) {
1378 : struct timeval tmp;
1379 : /*
1380 : * In case of failure, give the DC a minute to recover
1381 : */
1382 0 : tmp = timeval_current_ofs(60, 0);
1383 0 : next_change = timeval_max(&next_change, &tmp);
1384 : }
1385 :
1386 0 : done:
1387 0 : child->machine_password_change_event = tevent_add_timer(global_event_context(), NULL,
1388 : next_change,
1389 : machine_password_change_handler,
1390 : child);
1391 : }
1392 :
1393 : /* Deal with a request to go offline. */
1394 :
1395 0 : static void child_msg_offline(struct messaging_context *msg,
1396 : void *private_data,
1397 : uint32_t msg_type,
1398 : struct server_id server_id,
1399 : DATA_BLOB *data)
1400 : {
1401 : struct winbindd_domain *domain;
1402 0 : struct winbindd_domain *primary_domain = NULL;
1403 0 : const char *domainname = (const char *)data->data;
1404 :
1405 0 : if (data->data == NULL || data->length == 0) {
1406 0 : return;
1407 : }
1408 :
1409 0 : DEBUG(5,("child_msg_offline received for domain %s.\n", domainname));
1410 :
1411 0 : if (!lp_winbind_offline_logon()) {
1412 0 : DEBUG(10,("child_msg_offline: rejecting offline message.\n"));
1413 0 : return;
1414 : }
1415 :
1416 0 : primary_domain = find_our_domain();
1417 :
1418 : /* Mark the requested domain offline. */
1419 :
1420 0 : for (domain = domain_list(); domain; domain = domain->next) {
1421 0 : if (domain->internal) {
1422 0 : continue;
1423 : }
1424 0 : if (strequal(domain->name, domainname)) {
1425 0 : DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
1426 0 : set_domain_offline(domain);
1427 : /* we are in the trusted domain, set the primary domain
1428 : * offline too */
1429 0 : if (domain != primary_domain) {
1430 0 : set_domain_offline(primary_domain);
1431 : }
1432 : }
1433 : }
1434 : }
1435 :
1436 : /* Deal with a request to go online. */
1437 :
1438 0 : static void child_msg_online(struct messaging_context *msg,
1439 : void *private_data,
1440 : uint32_t msg_type,
1441 : struct server_id server_id,
1442 : DATA_BLOB *data)
1443 : {
1444 : struct winbindd_domain *domain;
1445 0 : struct winbindd_domain *primary_domain = NULL;
1446 0 : const char *domainname = (const char *)data->data;
1447 :
1448 0 : if (data->data == NULL || data->length == 0) {
1449 0 : return;
1450 : }
1451 :
1452 0 : DEBUG(5,("child_msg_online received for domain %s.\n", domainname));
1453 :
1454 0 : if (!lp_winbind_offline_logon()) {
1455 0 : DEBUG(10,("child_msg_online: rejecting online message.\n"));
1456 0 : return;
1457 : }
1458 :
1459 0 : primary_domain = find_our_domain();
1460 :
1461 : /* Set our global state as online. */
1462 0 : set_global_winbindd_state_online();
1463 :
1464 : /* Try and mark everything online - delete any negative cache entries
1465 : to force a reconnect now. */
1466 :
1467 0 : for (domain = domain_list(); domain; domain = domain->next) {
1468 0 : if (domain->internal) {
1469 0 : continue;
1470 : }
1471 0 : if (strequal(domain->name, domainname)) {
1472 0 : DEBUG(5,("child_msg_online: requesting %s to go online.\n", domain->name));
1473 0 : winbindd_flush_negative_conn_cache(domain);
1474 0 : set_domain_online_request(domain);
1475 :
1476 : /* we can be in trusted domain, which will contact primary domain
1477 : * we have to bring primary domain online in trusted domain process
1478 : * see, winbindd_dual_pam_auth() --> winbindd_dual_pam_auth_samlogon()
1479 : * --> contact_domain = find_our_domain()
1480 : * */
1481 0 : if (domain != primary_domain) {
1482 0 : winbindd_flush_negative_conn_cache(primary_domain);
1483 0 : set_domain_online_request(primary_domain);
1484 : }
1485 : }
1486 : }
1487 : }
1488 :
1489 : struct winbindd_reinit_after_fork_state {
1490 : const struct winbindd_child *myself;
1491 : };
1492 :
1493 0 : static bool winbindd_reinit_after_fork_fn(struct winbindd_child *child,
1494 : void *private_data)
1495 : {
1496 0 : struct winbindd_reinit_after_fork_state *state = private_data;
1497 :
1498 0 : if (child == state->myself) {
1499 0 : return true;
1500 : }
1501 :
1502 : /* Destroy all possible events in child list. */
1503 0 : TALLOC_FREE(child->lockout_policy_event);
1504 0 : TALLOC_FREE(child->machine_password_change_event);
1505 :
1506 : /*
1507 : * Children should never be able to send each other messages,
1508 : * all messages must go through the parent.
1509 : */
1510 0 : child->pid = (pid_t)0;
1511 :
1512 : /*
1513 : * Close service sockets to all other children
1514 : */
1515 0 : if (child->sock != -1) {
1516 0 : close(child->sock);
1517 0 : child->sock = -1;
1518 : }
1519 :
1520 0 : return true;
1521 : }
1522 :
1523 0 : NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself,
1524 : const char *logfilename)
1525 : {
1526 0 : struct winbindd_reinit_after_fork_state state = { .myself = myself };
1527 : struct winbindd_domain *domain;
1528 : NTSTATUS status;
1529 :
1530 0 : status = reinit_after_fork(
1531 : global_messaging_context(),
1532 : global_event_context(),
1533 : true);
1534 0 : if (!NT_STATUS_IS_OK(status)) {
1535 0 : DEBUG(0,("reinit_after_fork() failed\n"));
1536 0 : return status;
1537 : }
1538 0 : initialize_password_db(true, global_event_context());
1539 :
1540 0 : close_conns_after_fork();
1541 :
1542 0 : if (logfilename != NULL) {
1543 0 : lp_set_logfile(logfilename);
1544 0 : reopen_logs();
1545 : }
1546 :
1547 0 : if (!winbindd_setup_sig_term_handler(false)) {
1548 0 : return NT_STATUS_NO_MEMORY;
1549 : }
1550 :
1551 0 : if (!winbindd_setup_sig_hup_handler(logfilename)) {
1552 0 : return NT_STATUS_NO_MEMORY;
1553 : }
1554 :
1555 : /* Stop zombies in children */
1556 0 : CatchChild();
1557 :
1558 : /* Don't handle the same messages as our parent. */
1559 0 : messaging_deregister(global_messaging_context(),
1560 : MSG_SMB_CONF_UPDATED, NULL);
1561 0 : messaging_deregister(global_messaging_context(),
1562 : MSG_SHUTDOWN, NULL);
1563 0 : messaging_deregister(global_messaging_context(),
1564 : MSG_WINBIND_OFFLINE, NULL);
1565 0 : messaging_deregister(global_messaging_context(),
1566 : MSG_WINBIND_ONLINE, NULL);
1567 0 : messaging_deregister(global_messaging_context(),
1568 : MSG_WINBIND_ONLINESTATUS, NULL);
1569 0 : messaging_deregister(global_messaging_context(),
1570 : MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1571 0 : messaging_deregister(global_messaging_context(),
1572 : MSG_DEBUG, NULL);
1573 :
1574 0 : messaging_deregister(global_messaging_context(),
1575 : MSG_WINBIND_DOMAIN_OFFLINE, NULL);
1576 0 : messaging_deregister(global_messaging_context(),
1577 : MSG_WINBIND_DOMAIN_ONLINE, NULL);
1578 :
1579 : /* We have destroyed all events in the winbindd_event_context
1580 : * in reinit_after_fork(), so clean out all possible pending
1581 : * event pointers. */
1582 :
1583 : /* Deal with check_online_events. */
1584 :
1585 0 : for (domain = domain_list(); domain; domain = domain->next) {
1586 0 : TALLOC_FREE(domain->check_online_event);
1587 : }
1588 :
1589 : /* Ensure we're not handling a credential cache event inherited
1590 : * from our parent. */
1591 :
1592 0 : ccache_remove_all_after_fork();
1593 :
1594 0 : forall_children(winbindd_reinit_after_fork_fn, &state);
1595 :
1596 0 : return NT_STATUS_OK;
1597 : }
1598 :
1599 : /*
1600 : * In a child there will be only one domain, reference that here.
1601 : */
1602 : static struct winbindd_domain *child_domain;
1603 :
1604 49 : struct winbindd_domain *wb_child_domain(void)
1605 : {
1606 49 : return child_domain;
1607 : }
1608 :
1609 : struct child_handler_state {
1610 : struct winbindd_child *child;
1611 : struct winbindd_cli_state cli;
1612 : };
1613 :
1614 0 : static void child_handler(struct tevent_context *ev, struct tevent_fd *fde,
1615 : uint16_t flags, void *private_data)
1616 : {
1617 0 : struct child_handler_state *state =
1618 : (struct child_handler_state *)private_data;
1619 : NTSTATUS status;
1620 : uint64_t parent_traceid;
1621 :
1622 : /* fetch a request from the main daemon */
1623 0 : status = child_read_request(state->cli.sock, state->cli.request);
1624 :
1625 0 : if (!NT_STATUS_IS_OK(status)) {
1626 : /* we lost contact with our parent */
1627 0 : _exit(0);
1628 : }
1629 :
1630 : /* read traceid from request */
1631 0 : parent_traceid = state->cli.request->traceid;
1632 0 : debug_traceid_set(parent_traceid);
1633 :
1634 0 : DEBUG(4,("child daemon request %d\n",
1635 : (int)state->cli.request->cmd));
1636 :
1637 0 : ZERO_STRUCTP(state->cli.response);
1638 0 : state->cli.request->null_term = '\0';
1639 0 : state->cli.mem_ctx = talloc_tos();
1640 0 : child_process_request(state->child, &state->cli);
1641 :
1642 0 : DEBUG(4, ("Finished processing child request %d\n",
1643 : (int)state->cli.request->cmd));
1644 :
1645 0 : SAFE_FREE(state->cli.request->extra_data.data);
1646 :
1647 0 : status = child_write_response(state->cli.sock, state->cli.response);
1648 0 : if (!NT_STATUS_IS_OK(status)) {
1649 0 : exit(1);
1650 : }
1651 0 : }
1652 :
1653 97 : static bool fork_domain_child(struct winbindd_child *child)
1654 : {
1655 : int fdpair[2];
1656 : struct child_handler_state state;
1657 : struct winbindd_request request;
1658 : struct winbindd_response response;
1659 97 : struct winbindd_domain *primary_domain = NULL;
1660 : NTSTATUS status;
1661 : ssize_t nwritten;
1662 : struct tevent_fd *fde;
1663 :
1664 97 : if (child->domain) {
1665 69 : DEBUG(10, ("fork_domain_child called for domain '%s'\n",
1666 : child->domain->name));
1667 : } else {
1668 28 : DEBUG(10, ("fork_domain_child called without domain.\n"));
1669 : }
1670 :
1671 97 : if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
1672 0 : DEBUG(0, ("Could not open child pipe: %s\n",
1673 : strerror(errno)));
1674 0 : return False;
1675 : }
1676 :
1677 97 : ZERO_STRUCT(state);
1678 97 : state.child = child;
1679 97 : state.cli.pid = getpid();
1680 97 : state.cli.request = &request;
1681 97 : state.cli.response = &response;
1682 :
1683 97 : child->pid = fork();
1684 :
1685 97 : if (child->pid == -1) {
1686 0 : DEBUG(0, ("Could not fork: %s\n", strerror(errno)));
1687 0 : close(fdpair[0]);
1688 0 : close(fdpair[1]);
1689 0 : return False;
1690 : }
1691 :
1692 97 : if (child->pid != 0) {
1693 : /* Parent */
1694 : ssize_t nread;
1695 : int rc;
1696 :
1697 97 : close(fdpair[0]);
1698 :
1699 97 : nread = sys_read(fdpair[1], &status, sizeof(status));
1700 97 : if (nread != sizeof(status)) {
1701 0 : DEBUG(1, ("fork_domain_child: Could not read child status: "
1702 : "nread=%d, error=%s\n", (int)nread,
1703 : strerror(errno)));
1704 0 : close(fdpair[1]);
1705 0 : return false;
1706 : }
1707 97 : if (!NT_STATUS_IS_OK(status)) {
1708 0 : DEBUG(1, ("fork_domain_child: Child status is %s\n",
1709 : nt_errstr(status)));
1710 0 : close(fdpair[1]);
1711 0 : return false;
1712 : }
1713 :
1714 97 : child->monitor_fde = tevent_add_fd(global_event_context(),
1715 : global_event_context(),
1716 : fdpair[1],
1717 : TEVENT_FD_READ,
1718 : child_socket_readable,
1719 : child);
1720 97 : if (child->monitor_fde == NULL) {
1721 0 : DBG_WARNING("tevent_add_fd failed\n");
1722 0 : close(fdpair[1]);
1723 0 : return false;
1724 : }
1725 :
1726 97 : rc = set_blocking(fdpair[1], false);
1727 97 : if (rc < 0) {
1728 0 : close(fdpair[1]);
1729 0 : return false;
1730 : }
1731 :
1732 97 : child->sock = fdpair[1];
1733 :
1734 97 : return true;
1735 : }
1736 :
1737 : /* Child */
1738 0 : child_domain = child->domain;
1739 :
1740 0 : DEBUG(10, ("Child process %d\n", (int)getpid()));
1741 :
1742 0 : state.cli.sock = fdpair[0];
1743 0 : close(fdpair[1]);
1744 :
1745 0 : status = winbindd_reinit_after_fork(child, child->logfilename);
1746 :
1747 : /* setup callbacks again, one of them is removed in reinit_after_fork */
1748 0 : if (lp_winbind_debug_traceid()) {
1749 0 : winbind_debug_traceid_setup(global_event_context());
1750 : }
1751 :
1752 0 : nwritten = sys_write(state.cli.sock, &status, sizeof(status));
1753 0 : if (nwritten != sizeof(status)) {
1754 0 : DEBUG(1, ("fork_domain_child: Could not write status: "
1755 : "nwritten=%d, error=%s\n", (int)nwritten,
1756 : strerror(errno)));
1757 0 : _exit(0);
1758 : }
1759 0 : if (!NT_STATUS_IS_OK(status)) {
1760 0 : DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
1761 : nt_errstr(status)));
1762 0 : _exit(0);
1763 : }
1764 :
1765 0 : if (child_domain != NULL) {
1766 0 : process_set_title("wb[%s]", "domain child [%s]", child_domain->name);
1767 0 : } else if (is_idmap_child(child)) {
1768 0 : process_set_title("wb-idmap", "idmap child");
1769 : }
1770 :
1771 : /* Handle online/offline messages. */
1772 0 : messaging_register(global_messaging_context(), NULL,
1773 : MSG_WINBIND_OFFLINE, child_msg_offline);
1774 0 : messaging_register(global_messaging_context(), NULL,
1775 : MSG_WINBIND_ONLINE, child_msg_online);
1776 0 : messaging_register(global_messaging_context(), NULL,
1777 : MSG_DEBUG, debug_message);
1778 0 : messaging_register(global_messaging_context(), NULL,
1779 : MSG_WINBIND_IP_DROPPED,
1780 : winbind_msg_ip_dropped);
1781 0 : messaging_register(global_messaging_context(), NULL,
1782 : MSG_WINBIND_DISCONNECT_DC,
1783 : winbind_msg_disconnect_dc);
1784 0 : messaging_register(
1785 : global_messaging_context(),
1786 0 : child->logfilename,
1787 : MSG_SMB_CONF_UPDATED,
1788 : winbindd_msg_reload_services_child);
1789 :
1790 0 : primary_domain = find_our_domain();
1791 :
1792 0 : if (primary_domain == NULL) {
1793 0 : smb_panic("no primary domain found");
1794 : }
1795 :
1796 : /* It doesn't matter if we allow cache login,
1797 : * try to bring domain online after fork. */
1798 0 : if ( child->domain ) {
1799 0 : child->domain->startup = True;
1800 0 : child->domain->startup_time = time_mono(NULL);
1801 : /* we can be in primary domain or in trusted domain
1802 : * If we are in trusted domain, set the primary domain
1803 : * in start-up mode */
1804 0 : if (!(child->domain->internal)) {
1805 0 : set_domain_online_request(child->domain);
1806 0 : if (!(child->domain->primary)) {
1807 0 : primary_domain->startup = True;
1808 0 : primary_domain->startup_time = time_mono(NULL);
1809 0 : set_domain_online_request(primary_domain);
1810 : }
1811 : }
1812 : }
1813 :
1814 : /* We might be in the idmap child...*/
1815 0 : if (child->domain && !(child->domain->internal) &&
1816 0 : lp_winbind_offline_logon()) {
1817 :
1818 0 : set_domain_online_request(child->domain);
1819 :
1820 0 : if (primary_domain && (primary_domain != child->domain)) {
1821 : /* We need to talk to the primary
1822 : * domain as well as the trusted
1823 : * domain inside a trusted domain
1824 : * child.
1825 : * See the code in :
1826 : * set_dc_type_and_flags_trustinfo()
1827 : * for details.
1828 : */
1829 0 : set_domain_online_request(primary_domain);
1830 : }
1831 :
1832 0 : child->lockout_policy_event = tevent_add_timer(
1833 : global_event_context(), NULL, timeval_zero(),
1834 : account_lockout_policy_handler,
1835 : child);
1836 : }
1837 :
1838 0 : if (child->domain && child->domain->primary &&
1839 0 : !USE_KERBEROS_KEYTAB &&
1840 0 : lp_server_role() == ROLE_DOMAIN_MEMBER) {
1841 :
1842 : struct timeval next_change;
1843 :
1844 0 : if (calculate_next_machine_pwd_change(child->domain->name,
1845 : &next_change)) {
1846 0 : child->machine_password_change_event = tevent_add_timer(
1847 : global_event_context(), NULL, next_change,
1848 : machine_password_change_handler,
1849 : child);
1850 : }
1851 : }
1852 :
1853 0 : fde = tevent_add_fd(global_event_context(), NULL, state.cli.sock,
1854 : TEVENT_FD_READ, child_handler, &state);
1855 0 : if (fde == NULL) {
1856 0 : DEBUG(1, ("tevent_add_fd failed\n"));
1857 0 : _exit(1);
1858 : }
1859 :
1860 0 : while (1) {
1861 :
1862 : int ret;
1863 0 : TALLOC_CTX *frame = talloc_stackframe();
1864 :
1865 0 : ret = tevent_loop_once(global_event_context());
1866 0 : if (ret != 0) {
1867 0 : DEBUG(1, ("tevent_loop_once failed: %s\n",
1868 : strerror(errno)));
1869 0 : _exit(1);
1870 : }
1871 :
1872 0 : if (child->domain && child->domain->startup &&
1873 0 : (time_mono(NULL) > child->domain->startup_time + 30)) {
1874 : /* No longer in "startup" mode. */
1875 0 : DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n",
1876 : child->domain->name ));
1877 0 : child->domain->startup = False;
1878 : }
1879 :
1880 0 : TALLOC_FREE(frame);
1881 : }
1882 : }
1883 :
1884 0 : void winbind_msg_ip_dropped_parent(struct messaging_context *msg_ctx,
1885 : void *private_data,
1886 : uint32_t msg_type,
1887 : struct server_id server_id,
1888 : DATA_BLOB *data)
1889 : {
1890 0 : struct winbind_msg_relay_state state = {
1891 : .msg_ctx = msg_ctx,
1892 : .msg_type = msg_type,
1893 : .data = data,
1894 : };
1895 :
1896 0 : winbind_msg_ip_dropped(msg_ctx, private_data, msg_type,
1897 : server_id, data);
1898 :
1899 0 : forall_children(winbind_msg_relay_fn, &state);
1900 0 : }
1901 :
1902 30 : void winbindd_terminate(bool is_parent)
1903 : {
1904 30 : if (is_parent) {
1905 : /* When parent goes away we should
1906 : * remove the socket file. Not so
1907 : * when children terminate.
1908 : */
1909 30 : char *path = NULL;
1910 :
1911 30 : if (asprintf(&path, "%s/%s",
1912 : lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
1913 30 : unlink(path);
1914 30 : SAFE_FREE(path);
1915 : }
1916 : }
1917 :
1918 30 : idmap_close();
1919 :
1920 30 : netlogon_creds_cli_close_global_db();
1921 :
1922 : #if 0
1923 : if (interactive) {
1924 : TALLOC_CTX *mem_ctx = talloc_init("end_description");
1925 : char *description = talloc_describe_all(mem_ctx);
1926 :
1927 : DEBUG(3, ("tallocs left:\n%s\n", description));
1928 : talloc_destroy(mem_ctx);
1929 : }
1930 : #endif
1931 :
1932 30 : if (is_parent) {
1933 30 : pidfile_unlink(lp_pid_directory(), "winbindd");
1934 : }
1935 :
1936 30 : exit(0);
1937 : }
1938 :
1939 0 : static void winbindd_sig_term_handler(struct tevent_context *ev,
1940 : struct tevent_signal *se,
1941 : int signum,
1942 : int count,
1943 : void *siginfo,
1944 : void *private_data)
1945 : {
1946 0 : bool *p = talloc_get_type_abort(private_data, bool);
1947 0 : bool is_parent = *p;
1948 :
1949 0 : TALLOC_FREE(p);
1950 :
1951 0 : DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
1952 : signum, is_parent));
1953 0 : winbindd_terminate(is_parent);
1954 0 : }
1955 :
1956 30 : bool winbindd_setup_sig_term_handler(bool parent)
1957 : {
1958 : struct tevent_signal *se;
1959 : bool *is_parent;
1960 :
1961 30 : is_parent = talloc(global_event_context(), bool);
1962 30 : if (!is_parent) {
1963 0 : return false;
1964 : }
1965 :
1966 30 : *is_parent = parent;
1967 :
1968 30 : se = tevent_add_signal(global_event_context(),
1969 : is_parent,
1970 : SIGTERM, 0,
1971 : winbindd_sig_term_handler,
1972 : is_parent);
1973 30 : if (!se) {
1974 0 : DEBUG(0,("failed to setup SIGTERM handler"));
1975 0 : talloc_free(is_parent);
1976 0 : return false;
1977 : }
1978 :
1979 30 : se = tevent_add_signal(global_event_context(),
1980 : is_parent,
1981 : SIGINT, 0,
1982 : winbindd_sig_term_handler,
1983 : is_parent);
1984 30 : if (!se) {
1985 0 : DEBUG(0,("failed to setup SIGINT handler"));
1986 0 : talloc_free(is_parent);
1987 0 : return false;
1988 : }
1989 :
1990 30 : se = tevent_add_signal(global_event_context(),
1991 : is_parent,
1992 : SIGQUIT, 0,
1993 : winbindd_sig_term_handler,
1994 : is_parent);
1995 30 : if (!se) {
1996 0 : DEBUG(0,("failed to setup SIGINT handler"));
1997 0 : talloc_free(is_parent);
1998 0 : return false;
1999 : }
2000 :
2001 30 : return true;
2002 : }
2003 :
2004 0 : static void flush_caches_noinit(void)
2005 : {
2006 : /*
2007 : * We need to invalidate cached user list entries on a SIGHUP
2008 : * otherwise cached access denied errors due to restrict anonymous
2009 : * hang around until the sequence number changes.
2010 : * NB
2011 : * Skip uninitialized domains when flush cache.
2012 : * If domain is not initialized, it means it is never
2013 : * used or never become online. look, wcache_invalidate_cache()
2014 : * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
2015 : * for unused domains and large traffic for primay domain's DC if there
2016 : * are many domains..
2017 : */
2018 :
2019 0 : if (!wcache_invalidate_cache_noinit()) {
2020 0 : DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
2021 0 : if (!winbindd_cache_validate_and_initialize()) {
2022 0 : exit(1);
2023 : }
2024 : }
2025 0 : }
2026 :
2027 0 : static void winbindd_sig_hup_handler(struct tevent_context *ev,
2028 : struct tevent_signal *se,
2029 : int signum,
2030 : int count,
2031 : void *siginfo,
2032 : void *private_data)
2033 : {
2034 0 : const char *file = (const char *)private_data;
2035 :
2036 0 : DEBUG(1,("Reloading services after SIGHUP\n"));
2037 0 : flush_caches_noinit();
2038 0 : winbindd_reload_services_file(file);
2039 0 : }
2040 :
2041 30 : bool winbindd_setup_sig_hup_handler(const char *lfile)
2042 : {
2043 : struct tevent_signal *se;
2044 30 : char *file = NULL;
2045 :
2046 30 : if (lfile) {
2047 0 : file = talloc_strdup(global_event_context(),
2048 : lfile);
2049 0 : if (!file) {
2050 0 : return false;
2051 : }
2052 : }
2053 :
2054 30 : se = tevent_add_signal(global_event_context(),
2055 : global_event_context(),
2056 : SIGHUP, 0,
2057 : winbindd_sig_hup_handler,
2058 : file);
2059 30 : if (!se) {
2060 0 : return false;
2061 : }
2062 :
2063 30 : return true;
2064 : }
|