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 struct tevent_timer *te = NULL;
1388 /* Setup signal handlers */
1390 if (!winbindd_setup_sig_term_handler(true))
1392 if (!winbindd_setup_stdin_handler(true, foreground))
1394 if (!winbindd_setup_sig_hup_handler(NULL))
1396 if (!winbindd_setup_sig_chld_handler())
1398 if (!winbindd_setup_sig_usr2_handler())
1401 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1404 * Ensure all cache and idmap caches are consistent
1405 * and initialized before we startup.
1407 if (!winbindd_cache_validate_and_initialize()) {
1411 /* React on 'smbcontrol winbindd reload-config' in the same way
1412 as to SIGHUP signal */
1413 messaging_register(msg_ctx, NULL,
1414 MSG_SMB_CONF_UPDATED,
1415 winbindd_msg_reload_services_parent);
1416 messaging_register(msg_ctx, NULL,
1417 MSG_SHUTDOWN, msg_shutdown);
1419 /* Handle online/offline messages. */
1420 messaging_register(msg_ctx, NULL,
1421 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1422 messaging_register(msg_ctx, NULL,
1423 MSG_WINBIND_ONLINE, winbind_msg_online);
1424 messaging_register(msg_ctx, NULL,
1425 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1427 /* Handle domain online/offline messages for domains */
1428 messaging_register(global_messaging_context(), NULL,
1429 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1430 messaging_register(global_messaging_context(), NULL,
1431 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1433 messaging_register(msg_ctx, NULL,
1434 MSG_WINBIND_VALIDATE_CACHE,
1435 winbind_msg_validate_cache);
1437 messaging_register(msg_ctx, NULL,
1438 MSG_WINBIND_DUMP_DOMAIN_LIST,
1439 winbind_msg_dump_domain_list);
1441 messaging_register(msg_ctx, NULL,
1442 MSG_WINBIND_IP_DROPPED,
1443 winbind_msg_ip_dropped_parent);
1445 /* Register handler for MSG_DEBUG. */
1446 messaging_register(msg_ctx, NULL,
1450 messaging_register(msg_ctx, NULL,
1451 MSG_WINBIND_DISCONNECT_DC,
1452 winbind_disconnect_dc_parent);
1454 netsamlogon_cache_init(); /* Non-critical */
1456 /* clear the cached list of trusted domains */
1460 if (!init_domain_list()) {
1461 DEBUG(0,("unable to initialize domain list\n"));
1466 init_locator_child();
1468 smb_nscd_flush_user_cache();
1469 smb_nscd_flush_group_cache();
1471 if (!lp_winbind_scan_trusted_domains()) {
1472 scan_trusts = false;
1475 if (!lp_allow_trusted_domains()) {
1476 scan_trusts = false;
1480 scan_trusts = false;
1484 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1485 rescan_trusted_domains, NULL) == NULL) {
1486 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1491 te = tevent_add_timer(global_event_context(),
1494 winbindd_ping_offline_domains,
1497 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
1501 status = wb_irpc_register();
1503 if (!NT_STATUS_IS_OK(status)) {
1504 DEBUG(0, ("Could not register IRPC handlers\n"));
1509 struct winbindd_addrchanged_state {
1510 struct addrchange_context *ctx;
1511 struct tevent_context *ev;
1512 struct messaging_context *msg_ctx;
1515 static void winbindd_addr_changed(struct tevent_req *req);
1517 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1518 struct tevent_context *ev,
1519 struct messaging_context *msg_ctx)
1521 struct winbindd_addrchanged_state *state;
1522 struct tevent_req *req;
1525 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1526 if (state == NULL) {
1527 DEBUG(10, ("talloc failed\n"));
1531 state->msg_ctx = msg_ctx;
1533 status = addrchange_context_create(state, &state->ctx);
1534 if (!NT_STATUS_IS_OK(status)) {
1535 DEBUG(10, ("addrchange_context_create failed: %s\n",
1536 nt_errstr(status)));
1540 req = addrchange_send(state, ev, state->ctx);
1542 DEBUG(0, ("addrchange_send failed\n"));
1546 tevent_req_set_callback(req, winbindd_addr_changed, state);
1549 static void winbindd_addr_changed(struct tevent_req *req)
1551 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1552 req, struct winbindd_addrchanged_state);
1553 enum addrchange_type type;
1554 struct sockaddr_storage addr;
1557 status = addrchange_recv(req, &type, &addr);
1559 if (!NT_STATUS_IS_OK(status)) {
1560 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1561 nt_errstr(status)));
1565 if (type == ADDRCHANGE_DEL) {
1566 char addrstr[INET6_ADDRSTRLEN];
1569 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1571 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1574 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1576 status = messaging_send(state->msg_ctx,
1577 messaging_server_id(state->msg_ctx),
1578 MSG_WINBIND_IP_DROPPED, &blob);
1579 if (!NT_STATUS_IS_OK(status)) {
1580 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1581 nt_errstr(status)));
1584 req = addrchange_send(state, state->ev, state->ctx);
1586 DEBUG(0, ("addrchange_send failed\n"));
1590 tevent_req_set_callback(req, winbindd_addr_changed, state);
1595 int main(int argc, const char **argv)
1597 static bool is_daemon = False;
1598 static bool Fork = True;
1599 static bool log_stdout = False;
1600 static bool no_process_group = False;
1604 OPT_NO_PROCESS_GROUP
1606 struct poptOption long_options[] = {
1609 .longName = "foreground",
1611 .argInfo = POPT_ARG_NONE,
1614 .descrip = "Daemon in foreground mode",
1617 .longName = "no-process-group",
1619 .argInfo = POPT_ARG_NONE,
1621 .val = OPT_NO_PROCESS_GROUP,
1622 .descrip = "Don't create a new process group",
1625 .longName = "daemon",
1627 .argInfo = POPT_ARG_NONE,
1630 .descrip = "Become a daemon (default)",
1633 .longName = "interactive",
1635 .argInfo = POPT_ARG_NONE,
1638 .descrip = "Interactive mode",
1641 .longName = "no-caching",
1643 .argInfo = POPT_ARG_NONE,
1646 .descrip = "Disable caching",
1652 const struct loadparm_substitution *lp_sub =
1653 loadparm_s3_global_substitution();
1659 const struct dcesrv_endpoint_server *ep_server = NULL;
1660 struct dcesrv_context *dce_ctx = NULL;
1662 setproctitle_init(argc, discard_const(argv), environ);
1665 * Do this before any other talloc operation
1667 talloc_enable_null_tracking();
1668 frame = talloc_stackframe();
1671 * We want total control over the permissions on created files,
1672 * so set our umask to 0.
1678 /* glibc (?) likes to print "User defined signal 1" and exit if a
1679 SIGUSR[12] is received before a handler is installed */
1681 CatchSignal(SIGUSR1, SIG_IGN);
1682 CatchSignal(SIGUSR2, SIG_IGN);
1684 ok = samba_cmdline_init(frame,
1685 SAMBA_CMDLINE_CONFIG_SERVER,
1686 true /* require_smbconf */);
1688 DBG_ERR("Failed to setup cmdline parser\n");
1693 pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
1695 DBG_ERR("Failed to setup popt parser!\n");
1700 while ((opt = poptGetNextOpt(pc)) != -1) {
1702 /* Don't become a daemon */
1712 case OPT_NO_PROCESS_GROUP:
1713 no_process_group = true;
1719 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1720 poptBadOption(pc, 0), poptStrerror(opt));
1721 poptPrintUsage(pc, stderr, 0);
1726 /* Set environment variable so we don't recursively call ourselves.
1727 This may also be useful interactively. */
1728 if ( !winbind_off() ) {
1729 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1733 /* Initialise for running in non-root mode */
1736 set_remote_machine_name("winbindd", False);
1738 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1739 if (is_daemon && interactive) {
1740 d_fprintf(stderr,"\nERROR: "
1741 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1742 poptPrintUsage(pc, stderr, 0);
1746 log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
1752 if (log_stdout && Fork) {
1753 d_fprintf(stderr, "\nERROR: "
1754 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1755 poptPrintUsage(pc, stderr, 0);
1759 poptFreeContext(pc);
1761 if (!override_logfile) {
1763 if (asprintf(&lfile,"%s/log.winbindd",
1764 get_dyn_LOGFILEBASE()) > 0) {
1765 lp_set_logfile(lfile);
1771 setup_logging("winbindd", DEBUG_STDOUT);
1773 setup_logging("winbindd", DEBUG_FILE);
1777 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1778 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1780 /* After parsing the configuration file we setup the core path one more time
1781 * as the log file might have been set in the configuration and cores's
1782 * path is by default basename(lp_logfile()).
1784 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1786 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1787 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1788 DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1789 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"));
1792 /* Main 'samba' daemon will notify */
1793 daemon_sd_notifications(false);
1796 if (lp_security() == SEC_ADS) {
1797 const char *realm = lp_realm();
1798 const char *workgroup = lp_workgroup();
1800 if (workgroup == NULL || strlen(workgroup) == 0) {
1801 DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
1802 "parameter is required to be set!\n");
1806 if (realm == NULL || strlen(realm) == 0) {
1807 DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
1808 "parameter is required to be set!\n");
1813 if (!cluster_probe_ok()) {
1817 /* Initialise messaging system */
1819 if (global_messaging_context() == NULL) {
1823 if (!winbindd_reload_services_file(NULL)) {
1824 DEBUG(0, ("error opening config file\n"));
1830 const char *idmap_backend;
1831 const char *invalid_backends[] = {
1832 "ad", "rfc2307", "rid",
1835 idmap_backend = lp_idmap_default_backend();
1836 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1837 ok = strequal(idmap_backend, invalid_backends[i]);
1839 DBG_ERR("FATAL: Invalid idmap backend %s "
1840 "configured as the default backend!\n",
1847 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1849 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1850 lp_lock_directory(), strerror(errno)));
1854 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1856 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1857 lp_pid_directory(), strerror(errno)));
1863 if (!secrets_init()) {
1865 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1869 status = rpccli_pre_open_netlogon_creds();
1870 if (!NT_STATUS_IS_OK(status)) {
1871 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1872 nt_errstr(status)));
1876 /* Unblock all signals we are interested in as they may have been
1877 blocked by the parent process. */
1879 BlockSignals(False, SIGINT);
1880 BlockSignals(False, SIGQUIT);
1881 BlockSignals(False, SIGTERM);
1882 BlockSignals(False, SIGUSR1);
1883 BlockSignals(False, SIGUSR2);
1884 BlockSignals(False, SIGHUP);
1885 BlockSignals(False, SIGCHLD);
1888 become_daemon(Fork, no_process_group, log_stdout);
1890 daemon_status("winbindd", "Starting process ...");
1893 pidfile_create(lp_pid_directory(), "winbindd");
1897 * If we're interactive we want to set our own process group for
1898 * signal management.
1900 if (interactive && !no_process_group)
1901 setpgid( (pid_t)0, (pid_t)0);
1906 /* Don't use winbindd_reinit_after_fork here as
1907 * we're just starting up and haven't created any
1908 * winbindd-specific resources we must free yet. JRA.
1911 status = reinit_after_fork(global_messaging_context(),
1912 global_event_context(),
1914 if (!NT_STATUS_IS_OK(status)) {
1915 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1918 ok = initialize_password_db(true, global_event_context());
1920 exit_daemon("Failed to initialize passdb backend! "
1921 "Check the 'passdb backend' variable in your "
1922 "smb.conf file.", EINVAL);
1926 * Do not initialize the parent-child-pipe before becoming
1927 * a daemon: this is used to detect a died parent in the child
1930 status = init_before_fork();
1931 if (!NT_STATUS_IS_OK(status)) {
1932 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1935 winbindd_register_handlers(global_messaging_context(), !Fork);
1937 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1941 status = init_system_session_info(NULL);
1942 if (!NT_STATUS_IS_OK(status)) {
1943 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1946 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1948 /* Register the endpoint server to dispatch calls locally through
1949 * the legacy api_struct */
1950 ep_server = lsarpc_get_ep_server();
1951 if (ep_server == NULL) {
1952 DBG_ERR("Failed to get 'lsarpc' endpoint server\n");
1955 status = dcerpc_register_ep_server(ep_server);
1956 if (!NT_STATUS_IS_OK(status)) {
1957 DBG_ERR("Failed to register 'lsarpc' endpoint "
1958 "server: %s\n", nt_errstr(status));
1962 /* Register the endpoint server to dispatch calls locally through
1963 * the legacy api_struct */
1964 ep_server = samr_get_ep_server();
1965 if (ep_server == NULL) {
1966 DBG_ERR("Failed to get 'samr' endpoint server\n");
1969 status = dcerpc_register_ep_server(ep_server);
1970 if (!NT_STATUS_IS_OK(status)) {
1971 DBG_ERR("Failed to register 'samr' endpoint "
1972 "server: %s\n", nt_errstr(status));
1976 ep_server = winbind_get_ep_server();
1977 if (ep_server == NULL) {
1978 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1981 status = dcerpc_register_ep_server(ep_server);
1982 if (!NT_STATUS_IS_OK(status)) {
1983 DBG_ERR("Failed to register 'winbind' endpoint "
1984 "server: %s\n", nt_errstr(status));
1988 dce_ctx = global_dcesrv_context();
1990 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1992 /* Init all registered ep servers */
1993 status = dcesrv_init_registered_ep_servers(dce_ctx);
1994 if (!NT_STATUS_IS_OK(status)) {
1995 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
2000 winbindd_init_addrchange(NULL, global_event_context(),
2001 global_messaging_context());
2003 /* setup listen sockets */
2005 if (!winbindd_setup_listeners()) {
2006 exit_daemon("Winbindd failed to setup listeners", EPIPE);
2009 irpc_add_name(winbind_imessaging_context(), "winbind_server");
2014 daemon_ready("winbindd");
2019 /* Loop waiting for requests */
2021 frame = talloc_stackframe();
2023 if (tevent_loop_once(global_event_context()) == -1) {
2024 DEBUG(1, ("tevent_loop_once() failed: %s\n",