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