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"
47 #define DBGC_CLASS DBGC_WINBIND
49 static bool client_is_idle(struct winbindd_cli_state *state);
50 static void remove_client(struct winbindd_cli_state *state);
52 static bool opt_nocache = False;
53 static bool interactive = False;
55 extern bool override_logfile;
57 struct tevent_context *winbind_event_context(void)
59 static struct tevent_context *ev = NULL;
66 * Note we MUST use the NULL context here, not the autofree context,
67 * to avoid side effects in forked children exiting.
69 ev = samba_tevent_context_init(NULL);
71 smb_panic("Could not init winbindd's messaging context.\n");
76 struct messaging_context *winbind_messaging_context(void)
78 static struct messaging_context *msg = NULL;
85 * Note we MUST use the NULL context here, not the autofree context,
86 * to avoid side effects in forked children exiting.
88 msg = messaging_init(NULL, winbind_event_context());
90 smb_panic("Could not init winbindd's messaging context.\n");
95 struct imessaging_context *winbind_imessaging_context(void)
97 static struct imessaging_context *msg = NULL;
98 struct loadparm_context *lp_ctx;
104 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
105 if (lp_ctx == NULL) {
106 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
110 * Note we MUST use the NULL context here, not the autofree context,
111 * to avoid side effects in forked children exiting.
113 msg = imessaging_init(NULL, lp_ctx, procid_self(), winbind_event_context(), false);
114 talloc_unlink(NULL, lp_ctx);
117 smb_panic("Could not init winbindd's messaging context.\n");
122 /* Reload configuration */
124 static bool reload_services_file(const char *lfile)
129 char *fname = lp_next_configfile(talloc_tos());
131 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
132 set_dyn_CONFIGFILE(fname);
137 /* if this is a child, restore the logfile to the special
138 name - <domain>, idmap, etc. */
139 if (lfile && *lfile) {
140 lp_set_logfile(lfile);
144 ret = lp_load_global(get_dyn_CONFIGFILE());
153 static void winbindd_status(void)
155 struct winbindd_cli_state *tmp;
157 DEBUG(0, ("winbindd status:\n"));
159 /* Print client state information */
161 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
163 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
164 DEBUG(2, ("\tclient list:\n"));
165 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
166 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
167 (unsigned long)tmp->pid, tmp->sock,
168 client_is_idle(tmp) ? "idle" : "active"));
173 /* Flush client cache */
175 static void flush_caches(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 if (!wcache_invalidate_cache()) {
182 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
183 if (!winbindd_cache_validate_and_initialize()) {
189 static void flush_caches_noinit(void)
192 * We need to invalidate cached user list entries on a SIGHUP
193 * otherwise cached access denied errors due to restrict anonymous
194 * hang around until the sequence number changes.
196 * Skip uninitialized domains when flush cache.
197 * If domain is not initialized, it means it is never
198 * used or never become online. look, wcache_invalidate_cache()
199 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
200 * for unused domains and large traffic for primay domain's DC if there
204 if (!wcache_invalidate_cache_noinit()) {
205 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
206 if (!winbindd_cache_validate_and_initialize()) {
212 /* Handle the signal by unlinking socket and exiting */
214 static void terminate(bool is_parent)
217 /* When parent goes away we should
218 * remove the socket file. Not so
219 * when children terminate.
223 if (asprintf(&path, "%s/%s",
224 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
232 trustdom_cache_shutdown();
234 gencache_stabilize();
238 TALLOC_CTX *mem_ctx = talloc_init("end_description");
239 char *description = talloc_describe_all(mem_ctx);
241 DEBUG(3, ("tallocs left:\n%s\n", description));
242 talloc_destroy(mem_ctx);
247 struct messaging_context *msg = winbind_messaging_context();
248 struct server_id self = messaging_server_id(msg);
249 serverid_deregister(self);
250 pidfile_unlink(lp_pid_directory(), "winbindd");
256 static void winbindd_sig_term_handler(struct tevent_context *ev,
257 struct tevent_signal *se,
263 bool *is_parent = talloc_get_type_abort(private_data, bool);
265 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
266 signum, (int)*is_parent));
267 terminate(*is_parent);
271 handle stdin becoming readable when we are in --foreground mode
273 static void winbindd_stdin_handler(struct tevent_context *ev,
274 struct tevent_fd *fde,
279 if (read(0, &c, 1) != 1) {
280 bool *is_parent = talloc_get_type_abort(private_data, bool);
282 /* we have reached EOF on stdin, which means the
283 parent has exited. Shutdown the server */
284 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
286 terminate(*is_parent);
290 bool winbindd_setup_sig_term_handler(bool parent)
292 struct tevent_signal *se;
295 is_parent = talloc(winbind_event_context(), bool);
302 se = tevent_add_signal(winbind_event_context(),
305 winbindd_sig_term_handler,
308 DEBUG(0,("failed to setup SIGTERM handler"));
309 talloc_free(is_parent);
313 se = tevent_add_signal(winbind_event_context(),
316 winbindd_sig_term_handler,
319 DEBUG(0,("failed to setup SIGINT handler"));
320 talloc_free(is_parent);
324 se = tevent_add_signal(winbind_event_context(),
327 winbindd_sig_term_handler,
330 DEBUG(0,("failed to setup SIGINT handler"));
331 talloc_free(is_parent);
338 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
345 is_parent = talloc(winbind_event_context(), bool);
352 /* if we are running in the foreground then look for
353 EOF on stdin, and exit if it happens. This allows
354 us to die if the parent process dies
355 Only do this on a pipe or socket, no other device.
357 if (fstat(0, &st) != 0) {
360 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
361 tevent_add_fd(winbind_event_context(),
365 winbindd_stdin_handler,
373 static void winbindd_sig_hup_handler(struct tevent_context *ev,
374 struct tevent_signal *se,
380 const char *file = (const char *)private_data;
382 DEBUG(1,("Reloading services after SIGHUP\n"));
383 flush_caches_noinit();
384 reload_services_file(file);
387 bool winbindd_setup_sig_hup_handler(const char *lfile)
389 struct tevent_signal *se;
393 file = talloc_strdup(winbind_event_context(),
400 se = tevent_add_signal(winbind_event_context(),
401 winbind_event_context(),
403 winbindd_sig_hup_handler,
412 static void winbindd_sig_chld_handler(struct tevent_context *ev,
413 struct tevent_signal *se,
421 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
422 winbind_child_died(pid);
426 static bool winbindd_setup_sig_chld_handler(void)
428 struct tevent_signal *se;
430 se = tevent_add_signal(winbind_event_context(),
431 winbind_event_context(),
433 winbindd_sig_chld_handler,
442 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
443 struct tevent_signal *se,
452 static bool winbindd_setup_sig_usr2_handler(void)
454 struct tevent_signal *se;
456 se = tevent_add_signal(winbind_event_context(),
457 winbind_event_context(),
459 winbindd_sig_usr2_handler,
468 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
469 static void msg_reload_services(struct messaging_context *msg,
472 struct server_id server_id,
475 /* Flush various caches */
477 reload_services_file((const char *) private_data);
480 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
481 static void msg_shutdown(struct messaging_context *msg,
484 struct server_id server_id,
487 /* only the parent waits for this message */
488 DEBUG(0,("Got shutdown message\n"));
493 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
496 struct server_id server_id,
503 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
507 * call the validation code from a child:
508 * so we don't block the main winbindd and the validation
509 * code can safely use fork/waitpid...
513 if (child_pid == -1) {
514 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
519 if (child_pid != 0) {
521 DEBUG(5, ("winbind_msg_validate_cache: child created with "
522 "pid %d.\n", (int)child_pid));
528 status = winbindd_reinit_after_fork(NULL, NULL);
529 if (!NT_STATUS_IS_OK(status)) {
530 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
535 /* install default SIGCHLD handler: validation code uses fork/waitpid */
536 CatchSignal(SIGCHLD, SIG_DFL);
538 ret = (uint8_t)winbindd_validate_cache_nobackup();
539 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
540 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
545 static struct winbindd_dispatch_table {
546 enum winbindd_cmd cmd;
547 void (*fn)(struct winbindd_cli_state *state);
548 const char *winbindd_cmd_name;
549 } dispatch_table[] = {
551 /* Enumeration functions */
553 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
558 { WINBINDD_INFO, winbindd_info, "INFO" },
559 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
560 "INTERFACE_VERSION" },
561 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
562 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
563 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
564 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
565 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
566 "WINBINDD_PRIV_PIPE_DIR" },
568 /* Credential cache access */
569 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
570 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
574 { WINBINDD_NUM_CMDS, NULL, "NONE" }
577 struct winbindd_async_dispatch_table {
578 enum winbindd_cmd cmd;
579 const char *cmd_name;
580 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
581 struct tevent_context *ev,
582 struct winbindd_cli_state *cli,
583 struct winbindd_request *request);
584 NTSTATUS (*recv_req)(struct tevent_req *req,
585 struct winbindd_response *presp);
588 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
589 { WINBINDD_PING, "PING",
590 wb_ping_send, wb_ping_recv },
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_SID_TO_UID, "SID_TO_UID",
598 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
599 { WINBINDD_SID_TO_GID, "SID_TO_GID",
600 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
601 { WINBINDD_UID_TO_SID, "UID_TO_SID",
602 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
603 { WINBINDD_GID_TO_SID, "GID_TO_SID",
604 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
605 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
606 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
607 { WINBINDD_GETPWSID, "GETPWSID",
608 winbindd_getpwsid_send, winbindd_getpwsid_recv },
609 { WINBINDD_GETPWNAM, "GETPWNAM",
610 winbindd_getpwnam_send, winbindd_getpwnam_recv },
611 { WINBINDD_GETPWUID, "GETPWUID",
612 winbindd_getpwuid_send, winbindd_getpwuid_recv },
613 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
614 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
615 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
616 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
617 { WINBINDD_GETGROUPS, "GETGROUPS",
618 winbindd_getgroups_send, winbindd_getgroups_recv },
619 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
620 winbindd_show_sequence_send, winbindd_show_sequence_recv },
621 { WINBINDD_GETGRGID, "GETGRGID",
622 winbindd_getgrgid_send, winbindd_getgrgid_recv },
623 { WINBINDD_GETGRNAM, "GETGRNAM",
624 winbindd_getgrnam_send, winbindd_getgrnam_recv },
625 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
626 winbindd_getusersids_send, winbindd_getusersids_recv },
627 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
628 winbindd_lookuprids_send, winbindd_lookuprids_recv },
629 { WINBINDD_SETPWENT, "SETPWENT",
630 winbindd_setpwent_send, winbindd_setpwent_recv },
631 { WINBINDD_GETPWENT, "GETPWENT",
632 winbindd_getpwent_send, winbindd_getpwent_recv },
633 { WINBINDD_ENDPWENT, "ENDPWENT",
634 winbindd_endpwent_send, winbindd_endpwent_recv },
635 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
636 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
637 { WINBINDD_GETDCNAME, "GETDCNAME",
638 winbindd_getdcname_send, winbindd_getdcname_recv },
639 { WINBINDD_SETGRENT, "SETGRENT",
640 winbindd_setgrent_send, winbindd_setgrent_recv },
641 { WINBINDD_GETGRENT, "GETGRENT",
642 winbindd_getgrent_send, winbindd_getgrent_recv },
643 { WINBINDD_ENDGRENT, "ENDGRENT",
644 winbindd_endgrent_send, winbindd_endgrent_recv },
645 { WINBINDD_LIST_USERS, "LIST_USERS",
646 winbindd_list_users_send, winbindd_list_users_recv },
647 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
648 winbindd_list_groups_send, winbindd_list_groups_recv },
649 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
650 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
651 { WINBINDD_PING_DC, "PING_DC",
652 winbindd_ping_dc_send, winbindd_ping_dc_recv },
653 { WINBINDD_PAM_AUTH, "PAM_AUTH",
654 winbindd_pam_auth_send, winbindd_pam_auth_recv },
655 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
656 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
657 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
658 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
659 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
660 winbindd_pam_chng_pswd_auth_crap_send,
661 winbindd_pam_chng_pswd_auth_crap_recv },
662 { WINBINDD_WINS_BYIP, "WINS_BYIP",
663 winbindd_wins_byip_send, winbindd_wins_byip_recv },
664 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
665 winbindd_wins_byname_send, winbindd_wins_byname_recv },
667 { 0, NULL, NULL, NULL }
670 static struct winbindd_async_dispatch_table async_priv_table[] = {
671 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
672 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
673 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
674 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
675 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
676 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
677 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
678 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
680 { 0, NULL, NULL, NULL }
683 static void wb_request_done(struct tevent_req *req);
685 static void process_request(struct winbindd_cli_state *state)
687 struct winbindd_dispatch_table *table = dispatch_table;
688 struct winbindd_async_dispatch_table *atable;
690 state->mem_ctx = talloc_named(state, 0, "winbind request");
691 if (state->mem_ctx == NULL)
694 /* Remember who asked us. */
695 state->pid = state->request->pid;
697 state->cmd_name = "unknown request";
698 state->recv_fn = NULL;
699 state->last_access = time(NULL);
701 /* Process command */
703 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
704 if (state->request->cmd == atable->cmd) {
709 if ((atable->send_req == NULL) && state->privileged) {
710 for (atable = async_priv_table; atable->send_req;
712 if (state->request->cmd == atable->cmd) {
718 if (atable->send_req != NULL) {
719 struct tevent_req *req;
721 state->cmd_name = atable->cmd_name;
722 state->recv_fn = atable->recv_req;
724 DEBUG(10, ("process_request: Handling async request %d:%s\n",
725 (int)state->pid, state->cmd_name));
727 req = atable->send_req(state->mem_ctx, winbind_event_context(),
728 state, state->request);
730 DEBUG(0, ("process_request: atable->send failed for "
731 "%s\n", atable->cmd_name));
732 request_error(state);
735 tevent_req_set_callback(req, wb_request_done, state);
739 state->response = talloc_zero(state->mem_ctx,
740 struct winbindd_response);
741 if (state->response == NULL) {
742 DEBUG(10, ("talloc failed\n"));
743 remove_client(state);
746 state->response->result = WINBINDD_PENDING;
747 state->response->length = sizeof(struct winbindd_response);
749 for (table = dispatch_table; table->fn; table++) {
750 if (state->request->cmd == table->cmd) {
751 DEBUG(10,("process_request: request fn %s\n",
752 table->winbindd_cmd_name ));
753 state->cmd_name = table->winbindd_cmd_name;
760 DEBUG(10,("process_request: unknown request fn number %d\n",
761 (int)state->request->cmd ));
762 request_error(state);
766 static void wb_request_done(struct tevent_req *req)
768 struct winbindd_cli_state *state = tevent_req_callback_data(
769 req, struct winbindd_cli_state);
772 state->response = talloc_zero(state->mem_ctx,
773 struct winbindd_response);
774 if (state->response == NULL) {
775 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
776 (int)state->pid, state->cmd_name));
777 remove_client(state);
780 state->response->result = WINBINDD_PENDING;
781 state->response->length = sizeof(struct winbindd_response);
783 status = state->recv_fn(req, state->response);
786 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
787 (int)state->pid, state->cmd_name, nt_errstr(status)));
789 if (!NT_STATUS_IS_OK(status)) {
790 request_error(state);
797 * This is the main event loop of winbind requests. It goes through a
798 * state-machine of 3 read/write requests, 4 if you have extra data to send.
800 * An idle winbind client has a read request of 4 bytes outstanding,
801 * finalizing function is request_len_recv, checking the length. request_recv
802 * then processes the packet. The processing function then at some point has
803 * to call request_finished which schedules sending the response.
806 static void request_finished(struct winbindd_cli_state *state);
808 static void winbind_client_request_read(struct tevent_req *req);
809 static void winbind_client_response_written(struct tevent_req *req);
811 static void request_finished(struct winbindd_cli_state *state)
813 struct tevent_req *req;
815 TALLOC_FREE(state->request);
817 req = wb_resp_write_send(state, winbind_event_context(),
818 state->out_queue, state->sock,
821 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
822 (int)state->pid, state->cmd_name));
823 remove_client(state);
826 tevent_req_set_callback(req, winbind_client_response_written, state);
830 static void winbind_client_response_written(struct tevent_req *req)
832 struct winbindd_cli_state *state = tevent_req_callback_data(
833 req, struct winbindd_cli_state);
837 state->io_req = NULL;
839 ret = wb_resp_write_recv(req, &err);
844 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
845 (int)state->pid, state->cmd_name, strerror(err)));
846 remove_client(state);
850 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
851 "to client\n", (int)state->pid, state->cmd_name));
853 TALLOC_FREE(state->mem_ctx);
854 state->response = NULL;
855 state->cmd_name = "no request";
856 state->recv_fn = NULL;
858 req = wb_req_read_send(state, winbind_event_context(), state->sock,
859 WINBINDD_MAX_EXTRA_DATA);
861 remove_client(state);
864 tevent_req_set_callback(req, winbind_client_request_read, state);
868 void request_error(struct winbindd_cli_state *state)
870 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
871 state->response->result = WINBINDD_ERROR;
872 request_finished(state);
875 void request_ok(struct winbindd_cli_state *state)
877 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
878 state->response->result = WINBINDD_OK;
879 request_finished(state);
882 /* Process a new connection by adding it to the client connection list */
884 static void new_connection(int listen_sock, bool privileged)
886 struct sockaddr_un sunaddr;
887 struct winbindd_cli_state *state;
888 struct tevent_req *req;
892 /* Accept connection */
894 len = sizeof(sunaddr);
896 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
899 if (errno != EINTR) {
900 DEBUG(0, ("Failed to accept socket - %s\n",
906 DEBUG(6,("accepted socket %d\n", sock));
908 /* Create new connection structure */
910 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
917 state->out_queue = tevent_queue_create(state, "winbind client reply");
918 if (state->out_queue == NULL) {
924 state->last_access = time(NULL);
926 state->privileged = privileged;
928 req = wb_req_read_send(state, winbind_event_context(), state->sock,
929 WINBINDD_MAX_EXTRA_DATA);
935 tevent_req_set_callback(req, winbind_client_request_read, state);
938 /* Add to connection list */
940 winbindd_add_client(state);
943 static void winbind_client_request_read(struct tevent_req *req)
945 struct winbindd_cli_state *state = tevent_req_callback_data(
946 req, struct winbindd_cli_state);
950 state->io_req = NULL;
952 ret = wb_req_read_recv(req, state, &state->request, &err);
956 DEBUG(6, ("closing socket %d, client exited\n",
959 DEBUG(2, ("Could not read client request from fd %d: "
960 "%s\n", state->sock, strerror(err)));
964 remove_client(state);
967 process_request(state);
970 /* Remove a client connection from client connection list */
972 static void remove_client(struct winbindd_cli_state *state)
977 /* It's a dead client - hold a funeral */
984 * We need to remove a pending wb_req_read_*
985 * or wb_resp_write_* request before closing the
988 * This is important as they might have used tevent_add_fd() and we
989 * use the epoll * backend on linux. So we must remove the tevent_fd
990 * before closing the fd.
992 * Otherwise we might hit a race with close_conns_after_fork() (via
993 * winbindd_reinit_after_fork()) where a file description
994 * is still open in a child, which means it's still active in
995 * the parents epoll queue, but the related tevent_fd is already
996 * already gone in the parent.
1000 TALLOC_FREE(state->io_req);
1002 if (state->sock != -1) {
1003 /* tell client, we are closing ... */
1004 nwritten = write(state->sock, &c, sizeof(c));
1005 if (nwritten == -1) {
1006 DEBUG(2, ("final write to client failed: %s\n",
1016 TALLOC_FREE(state->mem_ctx);
1018 /* Remove from list and free */
1020 winbindd_remove_client(state);
1024 /* Is a client idle? */
1026 static bool client_is_idle(struct winbindd_cli_state *state) {
1027 return (state->request == NULL &&
1028 state->response == NULL &&
1029 !state->pwent_state && !state->grent_state);
1032 /* Shutdown client connection which has been idle for the longest time */
1034 static bool remove_idle_client(void)
1036 struct winbindd_cli_state *state, *remove_state = NULL;
1037 time_t last_access = 0;
1040 for (state = winbindd_client_list(); state; state = state->next) {
1041 if (client_is_idle(state)) {
1043 if (!last_access || state->last_access < last_access) {
1044 last_access = state->last_access;
1045 remove_state = state;
1051 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1052 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1053 remove_client(remove_state);
1061 * Terminate all clients whose requests have taken longer than
1062 * "winbind request timeout" seconds to process, or have been
1063 * idle for more than "winbind request timeout" seconds.
1066 static void remove_timed_out_clients(void)
1068 struct winbindd_cli_state *state, *next = NULL;
1069 time_t curr_time = time(NULL);
1070 int timeout_val = lp_winbind_request_timeout();
1072 for (state = winbindd_client_list(); state; state = next) {
1076 expiry_time = state->last_access + timeout_val;
1078 if (curr_time > expiry_time) {
1079 if (client_is_idle(state)) {
1080 DEBUG(5,("Idle client timed out, "
1081 "shutting down sock %d, pid %u\n",
1083 (unsigned int)state->pid));
1085 DEBUG(5,("Client request timed out, "
1086 "shutting down sock %d, pid %u\n",
1088 (unsigned int)state->pid));
1090 remove_client(state);
1095 struct winbindd_listen_state {
1100 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1101 struct tevent_fd *fde,
1105 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1106 struct winbindd_listen_state);
1108 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1109 DEBUG(5,("winbindd: Exceeding %d client "
1110 "connections, removing idle "
1111 "connection.\n", lp_winbind_max_clients()));
1112 if (!remove_idle_client()) {
1113 DEBUG(0,("winbindd: Exceeding %d "
1114 "client connections, no idle "
1115 "connection found\n",
1116 lp_winbind_max_clients()));
1120 remove_timed_out_clients();
1121 new_connection(s->fd, s->privileged);
1125 * Winbindd socket accessor functions
1128 char *get_winbind_priv_pipe_dir(void)
1130 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1133 static bool winbindd_setup_listeners(void)
1135 struct winbindd_listen_state *pub_state = NULL;
1136 struct winbindd_listen_state *priv_state = NULL;
1137 struct tevent_fd *fde;
1141 pub_state = talloc(winbind_event_context(),
1142 struct winbindd_listen_state);
1147 pub_state->privileged = false;
1148 pub_state->fd = create_pipe_sock(
1149 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1150 if (pub_state->fd == -1) {
1153 rc = listen(pub_state->fd, 5);
1158 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1159 TEVENT_FD_READ, winbindd_listen_fde_handler,
1162 close(pub_state->fd);
1165 tevent_fd_set_auto_close(fde);
1167 priv_state = talloc(winbind_event_context(),
1168 struct winbindd_listen_state);
1173 socket_path = get_winbind_priv_pipe_dir();
1174 if (socket_path == NULL) {
1178 priv_state->privileged = true;
1179 priv_state->fd = create_pipe_sock(
1180 socket_path, WINBINDD_SOCKET_NAME, 0750);
1181 TALLOC_FREE(socket_path);
1182 if (priv_state->fd == -1) {
1185 rc = listen(priv_state->fd, 5);
1190 fde = tevent_add_fd(winbind_event_context(), priv_state,
1191 priv_state->fd, TEVENT_FD_READ,
1192 winbindd_listen_fde_handler, priv_state);
1194 close(priv_state->fd);
1197 tevent_fd_set_auto_close(fde);
1201 TALLOC_FREE(pub_state);
1202 TALLOC_FREE(priv_state);
1206 bool winbindd_use_idmap_cache(void)
1208 return !opt_nocache;
1211 bool winbindd_use_cache(void)
1213 return !opt_nocache;
1216 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1220 /* Setup signal handlers */
1222 if (!winbindd_setup_sig_term_handler(true))
1224 if (!winbindd_setup_stdin_handler(true, foreground))
1226 if (!winbindd_setup_sig_hup_handler(NULL))
1228 if (!winbindd_setup_sig_chld_handler())
1230 if (!winbindd_setup_sig_usr2_handler())
1233 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1236 * Ensure all cache and idmap caches are consistent
1237 * and initialized before we startup.
1239 if (!winbindd_cache_validate_and_initialize()) {
1243 /* get broadcast messages */
1245 if (!serverid_register(messaging_server_id(msg_ctx),
1249 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1253 /* React on 'smbcontrol winbindd reload-config' in the same way
1254 as to SIGHUP signal */
1255 messaging_register(msg_ctx, NULL,
1256 MSG_SMB_CONF_UPDATED, msg_reload_services);
1257 messaging_register(msg_ctx, NULL,
1258 MSG_SHUTDOWN, msg_shutdown);
1260 /* Handle online/offline messages. */
1261 messaging_register(msg_ctx, NULL,
1262 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1263 messaging_register(msg_ctx, NULL,
1264 MSG_WINBIND_ONLINE, winbind_msg_online);
1265 messaging_register(msg_ctx, NULL,
1266 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1268 /* Handle domain online/offline messages for domains */
1269 messaging_register(winbind_messaging_context(), NULL,
1270 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1271 messaging_register(winbind_messaging_context(), NULL,
1272 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1274 messaging_register(msg_ctx, NULL,
1275 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1277 messaging_register(msg_ctx, NULL,
1278 MSG_WINBIND_VALIDATE_CACHE,
1279 winbind_msg_validate_cache);
1281 messaging_register(msg_ctx, NULL,
1282 MSG_WINBIND_DUMP_DOMAIN_LIST,
1283 winbind_msg_dump_domain_list);
1285 messaging_register(msg_ctx, NULL,
1286 MSG_WINBIND_IP_DROPPED,
1287 winbind_msg_ip_dropped_parent);
1289 /* Register handler for MSG_DEBUG. */
1290 messaging_register(msg_ctx, NULL,
1294 netsamlogon_cache_init(); /* Non-critical */
1296 /* clear the cached list of trusted domains */
1300 if (!init_domain_list()) {
1301 DEBUG(0,("unable to initialize domain list\n"));
1306 init_locator_child();
1308 smb_nscd_flush_user_cache();
1309 smb_nscd_flush_group_cache();
1311 if (lp_allow_trusted_domains()) {
1312 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1313 rescan_trusted_domains, NULL) == NULL) {
1314 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1319 status = wb_irpc_register();
1321 if (!NT_STATUS_IS_OK(status)) {
1322 DEBUG(0, ("Could not register IRPC handlers\n"));
1327 struct winbindd_addrchanged_state {
1328 struct addrchange_context *ctx;
1329 struct tevent_context *ev;
1330 struct messaging_context *msg_ctx;
1333 static void winbindd_addr_changed(struct tevent_req *req);
1335 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1336 struct tevent_context *ev,
1337 struct messaging_context *msg_ctx)
1339 struct winbindd_addrchanged_state *state;
1340 struct tevent_req *req;
1343 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1344 if (state == NULL) {
1345 DEBUG(10, ("talloc failed\n"));
1349 state->msg_ctx = msg_ctx;
1351 status = addrchange_context_create(state, &state->ctx);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 DEBUG(10, ("addrchange_context_create failed: %s\n",
1354 nt_errstr(status)));
1358 req = addrchange_send(state, ev, state->ctx);
1360 DEBUG(0, ("addrchange_send failed\n"));
1364 tevent_req_set_callback(req, winbindd_addr_changed, state);
1367 static void winbindd_addr_changed(struct tevent_req *req)
1369 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1370 req, struct winbindd_addrchanged_state);
1371 enum addrchange_type type;
1372 struct sockaddr_storage addr;
1375 status = addrchange_recv(req, &type, &addr);
1377 if (!NT_STATUS_IS_OK(status)) {
1378 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1379 nt_errstr(status)));
1383 if (type == ADDRCHANGE_DEL) {
1384 char addrstr[INET6_ADDRSTRLEN];
1387 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1389 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1392 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1394 status = messaging_send(state->msg_ctx,
1395 messaging_server_id(state->msg_ctx),
1396 MSG_WINBIND_IP_DROPPED, &blob);
1397 if (!NT_STATUS_IS_OK(status)) {
1398 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1399 nt_errstr(status)));
1402 req = addrchange_send(state, state->ev, state->ctx);
1404 DEBUG(0, ("addrchange_send failed\n"));
1408 tevent_req_set_callback(req, winbindd_addr_changed, state);
1413 int main(int argc, const char **argv)
1415 static bool is_daemon = False;
1416 static bool Fork = True;
1417 static bool log_stdout = False;
1418 static bool no_process_group = False;
1422 OPT_NO_PROCESS_GROUP,
1425 struct poptOption long_options[] = {
1427 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1428 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1429 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1430 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1431 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1432 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1443 * Do this before any other talloc operation
1445 talloc_enable_null_tracking();
1446 frame = talloc_stackframe();
1449 * We want total control over the permissions on created files,
1450 * so set our umask to 0.
1454 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1456 /* glibc (?) likes to print "User defined signal 1" and exit if a
1457 SIGUSR[12] is received before a handler is installed */
1459 CatchSignal(SIGUSR1, SIG_IGN);
1460 CatchSignal(SIGUSR2, SIG_IGN);
1463 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1467 /* Initialise for running in non-root mode */
1471 set_remote_machine_name("winbindd", False);
1473 /* Set environment variable so we don't recursively call ourselves.
1474 This may also be useful interactively. */
1476 if ( !winbind_off() ) {
1477 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1481 /* Initialise samba/rpc client stuff */
1483 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1485 while ((opt = poptGetNextOpt(pc)) != -1) {
1487 /* Don't become a daemon */
1499 case OPT_NO_PROCESS_GROUP:
1500 no_process_group = true;
1502 case OPT_LOG_STDOUT:
1509 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1510 poptBadOption(pc, 0), poptStrerror(opt));
1511 poptPrintUsage(pc, stderr, 0);
1516 /* We call dump_core_setup one more time because the command line can
1517 * set the log file or the log-basename and this will influence where
1518 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1519 * the default value derived from build's prefix. For EOM this value
1520 * is often not related to the path where winbindd is actually run
1523 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1524 if (is_daemon && interactive) {
1525 d_fprintf(stderr,"\nERROR: "
1526 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1527 poptPrintUsage(pc, stderr, 0);
1531 if (log_stdout && Fork) {
1532 d_fprintf(stderr, "\nERROR: "
1533 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1534 poptPrintUsage(pc, stderr, 0);
1538 poptFreeContext(pc);
1540 if (!override_logfile) {
1542 if (asprintf(&lfile,"%s/log.winbindd",
1543 get_dyn_LOGFILEBASE()) > 0) {
1544 lp_set_logfile(lfile);
1550 setup_logging("winbindd", DEBUG_STDOUT);
1552 setup_logging("winbindd", DEBUG_FILE);
1556 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1557 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1559 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1560 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1563 /* After parsing the configuration file we setup the core path one more time
1564 * as the log file might have been set in the configuration and cores's
1565 * path is by default basename(lp_logfile()).
1567 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1569 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1570 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1571 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1572 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"));
1576 if (!cluster_probe_ok()) {
1580 /* Initialise messaging system */
1582 if (winbind_messaging_context() == NULL) {
1586 if (!reload_services_file(NULL)) {
1587 DEBUG(0, ("error opening config file\n"));
1591 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1593 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1594 lp_lock_directory(), strerror(errno)));
1598 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1600 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1601 lp_pid_directory(), strerror(errno)));
1612 if (!secrets_init()) {
1614 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1618 status = rpccli_pre_open_netlogon_creds();
1619 if (!NT_STATUS_IS_OK(status)) {
1620 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1621 nt_errstr(status)));
1625 /* Unblock all signals we are interested in as they may have been
1626 blocked by the parent process. */
1628 BlockSignals(False, SIGINT);
1629 BlockSignals(False, SIGQUIT);
1630 BlockSignals(False, SIGTERM);
1631 BlockSignals(False, SIGUSR1);
1632 BlockSignals(False, SIGUSR2);
1633 BlockSignals(False, SIGHUP);
1634 BlockSignals(False, SIGCHLD);
1637 become_daemon(Fork, no_process_group, log_stdout);
1639 pidfile_create(lp_pid_directory(), "winbindd");
1643 * If we're interactive we want to set our own process group for
1644 * signal management.
1646 if (interactive && !no_process_group)
1647 setpgid( (pid_t)0, (pid_t)0);
1652 /* Don't use winbindd_reinit_after_fork here as
1653 * we're just starting up and haven't created any
1654 * winbindd-specific resources we must free yet. JRA.
1657 status = reinit_after_fork(winbind_messaging_context(),
1658 winbind_event_context(),
1660 if (!NT_STATUS_IS_OK(status)) {
1661 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1665 * Do not initialize the parent-child-pipe before becoming
1666 * a daemon: this is used to detect a died parent in the child
1669 status = init_before_fork();
1670 if (!NT_STATUS_IS_OK(status)) {
1671 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1674 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1676 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1680 status = init_system_session_info();
1681 if (!NT_STATUS_IS_OK(status)) {
1682 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1685 rpc_lsarpc_init(NULL);
1686 rpc_samr_init(NULL);
1688 winbindd_init_addrchange(NULL, winbind_event_context(),
1689 winbind_messaging_context());
1691 /* setup listen sockets */
1693 if (!winbindd_setup_listeners()) {
1694 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1697 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1702 daemon_ready("winbindd");
1705 /* Loop waiting for requests */
1707 frame = talloc_stackframe();
1709 if (tevent_loop_once(winbind_event_context()) == -1) {
1710 DEBUG(1, ("tevent_loop_once() failed: %s\n",