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"
40 #include "../lib/util/pidfile.h"
41 #include "util_cluster.h"
42 #include "source4/lib/messaging/irpc.h"
43 #include "source4/lib/messaging/messaging.h"
44 #include "lib/param/param.h"
45 #include "lib/async_req/async_sock.h"
48 #define DBGC_CLASS DBGC_WINBIND
50 #define SCRUB_CLIENTS_INTERVAL 5
52 static bool client_is_idle(struct winbindd_cli_state *state);
53 static void remove_client(struct winbindd_cli_state *state);
54 static void winbindd_setup_max_fds(void);
56 static bool opt_nocache = False;
57 static bool interactive = False;
59 extern bool override_logfile;
61 struct tevent_context *winbind_event_context(void)
63 static struct tevent_context *ev = NULL;
70 * Note we MUST use the NULL context here, not the autofree context,
71 * to avoid side effects in forked children exiting.
73 ev = samba_tevent_context_init(NULL);
75 smb_panic("Could not init winbindd's messaging context.\n");
80 struct messaging_context *winbind_messaging_context(void)
82 static struct messaging_context *msg = NULL;
89 * Note we MUST use the NULL context here, not the autofree context,
90 * to avoid side effects in forked children exiting.
92 msg = messaging_init(NULL, winbind_event_context());
94 smb_panic("Could not init winbindd's messaging context.\n");
99 struct imessaging_context *winbind_imessaging_context(void)
101 static struct imessaging_context *msg = NULL;
102 struct messaging_context *msg_ctx;
103 struct server_id myself;
104 struct loadparm_context *lp_ctx;
110 msg_ctx = server_messaging_context();
111 if (msg_ctx == NULL) {
112 smb_panic("server_messaging_context failed\n");
114 myself = messaging_server_id(msg_ctx);
116 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
117 if (lp_ctx == NULL) {
118 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
122 * Note we MUST use the NULL context here, not the autofree context,
123 * to avoid side effects in forked children exiting.
125 msg = imessaging_init(NULL, lp_ctx, myself, winbind_event_context());
126 talloc_unlink(NULL, lp_ctx);
129 smb_panic("Could not init winbindd's messaging context.\n");
134 /* Reload configuration */
136 static bool reload_services_file(const char *lfile)
141 char *fname = lp_next_configfile(talloc_tos());
143 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
144 set_dyn_CONFIGFILE(fname);
149 /* if this is a child, restore the logfile to the special
150 name - <domain>, idmap, etc. */
151 if (lfile && *lfile) {
152 lp_set_logfile(lfile);
156 ret = lp_load_global(get_dyn_CONFIGFILE());
160 winbindd_setup_max_fds();
166 static void winbindd_status(void)
168 struct winbindd_cli_state *tmp;
170 DEBUG(0, ("winbindd status:\n"));
172 /* Print client state information */
174 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
176 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
177 DEBUG(2, ("\tclient list:\n"));
178 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
179 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
180 (unsigned long)tmp->pid, tmp->sock,
181 client_is_idle(tmp) ? "idle" : "active"));
186 /* Flush client cache */
188 static void flush_caches(void)
190 /* We need to invalidate cached user list entries on a SIGHUP
191 otherwise cached access denied errors due to restrict anonymous
192 hang around until the sequence number changes. */
194 if (!wcache_invalidate_cache()) {
195 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
196 if (!winbindd_cache_validate_and_initialize()) {
202 static void flush_caches_noinit(void)
205 * We need to invalidate cached user list entries on a SIGHUP
206 * otherwise cached access denied errors due to restrict anonymous
207 * hang around until the sequence number changes.
209 * Skip uninitialized domains when flush cache.
210 * If domain is not initialized, it means it is never
211 * used or never become online. look, wcache_invalidate_cache()
212 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
213 * for unused domains and large traffic for primay domain's DC if there
217 if (!wcache_invalidate_cache_noinit()) {
218 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
219 if (!winbindd_cache_validate_and_initialize()) {
225 /* Handle the signal by unlinking socket and exiting */
227 static void terminate(bool is_parent)
230 /* When parent goes away we should
231 * remove the socket file. Not so
232 * when children terminate.
236 if (asprintf(&path, "%s/%s",
237 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
245 trustdom_cache_shutdown();
247 gencache_stabilize();
251 TALLOC_CTX *mem_ctx = talloc_init("end_description");
252 char *description = talloc_describe_all(mem_ctx);
254 DEBUG(3, ("tallocs left:\n%s\n", description));
255 talloc_destroy(mem_ctx);
260 struct messaging_context *msg = winbind_messaging_context();
261 struct server_id self = messaging_server_id(msg);
262 serverid_deregister(self);
263 pidfile_unlink(lp_pid_directory(), "winbindd");
269 static void winbindd_sig_term_handler(struct tevent_context *ev,
270 struct tevent_signal *se,
276 bool *is_parent = talloc_get_type_abort(private_data, bool);
278 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
279 signum, (int)*is_parent));
280 terminate(*is_parent);
284 handle stdin becoming readable when we are in --foreground mode
286 static void winbindd_stdin_handler(struct tevent_context *ev,
287 struct tevent_fd *fde,
292 if (read(0, &c, 1) != 1) {
293 bool *is_parent = talloc_get_type_abort(private_data, bool);
295 /* we have reached EOF on stdin, which means the
296 parent has exited. Shutdown the server */
297 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
299 terminate(*is_parent);
303 bool winbindd_setup_sig_term_handler(bool parent)
305 struct tevent_signal *se;
308 is_parent = talloc(winbind_event_context(), bool);
315 se = tevent_add_signal(winbind_event_context(),
318 winbindd_sig_term_handler,
321 DEBUG(0,("failed to setup SIGTERM handler"));
322 talloc_free(is_parent);
326 se = tevent_add_signal(winbind_event_context(),
329 winbindd_sig_term_handler,
332 DEBUG(0,("failed to setup SIGINT handler"));
333 talloc_free(is_parent);
337 se = tevent_add_signal(winbind_event_context(),
340 winbindd_sig_term_handler,
343 DEBUG(0,("failed to setup SIGINT handler"));
344 talloc_free(is_parent);
351 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
358 is_parent = talloc(winbind_event_context(), bool);
365 /* if we are running in the foreground then look for
366 EOF on stdin, and exit if it happens. This allows
367 us to die if the parent process dies
368 Only do this on a pipe or socket, no other device.
370 if (fstat(0, &st) != 0) {
373 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
374 tevent_add_fd(winbind_event_context(),
378 winbindd_stdin_handler,
386 static void winbindd_sig_hup_handler(struct tevent_context *ev,
387 struct tevent_signal *se,
393 const char *file = (const char *)private_data;
395 DEBUG(1,("Reloading services after SIGHUP\n"));
396 flush_caches_noinit();
397 reload_services_file(file);
400 bool winbindd_setup_sig_hup_handler(const char *lfile)
402 struct tevent_signal *se;
406 file = talloc_strdup(winbind_event_context(),
413 se = tevent_add_signal(winbind_event_context(),
414 winbind_event_context(),
416 winbindd_sig_hup_handler,
425 static void winbindd_sig_chld_handler(struct tevent_context *ev,
426 struct tevent_signal *se,
434 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
435 winbind_child_died(pid);
439 static bool winbindd_setup_sig_chld_handler(void)
441 struct tevent_signal *se;
443 se = tevent_add_signal(winbind_event_context(),
444 winbind_event_context(),
446 winbindd_sig_chld_handler,
455 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
456 struct tevent_signal *se,
465 static bool winbindd_setup_sig_usr2_handler(void)
467 struct tevent_signal *se;
469 se = tevent_add_signal(winbind_event_context(),
470 winbind_event_context(),
472 winbindd_sig_usr2_handler,
481 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
482 static void msg_reload_services(struct messaging_context *msg,
485 struct server_id server_id,
488 /* Flush various caches */
490 reload_services_file((const char *) private_data);
493 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
494 static void msg_shutdown(struct messaging_context *msg,
497 struct server_id server_id,
500 /* only the parent waits for this message */
501 DEBUG(0,("Got shutdown message\n"));
506 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
509 struct server_id server_id,
516 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
520 * call the validation code from a child:
521 * so we don't block the main winbindd and the validation
522 * code can safely use fork/waitpid...
526 if (child_pid == -1) {
527 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
532 if (child_pid != 0) {
534 DEBUG(5, ("winbind_msg_validate_cache: child created with "
535 "pid %d.\n", (int)child_pid));
541 status = winbindd_reinit_after_fork(NULL, NULL);
542 if (!NT_STATUS_IS_OK(status)) {
543 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
548 /* install default SIGCHLD handler: validation code uses fork/waitpid */
549 CatchSignal(SIGCHLD, SIG_DFL);
551 ret = (uint8_t)winbindd_validate_cache_nobackup();
552 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
553 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
558 static struct winbindd_dispatch_table {
559 enum winbindd_cmd cmd;
560 void (*fn)(struct winbindd_cli_state *state);
561 const char *winbindd_cmd_name;
562 } dispatch_table[] = {
564 /* Enumeration functions */
566 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
571 { WINBINDD_INFO, winbindd_info, "INFO" },
572 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
573 "INTERFACE_VERSION" },
574 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
575 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
576 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
577 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
578 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
579 "WINBINDD_PRIV_PIPE_DIR" },
581 /* Credential cache access */
582 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
583 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
587 { WINBINDD_NUM_CMDS, NULL, "NONE" }
590 struct winbindd_async_dispatch_table {
591 enum winbindd_cmd cmd;
592 const char *cmd_name;
593 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
594 struct tevent_context *ev,
595 struct winbindd_cli_state *cli,
596 struct winbindd_request *request);
597 NTSTATUS (*recv_req)(struct tevent_req *req,
598 struct winbindd_response *presp);
601 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
602 { WINBINDD_PING, "PING",
603 wb_ping_send, wb_ping_recv },
604 { WINBINDD_LOOKUPSID, "LOOKUPSID",
605 winbindd_lookupsid_send, winbindd_lookupsid_recv },
606 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
607 winbindd_lookupsids_send, winbindd_lookupsids_recv },
608 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
609 winbindd_lookupname_send, winbindd_lookupname_recv },
610 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
611 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
612 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
613 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
614 { WINBINDD_GETPWSID, "GETPWSID",
615 winbindd_getpwsid_send, winbindd_getpwsid_recv },
616 { WINBINDD_GETPWNAM, "GETPWNAM",
617 winbindd_getpwnam_send, winbindd_getpwnam_recv },
618 { WINBINDD_GETPWUID, "GETPWUID",
619 winbindd_getpwuid_send, winbindd_getpwuid_recv },
620 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
621 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
622 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
623 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
624 { WINBINDD_GETGROUPS, "GETGROUPS",
625 winbindd_getgroups_send, winbindd_getgroups_recv },
626 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
627 winbindd_show_sequence_send, winbindd_show_sequence_recv },
628 { WINBINDD_GETGRGID, "GETGRGID",
629 winbindd_getgrgid_send, winbindd_getgrgid_recv },
630 { WINBINDD_GETGRNAM, "GETGRNAM",
631 winbindd_getgrnam_send, winbindd_getgrnam_recv },
632 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
633 winbindd_getusersids_send, winbindd_getusersids_recv },
634 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
635 winbindd_lookuprids_send, winbindd_lookuprids_recv },
636 { WINBINDD_SETPWENT, "SETPWENT",
637 winbindd_setpwent_send, winbindd_setpwent_recv },
638 { WINBINDD_GETPWENT, "GETPWENT",
639 winbindd_getpwent_send, winbindd_getpwent_recv },
640 { WINBINDD_ENDPWENT, "ENDPWENT",
641 winbindd_endpwent_send, winbindd_endpwent_recv },
642 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
643 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
644 { WINBINDD_GETDCNAME, "GETDCNAME",
645 winbindd_getdcname_send, winbindd_getdcname_recv },
646 { WINBINDD_SETGRENT, "SETGRENT",
647 winbindd_setgrent_send, winbindd_setgrent_recv },
648 { WINBINDD_GETGRENT, "GETGRENT",
649 winbindd_getgrent_send, winbindd_getgrent_recv },
650 { WINBINDD_ENDGRENT, "ENDGRENT",
651 winbindd_endgrent_send, winbindd_endgrent_recv },
652 { WINBINDD_LIST_USERS, "LIST_USERS",
653 winbindd_list_users_send, winbindd_list_users_recv },
654 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
655 winbindd_list_groups_send, winbindd_list_groups_recv },
656 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
657 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
658 { WINBINDD_PING_DC, "PING_DC",
659 winbindd_ping_dc_send, winbindd_ping_dc_recv },
660 { WINBINDD_PAM_AUTH, "PAM_AUTH",
661 winbindd_pam_auth_send, winbindd_pam_auth_recv },
662 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
663 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
664 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
665 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
666 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
667 winbindd_pam_chng_pswd_auth_crap_send,
668 winbindd_pam_chng_pswd_auth_crap_recv },
669 { WINBINDD_WINS_BYIP, "WINS_BYIP",
670 winbindd_wins_byip_send, winbindd_wins_byip_recv },
671 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
672 winbindd_wins_byname_send, winbindd_wins_byname_recv },
674 { 0, NULL, NULL, NULL }
677 static struct winbindd_async_dispatch_table async_priv_table[] = {
678 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
679 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
680 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
681 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
682 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
683 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
684 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
685 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
687 { 0, NULL, NULL, NULL }
690 static void wb_request_done(struct tevent_req *req);
692 static void process_request(struct winbindd_cli_state *state)
694 struct winbindd_dispatch_table *table = dispatch_table;
695 struct winbindd_async_dispatch_table *atable;
697 state->mem_ctx = talloc_named(state, 0, "winbind request");
698 if (state->mem_ctx == NULL)
701 /* Remember who asked us. */
702 state->pid = state->request->pid;
704 state->cmd_name = "unknown request";
705 state->recv_fn = NULL;
706 /* client is newest */
707 winbindd_promote_client(state);
709 /* Process command */
711 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
712 if (state->request->cmd == atable->cmd) {
717 if ((atable->send_req == NULL) && state->privileged) {
718 for (atable = async_priv_table; atable->send_req;
720 if (state->request->cmd == atable->cmd) {
726 if (atable->send_req != NULL) {
727 struct tevent_req *req;
729 state->cmd_name = atable->cmd_name;
730 state->recv_fn = atable->recv_req;
732 DEBUG(10, ("process_request: Handling async request %d:%s\n",
733 (int)state->pid, state->cmd_name));
735 req = atable->send_req(state->mem_ctx, winbind_event_context(),
736 state, state->request);
738 DEBUG(0, ("process_request: atable->send failed for "
739 "%s\n", atable->cmd_name));
740 request_error(state);
743 tevent_req_set_callback(req, wb_request_done, state);
747 state->response = talloc_zero(state->mem_ctx,
748 struct winbindd_response);
749 if (state->response == NULL) {
750 DEBUG(10, ("talloc failed\n"));
751 remove_client(state);
754 state->response->result = WINBINDD_PENDING;
755 state->response->length = sizeof(struct winbindd_response);
757 for (table = dispatch_table; table->fn; table++) {
758 if (state->request->cmd == table->cmd) {
759 DEBUG(10,("process_request: request fn %s\n",
760 table->winbindd_cmd_name ));
761 state->cmd_name = table->winbindd_cmd_name;
768 DEBUG(10,("process_request: unknown request fn number %d\n",
769 (int)state->request->cmd ));
770 request_error(state);
774 static void wb_request_done(struct tevent_req *req)
776 struct winbindd_cli_state *state = tevent_req_callback_data(
777 req, struct winbindd_cli_state);
780 state->response = talloc_zero(state->mem_ctx,
781 struct winbindd_response);
782 if (state->response == NULL) {
783 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
784 (int)state->pid, state->cmd_name));
785 remove_client(state);
788 state->response->result = WINBINDD_PENDING;
789 state->response->length = sizeof(struct winbindd_response);
791 status = state->recv_fn(req, state->response);
794 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
795 (int)state->pid, state->cmd_name, nt_errstr(status)));
797 if (!NT_STATUS_IS_OK(status)) {
798 request_error(state);
805 * This is the main event loop of winbind requests. It goes through a
806 * state-machine of 3 read/write requests, 4 if you have extra data to send.
808 * An idle winbind client has a read request of 4 bytes outstanding,
809 * finalizing function is request_len_recv, checking the length. request_recv
810 * then processes the packet. The processing function then at some point has
811 * to call request_finished which schedules sending the response.
814 static void request_finished(struct winbindd_cli_state *state);
816 static void winbind_client_request_read(struct tevent_req *req);
817 static void winbind_client_response_written(struct tevent_req *req);
818 static void winbind_client_activity(struct tevent_req *req);
820 static void request_finished(struct winbindd_cli_state *state)
822 struct tevent_req *req;
824 /* free client socket monitoring request */
825 TALLOC_FREE(state->io_req);
827 TALLOC_FREE(state->request);
829 req = wb_resp_write_send(state, winbind_event_context(),
830 state->out_queue, state->sock,
833 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
834 (int)state->pid, state->cmd_name));
835 remove_client(state);
838 tevent_req_set_callback(req, winbind_client_response_written, state);
842 static void winbind_client_response_written(struct tevent_req *req)
844 struct winbindd_cli_state *state = tevent_req_callback_data(
845 req, struct winbindd_cli_state);
849 state->io_req = NULL;
851 ret = wb_resp_write_recv(req, &err);
856 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
857 (int)state->pid, state->cmd_name, strerror(err)));
858 remove_client(state);
862 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
863 "to client\n", (int)state->pid, state->cmd_name));
865 TALLOC_FREE(state->mem_ctx);
866 state->response = NULL;
867 state->cmd_name = "no request";
868 state->recv_fn = NULL;
870 req = wb_req_read_send(state, winbind_event_context(), state->sock,
871 WINBINDD_MAX_EXTRA_DATA);
873 remove_client(state);
876 tevent_req_set_callback(req, winbind_client_request_read, state);
880 void request_error(struct winbindd_cli_state *state)
882 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
883 state->response->result = WINBINDD_ERROR;
884 request_finished(state);
887 void request_ok(struct winbindd_cli_state *state)
889 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
890 state->response->result = WINBINDD_OK;
891 request_finished(state);
894 /* Process a new connection by adding it to the client connection list */
896 static void new_connection(int listen_sock, bool privileged)
898 struct sockaddr_un sunaddr;
899 struct winbindd_cli_state *state;
900 struct tevent_req *req;
904 /* Accept connection */
906 len = sizeof(sunaddr);
908 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
911 if (errno != EINTR) {
912 DEBUG(0, ("Failed to accept socket - %s\n",
918 DEBUG(6,("accepted socket %d\n", sock));
920 /* Create new connection structure */
922 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
929 state->out_queue = tevent_queue_create(state, "winbind client reply");
930 if (state->out_queue == NULL) {
936 state->privileged = privileged;
938 req = wb_req_read_send(state, winbind_event_context(), state->sock,
939 WINBINDD_MAX_EXTRA_DATA);
945 tevent_req_set_callback(req, winbind_client_request_read, state);
948 /* Add to connection list */
950 winbindd_add_client(state);
953 static void winbind_client_request_read(struct tevent_req *req)
955 struct winbindd_cli_state *state = tevent_req_callback_data(
956 req, struct winbindd_cli_state);
960 state->io_req = NULL;
962 ret = wb_req_read_recv(req, state, &state->request, &err);
966 DEBUG(6, ("closing socket %d, client exited\n",
969 DEBUG(2, ("Could not read client request from fd %d: "
970 "%s\n", state->sock, strerror(err)));
974 remove_client(state);
978 req = wait_for_read_send(state, winbind_event_context(), state->sock,
981 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
982 " wait_for_read_send failed - removing client\n",
983 (int)state->pid, state->cmd_name));
984 remove_client(state);
987 tevent_req_set_callback(req, winbind_client_activity, state);
990 process_request(state);
993 static void winbind_client_activity(struct tevent_req *req)
995 struct winbindd_cli_state *state =
996 tevent_req_callback_data(req, struct winbindd_cli_state);
1000 has_data = wait_for_read_recv(req, &err);
1003 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1004 "unexpected data from client - removing client\n",
1005 (int)state->pid, state->cmd_name));
1008 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1009 "client has closed connection - removing "
1011 (int)state->pid, state->cmd_name));
1013 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1014 "client socket error (%s) - removing "
1016 (int)state->pid, state->cmd_name,
1021 remove_client(state);
1024 /* Remove a client connection from client connection list */
1026 static void remove_client(struct winbindd_cli_state *state)
1031 /* It's a dead client - hold a funeral */
1033 if (state == NULL) {
1038 * We need to remove a pending wb_req_read_*
1039 * or wb_resp_write_* request before closing the
1042 * This is important as they might have used tevent_add_fd() and we
1043 * use the epoll * backend on linux. So we must remove the tevent_fd
1044 * before closing the fd.
1046 * Otherwise we might hit a race with close_conns_after_fork() (via
1047 * winbindd_reinit_after_fork()) where a file description
1048 * is still open in a child, which means it's still active in
1049 * the parents epoll queue, but the related tevent_fd is already
1050 * already gone in the parent.
1054 TALLOC_FREE(state->io_req);
1056 if (state->sock != -1) {
1057 /* tell client, we are closing ... */
1058 nwritten = write(state->sock, &c, sizeof(c));
1059 if (nwritten == -1) {
1060 DEBUG(2, ("final write to client failed: %s\n",
1070 TALLOC_FREE(state->mem_ctx);
1072 /* Remove from list and free */
1074 winbindd_remove_client(state);
1078 /* Is a client idle? */
1080 static bool client_is_idle(struct winbindd_cli_state *state) {
1081 return (state->request == NULL &&
1082 state->response == NULL &&
1083 !state->pwent_state && !state->grent_state);
1086 /* Shutdown client connection which has been idle for the longest time */
1088 static bool remove_idle_client(void)
1090 struct winbindd_cli_state *state, *remove_state = NULL;
1093 for (state = winbindd_client_list(); state; state = state->next) {
1094 if (client_is_idle(state)) {
1096 /* list is sorted by access time */
1097 remove_state = state;
1102 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1103 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1104 remove_client(remove_state);
1112 * Terminate all clients whose requests have taken longer than
1113 * "winbind request timeout" seconds to process, or have been
1114 * idle for more than "winbind request timeout" seconds.
1117 static void remove_timed_out_clients(void)
1119 struct winbindd_cli_state *state, *prev = NULL;
1120 time_t curr_time = time(NULL);
1121 int timeout_val = lp_winbind_request_timeout();
1123 for (state = winbindd_client_list_tail(); state; state = prev) {
1126 prev = winbindd_client_list_prev(state);
1127 expiry_time = state->last_access + timeout_val;
1129 if (curr_time > expiry_time) {
1130 if (client_is_idle(state)) {
1131 DEBUG(5,("Idle client timed out, "
1132 "shutting down sock %d, pid %u\n",
1134 (unsigned int)state->pid));
1136 DEBUG(5,("Client request timed out, "
1137 "shutting down sock %d, pid %u\n",
1139 (unsigned int)state->pid));
1141 remove_client(state);
1143 /* list is sorted, previous clients in
1150 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1151 struct tevent_timer *te,
1152 struct timeval current_time,
1155 remove_timed_out_clients();
1156 if (tevent_add_timer(ev, ev,
1157 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1158 winbindd_scrub_clients_handler, NULL) == NULL) {
1159 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1164 struct winbindd_listen_state {
1169 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1170 struct tevent_fd *fde,
1174 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1175 struct winbindd_listen_state);
1177 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1178 DEBUG(5,("winbindd: Exceeding %d client "
1179 "connections, removing idle "
1180 "connection.\n", lp_winbind_max_clients()));
1181 if (!remove_idle_client()) {
1182 DEBUG(0,("winbindd: Exceeding %d "
1183 "client connections, no idle "
1184 "connection found\n",
1185 lp_winbind_max_clients()));
1189 remove_timed_out_clients();
1190 new_connection(s->fd, s->privileged);
1194 * Winbindd socket accessor functions
1197 char *get_winbind_priv_pipe_dir(void)
1199 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1202 static void winbindd_setup_max_fds(void)
1204 int num_fds = MAX_OPEN_FUDGEFACTOR;
1207 num_fds += lp_winbind_max_clients();
1208 /* Add some more to account for 2 sockets open
1209 when the client transitions from unprivileged
1210 to privileged socket
1212 num_fds += lp_winbind_max_clients() / 10;
1214 /* Add one socket per child process
1215 (yeah there are child processes other than the
1216 domain children but only domain children can vary
1219 num_fds += lp_winbind_max_domain_connections() *
1220 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1222 actual_fds = set_maxfiles(num_fds);
1224 if (actual_fds < num_fds) {
1225 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1226 "requested %d open files, %d are available.\n",
1227 num_fds, actual_fds));
1231 static bool winbindd_setup_listeners(void)
1233 struct winbindd_listen_state *pub_state = NULL;
1234 struct winbindd_listen_state *priv_state = NULL;
1235 struct tevent_fd *fde;
1239 pub_state = talloc(winbind_event_context(),
1240 struct winbindd_listen_state);
1245 pub_state->privileged = false;
1246 pub_state->fd = create_pipe_sock(
1247 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1248 if (pub_state->fd == -1) {
1251 rc = listen(pub_state->fd, 5);
1256 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1257 TEVENT_FD_READ, winbindd_listen_fde_handler,
1260 close(pub_state->fd);
1263 tevent_fd_set_auto_close(fde);
1265 priv_state = talloc(winbind_event_context(),
1266 struct winbindd_listen_state);
1271 socket_path = get_winbind_priv_pipe_dir();
1272 if (socket_path == NULL) {
1276 priv_state->privileged = true;
1277 priv_state->fd = create_pipe_sock(
1278 socket_path, WINBINDD_SOCKET_NAME, 0750);
1279 TALLOC_FREE(socket_path);
1280 if (priv_state->fd == -1) {
1283 rc = listen(priv_state->fd, 5);
1288 fde = tevent_add_fd(winbind_event_context(), priv_state,
1289 priv_state->fd, TEVENT_FD_READ,
1290 winbindd_listen_fde_handler, priv_state);
1292 close(priv_state->fd);
1295 tevent_fd_set_auto_close(fde);
1297 winbindd_scrub_clients_handler(winbind_event_context(), NULL,
1298 timeval_current(), NULL);
1301 TALLOC_FREE(pub_state);
1302 TALLOC_FREE(priv_state);
1306 bool winbindd_use_idmap_cache(void)
1308 return !opt_nocache;
1311 bool winbindd_use_cache(void)
1313 return !opt_nocache;
1316 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1320 /* Setup signal handlers */
1322 if (!winbindd_setup_sig_term_handler(true))
1324 if (!winbindd_setup_stdin_handler(true, foreground))
1326 if (!winbindd_setup_sig_hup_handler(NULL))
1328 if (!winbindd_setup_sig_chld_handler())
1330 if (!winbindd_setup_sig_usr2_handler())
1333 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1336 * Ensure all cache and idmap caches are consistent
1337 * and initialized before we startup.
1339 if (!winbindd_cache_validate_and_initialize()) {
1343 /* get broadcast messages */
1345 if (!serverid_register(messaging_server_id(msg_ctx),
1349 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
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(winbind_messaging_context(), NULL,
1370 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1371 messaging_register(winbind_messaging_context(), NULL,
1372 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1374 messaging_register(msg_ctx, NULL,
1375 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1377 messaging_register(msg_ctx, NULL,
1378 MSG_WINBIND_VALIDATE_CACHE,
1379 winbind_msg_validate_cache);
1381 messaging_register(msg_ctx, NULL,
1382 MSG_WINBIND_DUMP_DOMAIN_LIST,
1383 winbind_msg_dump_domain_list);
1385 messaging_register(msg_ctx, NULL,
1386 MSG_WINBIND_IP_DROPPED,
1387 winbind_msg_ip_dropped_parent);
1389 /* Register handler for MSG_DEBUG. */
1390 messaging_register(msg_ctx, NULL,
1394 netsamlogon_cache_init(); /* Non-critical */
1396 /* clear the cached list of trusted domains */
1400 if (!init_domain_list()) {
1401 DEBUG(0,("unable to initialize domain list\n"));
1406 init_locator_child();
1408 smb_nscd_flush_user_cache();
1409 smb_nscd_flush_group_cache();
1411 if (lp_allow_trusted_domains()) {
1412 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1413 rescan_trusted_domains, NULL) == NULL) {
1414 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1419 status = wb_irpc_register();
1421 if (!NT_STATUS_IS_OK(status)) {
1422 DEBUG(0, ("Could not register IRPC handlers\n"));
1427 struct winbindd_addrchanged_state {
1428 struct addrchange_context *ctx;
1429 struct tevent_context *ev;
1430 struct messaging_context *msg_ctx;
1433 static void winbindd_addr_changed(struct tevent_req *req);
1435 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1436 struct tevent_context *ev,
1437 struct messaging_context *msg_ctx)
1439 struct winbindd_addrchanged_state *state;
1440 struct tevent_req *req;
1443 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1444 if (state == NULL) {
1445 DEBUG(10, ("talloc failed\n"));
1449 state->msg_ctx = msg_ctx;
1451 status = addrchange_context_create(state, &state->ctx);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 DEBUG(10, ("addrchange_context_create failed: %s\n",
1454 nt_errstr(status)));
1458 req = addrchange_send(state, ev, state->ctx);
1460 DEBUG(0, ("addrchange_send failed\n"));
1464 tevent_req_set_callback(req, winbindd_addr_changed, state);
1467 static void winbindd_addr_changed(struct tevent_req *req)
1469 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1470 req, struct winbindd_addrchanged_state);
1471 enum addrchange_type type;
1472 struct sockaddr_storage addr;
1475 status = addrchange_recv(req, &type, &addr);
1477 if (!NT_STATUS_IS_OK(status)) {
1478 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1479 nt_errstr(status)));
1483 if (type == ADDRCHANGE_DEL) {
1484 char addrstr[INET6_ADDRSTRLEN];
1487 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1489 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1492 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1494 status = messaging_send(state->msg_ctx,
1495 messaging_server_id(state->msg_ctx),
1496 MSG_WINBIND_IP_DROPPED, &blob);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1499 nt_errstr(status)));
1502 req = addrchange_send(state, state->ev, state->ctx);
1504 DEBUG(0, ("addrchange_send failed\n"));
1508 tevent_req_set_callback(req, winbindd_addr_changed, state);
1513 int main(int argc, const char **argv)
1515 static bool is_daemon = False;
1516 static bool Fork = True;
1517 static bool log_stdout = False;
1518 static bool no_process_group = False;
1522 OPT_NO_PROCESS_GROUP,
1525 struct poptOption long_options[] = {
1527 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1528 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1529 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1530 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1531 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1532 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1543 * Do this before any other talloc operation
1545 talloc_enable_null_tracking();
1546 frame = talloc_stackframe();
1549 * We want total control over the permissions on created files,
1550 * so set our umask to 0.
1554 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1556 /* glibc (?) likes to print "User defined signal 1" and exit if a
1557 SIGUSR[12] is received before a handler is installed */
1559 CatchSignal(SIGUSR1, SIG_IGN);
1560 CatchSignal(SIGUSR2, SIG_IGN);
1563 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1567 /* Initialise for running in non-root mode */
1571 set_remote_machine_name("winbindd", False);
1573 /* Set environment variable so we don't recursively call ourselves.
1574 This may also be useful interactively. */
1576 if ( !winbind_off() ) {
1577 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1581 /* Initialise samba/rpc client stuff */
1583 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1585 while ((opt = poptGetNextOpt(pc)) != -1) {
1587 /* Don't become a daemon */
1599 case OPT_NO_PROCESS_GROUP:
1600 no_process_group = true;
1602 case OPT_LOG_STDOUT:
1609 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1610 poptBadOption(pc, 0), poptStrerror(opt));
1611 poptPrintUsage(pc, stderr, 0);
1616 /* We call dump_core_setup one more time because the command line can
1617 * set the log file or the log-basename and this will influence where
1618 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1619 * the default value derived from build's prefix. For EOM this value
1620 * is often not related to the path where winbindd is actually run
1623 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1624 if (is_daemon && interactive) {
1625 d_fprintf(stderr,"\nERROR: "
1626 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1627 poptPrintUsage(pc, stderr, 0);
1631 if (log_stdout && Fork) {
1632 d_fprintf(stderr, "\nERROR: "
1633 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1634 poptPrintUsage(pc, stderr, 0);
1638 poptFreeContext(pc);
1640 if (!override_logfile) {
1642 if (asprintf(&lfile,"%s/log.winbindd",
1643 get_dyn_LOGFILEBASE()) > 0) {
1644 lp_set_logfile(lfile);
1650 setup_logging("winbindd", DEBUG_STDOUT);
1652 setup_logging("winbindd", DEBUG_FILE);
1656 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1657 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1659 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1660 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1663 /* After parsing the configuration file we setup the core path one more time
1664 * as the log file might have been set in the configuration and cores's
1665 * path is by default basename(lp_logfile()).
1667 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1669 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1670 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1671 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1672 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"));
1676 if (!cluster_probe_ok()) {
1680 /* Initialise messaging system */
1682 if (winbind_messaging_context() == NULL) {
1686 if (!reload_services_file(NULL)) {
1687 DEBUG(0, ("error opening config file\n"));
1691 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1693 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1694 lp_lock_directory(), strerror(errno)));
1698 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1700 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1701 lp_pid_directory(), strerror(errno)));
1712 if (!secrets_init()) {
1714 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1718 status = rpccli_pre_open_netlogon_creds();
1719 if (!NT_STATUS_IS_OK(status)) {
1720 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1721 nt_errstr(status)));
1725 /* Unblock all signals we are interested in as they may have been
1726 blocked by the parent process. */
1728 BlockSignals(False, SIGINT);
1729 BlockSignals(False, SIGQUIT);
1730 BlockSignals(False, SIGTERM);
1731 BlockSignals(False, SIGUSR1);
1732 BlockSignals(False, SIGUSR2);
1733 BlockSignals(False, SIGHUP);
1734 BlockSignals(False, SIGCHLD);
1737 become_daemon(Fork, no_process_group, log_stdout);
1739 pidfile_create(lp_pid_directory(), "winbindd");
1743 * If we're interactive we want to set our own process group for
1744 * signal management.
1746 if (interactive && !no_process_group)
1747 setpgid( (pid_t)0, (pid_t)0);
1752 /* Don't use winbindd_reinit_after_fork here as
1753 * we're just starting up and haven't created any
1754 * winbindd-specific resources we must free yet. JRA.
1757 status = reinit_after_fork(winbind_messaging_context(),
1758 winbind_event_context(),
1760 if (!NT_STATUS_IS_OK(status)) {
1761 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1765 * Do not initialize the parent-child-pipe before becoming
1766 * a daemon: this is used to detect a died parent in the child
1769 status = init_before_fork();
1770 if (!NT_STATUS_IS_OK(status)) {
1771 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1774 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1776 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1780 status = init_system_session_info();
1781 if (!NT_STATUS_IS_OK(status)) {
1782 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1785 rpc_lsarpc_init(NULL);
1786 rpc_samr_init(NULL);
1788 winbindd_init_addrchange(NULL, winbind_event_context(),
1789 winbind_messaging_context());
1791 /* setup listen sockets */
1793 if (!winbindd_setup_listeners()) {
1794 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1797 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1802 daemon_ready("winbindd");
1805 /* Loop waiting for requests */
1807 frame = talloc_stackframe();
1809 if (tevent_loop_once(winbind_event_context()) == -1) {
1810 DEBUG(1, ("tevent_loop_once() failed: %s\n",