s3:utils: Fix 'Usage:' for 'net ads enctypes'
[samba4-gss.git] / source3 / winbindd / winbindd.c
blobc7370bc859d5be306d71cc17bf923a95d5400f5c
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) by Tim Potter 2000-2002
7 Copyright (C) Andrew Tridgell 2002
8 Copyright (C) Jelmer Vernooij 2003
9 Copyright (C) Volker Lendecke 2004
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "lib/cmdline/cmdline.h"
27 #include "winbindd.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
30 #include "ntdomain.h"
31 #include "librpc/rpc/dcesrv_core.h"
32 #include "librpc/gen_ndr/ndr_lsa_scompat.h"
33 #include "librpc/gen_ndr/ndr_samr_scompat.h"
34 #include "librpc/gen_ndr/ndr_winbind_scompat.h"
35 #include "secrets.h"
36 #include "rpc_client/cli_netlogon.h"
37 #include "idmap.h"
38 #include "lib/addrchange.h"
39 #include "auth.h"
40 #include "messages.h"
41 #include "../lib/util/pidfile.h"
42 #include "util_cluster.h"
43 #include "source4/lib/messaging/irpc.h"
44 #include "source4/lib/messaging/messaging.h"
45 #include "lib/param/param.h"
46 #include "lib/async_req/async_sock.h"
47 #include "libsmb/samlogon_cache.h"
48 #include "libcli/auth/netlogon_creds_cli.h"
49 #include "passdb.h"
50 #include "lib/util/tevent_req_profile.h"
51 #include "lib/gencache.h"
52 #include "rpc_server/rpc_config.h"
53 #include "lib/global_contexts.h"
54 #include "source3/lib/substitute.h"
55 #include "winbindd_traceid.h"
56 #include "lib/util/util_process.h"
58 #undef DBGC_CLASS
59 #define DBGC_CLASS DBGC_WINBIND
61 #define SCRUB_CLIENTS_INTERVAL 5
63 static bool client_is_idle(struct winbindd_cli_state *state);
64 static void remove_client(struct winbindd_cli_state *state);
66 static bool interactive = False;
68 /* Reload configuration */
72 static void winbindd_status(void)
74 struct winbindd_cli_state *tmp;
76 DEBUG(0, ("winbindd status:\n"));
78 /* Print client state information */
80 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
82 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
83 DEBUG(2, ("\tclient list:\n"));
84 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
85 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
86 (unsigned long)tmp->pid, tmp->sock,
87 client_is_idle(tmp) ? "idle" : "active"));
93 handle stdin becoming readable when we are in --foreground mode
95 static void winbindd_stdin_handler(struct tevent_context *ev,
96 struct tevent_fd *fde,
97 uint16_t flags,
98 void *private_data)
100 char c;
101 if (read(0, &c, 1) != 1) {
102 bool *is_parent = talloc_get_type_abort(private_data, bool);
104 /* we have reached EOF on stdin, which means the
105 parent has exited. Shutdown the server */
106 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
107 (int)*is_parent));
108 winbindd_terminate(*is_parent);
112 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
114 bool *is_parent;
116 if (foreground) {
117 struct stat st;
119 is_parent = talloc(global_event_context(), bool);
120 if (!is_parent) {
121 return false;
124 *is_parent = parent;
126 /* if we are running in the foreground then look for
127 EOF on stdin, and exit if it happens. This allows
128 us to die if the parent process dies
129 Only do this on a pipe or socket, no other device.
131 if (fstat(0, &st) != 0) {
132 return false;
134 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
135 tevent_add_fd(global_event_context(),
136 is_parent,
138 TEVENT_FD_READ,
139 winbindd_stdin_handler,
140 is_parent);
144 return true;
147 static void winbindd_sig_chld_handler(struct tevent_context *ev,
148 struct tevent_signal *se,
149 int signum,
150 int count,
151 void *siginfo,
152 void *private_data)
154 pid_t pid;
156 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
157 winbind_child_died(pid);
161 static bool winbindd_setup_sig_chld_handler(void)
163 struct tevent_signal *se;
165 se = tevent_add_signal(global_event_context(),
166 global_event_context(),
167 SIGCHLD, 0,
168 winbindd_sig_chld_handler,
169 NULL);
170 if (!se) {
171 return false;
174 return true;
177 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
178 struct tevent_signal *se,
179 int signum,
180 int count,
181 void *siginfo,
182 void *private_data)
184 winbindd_status();
187 static bool winbindd_setup_sig_usr2_handler(void)
189 struct tevent_signal *se;
191 se = tevent_add_signal(global_event_context(),
192 global_event_context(),
193 SIGUSR2, 0,
194 winbindd_sig_usr2_handler,
195 NULL);
196 if (!se) {
197 return false;
200 return true;
203 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
204 static void msg_shutdown(struct messaging_context *msg,
205 void *private_data,
206 uint32_t msg_type,
207 struct server_id server_id,
208 DATA_BLOB *data)
210 /* only the parent waits for this message */
211 DEBUG(0,("Got shutdown message\n"));
212 winbindd_terminate(true);
216 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
217 void *private_data,
218 uint32_t msg_type,
219 struct server_id server_id,
220 DATA_BLOB *data)
222 uint8_t ret;
223 pid_t child_pid;
224 NTSTATUS status;
226 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
227 "message.\n"));
230 * call the validation code from a child:
231 * so we don't block the main winbindd and the validation
232 * code can safely use fork/waitpid...
234 child_pid = fork();
236 if (child_pid == -1) {
237 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
238 strerror(errno)));
239 return;
242 if (child_pid != 0) {
243 /* parent */
244 DEBUG(5, ("winbind_msg_validate_cache: child created with "
245 "pid %d.\n", (int)child_pid));
246 return;
249 /* child */
251 status = winbindd_reinit_after_fork(NULL, NULL);
252 if (!NT_STATUS_IS_OK(status)) {
253 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
254 nt_errstr(status)));
255 _exit(0);
258 /* install default SIGCHLD handler: validation code uses fork/waitpid */
259 CatchSignal(SIGCHLD, SIG_DFL);
261 process_set_title("wb: check cache", "validate cache child");
263 ret = (uint8_t)winbindd_validate_cache_nobackup();
264 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
265 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
266 (size_t)1);
267 _exit(0);
270 static struct winbindd_bool_dispatch_table {
271 enum winbindd_cmd cmd;
272 bool (*fn)(struct winbindd_cli_state *state);
273 const char *cmd_name;
274 } bool_dispatch_table[] = {
275 { WINBINDD_INTERFACE_VERSION,
276 winbindd_interface_version,
277 "INTERFACE_VERSION" },
278 { WINBINDD_INFO,
279 winbindd_info,
280 "INFO" },
281 { WINBINDD_PING,
282 winbindd_ping,
283 "PING" },
284 { WINBINDD_DOMAIN_NAME,
285 winbindd_domain_name,
286 "DOMAIN_NAME" },
287 { WINBINDD_NETBIOS_NAME,
288 winbindd_netbios_name,
289 "NETBIOS_NAME" },
290 { WINBINDD_DC_INFO,
291 winbindd_dc_info,
292 "DC_INFO" },
293 { WINBINDD_CCACHE_NTLMAUTH,
294 winbindd_ccache_ntlm_auth,
295 "NTLMAUTH" },
296 { WINBINDD_CCACHE_SAVE,
297 winbindd_ccache_save,
298 "CCACHE_SAVE" },
299 { WINBINDD_PRIV_PIPE_DIR,
300 winbindd_priv_pipe_dir,
301 "WINBINDD_PRIV_PIPE_DIR" },
302 { WINBINDD_LIST_TRUSTDOM,
303 winbindd_list_trusted_domains,
304 "LIST_TRUSTDOM" },
307 struct winbindd_async_dispatch_table {
308 enum winbindd_cmd cmd;
309 const char *cmd_name;
310 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
311 struct tevent_context *ev,
312 struct winbindd_cli_state *cli,
313 struct winbindd_request *request);
314 NTSTATUS (*recv_req)(struct tevent_req *req,
315 struct winbindd_response *presp);
318 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
319 { WINBINDD_LOOKUPSID, "LOOKUPSID",
320 winbindd_lookupsid_send, winbindd_lookupsid_recv },
321 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
322 winbindd_lookupsids_send, winbindd_lookupsids_recv },
323 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
324 winbindd_lookupname_send, winbindd_lookupname_recv },
325 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
326 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
327 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
328 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
329 { WINBINDD_GETPWSID, "GETPWSID",
330 winbindd_getpwsid_send, winbindd_getpwsid_recv },
331 { WINBINDD_GETPWNAM, "GETPWNAM",
332 winbindd_getpwnam_send, winbindd_getpwnam_recv },
333 { WINBINDD_GETPWUID, "GETPWUID",
334 winbindd_getpwuid_send, winbindd_getpwuid_recv },
335 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
336 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
337 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
338 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
339 { WINBINDD_GETGROUPS, "GETGROUPS",
340 winbindd_getgroups_send, winbindd_getgroups_recv },
341 { WINBINDD_GETGRGID, "GETGRGID",
342 winbindd_getgrgid_send, winbindd_getgrgid_recv },
343 { WINBINDD_GETGRNAM, "GETGRNAM",
344 winbindd_getgrnam_send, winbindd_getgrnam_recv },
345 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
346 winbindd_getusersids_send, winbindd_getusersids_recv },
347 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
348 winbindd_lookuprids_send, winbindd_lookuprids_recv },
349 { WINBINDD_SETPWENT, "SETPWENT",
350 winbindd_setpwent_send, winbindd_setpwent_recv },
351 { WINBINDD_GETPWENT, "GETPWENT",
352 winbindd_getpwent_send, winbindd_getpwent_recv },
353 { WINBINDD_ENDPWENT, "ENDPWENT",
354 winbindd_endpwent_send, winbindd_endpwent_recv },
355 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
356 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
357 { WINBINDD_GETDCNAME, "GETDCNAME",
358 winbindd_getdcname_send, winbindd_getdcname_recv },
359 { WINBINDD_SETGRENT, "SETGRENT",
360 winbindd_setgrent_send, winbindd_setgrent_recv },
361 { WINBINDD_GETGRENT, "GETGRENT",
362 winbindd_getgrent_send, winbindd_getgrent_recv },
363 { WINBINDD_ENDGRENT, "ENDGRENT",
364 winbindd_endgrent_send, winbindd_endgrent_recv },
365 { WINBINDD_LIST_USERS, "LIST_USERS",
366 winbindd_list_users_send, winbindd_list_users_recv },
367 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
368 winbindd_list_groups_send, winbindd_list_groups_recv },
369 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
370 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
371 { WINBINDD_PING_DC, "PING_DC",
372 winbindd_ping_dc_send, winbindd_ping_dc_recv },
373 { WINBINDD_PAM_AUTH, "PAM_AUTH",
374 winbindd_pam_auth_send, winbindd_pam_auth_recv },
375 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
376 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
377 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
378 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
379 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
380 winbindd_pam_chng_pswd_auth_crap_send,
381 winbindd_pam_chng_pswd_auth_crap_recv },
382 { WINBINDD_WINS_BYIP, "WINS_BYIP",
383 winbindd_wins_byip_send, winbindd_wins_byip_recv },
384 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
385 winbindd_wins_byname_send, winbindd_wins_byname_recv },
386 { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
387 winbindd_domain_info_send, winbindd_domain_info_recv },
389 { 0, NULL, NULL, NULL }
392 static struct winbindd_async_dispatch_table async_priv_table[] = {
393 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
394 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
395 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
396 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
397 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
398 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
399 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
400 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
402 { 0, NULL, NULL, NULL }
405 struct process_request_state {
406 struct winbindd_cli_state *cli_state;
407 struct tevent_context *ev;
410 static void process_request_done(struct tevent_req *subreq);
411 static void process_request_written(struct tevent_req *subreq);
413 static struct tevent_req *process_request_send(
414 TALLOC_CTX *mem_ctx,
415 struct tevent_context *ev,
416 struct winbindd_cli_state *cli_state)
418 struct tevent_req *req, *subreq;
419 struct process_request_state *state;
420 struct winbindd_async_dispatch_table *atable;
421 enum winbindd_cmd cmd = cli_state->request->cmd;
422 size_t i;
423 bool ok;
424 static uint64_t request_index = 1;
427 * debug traceid values:
428 * 0 .. inactive
429 * 1 .. not processing a winbind request, but in other code (timers)
430 * >=2 .. winbind request processing
432 if (debug_traceid_get() != 0) {
433 request_index = ++request_index == 0 ? 2 : request_index;
434 debug_traceid_set(request_index);
436 req = tevent_req_create(mem_ctx, &state,
437 struct process_request_state);
438 if (req == NULL) {
439 return NULL;
441 state->cli_state = cli_state;
442 state->ev = ev;
444 ok = tevent_req_set_profile(req);
445 if (!ok) {
446 return tevent_req_post(req, ev);
449 SMB_ASSERT(cli_state->mem_ctx == NULL);
450 cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
451 if (tevent_req_nomem(cli_state->mem_ctx, req)) {
452 return tevent_req_post(req, ev);
455 cli_state->response = talloc_zero(
456 cli_state->mem_ctx,
457 struct winbindd_response);
458 if (tevent_req_nomem(cli_state->response, req)) {
459 return tevent_req_post(req, ev);
461 cli_state->response->result = WINBINDD_PENDING;
462 cli_state->response->length = sizeof(struct winbindd_response);
464 /* Remember who asked us. */
465 cli_state->pid = cli_state->request->pid;
466 memcpy(cli_state->client_name,
467 cli_state->request->client_name,
468 sizeof(cli_state->client_name));
470 cli_state->cmd_name = "unknown request";
471 cli_state->recv_fn = NULL;
473 /* client is newest */
474 winbindd_promote_client(cli_state);
476 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
477 if (cmd == atable->cmd) {
478 break;
482 if ((atable->send_req == NULL) && cli_state->privileged) {
483 for (atable = async_priv_table; atable->send_req;
484 atable += 1) {
485 if (cmd == atable->cmd) {
486 break;
491 if (atable->send_req != NULL) {
492 cli_state->cmd_name = atable->cmd_name;
493 cli_state->recv_fn = atable->recv_req;
495 DBG_NOTICE("[%s (%d)] Handling async request: %s\n",
496 cli_state->client_name,
497 (int)cli_state->pid,
498 cli_state->cmd_name);
500 subreq = atable->send_req(
501 state,
502 state->ev,
503 cli_state,
504 cli_state->request);
505 if (tevent_req_nomem(subreq, req)) {
506 return tevent_req_post(req, ev);
508 tevent_req_set_callback(subreq, process_request_done, req);
509 return req;
512 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
513 if (cmd == bool_dispatch_table[i].cmd) {
514 break;
518 ok = false;
520 if (i < ARRAY_SIZE(bool_dispatch_table)) {
521 cli_state->cmd_name = bool_dispatch_table[i].cmd_name;
523 DBG_DEBUG("process_request: request fn %s\n",
524 bool_dispatch_table[i].cmd_name);
525 ok = bool_dispatch_table[i].fn(cli_state);
528 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
530 TALLOC_FREE(cli_state->io_req);
531 TALLOC_FREE(cli_state->request);
533 subreq = wb_resp_write_send(
534 state,
535 state->ev,
536 cli_state->out_queue,
537 cli_state->sock,
538 cli_state->response);
539 if (tevent_req_nomem(subreq, req)) {
540 return tevent_req_post(req, ev);
542 tevent_req_set_callback(subreq, process_request_written, req);
544 cli_state->io_req = subreq;
546 return req;
549 static void process_request_done(struct tevent_req *subreq)
551 struct tevent_req *req = tevent_req_callback_data(
552 subreq, struct tevent_req);
553 struct process_request_state *state = tevent_req_data(
554 req, struct process_request_state);
555 struct winbindd_cli_state *cli_state = state->cli_state;
556 NTSTATUS status;
557 bool ok;
559 status = cli_state->recv_fn(subreq, cli_state->response);
560 TALLOC_FREE(subreq);
562 DBG_NOTICE("[%s(%d):%s]: %s\n",
563 cli_state->client_name,
564 (int)cli_state->pid,
565 cli_state->cmd_name,
566 nt_errstr(status));
568 ok = NT_STATUS_IS_OK(status);
569 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
571 TALLOC_FREE(cli_state->io_req);
572 TALLOC_FREE(cli_state->request);
574 subreq = wb_resp_write_send(
575 state,
576 state->ev,
577 cli_state->out_queue,
578 cli_state->sock,
579 cli_state->response);
580 if (tevent_req_nomem(subreq, req)) {
581 return;
583 tevent_req_set_callback(subreq, process_request_written, req);
585 cli_state->io_req = subreq;
588 static void process_request_written(struct tevent_req *subreq)
590 struct tevent_req *req = tevent_req_callback_data(
591 subreq, struct tevent_req);
592 struct process_request_state *state = tevent_req_data(
593 req, struct process_request_state);
594 struct winbindd_cli_state *cli_state = state->cli_state;
595 ssize_t ret;
596 int err;
598 cli_state->io_req = NULL;
600 ret = wb_resp_write_recv(subreq, &err);
601 TALLOC_FREE(subreq);
602 if (ret == -1) {
603 tevent_req_nterror(req, map_nt_error_from_unix(err));
604 return;
607 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
608 cli_state->client_name,
609 (int)cli_state->pid,
610 cli_state->cmd_name);
612 TALLOC_FREE(cli_state->mem_ctx);
613 cli_state->response = NULL;
614 cli_state->cmd_name = "no request";
615 cli_state->recv_fn = NULL;
617 tevent_req_done(req);
620 static NTSTATUS process_request_recv(
621 struct tevent_req *req,
622 TALLOC_CTX *mem_ctx,
623 struct tevent_req_profile **profile)
625 NTSTATUS status;
627 if (tevent_req_is_nterror(req, &status)) {
628 tevent_req_received(req);
629 return status;
632 *profile = tevent_req_move_profile(req, mem_ctx);
633 tevent_req_received(req);
634 return NT_STATUS_OK;
638 * This is the main event loop of winbind requests. It goes through a
639 * state-machine of 3 read/write requests, 4 if you have extra data to send.
641 * An idle winbind client has a read request of 4 bytes outstanding,
642 * finalizing function is request_len_recv, checking the length. request_recv
643 * then processes the packet. The processing function then at some point has
644 * to call request_finished which schedules sending the response.
647 static void winbind_client_request_read(struct tevent_req *req);
648 static void winbind_client_activity(struct tevent_req *req);
649 static void winbind_client_processed(struct tevent_req *req);
651 /* Process a new connection by adding it to the client connection list */
653 static void new_connection(int listen_sock, bool privileged)
655 struct samba_sockaddr saddr = { .sa_socklen = 0, };
656 struct winbindd_cli_state *state;
657 struct tevent_req *req;
658 int sock;
660 /* Accept connection */
662 saddr.sa_socklen = sizeof(saddr.u.un);
663 sock = accept(listen_sock, &saddr.u.sa, &saddr.sa_socklen);
664 if (sock == -1) {
665 if (errno != EINTR) {
666 D_ERR("Failed to accept socket: %s\n", strerror(errno));
668 return;
670 smb_set_close_on_exec(sock);
672 D_INFO("Accepted client socket %d\n", sock);
674 /* Create new connection structure */
676 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
677 close(sock);
678 return;
681 state->sock = sock;
683 state->out_queue = tevent_queue_create(state, "winbind client reply");
684 if (state->out_queue == NULL) {
685 close(sock);
686 TALLOC_FREE(state);
687 return;
690 state->privileged = privileged;
692 req = wb_req_read_send(state, global_event_context(), state->sock,
693 WINBINDD_MAX_EXTRA_DATA);
694 if (req == NULL) {
695 TALLOC_FREE(state);
696 close(sock);
697 return;
699 tevent_req_set_callback(req, winbind_client_request_read, state);
700 state->io_req = req;
702 /* Add to connection list */
704 winbindd_add_client(state);
707 static void winbind_client_request_read(struct tevent_req *req)
709 struct winbindd_cli_state *state = tevent_req_callback_data(
710 req, struct winbindd_cli_state);
711 ssize_t ret;
712 int err;
714 state->io_req = NULL;
716 ret = wb_req_read_recv(req, state, &state->request, &err);
717 TALLOC_FREE(req);
718 if (ret == -1) {
719 if (err == EPIPE) {
720 DEBUG(6, ("closing socket %d, client exited\n",
721 state->sock));
722 } else {
723 DEBUG(2, ("Could not read client request from fd %d: "
724 "%s\n", state->sock, strerror(err)));
726 close(state->sock);
727 state->sock = -1;
728 remove_client(state);
729 return;
732 req = wait_for_read_send(state, global_event_context(), state->sock,
733 true);
734 if (req == NULL) {
735 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
736 " wait_for_read_send failed - removing client\n",
737 (int)state->pid, state->cmd_name));
738 remove_client(state);
739 return;
741 tevent_req_set_callback(req, winbind_client_activity, state);
742 state->io_req = req;
744 req = process_request_send(state, global_event_context(), state);
745 if (req == NULL) {
746 DBG_ERR("process_request_send failed\n");
747 remove_client(state);
748 return;
750 tevent_req_set_callback(req, winbind_client_processed, state);
753 static void winbind_client_activity(struct tevent_req *req)
755 struct winbindd_cli_state *state =
756 tevent_req_callback_data(req, struct winbindd_cli_state);
757 int err;
758 bool has_data;
760 has_data = wait_for_read_recv(req, &err);
762 if (has_data) {
763 DEBUG(0, ("winbind_client_activity[%d:%s]:"
764 "unexpected data from client - removing client\n",
765 (int)state->pid, state->cmd_name));
766 } else {
767 if (err == EPIPE) {
768 DEBUG(6, ("winbind_client_activity[%d:%s]: "
769 "client has closed connection - removing "
770 "client\n",
771 (int)state->pid, state->cmd_name));
772 } else {
773 DEBUG(2, ("winbind_client_activity[%d:%s]: "
774 "client socket error (%s) - removing "
775 "client\n",
776 (int)state->pid, state->cmd_name,
777 strerror(err)));
781 remove_client(state);
784 static void winbind_client_processed(struct tevent_req *req)
786 struct winbindd_cli_state *cli_state = tevent_req_callback_data(
787 req, struct winbindd_cli_state);
788 struct tevent_req_profile *profile = NULL;
789 struct timeval start, stop, diff;
790 int threshold;
791 NTSTATUS status;
793 status = process_request_recv(req, cli_state, &profile);
794 TALLOC_FREE(req);
795 if (!NT_STATUS_IS_OK(status)) {
796 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
797 remove_client(cli_state);
798 return;
801 tevent_req_profile_get_start(profile, NULL, &start);
802 tevent_req_profile_get_stop(profile, NULL, &stop);
803 diff = tevent_timeval_until(&start, &stop);
805 threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
807 if (diff.tv_sec >= threshold) {
808 int depth;
809 char *str;
811 depth = lp_parm_int(
813 "winbind",
814 "request profile depth",
815 INT_MAX);
817 DBG_ERR("request took %u.%.6u seconds\n",
818 (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
820 str = tevent_req_profile_string(
821 talloc_tos(), profile, 0, depth);
822 if (str != NULL) {
823 /* No "\n", already contained in "str" */
824 DEBUGADD(0, ("%s", str));
826 TALLOC_FREE(str);
829 TALLOC_FREE(profile);
831 req = wb_req_read_send(
832 cli_state,
833 global_event_context(),
834 cli_state->sock,
835 WINBINDD_MAX_EXTRA_DATA);
836 if (req == NULL) {
837 remove_client(cli_state);
838 return;
840 tevent_req_set_callback(req, winbind_client_request_read, cli_state);
841 cli_state->io_req = req;
844 /* Remove a client connection from client connection list */
846 static void remove_client(struct winbindd_cli_state *state)
848 /* It's a dead client - hold a funeral */
850 if (state == NULL) {
851 return;
855 * We need to remove a pending wb_req_read_*
856 * or wb_resp_write_* request before closing the
857 * socket.
859 * This is important as they might have used tevent_add_fd() and we
860 * use the epoll * backend on linux. So we must remove the tevent_fd
861 * before closing the fd.
863 * Otherwise we might hit a race with close_conns_after_fork() (via
864 * winbindd_reinit_after_fork()) where a file descriptor
865 * is still open in a child, which means it's still active in
866 * the parents epoll queue, but the related tevent_fd is already
867 * already gone in the parent.
869 * See bug #11141.
871 TALLOC_FREE(state->io_req);
873 if (state->sock != -1) {
874 char c = 0;
875 int nwritten;
877 /* tell client, we are closing ... */
878 nwritten = write(state->sock, &c, sizeof(c));
879 if (nwritten == -1) {
880 DEBUG(2, ("final write to client failed: %s\n",
881 strerror(errno)));
884 /* Close socket */
886 close(state->sock);
887 state->sock = -1;
890 TALLOC_FREE(state->mem_ctx);
892 /* Remove from list and free */
894 winbindd_remove_client(state);
895 TALLOC_FREE(state);
898 /* Is a client idle? */
900 static bool client_is_idle(struct winbindd_cli_state *state) {
901 return (state->request == NULL &&
902 state->response == NULL &&
903 !state->pwent_state && !state->grent_state);
906 /* Shutdown client connection which has been idle for the longest time */
908 static bool remove_idle_client(void)
910 struct winbindd_cli_state *state, *remove_state = NULL;
911 int nidle = 0;
913 for (state = winbindd_client_list(); state; state = state->next) {
914 if (client_is_idle(state)) {
915 nidle++;
916 /* list is sorted by access time */
917 remove_state = state;
921 if (remove_state) {
922 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
923 nidle, remove_state->sock, (unsigned int)remove_state->pid));
924 remove_client(remove_state);
925 return True;
928 return False;
932 * Terminate all clients whose requests have taken longer than
933 * "winbind request timeout" seconds to process, or have been
934 * idle for more than "winbind request timeout" seconds.
937 static void remove_timed_out_clients(void)
939 struct winbindd_cli_state *state, *prev = NULL;
940 time_t curr_time = time(NULL);
941 int timeout_val = lp_winbind_request_timeout();
943 for (state = winbindd_client_list_tail(); state; state = prev) {
944 time_t expiry_time;
946 prev = winbindd_client_list_prev(state);
947 expiry_time = state->last_access + timeout_val;
949 if (curr_time <= expiry_time) {
950 /* list is sorted, previous clients in
951 list are newer */
952 break;
955 if (client_is_idle(state)) {
956 DEBUG(5,("Idle client timed out, "
957 "shutting down sock %d, pid %u\n",
958 state->sock,
959 (unsigned int)state->pid));
960 } else {
961 DEBUG(5,("Client request timed out, "
962 "shutting down sock %d, pid %u\n",
963 state->sock,
964 (unsigned int)state->pid));
967 remove_client(state);
971 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
972 struct tevent_timer *te,
973 struct timeval current_time,
974 void *private_data)
976 remove_timed_out_clients();
977 if (tevent_add_timer(ev, ev,
978 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
979 winbindd_scrub_clients_handler, NULL) == NULL) {
980 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
981 exit(1);
985 struct winbindd_listen_state {
986 bool privileged;
987 int fd;
990 static void winbindd_listen_fde_handler(struct tevent_context *ev,
991 struct tevent_fd *fde,
992 uint16_t flags,
993 void *private_data)
995 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
996 struct winbindd_listen_state);
998 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
999 DEBUG(5,("winbindd: Exceeding %d client "
1000 "connections, removing idle "
1001 "connection.\n", lp_winbind_max_clients()));
1002 if (!remove_idle_client()) {
1003 DEBUG(0,("winbindd: Exceeding %d "
1004 "client connections, no idle "
1005 "connection found\n",
1006 lp_winbind_max_clients()));
1007 break;
1010 remove_timed_out_clients();
1011 new_connection(s->fd, s->privileged);
1015 * Winbindd socket accessor functions
1018 static bool winbindd_setup_listeners(void)
1020 struct winbindd_listen_state *pub_state = NULL;
1021 struct winbindd_listen_state *priv_state = NULL;
1022 struct tevent_fd *fde;
1023 int rc;
1024 char *socket_path;
1026 pub_state = talloc(global_event_context(),
1027 struct winbindd_listen_state);
1028 if (!pub_state) {
1029 goto failed;
1032 pub_state->privileged = false;
1033 pub_state->fd = create_pipe_sock(
1034 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1035 if (pub_state->fd == -1) {
1036 goto failed;
1038 rc = listen(pub_state->fd, 5);
1039 if (rc < 0) {
1040 goto failed;
1043 fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1044 TEVENT_FD_READ, winbindd_listen_fde_handler,
1045 pub_state);
1046 if (fde == NULL) {
1047 close(pub_state->fd);
1048 goto failed;
1050 tevent_fd_set_auto_close(fde);
1052 priv_state = talloc(global_event_context(),
1053 struct winbindd_listen_state);
1054 if (!priv_state) {
1055 goto failed;
1058 socket_path = get_winbind_priv_pipe_dir();
1059 if (socket_path == NULL) {
1060 goto failed;
1063 priv_state->privileged = true;
1064 priv_state->fd = create_pipe_sock(
1065 socket_path, WINBINDD_SOCKET_NAME, 0750);
1066 TALLOC_FREE(socket_path);
1067 if (priv_state->fd == -1) {
1068 goto failed;
1070 rc = listen(priv_state->fd, 5);
1071 if (rc < 0) {
1072 goto failed;
1075 fde = tevent_add_fd(global_event_context(), priv_state,
1076 priv_state->fd, TEVENT_FD_READ,
1077 winbindd_listen_fde_handler, priv_state);
1078 if (fde == NULL) {
1079 close(priv_state->fd);
1080 goto failed;
1082 tevent_fd_set_auto_close(fde);
1084 winbindd_scrub_clients_handler(global_event_context(), NULL,
1085 timeval_current(), NULL);
1086 return true;
1087 failed:
1088 TALLOC_FREE(pub_state);
1089 TALLOC_FREE(priv_state);
1090 return false;
1093 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1094 bool foreground)
1096 bool scan_trusts = true;
1097 NTSTATUS status;
1098 struct tevent_timer *te = NULL;
1100 /* Setup signal handlers */
1102 if (!winbindd_setup_sig_term_handler(true))
1103 exit(1);
1104 if (!winbindd_setup_stdin_handler(true, foreground))
1105 exit(1);
1106 if (!winbindd_setup_sig_hup_handler(NULL))
1107 exit(1);
1108 if (!winbindd_setup_sig_chld_handler())
1109 exit(1);
1110 if (!winbindd_setup_sig_usr2_handler())
1111 exit(1);
1113 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1116 * Ensure all cache and idmap caches are consistent
1117 * and initialized before we startup.
1119 if (!winbindd_cache_validate_and_initialize()) {
1120 exit(1);
1123 /* React on 'smbcontrol winbindd reload-config' in the same way
1124 as to SIGHUP signal */
1125 messaging_register(msg_ctx, NULL,
1126 MSG_SMB_CONF_UPDATED,
1127 winbindd_msg_reload_services_parent);
1128 messaging_register(msg_ctx, NULL,
1129 MSG_SHUTDOWN, msg_shutdown);
1131 /* Handle online/offline messages. */
1132 messaging_register(msg_ctx, NULL,
1133 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1134 messaging_register(msg_ctx, NULL,
1135 MSG_WINBIND_ONLINE, winbind_msg_online);
1136 messaging_register(msg_ctx, NULL,
1137 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1139 /* Handle domain online/offline messages for domains */
1140 messaging_register(global_messaging_context(), NULL,
1141 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1142 messaging_register(global_messaging_context(), NULL,
1143 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1145 messaging_register(msg_ctx, NULL,
1146 MSG_WINBIND_VALIDATE_CACHE,
1147 winbind_msg_validate_cache);
1149 messaging_register(msg_ctx, NULL,
1150 MSG_WINBIND_DUMP_DOMAIN_LIST,
1151 winbind_msg_dump_domain_list);
1153 messaging_register(msg_ctx, NULL,
1154 MSG_WINBIND_IP_DROPPED,
1155 winbind_msg_ip_dropped_parent);
1157 /* Register handler for MSG_DEBUG. */
1158 messaging_register(msg_ctx, NULL,
1159 MSG_DEBUG,
1160 winbind_msg_debug);
1162 messaging_register(msg_ctx, NULL,
1163 MSG_WINBIND_DISCONNECT_DC,
1164 winbind_disconnect_dc_parent);
1166 netsamlogon_cache_init(); /* Non-critical */
1168 /* clear the cached list of trusted domains */
1170 wcache_tdc_clear();
1172 if (!init_domain_list()) {
1173 DEBUG(0,("unable to initialize domain list\n"));
1174 exit(1);
1177 status = init_idmap_child(global_event_context());
1178 if (NT_STATUS_IS_ERR(status)) {
1179 DBG_ERR("Unable to start idmap child: %s\n", nt_errstr(status));
1180 exit(1);
1183 status = init_locator_child(global_event_context());
1184 if (NT_STATUS_IS_ERR(status)) {
1185 DBG_ERR("Unable to start locator child: %s\n", nt_errstr(status));
1186 exit(1);
1189 smb_nscd_flush_user_cache();
1190 smb_nscd_flush_group_cache();
1192 if (!lp_winbind_scan_trusted_domains()) {
1193 scan_trusts = false;
1196 if (!lp_allow_trusted_domains()) {
1197 scan_trusts = false;
1200 if (IS_DC) {
1201 scan_trusts = false;
1204 if (scan_trusts) {
1205 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1206 rescan_trusted_domains, NULL) == NULL) {
1207 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1208 exit(1);
1212 te = tevent_add_timer(global_event_context(),
1213 NULL,
1214 timeval_zero(),
1215 winbindd_ping_offline_domains,
1216 NULL);
1217 if (te == NULL) {
1218 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
1219 exit(1);
1222 status = wb_irpc_register();
1224 if (!NT_STATUS_IS_OK(status)) {
1225 DEBUG(0, ("Could not register IRPC handlers\n"));
1226 exit(1);
1230 struct winbindd_addrchanged_state {
1231 struct addrchange_context *ctx;
1232 struct tevent_context *ev;
1233 struct messaging_context *msg_ctx;
1236 static void winbindd_addr_changed(struct tevent_req *req);
1238 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1239 struct tevent_context *ev,
1240 struct messaging_context *msg_ctx)
1242 struct winbindd_addrchanged_state *state;
1243 struct tevent_req *req;
1244 NTSTATUS status;
1246 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1247 if (state == NULL) {
1248 DEBUG(10, ("talloc failed\n"));
1249 return;
1251 state->ev = ev;
1252 state->msg_ctx = msg_ctx;
1254 status = addrchange_context_create(state, &state->ctx);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 DEBUG(10, ("addrchange_context_create failed: %s\n",
1257 nt_errstr(status)));
1258 TALLOC_FREE(state);
1259 return;
1261 req = addrchange_send(state, ev, state->ctx);
1262 if (req == NULL) {
1263 DEBUG(0, ("addrchange_send failed\n"));
1264 TALLOC_FREE(state);
1265 return;
1267 tevent_req_set_callback(req, winbindd_addr_changed, state);
1270 static void winbindd_addr_changed(struct tevent_req *req)
1272 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1273 req, struct winbindd_addrchanged_state);
1274 enum addrchange_type type;
1275 struct sockaddr_storage addr;
1276 NTSTATUS status;
1278 status = addrchange_recv(req, &type, &addr, NULL);
1279 TALLOC_FREE(req);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1282 nt_errstr(status)));
1283 TALLOC_FREE(state);
1284 return;
1286 if (type == ADDRCHANGE_DEL) {
1287 char addrstr[INET6_ADDRSTRLEN];
1288 DATA_BLOB blob;
1290 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1292 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1293 addrstr));
1295 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1297 status = messaging_send(state->msg_ctx,
1298 messaging_server_id(state->msg_ctx),
1299 MSG_WINBIND_IP_DROPPED, &blob);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1302 nt_errstr(status)));
1305 req = addrchange_send(state, state->ev, state->ctx);
1306 if (req == NULL) {
1307 DEBUG(0, ("addrchange_send failed\n"));
1308 TALLOC_FREE(state);
1309 return;
1311 tevent_req_set_callback(req, winbindd_addr_changed, state);
1314 /* Main function */
1316 int main(int argc, const char **argv)
1318 static bool log_stdout = False;
1319 struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
1320 struct poptOption long_options[] = {
1321 POPT_AUTOHELP
1323 .longName = "no-caching",
1324 .shortName = 'n',
1325 .argInfo = POPT_ARG_NONE,
1326 .arg = NULL,
1327 .val = 'n',
1328 .descrip = "Disable caching",
1330 POPT_COMMON_SAMBA
1331 POPT_COMMON_DAEMON
1332 POPT_COMMON_VERSION
1333 POPT_TABLEEND
1335 const struct loadparm_substitution *lp_sub =
1336 loadparm_s3_global_substitution();
1337 poptContext pc;
1338 int opt;
1339 TALLOC_CTX *frame;
1340 NTSTATUS status;
1341 bool ok;
1342 const struct dcesrv_endpoint_server *ep_server = NULL;
1343 struct dcesrv_context *dce_ctx = NULL;
1344 size_t winbindd_socket_dir_len = 0;
1345 char *winbindd_priv_socket_dir = NULL;
1346 size_t winbindd_priv_socket_dir_len = 0;
1348 setproctitle_init(argc, discard_const(argv), environ);
1351 * Do this before any other talloc operation
1353 talloc_enable_null_tracking();
1354 frame = talloc_stackframe();
1357 * We want total control over the permissions on created files,
1358 * so set our umask to 0.
1360 umask(0);
1362 smb_init_locale();
1364 /* glibc (?) likes to print "User defined signal 1" and exit if a
1365 SIGUSR[12] is received before a handler is installed */
1367 CatchSignal(SIGUSR1, SIG_IGN);
1368 CatchSignal(SIGUSR2, SIG_IGN);
1370 ok = samba_cmdline_init(frame,
1371 SAMBA_CMDLINE_CONFIG_SERVER,
1372 true /* require_smbconf */);
1373 if (!ok) {
1374 DBG_ERR("Failed to setup cmdline parser\n");
1375 TALLOC_FREE(frame);
1376 exit(1);
1379 cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
1381 pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
1382 if (pc == NULL) {
1383 DBG_ERR("Failed to setup popt parser!\n");
1384 TALLOC_FREE(frame);
1385 exit(1);
1388 while ((opt = poptGetNextOpt(pc)) != -1) {
1389 switch (opt) {
1390 case 'n':
1391 winbindd_set_use_cache(false);
1392 break;
1393 default:
1394 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1395 poptBadOption(pc, 0), poptStrerror(opt));
1396 poptPrintUsage(pc, stderr, 0);
1397 exit(1);
1401 /* Set environment variable so we don't recursively call ourselves.
1402 This may also be useful interactively. */
1403 if ( !winbind_off() ) {
1404 DEBUG(0,("Failed to disable recursive winbindd calls. Exiting.\n"));
1405 exit(1);
1408 /* Initialise for running in non-root mode */
1409 sec_init();
1411 set_remote_machine_name("winbindd", False);
1413 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1414 if (cmdline_daemon_cfg->daemon && cmdline_daemon_cfg->interactive) {
1415 d_fprintf(stderr,"\nERROR: "
1416 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1417 poptPrintUsage(pc, stderr, 0);
1418 exit(1);
1421 log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
1422 if (cmdline_daemon_cfg->interactive) {
1424 * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
1425 * for interactive is passed on the commandline. Set it back to
1426 * true. TODO: check if this is correct, smbd and nmbd don't do
1427 * this.
1429 cmdline_daemon_cfg->fork = true;
1430 log_stdout = true;
1433 if (log_stdout && cmdline_daemon_cfg->fork) {
1434 d_fprintf(stderr, "\nERROR: "
1435 "Can't log to stdout (-S) unless daemon is in "
1436 "foreground (-F) or interactive (-i)\n\n");
1437 poptPrintUsage(pc, stderr, 0);
1438 exit(1);
1441 poptFreeContext(pc);
1443 reopen_logs();
1445 DBG_STARTUP_NOTICE("winbindd version %s started.\n%s\n",
1446 samba_version_string(),
1447 samba_copyright_string());
1449 /* After parsing the configuration file we setup the core path one more time
1450 * as the log file might have been set in the configuration and cores's
1451 * path is by default basename(lp_logfile()).
1453 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1455 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1456 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1457 DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1458 DEBUGADD(0, ("You should start 'samba' instead, and it will control starting the internal AD DC winbindd implementation, which is not the same as this one\n"));
1459 exit(1);
1461 /* Main 'samba' daemon will notify */
1462 daemon_sd_notifications(false);
1465 if (lp_security() == SEC_ADS) {
1466 const char *realm = lp_realm();
1467 const char *workgroup = lp_workgroup();
1469 if (workgroup == NULL || strlen(workgroup) == 0) {
1470 DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
1471 "parameter is required to be set!\n");
1472 exit(1);
1475 if (realm == NULL || strlen(realm) == 0) {
1476 DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
1477 "parameter is required to be set!\n");
1478 exit(1);
1482 winbindd_socket_dir_len = strlen(lp_winbindd_socket_directory());
1483 if (winbindd_socket_dir_len > 0) {
1484 size_t winbindd_socket_len =
1485 winbindd_socket_dir_len + 1 +
1486 strlen(WINBINDD_SOCKET_NAME);
1487 struct sockaddr_un un = {
1488 .sun_family = AF_UNIX,
1490 size_t sun_path_len = sizeof(un.sun_path);
1492 if (winbindd_socket_len >= sun_path_len) {
1493 DBG_ERR("The winbind socket path [%s/%s] is too long "
1494 "(%zu >= %zu)\n",
1495 lp_winbindd_socket_directory(),
1496 WINBINDD_SOCKET_NAME,
1497 winbindd_socket_len,
1498 sun_path_len);
1499 exit(1);
1501 } else {
1502 DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
1503 exit(1);
1506 winbindd_priv_socket_dir = get_winbind_priv_pipe_dir();
1507 winbindd_priv_socket_dir_len = strlen(winbindd_priv_socket_dir);
1508 if (winbindd_priv_socket_dir_len > 0) {
1509 size_t winbindd_priv_socket_len =
1510 winbindd_priv_socket_dir_len + 1 +
1511 strlen(WINBINDD_SOCKET_NAME);
1512 struct sockaddr_un un = {
1513 .sun_family = AF_UNIX,
1515 size_t sun_path_len = sizeof(un.sun_path);
1517 if (winbindd_priv_socket_len >= sun_path_len) {
1518 DBG_ERR("The winbind privileged socket path [%s/%s] is too long "
1519 "(%zu >= %zu)\n",
1520 winbindd_priv_socket_dir,
1521 WINBINDD_SOCKET_NAME,
1522 winbindd_priv_socket_len,
1523 sun_path_len);
1524 exit(1);
1526 } else {
1527 DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
1528 exit(1);
1530 TALLOC_FREE(winbindd_priv_socket_dir);
1532 if (!cluster_probe_ok()) {
1533 exit(1);
1536 /* Initialise messaging system */
1538 if (global_messaging_context() == NULL) {
1539 exit(1);
1542 if (!winbindd_reload_services_file(NULL)) {
1543 DEBUG(0, ("error opening config file\n"));
1544 exit(1);
1548 size_t i;
1549 const char *idmap_backend;
1550 const char *invalid_backends[] = {
1551 "ad", "rfc2307", "rid",
1554 idmap_backend = lp_idmap_default_backend();
1555 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1556 ok = strequal(idmap_backend, invalid_backends[i]);
1557 if (ok) {
1558 DBG_ERR("FATAL: Invalid idmap backend %s "
1559 "configured as the default backend!\n",
1560 idmap_backend);
1561 exit(1);
1566 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1567 if (!ok) {
1568 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1569 lp_lock_directory(), strerror(errno)));
1570 exit(1);
1573 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1574 if (!ok) {
1575 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1576 lp_pid_directory(), strerror(errno)));
1577 exit(1);
1580 load_interfaces();
1582 if (!secrets_init()) {
1584 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1585 return False;
1588 status = rpccli_pre_open_netlogon_creds();
1589 if (!NT_STATUS_IS_OK(status)) {
1590 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1591 nt_errstr(status)));
1592 exit(1);
1595 /* Unblock all signals we are interested in as they may have been
1596 blocked by the parent process. */
1598 BlockSignals(False, SIGINT);
1599 BlockSignals(False, SIGQUIT);
1600 BlockSignals(False, SIGTERM);
1601 BlockSignals(False, SIGUSR1);
1602 BlockSignals(False, SIGUSR2);
1603 BlockSignals(False, SIGHUP);
1604 BlockSignals(False, SIGCHLD);
1606 if (!interactive) {
1607 become_daemon(cmdline_daemon_cfg->fork,
1608 cmdline_daemon_cfg->no_process_group,
1609 log_stdout);
1610 } else {
1611 daemon_status("winbindd", "Starting process ...");
1614 pidfile_create(lp_pid_directory(), "winbindd");
1616 #ifdef HAVE_SETPGID
1618 * If we're interactive we want to set our own process group for
1619 * signal management.
1621 if (cmdline_daemon_cfg->interactive &&
1622 !cmdline_daemon_cfg->no_process_group)
1624 setpgid( (pid_t)0, (pid_t)0);
1626 #endif
1628 TimeInit();
1630 /* Don't use winbindd_reinit_after_fork here as
1631 * we're just starting up and haven't created any
1632 * winbindd-specific resources we must free yet. JRA.
1635 status = reinit_after_fork(global_messaging_context(),
1636 global_event_context(),
1637 false);
1638 if (!NT_STATUS_IS_OK(status)) {
1639 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1642 if (lp_winbind_debug_traceid()) {
1643 winbind_debug_traceid_setup(global_event_context());
1644 winbind_debug_call_depth_setup(debug_call_depth_addr());
1645 tevent_thread_call_depth_set_callback(
1646 debuglevel_get() > 1 ? winbind_call_flow : NULL,
1647 NULL);
1649 ok = initialize_password_db(true, global_event_context());
1650 if (!ok) {
1651 exit_daemon("Failed to initialize passdb backend! "
1652 "Check the 'passdb backend' variable in your "
1653 "smb.conf file.", EINVAL);
1657 * Do not initialize the parent-child-pipe before becoming
1658 * a daemon: this is used to detect a died parent in the child
1659 * process.
1661 status = init_before_fork();
1662 if (!NT_STATUS_IS_OK(status)) {
1663 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1666 winbindd_register_handlers(global_messaging_context(),
1667 !cmdline_daemon_cfg->fork);
1669 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1670 exit(1);
1673 status = init_system_session_info(NULL);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1678 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1680 ep_server = winbind_get_ep_server();
1681 if (ep_server == NULL) {
1682 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1683 exit(1);
1685 status = dcerpc_register_ep_server(ep_server);
1686 if (!NT_STATUS_IS_OK(status)) {
1687 DBG_ERR("Failed to register 'winbind' endpoint "
1688 "server: %s\n", nt_errstr(status));
1689 exit(1);
1692 dce_ctx = global_dcesrv_context();
1694 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1696 /* Init all registered ep servers */
1697 status = dcesrv_init_registered_ep_servers(dce_ctx);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1700 nt_errstr(status));
1701 exit(1);
1704 winbindd_init_addrchange(NULL, global_event_context(),
1705 global_messaging_context());
1707 /* setup listen sockets */
1709 if (!winbindd_setup_listeners()) {
1710 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1713 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1715 TALLOC_FREE(frame);
1717 if (!interactive) {
1718 daemon_ready("winbindd");
1721 gpupdate_init();
1723 /* Loop waiting for requests */
1724 while (1) {
1725 frame = talloc_stackframe();
1727 if (tevent_loop_once(global_event_context()) == -1) {
1728 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1729 strerror(errno)));
1730 return 1;
1733 TALLOC_FREE(frame);
1736 return 0;