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"
50 #define DBGC_CLASS DBGC_WINBIND
52 #define SCRUB_CLIENTS_INTERVAL 5
54 static bool client_is_idle(struct winbindd_cli_state *state);
55 static void remove_client(struct winbindd_cli_state *state);
56 static void winbindd_setup_max_fds(void);
58 static bool opt_nocache = False;
59 static bool interactive = False;
61 extern bool override_logfile;
63 struct imessaging_context *winbind_imessaging_context(void)
65 static struct imessaging_context *msg = NULL;
66 struct messaging_context *msg_ctx;
67 struct server_id myself;
68 struct loadparm_context *lp_ctx;
74 msg_ctx = server_messaging_context();
75 if (msg_ctx == NULL) {
76 smb_panic("server_messaging_context failed\n");
78 myself = messaging_server_id(msg_ctx);
80 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
82 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
86 * Note we MUST use the NULL context here, not the autofree context,
87 * to avoid side effects in forked children exiting.
89 msg = imessaging_init(NULL, lp_ctx, myself, server_event_context());
90 talloc_unlink(NULL, lp_ctx);
93 smb_panic("Could not init winbindd's messaging context.\n");
98 /* Reload configuration */
100 static bool reload_services_file(const char *lfile)
105 char *fname = lp_next_configfile(talloc_tos());
107 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
108 set_dyn_CONFIGFILE(fname);
113 /* if this is a child, restore the logfile to the special
114 name - <domain>, idmap, etc. */
115 if (lfile && *lfile) {
116 lp_set_logfile(lfile);
120 ret = lp_load_global(get_dyn_CONFIGFILE());
124 winbindd_setup_max_fds();
130 static void winbindd_status(void)
132 struct winbindd_cli_state *tmp;
134 DEBUG(0, ("winbindd status:\n"));
136 /* Print client state information */
138 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
140 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
141 DEBUG(2, ("\tclient list:\n"));
142 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
143 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
144 (unsigned long)tmp->pid, tmp->sock,
145 client_is_idle(tmp) ? "idle" : "active"));
150 /* Flush client cache */
152 static void flush_caches(void)
154 /* We need to invalidate cached user list entries on a SIGHUP
155 otherwise cached access denied errors due to restrict anonymous
156 hang around until the sequence number changes. */
158 if (!wcache_invalidate_cache()) {
159 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
160 if (!winbindd_cache_validate_and_initialize()) {
166 static void flush_caches_noinit(void)
169 * We need to invalidate cached user list entries on a SIGHUP
170 * otherwise cached access denied errors due to restrict anonymous
171 * hang around until the sequence number changes.
173 * Skip uninitialized domains when flush cache.
174 * If domain is not initialized, it means it is never
175 * used or never become online. look, wcache_invalidate_cache()
176 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
177 * for unused domains and large traffic for primay domain's DC if there
181 if (!wcache_invalidate_cache_noinit()) {
182 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
183 if (!winbindd_cache_validate_and_initialize()) {
189 /* Handle the signal by unlinking socket and exiting */
191 static void terminate(bool is_parent)
194 /* When parent goes away we should
195 * remove the socket file. Not so
196 * when children terminate.
200 if (asprintf(&path, "%s/%s",
201 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
209 gencache_stabilize();
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(server_event_context(), bool);
279 se = tevent_add_signal(server_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(server_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(server_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(server_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(server_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(server_event_context(),
377 se = tevent_add_signal(server_event_context(),
378 server_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(server_event_context(),
408 server_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(server_event_context(),
434 server_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_dispatch_table {
525 enum winbindd_cmd cmd;
526 void (*fn)(struct winbindd_cli_state *state);
527 const char *winbindd_cmd_name;
528 } dispatch_table[] = {
530 /* Enumeration functions */
532 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
537 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
538 /* Credential cache access */
542 { WINBINDD_NUM_CMDS, NULL, "NONE" }
545 static struct winbindd_bool_dispatch_table {
546 enum winbindd_cmd cmd;
547 bool (*fn)(struct winbindd_cli_state *state);
548 const char *cmd_name;
549 } bool_dispatch_table[] = {
550 { WINBINDD_INTERFACE_VERSION,
551 winbindd_interface_version,
552 "INTERFACE_VERSION" },
559 { WINBINDD_DOMAIN_NAME,
560 winbindd_domain_name,
562 { WINBINDD_NETBIOS_NAME,
563 winbindd_netbios_name,
568 { WINBINDD_CCACHE_NTLMAUTH,
569 winbindd_ccache_ntlm_auth,
571 { WINBINDD_CCACHE_SAVE,
572 winbindd_ccache_save,
574 { WINBINDD_PRIV_PIPE_DIR,
575 winbindd_priv_pipe_dir,
576 "WINBINDD_PRIV_PIPE_DIR" },
579 struct winbindd_async_dispatch_table {
580 enum winbindd_cmd cmd;
581 const char *cmd_name;
582 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
583 struct tevent_context *ev,
584 struct winbindd_cli_state *cli,
585 struct winbindd_request *request);
586 NTSTATUS (*recv_req)(struct tevent_req *req,
587 struct winbindd_response *presp);
590 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
591 { WINBINDD_LOOKUPSID, "LOOKUPSID",
592 winbindd_lookupsid_send, winbindd_lookupsid_recv },
593 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
594 winbindd_lookupsids_send, winbindd_lookupsids_recv },
595 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
596 winbindd_lookupname_send, winbindd_lookupname_recv },
597 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
598 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
599 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
600 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
601 { WINBINDD_GETPWSID, "GETPWSID",
602 winbindd_getpwsid_send, winbindd_getpwsid_recv },
603 { WINBINDD_GETPWNAM, "GETPWNAM",
604 winbindd_getpwnam_send, winbindd_getpwnam_recv },
605 { WINBINDD_GETPWUID, "GETPWUID",
606 winbindd_getpwuid_send, winbindd_getpwuid_recv },
607 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
608 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
609 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
610 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
611 { WINBINDD_GETGROUPS, "GETGROUPS",
612 winbindd_getgroups_send, winbindd_getgroups_recv },
613 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
614 winbindd_show_sequence_send, winbindd_show_sequence_recv },
615 { WINBINDD_GETGRGID, "GETGRGID",
616 winbindd_getgrgid_send, winbindd_getgrgid_recv },
617 { WINBINDD_GETGRNAM, "GETGRNAM",
618 winbindd_getgrnam_send, winbindd_getgrnam_recv },
619 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
620 winbindd_getusersids_send, winbindd_getusersids_recv },
621 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
622 winbindd_lookuprids_send, winbindd_lookuprids_recv },
623 { WINBINDD_SETPWENT, "SETPWENT",
624 winbindd_setpwent_send, winbindd_setpwent_recv },
625 { WINBINDD_GETPWENT, "GETPWENT",
626 winbindd_getpwent_send, winbindd_getpwent_recv },
627 { WINBINDD_ENDPWENT, "ENDPWENT",
628 winbindd_endpwent_send, winbindd_endpwent_recv },
629 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
630 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
631 { WINBINDD_GETDCNAME, "GETDCNAME",
632 winbindd_getdcname_send, winbindd_getdcname_recv },
633 { WINBINDD_SETGRENT, "SETGRENT",
634 winbindd_setgrent_send, winbindd_setgrent_recv },
635 { WINBINDD_GETGRENT, "GETGRENT",
636 winbindd_getgrent_send, winbindd_getgrent_recv },
637 { WINBINDD_ENDGRENT, "ENDGRENT",
638 winbindd_endgrent_send, winbindd_endgrent_recv },
639 { WINBINDD_LIST_USERS, "LIST_USERS",
640 winbindd_list_users_send, winbindd_list_users_recv },
641 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
642 winbindd_list_groups_send, winbindd_list_groups_recv },
643 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
644 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
645 { WINBINDD_PING_DC, "PING_DC",
646 winbindd_ping_dc_send, winbindd_ping_dc_recv },
647 { WINBINDD_PAM_AUTH, "PAM_AUTH",
648 winbindd_pam_auth_send, winbindd_pam_auth_recv },
649 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
650 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
651 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
652 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
653 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
654 winbindd_pam_chng_pswd_auth_crap_send,
655 winbindd_pam_chng_pswd_auth_crap_recv },
656 { WINBINDD_WINS_BYIP, "WINS_BYIP",
657 winbindd_wins_byip_send, winbindd_wins_byip_recv },
658 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
659 winbindd_wins_byname_send, winbindd_wins_byname_recv },
661 { 0, NULL, NULL, NULL }
664 static struct winbindd_async_dispatch_table async_priv_table[] = {
665 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
666 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
667 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
668 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
669 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
670 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
671 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
672 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
674 { 0, NULL, NULL, NULL }
677 static void wb_request_done(struct tevent_req *req);
679 static void process_request(struct winbindd_cli_state *state)
681 struct winbindd_dispatch_table *table = dispatch_table;
682 struct winbindd_async_dispatch_table *atable;
686 state->mem_ctx = talloc_named(state, 0, "winbind request");
687 if (state->mem_ctx == NULL)
690 /* Remember who asked us. */
691 state->pid = state->request->pid;
693 state->cmd_name = "unknown request";
694 state->recv_fn = NULL;
695 /* client is newest */
696 winbindd_promote_client(state);
698 /* Process command */
700 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
701 if (state->request->cmd == atable->cmd) {
706 if ((atable->send_req == NULL) && state->privileged) {
707 for (atable = async_priv_table; atable->send_req;
709 if (state->request->cmd == atable->cmd) {
715 if (atable->send_req != NULL) {
716 struct tevent_req *req;
718 state->cmd_name = atable->cmd_name;
719 state->recv_fn = atable->recv_req;
721 DEBUG(10, ("process_request: Handling async request %d:%s\n",
722 (int)state->pid, state->cmd_name));
724 req = atable->send_req(state->mem_ctx, server_event_context(),
725 state, state->request);
727 DEBUG(0, ("process_request: atable->send failed for "
728 "%s\n", atable->cmd_name));
729 request_error(state);
732 tevent_req_set_callback(req, wb_request_done, state);
736 state->response = talloc_zero(state->mem_ctx,
737 struct winbindd_response);
738 if (state->response == NULL) {
739 DEBUG(10, ("talloc failed\n"));
740 remove_client(state);
743 state->response->result = WINBINDD_PENDING;
744 state->response->length = sizeof(struct winbindd_response);
746 for (table = dispatch_table; table->fn; table++) {
747 if (state->request->cmd == table->cmd) {
748 DEBUG(10,("process_request: request fn %s\n",
749 table->winbindd_cmd_name ));
750 state->cmd_name = table->winbindd_cmd_name;
756 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
757 if (bool_dispatch_table[i].cmd == state->request->cmd) {
762 if (i == ARRAY_SIZE(bool_dispatch_table)) {
763 DEBUG(10,("process_request: unknown request fn number %d\n",
764 (int)state->request->cmd ));
765 request_error(state);
769 DBG_DEBUG("process_request: request fn %s\n",
770 bool_dispatch_table[i].cmd_name);
772 ok = bool_dispatch_table[i].fn(state);
777 request_error(state);
781 static void wb_request_done(struct tevent_req *req)
783 struct winbindd_cli_state *state = tevent_req_callback_data(
784 req, struct winbindd_cli_state);
787 state->response = talloc_zero(state->mem_ctx,
788 struct winbindd_response);
789 if (state->response == NULL) {
790 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
791 (int)state->pid, state->cmd_name));
792 remove_client(state);
795 state->response->result = WINBINDD_PENDING;
796 state->response->length = sizeof(struct winbindd_response);
798 status = state->recv_fn(req, state->response);
801 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
802 (int)state->pid, state->cmd_name, nt_errstr(status)));
804 if (!NT_STATUS_IS_OK(status)) {
805 request_error(state);
812 * This is the main event loop of winbind requests. It goes through a
813 * state-machine of 3 read/write requests, 4 if you have extra data to send.
815 * An idle winbind client has a read request of 4 bytes outstanding,
816 * finalizing function is request_len_recv, checking the length. request_recv
817 * then processes the packet. The processing function then at some point has
818 * to call request_finished which schedules sending the response.
821 static void request_finished(struct winbindd_cli_state *state);
823 static void winbind_client_request_read(struct tevent_req *req);
824 static void winbind_client_response_written(struct tevent_req *req);
825 static void winbind_client_activity(struct tevent_req *req);
827 static void request_finished(struct winbindd_cli_state *state)
829 struct tevent_req *req;
831 /* free client socket monitoring request */
832 TALLOC_FREE(state->io_req);
834 TALLOC_FREE(state->request);
836 req = wb_resp_write_send(state, server_event_context(),
837 state->out_queue, state->sock,
840 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
841 (int)state->pid, state->cmd_name));
842 remove_client(state);
845 tevent_req_set_callback(req, winbind_client_response_written, state);
849 static void winbind_client_response_written(struct tevent_req *req)
851 struct winbindd_cli_state *state = tevent_req_callback_data(
852 req, struct winbindd_cli_state);
856 state->io_req = NULL;
858 ret = wb_resp_write_recv(req, &err);
863 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
864 (int)state->pid, state->cmd_name, strerror(err)));
865 remove_client(state);
869 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
870 "to client\n", (int)state->pid, state->cmd_name));
872 TALLOC_FREE(state->mem_ctx);
873 state->response = NULL;
874 state->cmd_name = "no request";
875 state->recv_fn = NULL;
877 req = wb_req_read_send(state, server_event_context(), state->sock,
878 WINBINDD_MAX_EXTRA_DATA);
880 remove_client(state);
883 tevent_req_set_callback(req, winbind_client_request_read, state);
887 void request_error(struct winbindd_cli_state *state)
889 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
890 state->response->result = WINBINDD_ERROR;
891 request_finished(state);
894 void request_ok(struct winbindd_cli_state *state)
896 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
897 state->response->result = WINBINDD_OK;
898 request_finished(state);
901 /* Process a new connection by adding it to the client connection list */
903 static void new_connection(int listen_sock, bool privileged)
905 struct sockaddr_un sunaddr;
906 struct winbindd_cli_state *state;
907 struct tevent_req *req;
911 /* Accept connection */
913 len = sizeof(sunaddr);
915 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
918 if (errno != EINTR) {
919 DEBUG(0, ("Failed to accept socket - %s\n",
924 smb_set_close_on_exec(sock);
926 DEBUG(6,("accepted socket %d\n", sock));
928 /* Create new connection structure */
930 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
937 state->out_queue = tevent_queue_create(state, "winbind client reply");
938 if (state->out_queue == NULL) {
944 state->privileged = privileged;
946 req = wb_req_read_send(state, server_event_context(), state->sock,
947 WINBINDD_MAX_EXTRA_DATA);
953 tevent_req_set_callback(req, winbind_client_request_read, state);
956 /* Add to connection list */
958 winbindd_add_client(state);
961 static void winbind_client_request_read(struct tevent_req *req)
963 struct winbindd_cli_state *state = tevent_req_callback_data(
964 req, struct winbindd_cli_state);
968 state->io_req = NULL;
970 ret = wb_req_read_recv(req, state, &state->request, &err);
974 DEBUG(6, ("closing socket %d, client exited\n",
977 DEBUG(2, ("Could not read client request from fd %d: "
978 "%s\n", state->sock, strerror(err)));
982 remove_client(state);
986 req = wait_for_read_send(state, server_event_context(), state->sock,
989 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
990 " wait_for_read_send failed - removing client\n",
991 (int)state->pid, state->cmd_name));
992 remove_client(state);
995 tevent_req_set_callback(req, winbind_client_activity, state);
998 process_request(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 /* Remove a client connection from client connection list */
1034 static void remove_client(struct winbindd_cli_state *state)
1039 /* It's a dead client - hold a funeral */
1041 if (state == NULL) {
1046 * We need to remove a pending wb_req_read_*
1047 * or wb_resp_write_* request before closing the
1050 * This is important as they might have used tevent_add_fd() and we
1051 * use the epoll * backend on linux. So we must remove the tevent_fd
1052 * before closing the fd.
1054 * Otherwise we might hit a race with close_conns_after_fork() (via
1055 * winbindd_reinit_after_fork()) where a file description
1056 * is still open in a child, which means it's still active in
1057 * the parents epoll queue, but the related tevent_fd is already
1058 * already gone in the parent.
1062 TALLOC_FREE(state->io_req);
1064 if (state->sock != -1) {
1065 /* tell client, we are closing ... */
1066 nwritten = write(state->sock, &c, sizeof(c));
1067 if (nwritten == -1) {
1068 DEBUG(2, ("final write to client failed: %s\n",
1078 TALLOC_FREE(state->mem_ctx);
1080 /* Remove from list and free */
1082 winbindd_remove_client(state);
1086 /* Is a client idle? */
1088 static bool client_is_idle(struct winbindd_cli_state *state) {
1089 return (state->request == NULL &&
1090 state->response == NULL &&
1091 !state->pwent_state && !state->grent_state);
1094 /* Shutdown client connection which has been idle for the longest time */
1096 static bool remove_idle_client(void)
1098 struct winbindd_cli_state *state, *remove_state = NULL;
1101 for (state = winbindd_client_list(); state; state = state->next) {
1102 if (client_is_idle(state)) {
1104 /* list is sorted by access time */
1105 remove_state = state;
1110 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1111 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1112 remove_client(remove_state);
1120 * Terminate all clients whose requests have taken longer than
1121 * "winbind request timeout" seconds to process, or have been
1122 * idle for more than "winbind request timeout" seconds.
1125 static void remove_timed_out_clients(void)
1127 struct winbindd_cli_state *state, *prev = NULL;
1128 time_t curr_time = time(NULL);
1129 int timeout_val = lp_winbind_request_timeout();
1131 for (state = winbindd_client_list_tail(); state; state = prev) {
1134 prev = winbindd_client_list_prev(state);
1135 expiry_time = state->last_access + timeout_val;
1137 if (curr_time <= expiry_time) {
1138 /* list is sorted, previous clients in
1143 if (client_is_idle(state)) {
1144 DEBUG(5,("Idle client timed out, "
1145 "shutting down sock %d, pid %u\n",
1147 (unsigned int)state->pid));
1149 DEBUG(5,("Client request timed out, "
1150 "shutting down sock %d, pid %u\n",
1152 (unsigned int)state->pid));
1155 remove_client(state);
1159 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1160 struct tevent_timer *te,
1161 struct timeval current_time,
1164 remove_timed_out_clients();
1165 if (tevent_add_timer(ev, ev,
1166 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1167 winbindd_scrub_clients_handler, NULL) == NULL) {
1168 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1173 struct winbindd_listen_state {
1178 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1179 struct tevent_fd *fde,
1183 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1184 struct winbindd_listen_state);
1186 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1187 DEBUG(5,("winbindd: Exceeding %d client "
1188 "connections, removing idle "
1189 "connection.\n", lp_winbind_max_clients()));
1190 if (!remove_idle_client()) {
1191 DEBUG(0,("winbindd: Exceeding %d "
1192 "client connections, no idle "
1193 "connection found\n",
1194 lp_winbind_max_clients()));
1198 remove_timed_out_clients();
1199 new_connection(s->fd, s->privileged);
1203 * Winbindd socket accessor functions
1206 char *get_winbind_priv_pipe_dir(void)
1208 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1211 static void winbindd_setup_max_fds(void)
1213 int num_fds = MAX_OPEN_FUDGEFACTOR;
1216 num_fds += lp_winbind_max_clients();
1217 /* Add some more to account for 2 sockets open
1218 when the client transitions from unprivileged
1219 to privileged socket
1221 num_fds += lp_winbind_max_clients() / 10;
1223 /* Add one socket per child process
1224 (yeah there are child processes other than the
1225 domain children but only domain children can vary
1228 num_fds += lp_winbind_max_domain_connections() *
1229 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1231 actual_fds = set_maxfiles(num_fds);
1233 if (actual_fds < num_fds) {
1234 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1235 "requested %d open files, %d are available.\n",
1236 num_fds, actual_fds));
1240 static bool winbindd_setup_listeners(void)
1242 struct winbindd_listen_state *pub_state = NULL;
1243 struct winbindd_listen_state *priv_state = NULL;
1244 struct tevent_fd *fde;
1248 pub_state = talloc(server_event_context(),
1249 struct winbindd_listen_state);
1254 pub_state->privileged = false;
1255 pub_state->fd = create_pipe_sock(
1256 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1257 if (pub_state->fd == -1) {
1260 rc = listen(pub_state->fd, 5);
1265 fde = tevent_add_fd(server_event_context(), pub_state, pub_state->fd,
1266 TEVENT_FD_READ, winbindd_listen_fde_handler,
1269 close(pub_state->fd);
1272 tevent_fd_set_auto_close(fde);
1274 priv_state = talloc(server_event_context(),
1275 struct winbindd_listen_state);
1280 socket_path = get_winbind_priv_pipe_dir();
1281 if (socket_path == NULL) {
1285 priv_state->privileged = true;
1286 priv_state->fd = create_pipe_sock(
1287 socket_path, WINBINDD_SOCKET_NAME, 0750);
1288 TALLOC_FREE(socket_path);
1289 if (priv_state->fd == -1) {
1292 rc = listen(priv_state->fd, 5);
1297 fde = tevent_add_fd(server_event_context(), priv_state,
1298 priv_state->fd, TEVENT_FD_READ,
1299 winbindd_listen_fde_handler, priv_state);
1301 close(priv_state->fd);
1304 tevent_fd_set_auto_close(fde);
1306 winbindd_scrub_clients_handler(server_event_context(), NULL,
1307 timeval_current(), NULL);
1310 TALLOC_FREE(pub_state);
1311 TALLOC_FREE(priv_state);
1315 bool winbindd_use_idmap_cache(void)
1317 return !opt_nocache;
1320 bool winbindd_use_cache(void)
1322 return !opt_nocache;
1325 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1328 bool scan_trusts = true;
1330 /* Setup signal handlers */
1332 if (!winbindd_setup_sig_term_handler(true))
1334 if (!winbindd_setup_stdin_handler(true, foreground))
1336 if (!winbindd_setup_sig_hup_handler(NULL))
1338 if (!winbindd_setup_sig_chld_handler())
1340 if (!winbindd_setup_sig_usr2_handler())
1343 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1346 * Ensure all cache and idmap caches are consistent
1347 * and initialized before we startup.
1349 if (!winbindd_cache_validate_and_initialize()) {
1353 /* React on 'smbcontrol winbindd reload-config' in the same way
1354 as to SIGHUP signal */
1355 messaging_register(msg_ctx, NULL,
1356 MSG_SMB_CONF_UPDATED, msg_reload_services);
1357 messaging_register(msg_ctx, NULL,
1358 MSG_SHUTDOWN, msg_shutdown);
1360 /* Handle online/offline messages. */
1361 messaging_register(msg_ctx, NULL,
1362 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1363 messaging_register(msg_ctx, NULL,
1364 MSG_WINBIND_ONLINE, winbind_msg_online);
1365 messaging_register(msg_ctx, NULL,
1366 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1368 /* Handle domain online/offline messages for domains */
1369 messaging_register(server_messaging_context(), NULL,
1370 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1371 messaging_register(server_messaging_context(), NULL,
1372 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1374 messaging_register(msg_ctx, NULL,
1375 MSG_WINBIND_VALIDATE_CACHE,
1376 winbind_msg_validate_cache);
1378 messaging_register(msg_ctx, NULL,
1379 MSG_WINBIND_DUMP_DOMAIN_LIST,
1380 winbind_msg_dump_domain_list);
1382 messaging_register(msg_ctx, NULL,
1383 MSG_WINBIND_IP_DROPPED,
1384 winbind_msg_ip_dropped_parent);
1386 /* Register handler for MSG_DEBUG. */
1387 messaging_register(msg_ctx, NULL,
1391 messaging_register(msg_ctx, NULL,
1392 MSG_WINBIND_DISCONNECT_DC,
1393 winbind_disconnect_dc_parent);
1395 netsamlogon_cache_init(); /* Non-critical */
1397 /* clear the cached list of trusted domains */
1401 if (!init_domain_list()) {
1402 DEBUG(0,("unable to initialize domain list\n"));
1407 init_locator_child();
1409 smb_nscd_flush_user_cache();
1410 smb_nscd_flush_group_cache();
1412 if (!lp_winbind_scan_trusted_domains()) {
1413 scan_trusts = false;
1416 if (!lp_allow_trusted_domains()) {
1417 scan_trusts = false;
1421 scan_trusts = false;
1425 if (tevent_add_timer(server_event_context(), NULL, timeval_zero(),
1426 rescan_trusted_domains, NULL) == NULL) {
1427 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1432 status = wb_irpc_register();
1434 if (!NT_STATUS_IS_OK(status)) {
1435 DEBUG(0, ("Could not register IRPC handlers\n"));
1440 struct winbindd_addrchanged_state {
1441 struct addrchange_context *ctx;
1442 struct tevent_context *ev;
1443 struct messaging_context *msg_ctx;
1446 static void winbindd_addr_changed(struct tevent_req *req);
1448 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1449 struct tevent_context *ev,
1450 struct messaging_context *msg_ctx)
1452 struct winbindd_addrchanged_state *state;
1453 struct tevent_req *req;
1456 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1457 if (state == NULL) {
1458 DEBUG(10, ("talloc failed\n"));
1462 state->msg_ctx = msg_ctx;
1464 status = addrchange_context_create(state, &state->ctx);
1465 if (!NT_STATUS_IS_OK(status)) {
1466 DEBUG(10, ("addrchange_context_create failed: %s\n",
1467 nt_errstr(status)));
1471 req = addrchange_send(state, ev, state->ctx);
1473 DEBUG(0, ("addrchange_send failed\n"));
1477 tevent_req_set_callback(req, winbindd_addr_changed, state);
1480 static void winbindd_addr_changed(struct tevent_req *req)
1482 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1483 req, struct winbindd_addrchanged_state);
1484 enum addrchange_type type;
1485 struct sockaddr_storage addr;
1488 status = addrchange_recv(req, &type, &addr);
1490 if (!NT_STATUS_IS_OK(status)) {
1491 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1492 nt_errstr(status)));
1496 if (type == ADDRCHANGE_DEL) {
1497 char addrstr[INET6_ADDRSTRLEN];
1500 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1502 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1505 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1507 status = messaging_send(state->msg_ctx,
1508 messaging_server_id(state->msg_ctx),
1509 MSG_WINBIND_IP_DROPPED, &blob);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1512 nt_errstr(status)));
1515 req = addrchange_send(state, state->ev, state->ctx);
1517 DEBUG(0, ("addrchange_send failed\n"));
1521 tevent_req_set_callback(req, winbindd_addr_changed, state);
1526 int main(int argc, const char **argv)
1528 static bool is_daemon = False;
1529 static bool Fork = True;
1530 static bool log_stdout = False;
1531 static bool no_process_group = False;
1535 OPT_NO_PROCESS_GROUP,
1538 struct poptOption long_options[] = {
1540 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1541 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1542 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1543 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1544 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1545 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1555 setproctitle_init(argc, discard_const(argv), environ);
1558 * Do this before any other talloc operation
1560 talloc_enable_null_tracking();
1561 frame = talloc_stackframe();
1564 * We want total control over the permissions on created files,
1565 * so set our umask to 0.
1569 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1571 /* glibc (?) likes to print "User defined signal 1" and exit if a
1572 SIGUSR[12] is received before a handler is installed */
1574 CatchSignal(SIGUSR1, SIG_IGN);
1575 CatchSignal(SIGUSR2, SIG_IGN);
1578 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1582 /* Initialise for running in non-root mode */
1586 set_remote_machine_name("winbindd", False);
1588 /* Set environment variable so we don't recursively call ourselves.
1589 This may also be useful interactively. */
1591 if ( !winbind_off() ) {
1592 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1596 /* Initialise samba/rpc client stuff */
1598 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1600 while ((opt = poptGetNextOpt(pc)) != -1) {
1602 /* Don't become a daemon */
1614 case OPT_NO_PROCESS_GROUP:
1615 no_process_group = true;
1617 case OPT_LOG_STDOUT:
1624 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1625 poptBadOption(pc, 0), poptStrerror(opt));
1626 poptPrintUsage(pc, stderr, 0);
1631 /* We call dump_core_setup one more time because the command line can
1632 * set the log file or the log-basename and this will influence where
1633 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1634 * the default value derived from build's prefix. For EOM this value
1635 * is often not related to the path where winbindd is actually run
1638 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1639 if (is_daemon && interactive) {
1640 d_fprintf(stderr,"\nERROR: "
1641 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1642 poptPrintUsage(pc, stderr, 0);
1646 if (log_stdout && Fork) {
1647 d_fprintf(stderr, "\nERROR: "
1648 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1649 poptPrintUsage(pc, stderr, 0);
1653 poptFreeContext(pc);
1655 if (!override_logfile) {
1657 if (asprintf(&lfile,"%s/log.winbindd",
1658 get_dyn_LOGFILEBASE()) > 0) {
1659 lp_set_logfile(lfile);
1665 setup_logging("winbindd", DEBUG_STDOUT);
1667 setup_logging("winbindd", DEBUG_FILE);
1671 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1672 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1674 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1675 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1678 /* After parsing the configuration file we setup the core path one more time
1679 * as the log file might have been set in the configuration and cores's
1680 * path is by default basename(lp_logfile()).
1682 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1684 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1685 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1686 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1687 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"));
1691 if (!cluster_probe_ok()) {
1695 /* Initialise messaging system */
1697 if (server_messaging_context() == NULL) {
1701 if (!reload_services_file(NULL)) {
1702 DEBUG(0, ("error opening config file\n"));
1708 const char *idmap_backend;
1709 const char *invalid_backends[] = {
1710 "ad", "rfc2307", "rid",
1713 idmap_backend = lp_idmap_default_backend();
1714 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1715 ok = strequal(idmap_backend, invalid_backends[i]);
1717 DBG_ERR("FATAL: Invalid idmap backend %s "
1718 "configured as the default backend!\n",
1725 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1727 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1728 lp_lock_directory(), strerror(errno)));
1732 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1734 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1735 lp_pid_directory(), strerror(errno)));
1746 if (!secrets_init()) {
1748 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1752 status = rpccli_pre_open_netlogon_creds();
1753 if (!NT_STATUS_IS_OK(status)) {
1754 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1755 nt_errstr(status)));
1759 /* Unblock all signals we are interested in as they may have been
1760 blocked by the parent process. */
1762 BlockSignals(False, SIGINT);
1763 BlockSignals(False, SIGQUIT);
1764 BlockSignals(False, SIGTERM);
1765 BlockSignals(False, SIGUSR1);
1766 BlockSignals(False, SIGUSR2);
1767 BlockSignals(False, SIGHUP);
1768 BlockSignals(False, SIGCHLD);
1771 become_daemon(Fork, no_process_group, log_stdout);
1773 pidfile_create(lp_pid_directory(), "winbindd");
1777 * If we're interactive we want to set our own process group for
1778 * signal management.
1780 if (interactive && !no_process_group)
1781 setpgid( (pid_t)0, (pid_t)0);
1786 /* Don't use winbindd_reinit_after_fork here as
1787 * we're just starting up and haven't created any
1788 * winbindd-specific resources we must free yet. JRA.
1791 status = reinit_after_fork(server_messaging_context(),
1792 server_event_context(),
1794 if (!NT_STATUS_IS_OK(status)) {
1795 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1797 initialize_password_db(true, server_event_context());
1800 * Do not initialize the parent-child-pipe before becoming
1801 * a daemon: this is used to detect a died parent in the child
1804 status = init_before_fork();
1805 if (!NT_STATUS_IS_OK(status)) {
1806 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1809 winbindd_register_handlers(server_messaging_context(), !Fork);
1811 if (!messaging_parent_dgm_cleanup_init(server_messaging_context())) {
1815 status = init_system_session_info(NULL);
1816 if (!NT_STATUS_IS_OK(status)) {
1817 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1820 rpc_lsarpc_init(NULL);
1821 rpc_samr_init(NULL);
1823 winbindd_init_addrchange(NULL, server_event_context(),
1824 server_messaging_context());
1826 /* setup listen sockets */
1828 if (!winbindd_setup_listeners()) {
1829 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1832 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1837 daemon_ready("winbindd");
1842 /* Loop waiting for requests */
1844 frame = talloc_stackframe();
1846 if (tevent_loop_once(server_event_context()) == -1) {
1847 DEBUG(1, ("tevent_loop_once() failed: %s\n",