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 "lib/cmdline/cmdline.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.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"
36 #include "rpc_client/cli_netlogon.h"
38 #include "lib/addrchange.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"
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"
56 #define DBGC_CLASS DBGC_WINBIND
58 #define SCRUB_CLIENTS_INTERVAL 5
60 static bool client_is_idle(struct winbindd_cli_state *state);
61 static void remove_client(struct winbindd_cli_state *state);
62 static void winbindd_setup_max_fds(void);
64 static bool opt_nocache = False;
65 static bool interactive = False;
67 extern bool override_logfile;
69 struct imessaging_context *winbind_imessaging_context(void)
71 static struct imessaging_context *msg = NULL;
72 struct messaging_context *msg_ctx;
73 struct server_id myself;
74 struct loadparm_context *lp_ctx;
80 msg_ctx = global_messaging_context();
81 if (msg_ctx == NULL) {
82 smb_panic("global_messaging_context failed\n");
84 myself = messaging_server_id(msg_ctx);
86 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
88 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
92 * Note we MUST use the NULL context here, not the autofree context,
93 * to avoid side effects in forked children exiting.
95 msg = imessaging_init(NULL, lp_ctx, myself, global_event_context());
96 talloc_unlink(NULL, lp_ctx);
99 smb_panic("Could not init winbindd's messaging context.\n");
104 /* Reload configuration */
106 bool winbindd_reload_services_file(const char *lfile)
108 const struct loadparm_substitution *lp_sub =
109 loadparm_s3_global_substitution();
113 char *fname = lp_next_configfile(talloc_tos(), lp_sub);
115 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
116 set_dyn_CONFIGFILE(fname);
122 ret = lp_load_global(get_dyn_CONFIGFILE());
124 /* if this is a child, restore the logfile to the special
125 name - <domain>, idmap, etc. */
126 if (lfile && *lfile) {
127 lp_set_logfile(lfile);
132 winbindd_setup_max_fds();
138 static void winbindd_status(void)
140 struct winbindd_cli_state *tmp;
142 DEBUG(0, ("winbindd status:\n"));
144 /* Print client state information */
146 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
148 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
149 DEBUG(2, ("\tclient list:\n"));
150 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
151 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
152 (unsigned long)tmp->pid, tmp->sock,
153 client_is_idle(tmp) ? "idle" : "active"));
158 /* Flush client cache */
160 void winbindd_flush_caches(void)
162 /* We need to invalidate cached user list entries on a SIGHUP
163 otherwise cached access denied errors due to restrict anonymous
164 hang around until the sequence number changes. */
166 if (!wcache_invalidate_cache()) {
167 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
168 if (!winbindd_cache_validate_and_initialize()) {
174 static void flush_caches_noinit(void)
177 * We need to invalidate cached user list entries on a SIGHUP
178 * otherwise cached access denied errors due to restrict anonymous
179 * hang around until the sequence number changes.
181 * Skip uninitialized domains when flush cache.
182 * If domain is not initialized, it means it is never
183 * used or never become online. look, wcache_invalidate_cache()
184 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
185 * for unused domains and large traffic for primay domain's DC if there
189 if (!wcache_invalidate_cache_noinit()) {
190 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
191 if (!winbindd_cache_validate_and_initialize()) {
197 /* Handle the signal by unlinking socket and exiting */
199 static void terminate(bool is_parent)
202 /* When parent goes away we should
203 * remove the socket file. Not so
204 * when children terminate.
208 if (asprintf(&path, "%s/%s",
209 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
217 netlogon_creds_cli_close_global_db();
221 TALLOC_CTX *mem_ctx = talloc_init("end_description");
222 char *description = talloc_describe_all(mem_ctx);
224 DEBUG(3, ("tallocs left:\n%s\n", description));
225 talloc_destroy(mem_ctx);
230 pidfile_unlink(lp_pid_directory(), "winbindd");
236 static void winbindd_sig_term_handler(struct tevent_context *ev,
237 struct tevent_signal *se,
243 bool *p = talloc_get_type_abort(private_data, bool);
248 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
250 terminate(is_parent);
254 handle stdin becoming readable when we are in --foreground mode
256 static void winbindd_stdin_handler(struct tevent_context *ev,
257 struct tevent_fd *fde,
262 if (read(0, &c, 1) != 1) {
263 bool *is_parent = talloc_get_type_abort(private_data, bool);
265 /* we have reached EOF on stdin, which means the
266 parent has exited. Shutdown the server */
267 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
269 terminate(*is_parent);
273 bool winbindd_setup_sig_term_handler(bool parent)
275 struct tevent_signal *se;
278 is_parent = talloc(global_event_context(), bool);
285 se = tevent_add_signal(global_event_context(),
288 winbindd_sig_term_handler,
291 DEBUG(0,("failed to setup SIGTERM handler"));
292 talloc_free(is_parent);
296 se = tevent_add_signal(global_event_context(),
299 winbindd_sig_term_handler,
302 DEBUG(0,("failed to setup SIGINT handler"));
303 talloc_free(is_parent);
307 se = tevent_add_signal(global_event_context(),
310 winbindd_sig_term_handler,
313 DEBUG(0,("failed to setup SIGINT handler"));
314 talloc_free(is_parent);
321 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
328 is_parent = talloc(global_event_context(), bool);
335 /* if we are running in the foreground then look for
336 EOF on stdin, and exit if it happens. This allows
337 us to die if the parent process dies
338 Only do this on a pipe or socket, no other device.
340 if (fstat(0, &st) != 0) {
343 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
344 tevent_add_fd(global_event_context(),
348 winbindd_stdin_handler,
356 static void winbindd_sig_hup_handler(struct tevent_context *ev,
357 struct tevent_signal *se,
363 const char *file = (const char *)private_data;
365 DEBUG(1,("Reloading services after SIGHUP\n"));
366 flush_caches_noinit();
367 winbindd_reload_services_file(file);
370 bool winbindd_setup_sig_hup_handler(const char *lfile)
372 struct tevent_signal *se;
376 file = talloc_strdup(global_event_context(),
383 se = tevent_add_signal(global_event_context(),
384 global_event_context(),
386 winbindd_sig_hup_handler,
395 static void winbindd_sig_chld_handler(struct tevent_context *ev,
396 struct tevent_signal *se,
404 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
405 winbind_child_died(pid);
409 static bool winbindd_setup_sig_chld_handler(void)
411 struct tevent_signal *se;
413 se = tevent_add_signal(global_event_context(),
414 global_event_context(),
416 winbindd_sig_chld_handler,
425 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
426 struct tevent_signal *se,
435 static bool winbindd_setup_sig_usr2_handler(void)
437 struct tevent_signal *se;
439 se = tevent_add_signal(global_event_context(),
440 global_event_context(),
442 winbindd_sig_usr2_handler,
451 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
452 static void msg_shutdown(struct messaging_context *msg,
455 struct server_id server_id,
458 /* only the parent waits for this message */
459 DEBUG(0,("Got shutdown message\n"));
464 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
467 struct server_id server_id,
474 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
478 * call the validation code from a child:
479 * so we don't block the main winbindd and the validation
480 * code can safely use fork/waitpid...
484 if (child_pid == -1) {
485 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
490 if (child_pid != 0) {
492 DEBUG(5, ("winbind_msg_validate_cache: child created with "
493 "pid %d.\n", (int)child_pid));
499 status = winbindd_reinit_after_fork(NULL, NULL);
500 if (!NT_STATUS_IS_OK(status)) {
501 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
506 /* install default SIGCHLD handler: validation code uses fork/waitpid */
507 CatchSignal(SIGCHLD, SIG_DFL);
509 setproctitle("validate cache child");
511 ret = (uint8_t)winbindd_validate_cache_nobackup();
512 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
513 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
518 static struct winbindd_bool_dispatch_table {
519 enum winbindd_cmd cmd;
520 bool (*fn)(struct winbindd_cli_state *state);
521 const char *cmd_name;
522 } bool_dispatch_table[] = {
523 { WINBINDD_INTERFACE_VERSION,
524 winbindd_interface_version,
525 "INTERFACE_VERSION" },
532 { WINBINDD_DOMAIN_NAME,
533 winbindd_domain_name,
535 { WINBINDD_NETBIOS_NAME,
536 winbindd_netbios_name,
541 { WINBINDD_CCACHE_NTLMAUTH,
542 winbindd_ccache_ntlm_auth,
544 { WINBINDD_CCACHE_SAVE,
545 winbindd_ccache_save,
547 { WINBINDD_PRIV_PIPE_DIR,
548 winbindd_priv_pipe_dir,
549 "WINBINDD_PRIV_PIPE_DIR" },
550 { WINBINDD_LIST_TRUSTDOM,
551 winbindd_list_trusted_domains,
555 struct winbindd_async_dispatch_table {
556 enum winbindd_cmd cmd;
557 const char *cmd_name;
558 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
559 struct tevent_context *ev,
560 struct winbindd_cli_state *cli,
561 struct winbindd_request *request);
562 NTSTATUS (*recv_req)(struct tevent_req *req,
563 struct winbindd_response *presp);
566 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
567 { WINBINDD_LOOKUPSID, "LOOKUPSID",
568 winbindd_lookupsid_send, winbindd_lookupsid_recv },
569 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
570 winbindd_lookupsids_send, winbindd_lookupsids_recv },
571 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
572 winbindd_lookupname_send, winbindd_lookupname_recv },
573 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
574 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
575 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
576 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
577 { WINBINDD_GETPWSID, "GETPWSID",
578 winbindd_getpwsid_send, winbindd_getpwsid_recv },
579 { WINBINDD_GETPWNAM, "GETPWNAM",
580 winbindd_getpwnam_send, winbindd_getpwnam_recv },
581 { WINBINDD_GETPWUID, "GETPWUID",
582 winbindd_getpwuid_send, winbindd_getpwuid_recv },
583 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
584 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
585 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
586 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
587 { WINBINDD_GETGROUPS, "GETGROUPS",
588 winbindd_getgroups_send, winbindd_getgroups_recv },
589 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
590 winbindd_show_sequence_send, winbindd_show_sequence_recv },
591 { WINBINDD_GETGRGID, "GETGRGID",
592 winbindd_getgrgid_send, winbindd_getgrgid_recv },
593 { WINBINDD_GETGRNAM, "GETGRNAM",
594 winbindd_getgrnam_send, winbindd_getgrnam_recv },
595 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
596 winbindd_getusersids_send, winbindd_getusersids_recv },
597 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
598 winbindd_lookuprids_send, winbindd_lookuprids_recv },
599 { WINBINDD_SETPWENT, "SETPWENT",
600 winbindd_setpwent_send, winbindd_setpwent_recv },
601 { WINBINDD_GETPWENT, "GETPWENT",
602 winbindd_getpwent_send, winbindd_getpwent_recv },
603 { WINBINDD_ENDPWENT, "ENDPWENT",
604 winbindd_endpwent_send, winbindd_endpwent_recv },
605 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
606 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
607 { WINBINDD_GETDCNAME, "GETDCNAME",
608 winbindd_getdcname_send, winbindd_getdcname_recv },
609 { WINBINDD_SETGRENT, "SETGRENT",
610 winbindd_setgrent_send, winbindd_setgrent_recv },
611 { WINBINDD_GETGRENT, "GETGRENT",
612 winbindd_getgrent_send, winbindd_getgrent_recv },
613 { WINBINDD_ENDGRENT, "ENDGRENT",
614 winbindd_endgrent_send, winbindd_endgrent_recv },
615 { WINBINDD_LIST_USERS, "LIST_USERS",
616 winbindd_list_users_send, winbindd_list_users_recv },
617 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
618 winbindd_list_groups_send, winbindd_list_groups_recv },
619 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
620 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
621 { WINBINDD_PING_DC, "PING_DC",
622 winbindd_ping_dc_send, winbindd_ping_dc_recv },
623 { WINBINDD_PAM_AUTH, "PAM_AUTH",
624 winbindd_pam_auth_send, winbindd_pam_auth_recv },
625 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
626 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
627 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
628 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
629 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
630 winbindd_pam_chng_pswd_auth_crap_send,
631 winbindd_pam_chng_pswd_auth_crap_recv },
632 { WINBINDD_WINS_BYIP, "WINS_BYIP",
633 winbindd_wins_byip_send, winbindd_wins_byip_recv },
634 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
635 winbindd_wins_byname_send, winbindd_wins_byname_recv },
636 { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
637 winbindd_domain_info_send, winbindd_domain_info_recv },
639 { 0, NULL, NULL, NULL }
642 static struct winbindd_async_dispatch_table async_priv_table[] = {
643 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
644 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
645 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
646 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
647 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
648 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
649 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
650 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
652 { 0, NULL, NULL, NULL }
655 struct process_request_state {
656 struct winbindd_cli_state *cli_state;
657 struct tevent_context *ev;
660 static void process_request_done(struct tevent_req *subreq);
661 static void process_request_written(struct tevent_req *subreq);
663 static struct tevent_req *process_request_send(
665 struct tevent_context *ev,
666 struct winbindd_cli_state *cli_state)
668 struct tevent_req *req, *subreq;
669 struct process_request_state *state;
670 struct winbindd_async_dispatch_table *atable;
671 enum winbindd_cmd cmd = cli_state->request->cmd;
675 req = tevent_req_create(mem_ctx, &state,
676 struct process_request_state);
680 state->cli_state = cli_state;
683 ok = tevent_req_set_profile(req);
685 return tevent_req_post(req, ev);
688 SMB_ASSERT(cli_state->mem_ctx == NULL);
689 cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
690 if (tevent_req_nomem(cli_state->mem_ctx, req)) {
691 return tevent_req_post(req, ev);
694 cli_state->response = talloc_zero(
696 struct winbindd_response);
697 if (tevent_req_nomem(cli_state->response, req)) {
698 return tevent_req_post(req, ev);
700 cli_state->response->result = WINBINDD_PENDING;
701 cli_state->response->length = sizeof(struct winbindd_response);
703 /* Remember who asked us. */
704 cli_state->pid = cli_state->request->pid;
705 memcpy(cli_state->client_name,
706 cli_state->request->client_name,
707 sizeof(cli_state->client_name));
709 cli_state->cmd_name = "unknown request";
710 cli_state->recv_fn = NULL;
712 /* client is newest */
713 winbindd_promote_client(cli_state);
715 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
716 if (cmd == atable->cmd) {
721 if ((atable->send_req == NULL) && cli_state->privileged) {
722 for (atable = async_priv_table; atable->send_req;
724 if (cmd == atable->cmd) {
730 if (atable->send_req != NULL) {
731 cli_state->cmd_name = atable->cmd_name;
732 cli_state->recv_fn = atable->recv_req;
734 DBG_DEBUG("process_request: "
735 "Handling async request %s(%d):%s\n",
736 cli_state->client_name,
738 cli_state->cmd_name);
740 subreq = atable->send_req(
745 if (tevent_req_nomem(subreq, req)) {
746 return tevent_req_post(req, ev);
748 tevent_req_set_callback(subreq, process_request_done, req);
752 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
753 if (cmd == bool_dispatch_table[i].cmd) {
760 if (i < ARRAY_SIZE(bool_dispatch_table)) {
761 cli_state->cmd_name = bool_dispatch_table[i].cmd_name;
763 DBG_DEBUG("process_request: request fn %s\n",
764 bool_dispatch_table[i].cmd_name);
765 ok = bool_dispatch_table[i].fn(cli_state);
768 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
770 TALLOC_FREE(cli_state->io_req);
771 TALLOC_FREE(cli_state->request);
773 subreq = wb_resp_write_send(
776 cli_state->out_queue,
778 cli_state->response);
779 if (tevent_req_nomem(subreq, req)) {
780 return tevent_req_post(req, ev);
782 tevent_req_set_callback(subreq, process_request_written, req);
784 cli_state->io_req = subreq;
789 static void process_request_done(struct tevent_req *subreq)
791 struct tevent_req *req = tevent_req_callback_data(
792 subreq, struct tevent_req);
793 struct process_request_state *state = tevent_req_data(
794 req, struct process_request_state);
795 struct winbindd_cli_state *cli_state = state->cli_state;
799 status = cli_state->recv_fn(subreq, cli_state->response);
802 DBG_DEBUG("[%s(%d):%s]: %s\n",
803 cli_state->client_name,
808 ok = NT_STATUS_IS_OK(status);
809 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
811 TALLOC_FREE(cli_state->io_req);
812 TALLOC_FREE(cli_state->request);
814 subreq = wb_resp_write_send(
817 cli_state->out_queue,
819 cli_state->response);
820 if (tevent_req_nomem(subreq, req)) {
823 tevent_req_set_callback(subreq, process_request_written, req);
825 cli_state->io_req = subreq;
828 static void process_request_written(struct tevent_req *subreq)
830 struct tevent_req *req = tevent_req_callback_data(
831 subreq, struct tevent_req);
832 struct process_request_state *state = tevent_req_data(
833 req, struct process_request_state);
834 struct winbindd_cli_state *cli_state = state->cli_state;
838 cli_state->io_req = NULL;
840 ret = wb_resp_write_recv(subreq, &err);
843 tevent_req_nterror(req, map_nt_error_from_unix(err));
847 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
848 cli_state->client_name,
850 cli_state->cmd_name);
852 TALLOC_FREE(cli_state->mem_ctx);
853 cli_state->response = NULL;
854 cli_state->cmd_name = "no request";
855 cli_state->recv_fn = NULL;
857 tevent_req_done(req);
860 static NTSTATUS process_request_recv(
861 struct tevent_req *req,
863 struct tevent_req_profile **profile)
867 if (tevent_req_is_nterror(req, &status)) {
868 tevent_req_received(req);
872 *profile = tevent_req_move_profile(req, mem_ctx);
873 tevent_req_received(req);
878 * This is the main event loop of winbind requests. It goes through a
879 * state-machine of 3 read/write requests, 4 if you have extra data to send.
881 * An idle winbind client has a read request of 4 bytes outstanding,
882 * finalizing function is request_len_recv, checking the length. request_recv
883 * then processes the packet. The processing function then at some point has
884 * to call request_finished which schedules sending the response.
887 static void winbind_client_request_read(struct tevent_req *req);
888 static void winbind_client_activity(struct tevent_req *req);
889 static void winbind_client_processed(struct tevent_req *req);
891 /* Process a new connection by adding it to the client connection list */
893 static void new_connection(int listen_sock, bool privileged)
895 struct sockaddr_un sunaddr;
896 struct winbindd_cli_state *state;
897 struct tevent_req *req;
901 /* Accept connection */
903 len = sizeof(sunaddr);
905 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
908 if (errno != EINTR) {
909 DEBUG(0, ("Failed to accept socket - %s\n",
914 smb_set_close_on_exec(sock);
916 DEBUG(6,("accepted socket %d\n", sock));
918 /* Create new connection structure */
920 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
927 state->out_queue = tevent_queue_create(state, "winbind client reply");
928 if (state->out_queue == NULL) {
934 state->privileged = privileged;
936 req = wb_req_read_send(state, global_event_context(), state->sock,
937 WINBINDD_MAX_EXTRA_DATA);
943 tevent_req_set_callback(req, winbind_client_request_read, state);
946 /* Add to connection list */
948 winbindd_add_client(state);
951 static void winbind_client_request_read(struct tevent_req *req)
953 struct winbindd_cli_state *state = tevent_req_callback_data(
954 req, struct winbindd_cli_state);
958 state->io_req = NULL;
960 ret = wb_req_read_recv(req, state, &state->request, &err);
964 DEBUG(6, ("closing socket %d, client exited\n",
967 DEBUG(2, ("Could not read client request from fd %d: "
968 "%s\n", state->sock, strerror(err)));
972 remove_client(state);
976 req = wait_for_read_send(state, global_event_context(), state->sock,
979 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
980 " wait_for_read_send failed - removing client\n",
981 (int)state->pid, state->cmd_name));
982 remove_client(state);
985 tevent_req_set_callback(req, winbind_client_activity, state);
988 req = process_request_send(state, global_event_context(), state);
990 DBG_ERR("process_request_send failed\n");
991 remove_client(state);
994 tevent_req_set_callback(req, winbind_client_processed, state);
997 static void winbind_client_activity(struct tevent_req *req)
999 struct winbindd_cli_state *state =
1000 tevent_req_callback_data(req, struct winbindd_cli_state);
1004 has_data = wait_for_read_recv(req, &err);
1007 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1008 "unexpected data from client - removing client\n",
1009 (int)state->pid, state->cmd_name));
1012 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1013 "client has closed connection - removing "
1015 (int)state->pid, state->cmd_name));
1017 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1018 "client socket error (%s) - removing "
1020 (int)state->pid, state->cmd_name,
1025 remove_client(state);
1028 static void winbind_client_processed(struct tevent_req *req)
1030 struct winbindd_cli_state *cli_state = tevent_req_callback_data(
1031 req, struct winbindd_cli_state);
1032 struct tevent_req_profile *profile = NULL;
1033 struct timeval start, stop, diff;
1037 status = process_request_recv(req, cli_state, &profile);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
1041 remove_client(cli_state);
1045 tevent_req_profile_get_start(profile, NULL, &start);
1046 tevent_req_profile_get_stop(profile, NULL, &stop);
1047 diff = tevent_timeval_until(&start, &stop);
1049 threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
1051 if (diff.tv_sec >= threshold) {
1055 depth = lp_parm_int(
1058 "request profile depth",
1061 DBG_ERR("request took %u.%.6u seconds\n",
1062 (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
1064 str = tevent_req_profile_string(
1065 talloc_tos(), profile, 0, depth);
1067 /* No "\n", already contained in "str" */
1068 DEBUGADD(0, ("%s", str));
1073 TALLOC_FREE(profile);
1075 req = wb_req_read_send(
1077 global_event_context(),
1079 WINBINDD_MAX_EXTRA_DATA);
1081 remove_client(cli_state);
1084 tevent_req_set_callback(req, winbind_client_request_read, cli_state);
1085 cli_state->io_req = req;
1088 /* Remove a client connection from client connection list */
1090 static void remove_client(struct winbindd_cli_state *state)
1092 /* It's a dead client - hold a funeral */
1094 if (state == NULL) {
1099 * We need to remove a pending wb_req_read_*
1100 * or wb_resp_write_* request before closing the
1103 * This is important as they might have used tevent_add_fd() and we
1104 * use the epoll * backend on linux. So we must remove the tevent_fd
1105 * before closing the fd.
1107 * Otherwise we might hit a race with close_conns_after_fork() (via
1108 * winbindd_reinit_after_fork()) where a file descriptor
1109 * is still open in a child, which means it's still active in
1110 * the parents epoll queue, but the related tevent_fd is already
1111 * already gone in the parent.
1115 TALLOC_FREE(state->io_req);
1117 if (state->sock != -1) {
1121 /* tell client, we are closing ... */
1122 nwritten = write(state->sock, &c, sizeof(c));
1123 if (nwritten == -1) {
1124 DEBUG(2, ("final write to client failed: %s\n",
1134 TALLOC_FREE(state->mem_ctx);
1136 /* Remove from list and free */
1138 winbindd_remove_client(state);
1142 /* Is a client idle? */
1144 static bool client_is_idle(struct winbindd_cli_state *state) {
1145 return (state->request == NULL &&
1146 state->response == NULL &&
1147 !state->pwent_state && !state->grent_state);
1150 /* Shutdown client connection which has been idle for the longest time */
1152 static bool remove_idle_client(void)
1154 struct winbindd_cli_state *state, *remove_state = NULL;
1157 for (state = winbindd_client_list(); state; state = state->next) {
1158 if (client_is_idle(state)) {
1160 /* list is sorted by access time */
1161 remove_state = state;
1166 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1167 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1168 remove_client(remove_state);
1176 * Terminate all clients whose requests have taken longer than
1177 * "winbind request timeout" seconds to process, or have been
1178 * idle for more than "winbind request timeout" seconds.
1181 static void remove_timed_out_clients(void)
1183 struct winbindd_cli_state *state, *prev = NULL;
1184 time_t curr_time = time(NULL);
1185 int timeout_val = lp_winbind_request_timeout();
1187 for (state = winbindd_client_list_tail(); state; state = prev) {
1190 prev = winbindd_client_list_prev(state);
1191 expiry_time = state->last_access + timeout_val;
1193 if (curr_time <= expiry_time) {
1194 /* list is sorted, previous clients in
1199 if (client_is_idle(state)) {
1200 DEBUG(5,("Idle client timed out, "
1201 "shutting down sock %d, pid %u\n",
1203 (unsigned int)state->pid));
1205 DEBUG(5,("Client request timed out, "
1206 "shutting down sock %d, pid %u\n",
1208 (unsigned int)state->pid));
1211 remove_client(state);
1215 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1216 struct tevent_timer *te,
1217 struct timeval current_time,
1220 remove_timed_out_clients();
1221 if (tevent_add_timer(ev, ev,
1222 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1223 winbindd_scrub_clients_handler, NULL) == NULL) {
1224 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1229 struct winbindd_listen_state {
1234 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1235 struct tevent_fd *fde,
1239 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1240 struct winbindd_listen_state);
1242 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1243 DEBUG(5,("winbindd: Exceeding %d client "
1244 "connections, removing idle "
1245 "connection.\n", lp_winbind_max_clients()));
1246 if (!remove_idle_client()) {
1247 DEBUG(0,("winbindd: Exceeding %d "
1248 "client connections, no idle "
1249 "connection found\n",
1250 lp_winbind_max_clients()));
1254 remove_timed_out_clients();
1255 new_connection(s->fd, s->privileged);
1259 * Winbindd socket accessor functions
1262 char *get_winbind_priv_pipe_dir(void)
1264 return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR);
1267 static void winbindd_setup_max_fds(void)
1269 int num_fds = MAX_OPEN_FUDGEFACTOR;
1272 num_fds += lp_winbind_max_clients();
1273 /* Add some more to account for 2 sockets open
1274 when the client transitions from unprivileged
1275 to privileged socket
1277 num_fds += lp_winbind_max_clients() / 10;
1279 /* Add one socket per child process
1280 (yeah there are child processes other than the
1281 domain children but only domain children can vary
1284 num_fds += lp_winbind_max_domain_connections() *
1285 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1287 actual_fds = set_maxfiles(num_fds);
1289 if (actual_fds < num_fds) {
1290 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1291 "requested %d open files, %d are available.\n",
1292 num_fds, actual_fds));
1296 static bool winbindd_setup_listeners(void)
1298 struct winbindd_listen_state *pub_state = NULL;
1299 struct winbindd_listen_state *priv_state = NULL;
1300 struct tevent_fd *fde;
1304 pub_state = talloc(global_event_context(),
1305 struct winbindd_listen_state);
1310 pub_state->privileged = false;
1311 pub_state->fd = create_pipe_sock(
1312 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1313 if (pub_state->fd == -1) {
1316 rc = listen(pub_state->fd, 5);
1321 fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1322 TEVENT_FD_READ, winbindd_listen_fde_handler,
1325 close(pub_state->fd);
1328 tevent_fd_set_auto_close(fde);
1330 priv_state = talloc(global_event_context(),
1331 struct winbindd_listen_state);
1336 socket_path = get_winbind_priv_pipe_dir();
1337 if (socket_path == NULL) {
1341 priv_state->privileged = true;
1342 priv_state->fd = create_pipe_sock(
1343 socket_path, WINBINDD_SOCKET_NAME, 0750);
1344 TALLOC_FREE(socket_path);
1345 if (priv_state->fd == -1) {
1348 rc = listen(priv_state->fd, 5);
1353 fde = tevent_add_fd(global_event_context(), priv_state,
1354 priv_state->fd, TEVENT_FD_READ,
1355 winbindd_listen_fde_handler, priv_state);
1357 close(priv_state->fd);
1360 tevent_fd_set_auto_close(fde);
1362 winbindd_scrub_clients_handler(global_event_context(), NULL,
1363 timeval_current(), NULL);
1366 TALLOC_FREE(pub_state);
1367 TALLOC_FREE(priv_state);
1371 bool winbindd_use_idmap_cache(void)
1373 return !opt_nocache;
1376 bool winbindd_use_cache(void)
1378 return !opt_nocache;
1381 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1384 bool scan_trusts = true;
1386 /* Setup signal handlers */
1388 if (!winbindd_setup_sig_term_handler(true))
1390 if (!winbindd_setup_stdin_handler(true, foreground))
1392 if (!winbindd_setup_sig_hup_handler(NULL))
1394 if (!winbindd_setup_sig_chld_handler())
1396 if (!winbindd_setup_sig_usr2_handler())
1399 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1402 * Ensure all cache and idmap caches are consistent
1403 * and initialized before we startup.
1405 if (!winbindd_cache_validate_and_initialize()) {
1409 /* React on 'smbcontrol winbindd reload-config' in the same way
1410 as to SIGHUP signal */
1411 messaging_register(msg_ctx, NULL,
1412 MSG_SMB_CONF_UPDATED,
1413 winbindd_msg_reload_services_parent);
1414 messaging_register(msg_ctx, NULL,
1415 MSG_SHUTDOWN, msg_shutdown);
1417 /* Handle online/offline messages. */
1418 messaging_register(msg_ctx, NULL,
1419 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1420 messaging_register(msg_ctx, NULL,
1421 MSG_WINBIND_ONLINE, winbind_msg_online);
1422 messaging_register(msg_ctx, NULL,
1423 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1425 /* Handle domain online/offline messages for domains */
1426 messaging_register(global_messaging_context(), NULL,
1427 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1428 messaging_register(global_messaging_context(), NULL,
1429 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1431 messaging_register(msg_ctx, NULL,
1432 MSG_WINBIND_VALIDATE_CACHE,
1433 winbind_msg_validate_cache);
1435 messaging_register(msg_ctx, NULL,
1436 MSG_WINBIND_DUMP_DOMAIN_LIST,
1437 winbind_msg_dump_domain_list);
1439 messaging_register(msg_ctx, NULL,
1440 MSG_WINBIND_IP_DROPPED,
1441 winbind_msg_ip_dropped_parent);
1443 /* Register handler for MSG_DEBUG. */
1444 messaging_register(msg_ctx, NULL,
1448 messaging_register(msg_ctx, NULL,
1449 MSG_WINBIND_DISCONNECT_DC,
1450 winbind_disconnect_dc_parent);
1452 netsamlogon_cache_init(); /* Non-critical */
1454 /* clear the cached list of trusted domains */
1458 if (!init_domain_list()) {
1459 DEBUG(0,("unable to initialize domain list\n"));
1464 init_locator_child();
1466 smb_nscd_flush_user_cache();
1467 smb_nscd_flush_group_cache();
1469 if (!lp_winbind_scan_trusted_domains()) {
1470 scan_trusts = false;
1473 if (!lp_allow_trusted_domains()) {
1474 scan_trusts = false;
1478 scan_trusts = false;
1482 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1483 rescan_trusted_domains, NULL) == NULL) {
1484 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1489 status = wb_irpc_register();
1491 if (!NT_STATUS_IS_OK(status)) {
1492 DEBUG(0, ("Could not register IRPC handlers\n"));
1497 struct winbindd_addrchanged_state {
1498 struct addrchange_context *ctx;
1499 struct tevent_context *ev;
1500 struct messaging_context *msg_ctx;
1503 static void winbindd_addr_changed(struct tevent_req *req);
1505 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1506 struct tevent_context *ev,
1507 struct messaging_context *msg_ctx)
1509 struct winbindd_addrchanged_state *state;
1510 struct tevent_req *req;
1513 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1514 if (state == NULL) {
1515 DEBUG(10, ("talloc failed\n"));
1519 state->msg_ctx = msg_ctx;
1521 status = addrchange_context_create(state, &state->ctx);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 DEBUG(10, ("addrchange_context_create failed: %s\n",
1524 nt_errstr(status)));
1528 req = addrchange_send(state, ev, state->ctx);
1530 DEBUG(0, ("addrchange_send failed\n"));
1534 tevent_req_set_callback(req, winbindd_addr_changed, state);
1537 static void winbindd_addr_changed(struct tevent_req *req)
1539 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1540 req, struct winbindd_addrchanged_state);
1541 enum addrchange_type type;
1542 struct sockaddr_storage addr;
1545 status = addrchange_recv(req, &type, &addr);
1547 if (!NT_STATUS_IS_OK(status)) {
1548 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1549 nt_errstr(status)));
1553 if (type == ADDRCHANGE_DEL) {
1554 char addrstr[INET6_ADDRSTRLEN];
1557 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1559 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1562 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1564 status = messaging_send(state->msg_ctx,
1565 messaging_server_id(state->msg_ctx),
1566 MSG_WINBIND_IP_DROPPED, &blob);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1569 nt_errstr(status)));
1572 req = addrchange_send(state, state->ev, state->ctx);
1574 DEBUG(0, ("addrchange_send failed\n"));
1578 tevent_req_set_callback(req, winbindd_addr_changed, state);
1583 int main(int argc, const char **argv)
1585 static bool is_daemon = False;
1586 static bool Fork = True;
1587 static bool log_stdout = False;
1588 static bool no_process_group = False;
1592 OPT_NO_PROCESS_GROUP
1594 struct poptOption long_options[] = {
1597 .longName = "foreground",
1599 .argInfo = POPT_ARG_NONE,
1602 .descrip = "Daemon in foreground mode",
1605 .longName = "no-process-group",
1607 .argInfo = POPT_ARG_NONE,
1609 .val = OPT_NO_PROCESS_GROUP,
1610 .descrip = "Don't create a new process group",
1613 .longName = "daemon",
1615 .argInfo = POPT_ARG_NONE,
1618 .descrip = "Become a daemon (default)",
1621 .longName = "interactive",
1623 .argInfo = POPT_ARG_NONE,
1626 .descrip = "Interactive mode",
1629 .longName = "no-caching",
1631 .argInfo = POPT_ARG_NONE,
1634 .descrip = "Disable caching",
1640 const struct loadparm_substitution *lp_sub =
1641 loadparm_s3_global_substitution();
1647 const struct dcesrv_endpoint_server *ep_server = NULL;
1648 struct dcesrv_context *dce_ctx = NULL;
1650 setproctitle_init(argc, discard_const(argv), environ);
1653 * Do this before any other talloc operation
1655 talloc_enable_null_tracking();
1656 frame = talloc_stackframe();
1659 * We want total control over the permissions on created files,
1660 * so set our umask to 0.
1666 /* glibc (?) likes to print "User defined signal 1" and exit if a
1667 SIGUSR[12] is received before a handler is installed */
1669 CatchSignal(SIGUSR1, SIG_IGN);
1670 CatchSignal(SIGUSR2, SIG_IGN);
1672 ok = samba_cmdline_init(frame,
1673 SAMBA_CMDLINE_CONFIG_SERVER,
1674 true /* require_smbconf */);
1676 DBG_ERR("Failed to setup cmdline parser\n");
1681 pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
1683 DBG_ERR("Failed to setup popt parser!\n");
1688 while ((opt = poptGetNextOpt(pc)) != -1) {
1690 /* Don't become a daemon */
1700 case OPT_NO_PROCESS_GROUP:
1701 no_process_group = true;
1707 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1708 poptBadOption(pc, 0), poptStrerror(opt));
1709 poptPrintUsage(pc, stderr, 0);
1714 /* Set environment variable so we don't recursively call ourselves.
1715 This may also be useful interactively. */
1716 if ( !winbind_off() ) {
1717 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1721 /* Initialise for running in non-root mode */
1724 set_remote_machine_name("winbindd", False);
1726 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1727 if (is_daemon && interactive) {
1728 d_fprintf(stderr,"\nERROR: "
1729 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1730 poptPrintUsage(pc, stderr, 0);
1734 log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
1740 if (log_stdout && Fork) {
1741 d_fprintf(stderr, "\nERROR: "
1742 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1743 poptPrintUsage(pc, stderr, 0);
1747 poptFreeContext(pc);
1749 if (!override_logfile) {
1751 if (asprintf(&lfile,"%s/log.winbindd",
1752 get_dyn_LOGFILEBASE()) > 0) {
1753 lp_set_logfile(lfile);
1759 setup_logging("winbindd", DEBUG_STDOUT);
1761 setup_logging("winbindd", DEBUG_FILE);
1765 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1766 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1768 /* After parsing the configuration file we setup the core path one more time
1769 * as the log file might have been set in the configuration and cores's
1770 * path is by default basename(lp_logfile()).
1772 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1774 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1775 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1776 DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1777 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"));
1780 /* Main 'samba' daemon will notify */
1781 daemon_sd_notifications(false);
1784 if (!cluster_probe_ok()) {
1788 /* Initialise messaging system */
1790 if (global_messaging_context() == NULL) {
1794 if (!winbindd_reload_services_file(NULL)) {
1795 DEBUG(0, ("error opening config file\n"));
1801 const char *idmap_backend;
1802 const char *invalid_backends[] = {
1803 "ad", "rfc2307", "rid",
1806 idmap_backend = lp_idmap_default_backend();
1807 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1808 ok = strequal(idmap_backend, invalid_backends[i]);
1810 DBG_ERR("FATAL: Invalid idmap backend %s "
1811 "configured as the default backend!\n",
1818 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1820 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1821 lp_lock_directory(), strerror(errno)));
1825 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1827 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1828 lp_pid_directory(), strerror(errno)));
1834 if (!secrets_init()) {
1836 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1840 status = rpccli_pre_open_netlogon_creds();
1841 if (!NT_STATUS_IS_OK(status)) {
1842 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1843 nt_errstr(status)));
1847 /* Unblock all signals we are interested in as they may have been
1848 blocked by the parent process. */
1850 BlockSignals(False, SIGINT);
1851 BlockSignals(False, SIGQUIT);
1852 BlockSignals(False, SIGTERM);
1853 BlockSignals(False, SIGUSR1);
1854 BlockSignals(False, SIGUSR2);
1855 BlockSignals(False, SIGHUP);
1856 BlockSignals(False, SIGCHLD);
1859 become_daemon(Fork, no_process_group, log_stdout);
1861 daemon_status("winbindd", "Starting process ...");
1864 pidfile_create(lp_pid_directory(), "winbindd");
1868 * If we're interactive we want to set our own process group for
1869 * signal management.
1871 if (interactive && !no_process_group)
1872 setpgid( (pid_t)0, (pid_t)0);
1877 /* Don't use winbindd_reinit_after_fork here as
1878 * we're just starting up and haven't created any
1879 * winbindd-specific resources we must free yet. JRA.
1882 status = reinit_after_fork(global_messaging_context(),
1883 global_event_context(),
1885 if (!NT_STATUS_IS_OK(status)) {
1886 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1889 ok = initialize_password_db(true, global_event_context());
1891 exit_daemon("Failed to initialize passdb backend! "
1892 "Check the 'passdb backend' variable in your "
1893 "smb.conf file.", EINVAL);
1897 * Do not initialize the parent-child-pipe before becoming
1898 * a daemon: this is used to detect a died parent in the child
1901 status = init_before_fork();
1902 if (!NT_STATUS_IS_OK(status)) {
1903 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1906 winbindd_register_handlers(global_messaging_context(), !Fork);
1908 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1912 status = init_system_session_info(NULL);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1917 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1919 /* Register the endpoint server to dispatch calls locally through
1920 * the legacy api_struct */
1921 ep_server = lsarpc_get_ep_server();
1922 if (ep_server == NULL) {
1923 DBG_ERR("Failed to get 'lsarpc' endpoint server\n");
1926 status = dcerpc_register_ep_server(ep_server);
1927 if (!NT_STATUS_IS_OK(status)) {
1928 DBG_ERR("Failed to register 'lsarpc' endpoint "
1929 "server: %s\n", nt_errstr(status));
1933 /* Register the endpoint server to dispatch calls locally through
1934 * the legacy api_struct */
1935 ep_server = samr_get_ep_server();
1936 if (ep_server == NULL) {
1937 DBG_ERR("Failed to get 'samr' endpoint server\n");
1940 status = dcerpc_register_ep_server(ep_server);
1941 if (!NT_STATUS_IS_OK(status)) {
1942 DBG_ERR("Failed to register 'samr' endpoint "
1943 "server: %s\n", nt_errstr(status));
1947 ep_server = winbind_get_ep_server();
1948 if (ep_server == NULL) {
1949 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1952 status = dcerpc_register_ep_server(ep_server);
1953 if (!NT_STATUS_IS_OK(status)) {
1954 DBG_ERR("Failed to register 'winbind' endpoint "
1955 "server: %s\n", nt_errstr(status));
1959 dce_ctx = global_dcesrv_context();
1961 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1963 /* Init all registered ep servers */
1964 status = dcesrv_init_registered_ep_servers(dce_ctx);
1965 if (!NT_STATUS_IS_OK(status)) {
1966 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1971 winbindd_init_addrchange(NULL, global_event_context(),
1972 global_messaging_context());
1974 /* setup listen sockets */
1976 if (!winbindd_setup_listeners()) {
1977 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1980 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1985 daemon_ready("winbindd");
1990 /* Loop waiting for requests */
1992 frame = talloc_stackframe();
1994 if (tevent_loop_once(global_event_context()) == -1) {
1995 DEBUG(1, ("tevent_loop_once() failed: %s\n",