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/>.
26 #include "popt_common.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
31 #include "../librpc/gen_ndr/srv_lsa.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
34 #include "rpc_client/cli_netlogon.h"
36 #include "lib/addrchange.h"
39 #include "../lib/util/pidfile.h"
40 #include "util_cluster.h"
41 #include "source4/lib/messaging/irpc.h"
42 #include "source4/lib/messaging/messaging.h"
43 #include "lib/param/param.h"
44 #include "lib/async_req/async_sock.h"
45 #include "libsmb/samlogon_cache.h"
46 #include "libcli/auth/netlogon_creds_cli.h"
48 #include "lib/util/tevent_req_profile.h"
49 #include "lib/gencache.h"
52 #define DBGC_CLASS DBGC_WINBIND
54 #define SCRUB_CLIENTS_INTERVAL 5
56 static bool client_is_idle(struct winbindd_cli_state *state);
57 static void remove_client(struct winbindd_cli_state *state);
58 static void winbindd_setup_max_fds(void);
60 static bool opt_nocache = False;
61 static bool interactive = False;
63 extern bool override_logfile;
65 struct imessaging_context *winbind_imessaging_context(void)
67 static struct imessaging_context *msg = NULL;
68 struct messaging_context *msg_ctx;
69 struct server_id myself;
70 struct loadparm_context *lp_ctx;
76 msg_ctx = global_messaging_context();
77 if (msg_ctx == NULL) {
78 smb_panic("global_messaging_context failed\n");
80 myself = messaging_server_id(msg_ctx);
82 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
84 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
88 * Note we MUST use the NULL context here, not the autofree context,
89 * to avoid side effects in forked children exiting.
91 msg = imessaging_init(NULL, lp_ctx, myself, global_event_context());
92 talloc_unlink(NULL, lp_ctx);
95 smb_panic("Could not init winbindd's messaging context.\n");
100 /* Reload configuration */
102 static bool reload_services_file(const char *lfile)
107 char *fname = lp_next_configfile(talloc_tos());
109 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
110 set_dyn_CONFIGFILE(fname);
115 /* if this is a child, restore the logfile to the special
116 name - <domain>, idmap, etc. */
117 if (lfile && *lfile) {
118 lp_set_logfile(lfile);
122 ret = lp_load_global(get_dyn_CONFIGFILE());
126 winbindd_setup_max_fds();
132 static void winbindd_status(void)
134 struct winbindd_cli_state *tmp;
136 DEBUG(0, ("winbindd status:\n"));
138 /* Print client state information */
140 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
142 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
143 DEBUG(2, ("\tclient list:\n"));
144 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
145 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
146 (unsigned long)tmp->pid, tmp->sock,
147 client_is_idle(tmp) ? "idle" : "active"));
152 /* Flush client cache */
154 static void flush_caches(void)
156 /* We need to invalidate cached user list entries on a SIGHUP
157 otherwise cached access denied errors due to restrict anonymous
158 hang around until the sequence number changes. */
160 if (!wcache_invalidate_cache()) {
161 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
162 if (!winbindd_cache_validate_and_initialize()) {
168 static void flush_caches_noinit(void)
171 * We need to invalidate cached user list entries on a SIGHUP
172 * otherwise cached access denied errors due to restrict anonymous
173 * hang around until the sequence number changes.
175 * Skip uninitialized domains when flush cache.
176 * If domain is not initialized, it means it is never
177 * used or never become online. look, wcache_invalidate_cache()
178 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
179 * for unused domains and large traffic for primay domain's DC if there
183 if (!wcache_invalidate_cache_noinit()) {
184 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
185 if (!winbindd_cache_validate_and_initialize()) {
191 /* Handle the signal by unlinking socket and exiting */
193 static void terminate(bool is_parent)
196 /* When parent goes away we should
197 * remove the socket file. Not so
198 * when children terminate.
202 if (asprintf(&path, "%s/%s",
203 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
211 netlogon_creds_cli_close_global_db();
215 TALLOC_CTX *mem_ctx = talloc_init("end_description");
216 char *description = talloc_describe_all(mem_ctx);
218 DEBUG(3, ("tallocs left:\n%s\n", description));
219 talloc_destroy(mem_ctx);
224 pidfile_unlink(lp_pid_directory(), "winbindd");
230 static void winbindd_sig_term_handler(struct tevent_context *ev,
231 struct tevent_signal *se,
237 bool *p = talloc_get_type_abort(private_data, bool);
242 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
244 terminate(is_parent);
248 handle stdin becoming readable when we are in --foreground mode
250 static void winbindd_stdin_handler(struct tevent_context *ev,
251 struct tevent_fd *fde,
256 if (read(0, &c, 1) != 1) {
257 bool *is_parent = talloc_get_type_abort(private_data, bool);
259 /* we have reached EOF on stdin, which means the
260 parent has exited. Shutdown the server */
261 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
263 terminate(*is_parent);
267 bool winbindd_setup_sig_term_handler(bool parent)
269 struct tevent_signal *se;
272 is_parent = talloc(global_event_context(), bool);
279 se = tevent_add_signal(global_event_context(),
282 winbindd_sig_term_handler,
285 DEBUG(0,("failed to setup SIGTERM handler"));
286 talloc_free(is_parent);
290 se = tevent_add_signal(global_event_context(),
293 winbindd_sig_term_handler,
296 DEBUG(0,("failed to setup SIGINT handler"));
297 talloc_free(is_parent);
301 se = tevent_add_signal(global_event_context(),
304 winbindd_sig_term_handler,
307 DEBUG(0,("failed to setup SIGINT handler"));
308 talloc_free(is_parent);
315 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
322 is_parent = talloc(global_event_context(), bool);
329 /* if we are running in the foreground then look for
330 EOF on stdin, and exit if it happens. This allows
331 us to die if the parent process dies
332 Only do this on a pipe or socket, no other device.
334 if (fstat(0, &st) != 0) {
337 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
338 tevent_add_fd(global_event_context(),
342 winbindd_stdin_handler,
350 static void winbindd_sig_hup_handler(struct tevent_context *ev,
351 struct tevent_signal *se,
357 const char *file = (const char *)private_data;
359 DEBUG(1,("Reloading services after SIGHUP\n"));
360 flush_caches_noinit();
361 reload_services_file(file);
364 bool winbindd_setup_sig_hup_handler(const char *lfile)
366 struct tevent_signal *se;
370 file = talloc_strdup(global_event_context(),
377 se = tevent_add_signal(global_event_context(),
378 global_event_context(),
380 winbindd_sig_hup_handler,
389 static void winbindd_sig_chld_handler(struct tevent_context *ev,
390 struct tevent_signal *se,
398 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
399 winbind_child_died(pid);
403 static bool winbindd_setup_sig_chld_handler(void)
405 struct tevent_signal *se;
407 se = tevent_add_signal(global_event_context(),
408 global_event_context(),
410 winbindd_sig_chld_handler,
419 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
420 struct tevent_signal *se,
429 static bool winbindd_setup_sig_usr2_handler(void)
431 struct tevent_signal *se;
433 se = tevent_add_signal(global_event_context(),
434 global_event_context(),
436 winbindd_sig_usr2_handler,
445 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
446 static void msg_reload_services(struct messaging_context *msg,
449 struct server_id server_id,
452 /* Flush various caches */
454 reload_services_file((const char *) private_data);
457 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
458 static void msg_shutdown(struct messaging_context *msg,
461 struct server_id server_id,
464 /* only the parent waits for this message */
465 DEBUG(0,("Got shutdown message\n"));
470 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
473 struct server_id server_id,
480 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
484 * call the validation code from a child:
485 * so we don't block the main winbindd and the validation
486 * code can safely use fork/waitpid...
490 if (child_pid == -1) {
491 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
496 if (child_pid != 0) {
498 DEBUG(5, ("winbind_msg_validate_cache: child created with "
499 "pid %d.\n", (int)child_pid));
505 status = winbindd_reinit_after_fork(NULL, NULL);
506 if (!NT_STATUS_IS_OK(status)) {
507 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
512 /* install default SIGCHLD handler: validation code uses fork/waitpid */
513 CatchSignal(SIGCHLD, SIG_DFL);
515 setproctitle("validate cache child");
517 ret = (uint8_t)winbindd_validate_cache_nobackup();
518 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
519 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
524 static struct winbindd_bool_dispatch_table {
525 enum winbindd_cmd cmd;
526 bool (*fn)(struct winbindd_cli_state *state);
527 const char *cmd_name;
528 } bool_dispatch_table[] = {
529 { WINBINDD_INTERFACE_VERSION,
530 winbindd_interface_version,
531 "INTERFACE_VERSION" },
538 { WINBINDD_DOMAIN_NAME,
539 winbindd_domain_name,
541 { WINBINDD_NETBIOS_NAME,
542 winbindd_netbios_name,
547 { WINBINDD_CCACHE_NTLMAUTH,
548 winbindd_ccache_ntlm_auth,
550 { WINBINDD_CCACHE_SAVE,
551 winbindd_ccache_save,
553 { WINBINDD_PRIV_PIPE_DIR,
554 winbindd_priv_pipe_dir,
555 "WINBINDD_PRIV_PIPE_DIR" },
556 { WINBINDD_LIST_TRUSTDOM,
557 winbindd_list_trusted_domains,
561 struct winbindd_async_dispatch_table {
562 enum winbindd_cmd cmd;
563 const char *cmd_name;
564 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
565 struct tevent_context *ev,
566 struct winbindd_cli_state *cli,
567 struct winbindd_request *request);
568 NTSTATUS (*recv_req)(struct tevent_req *req,
569 struct winbindd_response *presp);
572 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
573 { WINBINDD_LOOKUPSID, "LOOKUPSID",
574 winbindd_lookupsid_send, winbindd_lookupsid_recv },
575 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
576 winbindd_lookupsids_send, winbindd_lookupsids_recv },
577 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
578 winbindd_lookupname_send, winbindd_lookupname_recv },
579 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
580 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
581 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
582 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
583 { WINBINDD_GETPWSID, "GETPWSID",
584 winbindd_getpwsid_send, winbindd_getpwsid_recv },
585 { WINBINDD_GETPWNAM, "GETPWNAM",
586 winbindd_getpwnam_send, winbindd_getpwnam_recv },
587 { WINBINDD_GETPWUID, "GETPWUID",
588 winbindd_getpwuid_send, winbindd_getpwuid_recv },
589 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
590 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
591 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
592 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
593 { WINBINDD_GETGROUPS, "GETGROUPS",
594 winbindd_getgroups_send, winbindd_getgroups_recv },
595 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
596 winbindd_show_sequence_send, winbindd_show_sequence_recv },
597 { WINBINDD_GETGRGID, "GETGRGID",
598 winbindd_getgrgid_send, winbindd_getgrgid_recv },
599 { WINBINDD_GETGRNAM, "GETGRNAM",
600 winbindd_getgrnam_send, winbindd_getgrnam_recv },
601 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
602 winbindd_getusersids_send, winbindd_getusersids_recv },
603 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
604 winbindd_lookuprids_send, winbindd_lookuprids_recv },
605 { WINBINDD_SETPWENT, "SETPWENT",
606 winbindd_setpwent_send, winbindd_setpwent_recv },
607 { WINBINDD_GETPWENT, "GETPWENT",
608 winbindd_getpwent_send, winbindd_getpwent_recv },
609 { WINBINDD_ENDPWENT, "ENDPWENT",
610 winbindd_endpwent_send, winbindd_endpwent_recv },
611 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
612 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
613 { WINBINDD_GETDCNAME, "GETDCNAME",
614 winbindd_getdcname_send, winbindd_getdcname_recv },
615 { WINBINDD_SETGRENT, "SETGRENT",
616 winbindd_setgrent_send, winbindd_setgrent_recv },
617 { WINBINDD_GETGRENT, "GETGRENT",
618 winbindd_getgrent_send, winbindd_getgrent_recv },
619 { WINBINDD_ENDGRENT, "ENDGRENT",
620 winbindd_endgrent_send, winbindd_endgrent_recv },
621 { WINBINDD_LIST_USERS, "LIST_USERS",
622 winbindd_list_users_send, winbindd_list_users_recv },
623 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
624 winbindd_list_groups_send, winbindd_list_groups_recv },
625 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
626 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
627 { WINBINDD_PING_DC, "PING_DC",
628 winbindd_ping_dc_send, winbindd_ping_dc_recv },
629 { WINBINDD_PAM_AUTH, "PAM_AUTH",
630 winbindd_pam_auth_send, winbindd_pam_auth_recv },
631 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
632 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
633 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
634 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
635 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
636 winbindd_pam_chng_pswd_auth_crap_send,
637 winbindd_pam_chng_pswd_auth_crap_recv },
638 { WINBINDD_WINS_BYIP, "WINS_BYIP",
639 winbindd_wins_byip_send, winbindd_wins_byip_recv },
640 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
641 winbindd_wins_byname_send, winbindd_wins_byname_recv },
642 { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
643 winbindd_domain_info_send, winbindd_domain_info_recv },
645 { 0, NULL, NULL, NULL }
648 static struct winbindd_async_dispatch_table async_priv_table[] = {
649 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
650 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
651 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
652 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
653 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
654 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
655 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
656 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
658 { 0, NULL, NULL, NULL }
661 struct process_request_state {
662 struct winbindd_cli_state *cli_state;
663 struct tevent_context *ev;
666 static void process_request_done(struct tevent_req *subreq);
667 static void process_request_written(struct tevent_req *subreq);
669 static struct tevent_req *process_request_send(
671 struct tevent_context *ev,
672 struct winbindd_cli_state *cli_state)
674 struct tevent_req *req, *subreq;
675 struct process_request_state *state;
676 struct winbindd_async_dispatch_table *atable;
677 enum winbindd_cmd cmd = cli_state->request->cmd;
681 req = tevent_req_create(mem_ctx, &state,
682 struct process_request_state);
686 state->cli_state = cli_state;
689 ok = tevent_req_set_profile(req);
691 return tevent_req_post(req, ev);
694 SMB_ASSERT(cli_state->mem_ctx == NULL);
695 cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
696 if (tevent_req_nomem(cli_state->mem_ctx, req)) {
697 return tevent_req_post(req, ev);
700 cli_state->response = talloc_zero(
702 struct winbindd_response);
703 if (tevent_req_nomem(cli_state->response, req)) {
704 return tevent_req_post(req, ev);
706 cli_state->response->result = WINBINDD_PENDING;
707 cli_state->response->length = sizeof(struct winbindd_response);
709 /* Remember who asked us. */
710 cli_state->pid = cli_state->request->pid;
711 memcpy(cli_state->client_name,
712 cli_state->request->client_name,
713 sizeof(cli_state->client_name));
715 cli_state->cmd_name = "unknown request";
716 cli_state->recv_fn = NULL;
718 /* client is newest */
719 winbindd_promote_client(cli_state);
721 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
722 if (cmd == atable->cmd) {
727 if ((atable->send_req == NULL) && cli_state->privileged) {
728 for (atable = async_priv_table; atable->send_req;
730 if (cmd == atable->cmd) {
736 if (atable->send_req != NULL) {
737 cli_state->cmd_name = atable->cmd_name;
738 cli_state->recv_fn = atable->recv_req;
740 DBG_DEBUG("process_request: "
741 "Handling async request %s(%d):%s\n",
742 cli_state->client_name,
744 cli_state->cmd_name);
746 subreq = atable->send_req(
751 if (tevent_req_nomem(subreq, req)) {
752 return tevent_req_post(req, ev);
754 tevent_req_set_callback(subreq, process_request_done, req);
758 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
759 if (cmd == bool_dispatch_table[i].cmd) {
766 if (i < ARRAY_SIZE(bool_dispatch_table)) {
767 DBG_DEBUG("process_request: request fn %s\n",
768 bool_dispatch_table[i].cmd_name);
769 ok = bool_dispatch_table[i].fn(cli_state);
772 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
774 TALLOC_FREE(cli_state->io_req);
775 TALLOC_FREE(cli_state->request);
777 subreq = wb_resp_write_send(
780 cli_state->out_queue,
782 cli_state->response);
783 if (tevent_req_nomem(subreq, req)) {
784 return tevent_req_post(req, ev);
786 tevent_req_set_callback(subreq, process_request_written, req);
788 cli_state->io_req = subreq;
793 static void process_request_done(struct tevent_req *subreq)
795 struct tevent_req *req = tevent_req_callback_data(
796 subreq, struct tevent_req);
797 struct process_request_state *state = tevent_req_data(
798 req, struct process_request_state);
799 struct winbindd_cli_state *cli_state = state->cli_state;
803 status = cli_state->recv_fn(subreq, cli_state->response);
806 DBG_DEBUG("[%s(%d):%s]: %s\n",
807 cli_state->client_name,
812 ok = NT_STATUS_IS_OK(status);
813 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
815 TALLOC_FREE(cli_state->io_req);
816 TALLOC_FREE(cli_state->request);
818 subreq = wb_resp_write_send(
821 cli_state->out_queue,
823 cli_state->response);
824 if (tevent_req_nomem(subreq, req)) {
827 tevent_req_set_callback(subreq, process_request_written, req);
829 cli_state->io_req = subreq;
832 static void process_request_written(struct tevent_req *subreq)
834 struct tevent_req *req = tevent_req_callback_data(
835 subreq, struct tevent_req);
836 struct process_request_state *state = tevent_req_data(
837 req, struct process_request_state);
838 struct winbindd_cli_state *cli_state = state->cli_state;
842 cli_state->io_req = NULL;
844 ret = wb_resp_write_recv(subreq, &err);
847 tevent_req_nterror(req, map_nt_error_from_unix(err));
851 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
852 cli_state->client_name,
854 cli_state->cmd_name);
856 TALLOC_FREE(cli_state->mem_ctx);
857 cli_state->response = NULL;
858 cli_state->cmd_name = "no request";
859 cli_state->recv_fn = NULL;
861 tevent_req_done(req);
864 static NTSTATUS process_request_recv(
865 struct tevent_req *req,
867 struct tevent_req_profile **profile)
871 if (tevent_req_is_nterror(req, &status)) {
872 tevent_req_received(req);
876 *profile = tevent_req_move_profile(req, mem_ctx);
877 tevent_req_received(req);
882 * This is the main event loop of winbind requests. It goes through a
883 * state-machine of 3 read/write requests, 4 if you have extra data to send.
885 * An idle winbind client has a read request of 4 bytes outstanding,
886 * finalizing function is request_len_recv, checking the length. request_recv
887 * then processes the packet. The processing function then at some point has
888 * to call request_finished which schedules sending the response.
891 static void winbind_client_request_read(struct tevent_req *req);
892 static void winbind_client_activity(struct tevent_req *req);
893 static void winbind_client_processed(struct tevent_req *req);
895 /* Process a new connection by adding it to the client connection list */
897 static void new_connection(int listen_sock, bool privileged)
899 struct sockaddr_un sunaddr;
900 struct winbindd_cli_state *state;
901 struct tevent_req *req;
905 /* Accept connection */
907 len = sizeof(sunaddr);
909 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
912 if (errno != EINTR) {
913 DEBUG(0, ("Failed to accept socket - %s\n",
918 smb_set_close_on_exec(sock);
920 DEBUG(6,("accepted socket %d\n", sock));
922 /* Create new connection structure */
924 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
931 state->out_queue = tevent_queue_create(state, "winbind client reply");
932 if (state->out_queue == NULL) {
938 state->privileged = privileged;
940 req = wb_req_read_send(state, global_event_context(), state->sock,
941 WINBINDD_MAX_EXTRA_DATA);
947 tevent_req_set_callback(req, winbind_client_request_read, state);
950 /* Add to connection list */
952 winbindd_add_client(state);
955 static void winbind_client_request_read(struct tevent_req *req)
957 struct winbindd_cli_state *state = tevent_req_callback_data(
958 req, struct winbindd_cli_state);
962 state->io_req = NULL;
964 ret = wb_req_read_recv(req, state, &state->request, &err);
968 DEBUG(6, ("closing socket %d, client exited\n",
971 DEBUG(2, ("Could not read client request from fd %d: "
972 "%s\n", state->sock, strerror(err)));
976 remove_client(state);
980 req = wait_for_read_send(state, global_event_context(), state->sock,
983 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
984 " wait_for_read_send failed - removing client\n",
985 (int)state->pid, state->cmd_name));
986 remove_client(state);
989 tevent_req_set_callback(req, winbind_client_activity, state);
992 req = process_request_send(state, global_event_context(), state);
994 DBG_ERR("process_request_send failed\n");
995 remove_client(state);
998 tevent_req_set_callback(req, winbind_client_processed, state);
1001 static void winbind_client_activity(struct tevent_req *req)
1003 struct winbindd_cli_state *state =
1004 tevent_req_callback_data(req, struct winbindd_cli_state);
1008 has_data = wait_for_read_recv(req, &err);
1011 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1012 "unexpected data from client - removing client\n",
1013 (int)state->pid, state->cmd_name));
1016 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1017 "client has closed connection - removing "
1019 (int)state->pid, state->cmd_name));
1021 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1022 "client socket error (%s) - removing "
1024 (int)state->pid, state->cmd_name,
1029 remove_client(state);
1032 static void winbind_client_processed(struct tevent_req *req)
1034 struct winbindd_cli_state *cli_state = tevent_req_callback_data(
1035 req, struct winbindd_cli_state);
1036 struct tevent_req_profile *profile = NULL;
1037 struct timeval start, stop, diff;
1041 status = process_request_recv(req, cli_state, &profile);
1043 if (!NT_STATUS_IS_OK(status)) {
1044 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
1045 remove_client(cli_state);
1049 tevent_req_profile_get_start(profile, NULL, &start);
1050 tevent_req_profile_get_stop(profile, NULL, &stop);
1051 diff = tevent_timeval_until(&start, &stop);
1053 threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
1055 if (diff.tv_sec >= threshold) {
1059 depth = lp_parm_int(
1062 "request profile depth",
1065 DBG_ERR("request took %u.%.6u seconds\n",
1066 (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
1068 str = tevent_req_profile_string(
1069 talloc_tos(), profile, 0, depth);
1071 /* No "\n", already contained in "str" */
1072 DEBUGADD(0, ("%s", str));
1077 TALLOC_FREE(profile);
1079 req = wb_req_read_send(
1081 global_event_context(),
1083 WINBINDD_MAX_EXTRA_DATA);
1085 remove_client(cli_state);
1088 tevent_req_set_callback(req, winbind_client_request_read, cli_state);
1089 cli_state->io_req = req;
1092 /* Remove a client connection from client connection list */
1094 static void remove_client(struct winbindd_cli_state *state)
1096 /* It's a dead client - hold a funeral */
1098 if (state == NULL) {
1103 * We need to remove a pending wb_req_read_*
1104 * or wb_resp_write_* request before closing the
1107 * This is important as they might have used tevent_add_fd() and we
1108 * use the epoll * backend on linux. So we must remove the tevent_fd
1109 * before closing the fd.
1111 * Otherwise we might hit a race with close_conns_after_fork() (via
1112 * winbindd_reinit_after_fork()) where a file descriptor
1113 * is still open in a child, which means it's still active in
1114 * the parents epoll queue, but the related tevent_fd is already
1115 * already gone in the parent.
1119 TALLOC_FREE(state->io_req);
1121 if (state->sock != -1) {
1125 /* tell client, we are closing ... */
1126 nwritten = write(state->sock, &c, sizeof(c));
1127 if (nwritten == -1) {
1128 DEBUG(2, ("final write to client failed: %s\n",
1138 TALLOC_FREE(state->mem_ctx);
1140 /* Remove from list and free */
1142 winbindd_remove_client(state);
1146 /* Is a client idle? */
1148 static bool client_is_idle(struct winbindd_cli_state *state) {
1149 return (state->request == NULL &&
1150 state->response == NULL &&
1151 !state->pwent_state && !state->grent_state);
1154 /* Shutdown client connection which has been idle for the longest time */
1156 static bool remove_idle_client(void)
1158 struct winbindd_cli_state *state, *remove_state = NULL;
1161 for (state = winbindd_client_list(); state; state = state->next) {
1162 if (client_is_idle(state)) {
1164 /* list is sorted by access time */
1165 remove_state = state;
1170 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1171 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1172 remove_client(remove_state);
1180 * Terminate all clients whose requests have taken longer than
1181 * "winbind request timeout" seconds to process, or have been
1182 * idle for more than "winbind request timeout" seconds.
1185 static void remove_timed_out_clients(void)
1187 struct winbindd_cli_state *state, *prev = NULL;
1188 time_t curr_time = time(NULL);
1189 int timeout_val = lp_winbind_request_timeout();
1191 for (state = winbindd_client_list_tail(); state; state = prev) {
1194 prev = winbindd_client_list_prev(state);
1195 expiry_time = state->last_access + timeout_val;
1197 if (curr_time <= expiry_time) {
1198 /* list is sorted, previous clients in
1203 if (client_is_idle(state)) {
1204 DEBUG(5,("Idle client timed out, "
1205 "shutting down sock %d, pid %u\n",
1207 (unsigned int)state->pid));
1209 DEBUG(5,("Client request timed out, "
1210 "shutting down sock %d, pid %u\n",
1212 (unsigned int)state->pid));
1215 remove_client(state);
1219 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1220 struct tevent_timer *te,
1221 struct timeval current_time,
1224 remove_timed_out_clients();
1225 if (tevent_add_timer(ev, ev,
1226 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1227 winbindd_scrub_clients_handler, NULL) == NULL) {
1228 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1233 struct winbindd_listen_state {
1238 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1239 struct tevent_fd *fde,
1243 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1244 struct winbindd_listen_state);
1246 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1247 DEBUG(5,("winbindd: Exceeding %d client "
1248 "connections, removing idle "
1249 "connection.\n", lp_winbind_max_clients()));
1250 if (!remove_idle_client()) {
1251 DEBUG(0,("winbindd: Exceeding %d "
1252 "client connections, no idle "
1253 "connection found\n",
1254 lp_winbind_max_clients()));
1258 remove_timed_out_clients();
1259 new_connection(s->fd, s->privileged);
1263 * Winbindd socket accessor functions
1266 char *get_winbind_priv_pipe_dir(void)
1268 return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR);
1271 static void winbindd_setup_max_fds(void)
1273 int num_fds = MAX_OPEN_FUDGEFACTOR;
1276 num_fds += lp_winbind_max_clients();
1277 /* Add some more to account for 2 sockets open
1278 when the client transitions from unprivileged
1279 to privileged socket
1281 num_fds += lp_winbind_max_clients() / 10;
1283 /* Add one socket per child process
1284 (yeah there are child processes other than the
1285 domain children but only domain children can vary
1288 num_fds += lp_winbind_max_domain_connections() *
1289 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1291 actual_fds = set_maxfiles(num_fds);
1293 if (actual_fds < num_fds) {
1294 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1295 "requested %d open files, %d are available.\n",
1296 num_fds, actual_fds));
1300 static bool winbindd_setup_listeners(void)
1302 struct winbindd_listen_state *pub_state = NULL;
1303 struct winbindd_listen_state *priv_state = NULL;
1304 struct tevent_fd *fde;
1308 pub_state = talloc(global_event_context(),
1309 struct winbindd_listen_state);
1314 pub_state->privileged = false;
1315 pub_state->fd = create_pipe_sock(
1316 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1317 if (pub_state->fd == -1) {
1320 rc = listen(pub_state->fd, 5);
1325 fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1326 TEVENT_FD_READ, winbindd_listen_fde_handler,
1329 close(pub_state->fd);
1332 tevent_fd_set_auto_close(fde);
1334 priv_state = talloc(global_event_context(),
1335 struct winbindd_listen_state);
1340 socket_path = get_winbind_priv_pipe_dir();
1341 if (socket_path == NULL) {
1345 priv_state->privileged = true;
1346 priv_state->fd = create_pipe_sock(
1347 socket_path, WINBINDD_SOCKET_NAME, 0750);
1348 TALLOC_FREE(socket_path);
1349 if (priv_state->fd == -1) {
1352 rc = listen(priv_state->fd, 5);
1357 fde = tevent_add_fd(global_event_context(), priv_state,
1358 priv_state->fd, TEVENT_FD_READ,
1359 winbindd_listen_fde_handler, priv_state);
1361 close(priv_state->fd);
1364 tevent_fd_set_auto_close(fde);
1366 winbindd_scrub_clients_handler(global_event_context(), NULL,
1367 timeval_current(), NULL);
1370 TALLOC_FREE(pub_state);
1371 TALLOC_FREE(priv_state);
1375 bool winbindd_use_idmap_cache(void)
1377 return !opt_nocache;
1380 bool winbindd_use_cache(void)
1382 return !opt_nocache;
1385 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1388 bool scan_trusts = true;
1390 /* Setup signal handlers */
1392 if (!winbindd_setup_sig_term_handler(true))
1394 if (!winbindd_setup_stdin_handler(true, foreground))
1396 if (!winbindd_setup_sig_hup_handler(NULL))
1398 if (!winbindd_setup_sig_chld_handler())
1400 if (!winbindd_setup_sig_usr2_handler())
1403 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1406 * Ensure all cache and idmap caches are consistent
1407 * and initialized before we startup.
1409 if (!winbindd_cache_validate_and_initialize()) {
1413 /* React on 'smbcontrol winbindd reload-config' in the same way
1414 as to SIGHUP signal */
1415 messaging_register(msg_ctx, NULL,
1416 MSG_SMB_CONF_UPDATED, msg_reload_services);
1417 messaging_register(msg_ctx, NULL,
1418 MSG_SHUTDOWN, msg_shutdown);
1420 /* Handle online/offline messages. */
1421 messaging_register(msg_ctx, NULL,
1422 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1423 messaging_register(msg_ctx, NULL,
1424 MSG_WINBIND_ONLINE, winbind_msg_online);
1425 messaging_register(msg_ctx, NULL,
1426 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1428 /* Handle domain online/offline messages for domains */
1429 messaging_register(global_messaging_context(), NULL,
1430 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1431 messaging_register(global_messaging_context(), NULL,
1432 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1434 messaging_register(msg_ctx, NULL,
1435 MSG_WINBIND_VALIDATE_CACHE,
1436 winbind_msg_validate_cache);
1438 messaging_register(msg_ctx, NULL,
1439 MSG_WINBIND_DUMP_DOMAIN_LIST,
1440 winbind_msg_dump_domain_list);
1442 messaging_register(msg_ctx, NULL,
1443 MSG_WINBIND_IP_DROPPED,
1444 winbind_msg_ip_dropped_parent);
1446 /* Register handler for MSG_DEBUG. */
1447 messaging_register(msg_ctx, NULL,
1451 messaging_register(msg_ctx, NULL,
1452 MSG_WINBIND_DISCONNECT_DC,
1453 winbind_disconnect_dc_parent);
1455 netsamlogon_cache_init(); /* Non-critical */
1457 /* clear the cached list of trusted domains */
1461 if (!init_domain_list()) {
1462 DEBUG(0,("unable to initialize domain list\n"));
1467 init_locator_child();
1469 smb_nscd_flush_user_cache();
1470 smb_nscd_flush_group_cache();
1472 if (!lp_winbind_scan_trusted_domains()) {
1473 scan_trusts = false;
1476 if (!lp_allow_trusted_domains()) {
1477 scan_trusts = false;
1481 scan_trusts = false;
1485 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1486 rescan_trusted_domains, NULL) == NULL) {
1487 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1492 status = wb_irpc_register();
1494 if (!NT_STATUS_IS_OK(status)) {
1495 DEBUG(0, ("Could not register IRPC handlers\n"));
1500 struct winbindd_addrchanged_state {
1501 struct addrchange_context *ctx;
1502 struct tevent_context *ev;
1503 struct messaging_context *msg_ctx;
1506 static void winbindd_addr_changed(struct tevent_req *req);
1508 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1509 struct tevent_context *ev,
1510 struct messaging_context *msg_ctx)
1512 struct winbindd_addrchanged_state *state;
1513 struct tevent_req *req;
1516 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1517 if (state == NULL) {
1518 DEBUG(10, ("talloc failed\n"));
1522 state->msg_ctx = msg_ctx;
1524 status = addrchange_context_create(state, &state->ctx);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 DEBUG(10, ("addrchange_context_create failed: %s\n",
1527 nt_errstr(status)));
1531 req = addrchange_send(state, ev, state->ctx);
1533 DEBUG(0, ("addrchange_send failed\n"));
1537 tevent_req_set_callback(req, winbindd_addr_changed, state);
1540 static void winbindd_addr_changed(struct tevent_req *req)
1542 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1543 req, struct winbindd_addrchanged_state);
1544 enum addrchange_type type;
1545 struct sockaddr_storage addr;
1548 status = addrchange_recv(req, &type, &addr);
1550 if (!NT_STATUS_IS_OK(status)) {
1551 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1552 nt_errstr(status)));
1556 if (type == ADDRCHANGE_DEL) {
1557 char addrstr[INET6_ADDRSTRLEN];
1560 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1562 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1565 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1567 status = messaging_send(state->msg_ctx,
1568 messaging_server_id(state->msg_ctx),
1569 MSG_WINBIND_IP_DROPPED, &blob);
1570 if (!NT_STATUS_IS_OK(status)) {
1571 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1572 nt_errstr(status)));
1575 req = addrchange_send(state, state->ev, state->ctx);
1577 DEBUG(0, ("addrchange_send failed\n"));
1581 tevent_req_set_callback(req, winbindd_addr_changed, state);
1586 int main(int argc, const char **argv)
1588 static bool is_daemon = False;
1589 static bool Fork = True;
1590 static bool log_stdout = False;
1591 static bool no_process_group = False;
1595 OPT_NO_PROCESS_GROUP,
1598 struct poptOption long_options[] = {
1600 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1601 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1602 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1603 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1604 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1605 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1615 setproctitle_init(argc, discard_const(argv), environ);
1618 * Do this before any other talloc operation
1620 talloc_enable_null_tracking();
1621 frame = talloc_stackframe();
1624 * We want total control over the permissions on created files,
1625 * so set our umask to 0.
1629 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1631 /* glibc (?) likes to print "User defined signal 1" and exit if a
1632 SIGUSR[12] is received before a handler is installed */
1634 CatchSignal(SIGUSR1, SIG_IGN);
1635 CatchSignal(SIGUSR2, SIG_IGN);
1638 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1642 /* Initialise for running in non-root mode */
1646 set_remote_machine_name("winbindd", False);
1648 /* Set environment variable so we don't recursively call ourselves.
1649 This may also be useful interactively. */
1651 if ( !winbind_off() ) {
1652 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1656 /* Initialise samba/rpc client stuff */
1658 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1660 while ((opt = poptGetNextOpt(pc)) != -1) {
1662 /* Don't become a daemon */
1674 case OPT_NO_PROCESS_GROUP:
1675 no_process_group = true;
1677 case OPT_LOG_STDOUT:
1684 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1685 poptBadOption(pc, 0), poptStrerror(opt));
1686 poptPrintUsage(pc, stderr, 0);
1691 /* We call dump_core_setup one more time because the command line can
1692 * set the log file or the log-basename and this will influence where
1693 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1694 * the default value derived from build's prefix. For EOM this value
1695 * is often not related to the path where winbindd is actually run
1698 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1699 if (is_daemon && interactive) {
1700 d_fprintf(stderr,"\nERROR: "
1701 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1702 poptPrintUsage(pc, stderr, 0);
1706 if (log_stdout && Fork) {
1707 d_fprintf(stderr, "\nERROR: "
1708 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1709 poptPrintUsage(pc, stderr, 0);
1713 poptFreeContext(pc);
1715 if (!override_logfile) {
1717 if (asprintf(&lfile,"%s/log.winbindd",
1718 get_dyn_LOGFILEBASE()) > 0) {
1719 lp_set_logfile(lfile);
1725 setup_logging("winbindd", DEBUG_STDOUT);
1727 setup_logging("winbindd", DEBUG_FILE);
1731 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1732 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1734 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1735 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1738 /* After parsing the configuration file we setup the core path one more time
1739 * as the log file might have been set in the configuration and cores's
1740 * path is by default basename(lp_logfile()).
1742 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1744 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1745 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1746 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1747 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"));
1751 if (!cluster_probe_ok()) {
1755 /* Initialise messaging system */
1757 if (global_messaging_context() == NULL) {
1761 if (!reload_services_file(NULL)) {
1762 DEBUG(0, ("error opening config file\n"));
1768 const char *idmap_backend;
1769 const char *invalid_backends[] = {
1770 "ad", "rfc2307", "rid",
1773 idmap_backend = lp_idmap_default_backend();
1774 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1775 ok = strequal(idmap_backend, invalid_backends[i]);
1777 DBG_ERR("FATAL: Invalid idmap backend %s "
1778 "configured as the default backend!\n",
1785 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1787 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1788 lp_lock_directory(), strerror(errno)));
1792 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1794 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1795 lp_pid_directory(), strerror(errno)));
1806 if (!secrets_init()) {
1808 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1812 status = rpccli_pre_open_netlogon_creds();
1813 if (!NT_STATUS_IS_OK(status)) {
1814 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1815 nt_errstr(status)));
1819 /* Unblock all signals we are interested in as they may have been
1820 blocked by the parent process. */
1822 BlockSignals(False, SIGINT);
1823 BlockSignals(False, SIGQUIT);
1824 BlockSignals(False, SIGTERM);
1825 BlockSignals(False, SIGUSR1);
1826 BlockSignals(False, SIGUSR2);
1827 BlockSignals(False, SIGHUP);
1828 BlockSignals(False, SIGCHLD);
1831 become_daemon(Fork, no_process_group, log_stdout);
1833 pidfile_create(lp_pid_directory(), "winbindd");
1837 * If we're interactive we want to set our own process group for
1838 * signal management.
1840 if (interactive && !no_process_group)
1841 setpgid( (pid_t)0, (pid_t)0);
1846 /* Don't use winbindd_reinit_after_fork here as
1847 * we're just starting up and haven't created any
1848 * winbindd-specific resources we must free yet. JRA.
1851 status = reinit_after_fork(global_messaging_context(),
1852 global_event_context(),
1854 if (!NT_STATUS_IS_OK(status)) {
1855 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1858 ok = initialize_password_db(true, global_event_context());
1860 exit_daemon("Failed to initialize passdb backend! "
1861 "Check the 'passdb backend' variable in your "
1862 "smb.conf file.", EINVAL);
1866 * Do not initialize the parent-child-pipe before becoming
1867 * a daemon: this is used to detect a died parent in the child
1870 status = init_before_fork();
1871 if (!NT_STATUS_IS_OK(status)) {
1872 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1875 winbindd_register_handlers(global_messaging_context(), !Fork);
1877 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1881 status = init_system_session_info(NULL);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1886 rpc_lsarpc_init(NULL);
1887 rpc_samr_init(NULL);
1889 winbindd_init_addrchange(NULL, global_event_context(),
1890 global_messaging_context());
1892 /* setup listen sockets */
1894 if (!winbindd_setup_listeners()) {
1895 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1898 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1903 daemon_ready("winbindd");
1908 /* Loop waiting for requests */
1910 frame = talloc_stackframe();
1912 if (tevent_loop_once(global_event_context()) == -1) {
1913 DEBUG(1, ("tevent_loop_once() failed: %s\n",