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