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