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 static bool client_is_idle(struct winbindd_cli_state *state);
51 static void remove_client(struct winbindd_cli_state *state);
52 static void winbindd_setup_max_fds(void);
54 static bool opt_nocache = False;
55 static bool interactive = False;
57 extern bool override_logfile;
59 struct tevent_context *winbind_event_context(void)
61 static struct tevent_context *ev = NULL;
68 * Note we MUST use the NULL context here, not the autofree context,
69 * to avoid side effects in forked children exiting.
71 ev = samba_tevent_context_init(NULL);
73 smb_panic("Could not init winbindd's messaging context.\n");
78 struct messaging_context *winbind_messaging_context(void)
80 static struct messaging_context *msg = NULL;
87 * Note we MUST use the NULL context here, not the autofree context,
88 * to avoid side effects in forked children exiting.
90 msg = messaging_init(NULL, winbind_event_context());
92 smb_panic("Could not init winbindd's messaging context.\n");
97 struct imessaging_context *winbind_imessaging_context(void)
99 static struct imessaging_context *msg = NULL;
100 struct loadparm_context *lp_ctx;
106 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
107 if (lp_ctx == NULL) {
108 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
112 * Note we MUST use the NULL context here, not the autofree context,
113 * to avoid side effects in forked children exiting.
115 msg = imessaging_init(NULL, lp_ctx, procid_self(), winbind_event_context(), false);
116 talloc_unlink(NULL, lp_ctx);
119 smb_panic("Could not init winbindd's messaging context.\n");
124 /* Reload configuration */
126 static bool reload_services_file(const char *lfile)
131 char *fname = lp_next_configfile(talloc_tos());
133 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
134 set_dyn_CONFIGFILE(fname);
139 /* if this is a child, restore the logfile to the special
140 name - <domain>, idmap, etc. */
141 if (lfile && *lfile) {
142 lp_set_logfile(lfile);
146 ret = lp_load_global(get_dyn_CONFIGFILE());
150 winbindd_setup_max_fds();
156 static void winbindd_status(void)
158 struct winbindd_cli_state *tmp;
160 DEBUG(0, ("winbindd status:\n"));
162 /* Print client state information */
164 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
166 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
167 DEBUG(2, ("\tclient list:\n"));
168 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
169 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
170 (unsigned long)tmp->pid, tmp->sock,
171 client_is_idle(tmp) ? "idle" : "active"));
176 /* Flush client cache */
178 static void flush_caches(void)
180 /* We need to invalidate cached user list entries on a SIGHUP
181 otherwise cached access denied errors due to restrict anonymous
182 hang around until the sequence number changes. */
184 if (!wcache_invalidate_cache()) {
185 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
186 if (!winbindd_cache_validate_and_initialize()) {
192 static void flush_caches_noinit(void)
195 * We need to invalidate cached user list entries on a SIGHUP
196 * otherwise cached access denied errors due to restrict anonymous
197 * hang around until the sequence number changes.
199 * Skip uninitialized domains when flush cache.
200 * If domain is not initialized, it means it is never
201 * used or never become online. look, wcache_invalidate_cache()
202 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
203 * for unused domains and large traffic for primay domain's DC if there
207 if (!wcache_invalidate_cache_noinit()) {
208 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
209 if (!winbindd_cache_validate_and_initialize()) {
215 /* Handle the signal by unlinking socket and exiting */
217 static void terminate(bool is_parent)
220 /* When parent goes away we should
221 * remove the socket file. Not so
222 * when children terminate.
226 if (asprintf(&path, "%s/%s",
227 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
235 trustdom_cache_shutdown();
237 gencache_stabilize();
241 TALLOC_CTX *mem_ctx = talloc_init("end_description");
242 char *description = talloc_describe_all(mem_ctx);
244 DEBUG(3, ("tallocs left:\n%s\n", description));
245 talloc_destroy(mem_ctx);
250 struct messaging_context *msg = winbind_messaging_context();
251 struct server_id self = messaging_server_id(msg);
252 serverid_deregister(self);
253 pidfile_unlink(lp_pid_directory(), "winbindd");
259 static void winbindd_sig_term_handler(struct tevent_context *ev,
260 struct tevent_signal *se,
266 bool *is_parent = talloc_get_type_abort(private_data, bool);
268 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
269 signum, (int)*is_parent));
270 terminate(*is_parent);
274 handle stdin becoming readable when we are in --foreground mode
276 static void winbindd_stdin_handler(struct tevent_context *ev,
277 struct tevent_fd *fde,
282 if (read(0, &c, 1) != 1) {
283 bool *is_parent = talloc_get_type_abort(private_data, bool);
285 /* we have reached EOF on stdin, which means the
286 parent has exited. Shutdown the server */
287 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
289 terminate(*is_parent);
293 bool winbindd_setup_sig_term_handler(bool parent)
295 struct tevent_signal *se;
298 is_parent = talloc(winbind_event_context(), bool);
305 se = tevent_add_signal(winbind_event_context(),
308 winbindd_sig_term_handler,
311 DEBUG(0,("failed to setup SIGTERM handler"));
312 talloc_free(is_parent);
316 se = tevent_add_signal(winbind_event_context(),
319 winbindd_sig_term_handler,
322 DEBUG(0,("failed to setup SIGINT handler"));
323 talloc_free(is_parent);
327 se = tevent_add_signal(winbind_event_context(),
330 winbindd_sig_term_handler,
333 DEBUG(0,("failed to setup SIGINT handler"));
334 talloc_free(is_parent);
341 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
348 is_parent = talloc(winbind_event_context(), bool);
355 /* if we are running in the foreground then look for
356 EOF on stdin, and exit if it happens. This allows
357 us to die if the parent process dies
358 Only do this on a pipe or socket, no other device.
360 if (fstat(0, &st) != 0) {
363 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
364 tevent_add_fd(winbind_event_context(),
368 winbindd_stdin_handler,
376 static void winbindd_sig_hup_handler(struct tevent_context *ev,
377 struct tevent_signal *se,
383 const char *file = (const char *)private_data;
385 DEBUG(1,("Reloading services after SIGHUP\n"));
386 flush_caches_noinit();
387 reload_services_file(file);
390 bool winbindd_setup_sig_hup_handler(const char *lfile)
392 struct tevent_signal *se;
396 file = talloc_strdup(winbind_event_context(),
403 se = tevent_add_signal(winbind_event_context(),
404 winbind_event_context(),
406 winbindd_sig_hup_handler,
415 static void winbindd_sig_chld_handler(struct tevent_context *ev,
416 struct tevent_signal *se,
424 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
425 winbind_child_died(pid);
429 static bool winbindd_setup_sig_chld_handler(void)
431 struct tevent_signal *se;
433 se = tevent_add_signal(winbind_event_context(),
434 winbind_event_context(),
436 winbindd_sig_chld_handler,
445 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
446 struct tevent_signal *se,
455 static bool winbindd_setup_sig_usr2_handler(void)
457 struct tevent_signal *se;
459 se = tevent_add_signal(winbind_event_context(),
460 winbind_event_context(),
462 winbindd_sig_usr2_handler,
471 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
472 static void msg_reload_services(struct messaging_context *msg,
475 struct server_id server_id,
478 /* Flush various caches */
480 reload_services_file((const char *) private_data);
483 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
484 static void msg_shutdown(struct messaging_context *msg,
487 struct server_id server_id,
490 /* only the parent waits for this message */
491 DEBUG(0,("Got shutdown message\n"));
496 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
499 struct server_id server_id,
506 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
510 * call the validation code from a child:
511 * so we don't block the main winbindd and the validation
512 * code can safely use fork/waitpid...
516 if (child_pid == -1) {
517 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
522 if (child_pid != 0) {
524 DEBUG(5, ("winbind_msg_validate_cache: child created with "
525 "pid %d.\n", (int)child_pid));
531 status = winbindd_reinit_after_fork(NULL, NULL);
532 if (!NT_STATUS_IS_OK(status)) {
533 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
538 /* install default SIGCHLD handler: validation code uses fork/waitpid */
539 CatchSignal(SIGCHLD, SIG_DFL);
541 ret = (uint8_t)winbindd_validate_cache_nobackup();
542 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
543 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
548 static struct winbindd_dispatch_table {
549 enum winbindd_cmd cmd;
550 void (*fn)(struct winbindd_cli_state *state);
551 const char *winbindd_cmd_name;
552 } dispatch_table[] = {
554 /* Enumeration functions */
556 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
561 { WINBINDD_INFO, winbindd_info, "INFO" },
562 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
563 "INTERFACE_VERSION" },
564 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
565 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
566 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
567 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
568 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
569 "WINBINDD_PRIV_PIPE_DIR" },
571 /* Credential cache access */
572 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
573 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
577 { WINBINDD_NUM_CMDS, NULL, "NONE" }
580 struct winbindd_async_dispatch_table {
581 enum winbindd_cmd cmd;
582 const char *cmd_name;
583 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
584 struct tevent_context *ev,
585 struct winbindd_cli_state *cli,
586 struct winbindd_request *request);
587 NTSTATUS (*recv_req)(struct tevent_req *req,
588 struct winbindd_response *presp);
591 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
592 { WINBINDD_PING, "PING",
593 wb_ping_send, wb_ping_recv },
594 { WINBINDD_LOOKUPSID, "LOOKUPSID",
595 winbindd_lookupsid_send, winbindd_lookupsid_recv },
596 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
597 winbindd_lookupsids_send, winbindd_lookupsids_recv },
598 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
599 winbindd_lookupname_send, winbindd_lookupname_recv },
600 { WINBINDD_SID_TO_UID, "SID_TO_UID",
601 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
602 { WINBINDD_SID_TO_GID, "SID_TO_GID",
603 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
604 { WINBINDD_UID_TO_SID, "UID_TO_SID",
605 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
606 { WINBINDD_GID_TO_SID, "GID_TO_SID",
607 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
608 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
609 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
610 { WINBINDD_GETPWSID, "GETPWSID",
611 winbindd_getpwsid_send, winbindd_getpwsid_recv },
612 { WINBINDD_GETPWNAM, "GETPWNAM",
613 winbindd_getpwnam_send, winbindd_getpwnam_recv },
614 { WINBINDD_GETPWUID, "GETPWUID",
615 winbindd_getpwuid_send, winbindd_getpwuid_recv },
616 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
617 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
618 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
619 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
620 { WINBINDD_GETGROUPS, "GETGROUPS",
621 winbindd_getgroups_send, winbindd_getgroups_recv },
622 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
623 winbindd_show_sequence_send, winbindd_show_sequence_recv },
624 { WINBINDD_GETGRGID, "GETGRGID",
625 winbindd_getgrgid_send, winbindd_getgrgid_recv },
626 { WINBINDD_GETGRNAM, "GETGRNAM",
627 winbindd_getgrnam_send, winbindd_getgrnam_recv },
628 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
629 winbindd_getusersids_send, winbindd_getusersids_recv },
630 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
631 winbindd_lookuprids_send, winbindd_lookuprids_recv },
632 { WINBINDD_SETPWENT, "SETPWENT",
633 winbindd_setpwent_send, winbindd_setpwent_recv },
634 { WINBINDD_GETPWENT, "GETPWENT",
635 winbindd_getpwent_send, winbindd_getpwent_recv },
636 { WINBINDD_ENDPWENT, "ENDPWENT",
637 winbindd_endpwent_send, winbindd_endpwent_recv },
638 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
639 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
640 { WINBINDD_GETDCNAME, "GETDCNAME",
641 winbindd_getdcname_send, winbindd_getdcname_recv },
642 { WINBINDD_SETGRENT, "SETGRENT",
643 winbindd_setgrent_send, winbindd_setgrent_recv },
644 { WINBINDD_GETGRENT, "GETGRENT",
645 winbindd_getgrent_send, winbindd_getgrent_recv },
646 { WINBINDD_ENDGRENT, "ENDGRENT",
647 winbindd_endgrent_send, winbindd_endgrent_recv },
648 { WINBINDD_LIST_USERS, "LIST_USERS",
649 winbindd_list_users_send, winbindd_list_users_recv },
650 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
651 winbindd_list_groups_send, winbindd_list_groups_recv },
652 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
653 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
654 { WINBINDD_PING_DC, "PING_DC",
655 winbindd_ping_dc_send, winbindd_ping_dc_recv },
656 { WINBINDD_PAM_AUTH, "PAM_AUTH",
657 winbindd_pam_auth_send, winbindd_pam_auth_recv },
658 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
659 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
660 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
661 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
662 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
663 winbindd_pam_chng_pswd_auth_crap_send,
664 winbindd_pam_chng_pswd_auth_crap_recv },
665 { WINBINDD_WINS_BYIP, "WINS_BYIP",
666 winbindd_wins_byip_send, winbindd_wins_byip_recv },
667 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
668 winbindd_wins_byname_send, winbindd_wins_byname_recv },
670 { 0, NULL, NULL, NULL }
673 static struct winbindd_async_dispatch_table async_priv_table[] = {
674 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
675 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
676 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
677 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
678 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
679 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
680 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
681 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
683 { 0, NULL, NULL, NULL }
686 static void wb_request_done(struct tevent_req *req);
688 static void process_request(struct winbindd_cli_state *state)
690 struct winbindd_dispatch_table *table = dispatch_table;
691 struct winbindd_async_dispatch_table *atable;
693 state->mem_ctx = talloc_named(state, 0, "winbind request");
694 if (state->mem_ctx == NULL)
697 /* Remember who asked us. */
698 state->pid = state->request->pid;
700 state->cmd_name = "unknown request";
701 state->recv_fn = NULL;
702 state->last_access = time(NULL);
704 /* Process command */
706 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
707 if (state->request->cmd == atable->cmd) {
712 if ((atable->send_req == NULL) && state->privileged) {
713 for (atable = async_priv_table; atable->send_req;
715 if (state->request->cmd == atable->cmd) {
721 if (atable->send_req != NULL) {
722 struct tevent_req *req;
724 state->cmd_name = atable->cmd_name;
725 state->recv_fn = atable->recv_req;
727 DEBUG(10, ("process_request: Handling async request %d:%s\n",
728 (int)state->pid, state->cmd_name));
730 req = atable->send_req(state->mem_ctx, winbind_event_context(),
731 state, state->request);
733 DEBUG(0, ("process_request: atable->send failed for "
734 "%s\n", atable->cmd_name));
735 request_error(state);
738 tevent_req_set_callback(req, wb_request_done, state);
742 state->response = talloc_zero(state->mem_ctx,
743 struct winbindd_response);
744 if (state->response == NULL) {
745 DEBUG(10, ("talloc failed\n"));
746 remove_client(state);
749 state->response->result = WINBINDD_PENDING;
750 state->response->length = sizeof(struct winbindd_response);
752 for (table = dispatch_table; table->fn; table++) {
753 if (state->request->cmd == table->cmd) {
754 DEBUG(10,("process_request: request fn %s\n",
755 table->winbindd_cmd_name ));
756 state->cmd_name = table->winbindd_cmd_name;
763 DEBUG(10,("process_request: unknown request fn number %d\n",
764 (int)state->request->cmd ));
765 request_error(state);
769 static void wb_request_done(struct tevent_req *req)
771 struct winbindd_cli_state *state = tevent_req_callback_data(
772 req, struct winbindd_cli_state);
775 state->response = talloc_zero(state->mem_ctx,
776 struct winbindd_response);
777 if (state->response == NULL) {
778 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
779 (int)state->pid, state->cmd_name));
780 remove_client(state);
783 state->response->result = WINBINDD_PENDING;
784 state->response->length = sizeof(struct winbindd_response);
786 status = state->recv_fn(req, state->response);
789 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
790 (int)state->pid, state->cmd_name, nt_errstr(status)));
792 if (!NT_STATUS_IS_OK(status)) {
793 request_error(state);
800 * This is the main event loop of winbind requests. It goes through a
801 * state-machine of 3 read/write requests, 4 if you have extra data to send.
803 * An idle winbind client has a read request of 4 bytes outstanding,
804 * finalizing function is request_len_recv, checking the length. request_recv
805 * then processes the packet. The processing function then at some point has
806 * to call request_finished which schedules sending the response.
809 static void request_finished(struct winbindd_cli_state *state);
811 static void winbind_client_request_read(struct tevent_req *req);
812 static void winbind_client_response_written(struct tevent_req *req);
813 static void winbind_client_activity(struct tevent_req *req);
815 static void request_finished(struct winbindd_cli_state *state)
817 struct tevent_req *req;
819 /* free client socket monitoring request */
820 TALLOC_FREE(state->io_req);
822 TALLOC_FREE(state->request);
824 req = wb_resp_write_send(state, winbind_event_context(),
825 state->out_queue, state->sock,
828 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
829 (int)state->pid, state->cmd_name));
830 remove_client(state);
833 tevent_req_set_callback(req, winbind_client_response_written, state);
837 static void winbind_client_response_written(struct tevent_req *req)
839 struct winbindd_cli_state *state = tevent_req_callback_data(
840 req, struct winbindd_cli_state);
844 state->io_req = NULL;
846 ret = wb_resp_write_recv(req, &err);
851 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
852 (int)state->pid, state->cmd_name, strerror(err)));
853 remove_client(state);
857 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
858 "to client\n", (int)state->pid, state->cmd_name));
860 TALLOC_FREE(state->mem_ctx);
861 state->response = NULL;
862 state->cmd_name = "no request";
863 state->recv_fn = NULL;
865 req = wb_req_read_send(state, winbind_event_context(), state->sock,
866 WINBINDD_MAX_EXTRA_DATA);
868 remove_client(state);
871 tevent_req_set_callback(req, winbind_client_request_read, state);
875 void request_error(struct winbindd_cli_state *state)
877 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
878 state->response->result = WINBINDD_ERROR;
879 request_finished(state);
882 void request_ok(struct winbindd_cli_state *state)
884 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
885 state->response->result = WINBINDD_OK;
886 request_finished(state);
889 /* Process a new connection by adding it to the client connection list */
891 static void new_connection(int listen_sock, bool privileged)
893 struct sockaddr_un sunaddr;
894 struct winbindd_cli_state *state;
895 struct tevent_req *req;
899 /* Accept connection */
901 len = sizeof(sunaddr);
903 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
906 if (errno != EINTR) {
907 DEBUG(0, ("Failed to accept socket - %s\n",
913 DEBUG(6,("accepted socket %d\n", sock));
915 /* Create new connection structure */
917 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
924 state->out_queue = tevent_queue_create(state, "winbind client reply");
925 if (state->out_queue == NULL) {
931 state->last_access = time(NULL);
933 state->privileged = privileged;
935 req = wb_req_read_send(state, winbind_event_context(), state->sock,
936 WINBINDD_MAX_EXTRA_DATA);
942 tevent_req_set_callback(req, winbind_client_request_read, state);
945 /* Add to connection list */
947 winbindd_add_client(state);
950 static void winbind_client_request_read(struct tevent_req *req)
952 struct winbindd_cli_state *state = tevent_req_callback_data(
953 req, struct winbindd_cli_state);
957 state->io_req = NULL;
959 ret = wb_req_read_recv(req, state, &state->request, &err);
963 DEBUG(6, ("closing socket %d, client exited\n",
966 DEBUG(2, ("Could not read client request from fd %d: "
967 "%s\n", state->sock, strerror(err)));
971 remove_client(state);
975 req = wait_for_read_send(state, winbind_event_context(), state->sock);
977 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
978 " wait_for_read_send failed - removing client\n",
979 (int)state->pid, state->cmd_name));
980 remove_client(state);
983 tevent_req_set_callback(req, winbind_client_activity, state);
986 process_request(state);
989 static void winbind_client_activity(struct tevent_req *req)
991 struct winbindd_cli_state *state =
992 tevent_req_callback_data(req, struct winbindd_cli_state);
995 wait_for_read_recv(req, &err);
997 remove_client(state);
1000 /* Remove a client connection from client connection list */
1002 static void remove_client(struct winbindd_cli_state *state)
1007 /* It's a dead client - hold a funeral */
1009 if (state == NULL) {
1014 * We need to remove a pending wb_req_read_*
1015 * or wb_resp_write_* request before closing the
1018 * This is important as they might have used tevent_add_fd() and we
1019 * use the epoll * backend on linux. So we must remove the tevent_fd
1020 * before closing the fd.
1022 * Otherwise we might hit a race with close_conns_after_fork() (via
1023 * winbindd_reinit_after_fork()) where a file description
1024 * is still open in a child, which means it's still active in
1025 * the parents epoll queue, but the related tevent_fd is already
1026 * already gone in the parent.
1030 TALLOC_FREE(state->io_req);
1032 if (state->sock != -1) {
1033 /* tell client, we are closing ... */
1034 nwritten = write(state->sock, &c, sizeof(c));
1035 if (nwritten == -1) {
1036 DEBUG(2, ("final write to client failed: %s\n",
1046 TALLOC_FREE(state->mem_ctx);
1048 /* Remove from list and free */
1050 winbindd_remove_client(state);
1054 /* Is a client idle? */
1056 static bool client_is_idle(struct winbindd_cli_state *state) {
1057 return (state->request == NULL &&
1058 state->response == NULL &&
1059 !state->pwent_state && !state->grent_state);
1062 /* Shutdown client connection which has been idle for the longest time */
1064 static bool remove_idle_client(void)
1066 struct winbindd_cli_state *state, *remove_state = NULL;
1067 time_t last_access = 0;
1070 for (state = winbindd_client_list(); state; state = state->next) {
1071 if (client_is_idle(state)) {
1073 if (!last_access || state->last_access < last_access) {
1074 last_access = state->last_access;
1075 remove_state = state;
1081 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1082 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1083 remove_client(remove_state);
1091 * Terminate all clients whose requests have taken longer than
1092 * "winbind request timeout" seconds to process, or have been
1093 * idle for more than "winbind request timeout" seconds.
1096 static void remove_timed_out_clients(void)
1098 struct winbindd_cli_state *state, *next = NULL;
1099 time_t curr_time = time(NULL);
1100 int timeout_val = lp_winbind_request_timeout();
1102 for (state = winbindd_client_list(); state; state = next) {
1106 expiry_time = state->last_access + timeout_val;
1108 if (curr_time > expiry_time) {
1109 if (client_is_idle(state)) {
1110 DEBUG(5,("Idle client timed out, "
1111 "shutting down sock %d, pid %u\n",
1113 (unsigned int)state->pid));
1115 DEBUG(5,("Client request timed out, "
1116 "shutting down sock %d, pid %u\n",
1118 (unsigned int)state->pid));
1120 remove_client(state);
1125 struct winbindd_listen_state {
1130 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1131 struct tevent_fd *fde,
1135 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1136 struct winbindd_listen_state);
1138 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1139 DEBUG(5,("winbindd: Exceeding %d client "
1140 "connections, removing idle "
1141 "connection.\n", lp_winbind_max_clients()));
1142 if (!remove_idle_client()) {
1143 DEBUG(0,("winbindd: Exceeding %d "
1144 "client connections, no idle "
1145 "connection found\n",
1146 lp_winbind_max_clients()));
1150 remove_timed_out_clients();
1151 new_connection(s->fd, s->privileged);
1155 * Winbindd socket accessor functions
1158 char *get_winbind_priv_pipe_dir(void)
1160 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1163 static void winbindd_setup_max_fds(void)
1165 int num_fds = MAX_OPEN_FUDGEFACTOR;
1168 num_fds += lp_winbind_max_clients();
1169 /* Add some more to account for 2 sockets open
1170 when the client transitions from unprivileged
1171 to privileged socket
1173 num_fds += lp_winbind_max_clients() / 10;
1175 /* Add one socket per child process
1176 (yeah there are child processes other than the
1177 domain children but only domain children can vary
1180 num_fds += lp_winbind_max_domain_connections() *
1181 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1183 actual_fds = set_maxfiles(num_fds);
1185 if (actual_fds < num_fds) {
1186 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1187 "requested %d open files, %d are available.\n",
1188 num_fds, actual_fds));
1192 static bool winbindd_setup_listeners(void)
1194 struct winbindd_listen_state *pub_state = NULL;
1195 struct winbindd_listen_state *priv_state = NULL;
1196 struct tevent_fd *fde;
1200 pub_state = talloc(winbind_event_context(),
1201 struct winbindd_listen_state);
1206 pub_state->privileged = false;
1207 pub_state->fd = create_pipe_sock(
1208 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1209 if (pub_state->fd == -1) {
1212 rc = listen(pub_state->fd, 5);
1217 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1218 TEVENT_FD_READ, winbindd_listen_fde_handler,
1221 close(pub_state->fd);
1224 tevent_fd_set_auto_close(fde);
1226 priv_state = talloc(winbind_event_context(),
1227 struct winbindd_listen_state);
1232 socket_path = get_winbind_priv_pipe_dir();
1233 if (socket_path == NULL) {
1237 priv_state->privileged = true;
1238 priv_state->fd = create_pipe_sock(
1239 socket_path, WINBINDD_SOCKET_NAME, 0750);
1240 TALLOC_FREE(socket_path);
1241 if (priv_state->fd == -1) {
1244 rc = listen(priv_state->fd, 5);
1249 fde = tevent_add_fd(winbind_event_context(), priv_state,
1250 priv_state->fd, TEVENT_FD_READ,
1251 winbindd_listen_fde_handler, priv_state);
1253 close(priv_state->fd);
1256 tevent_fd_set_auto_close(fde);
1260 TALLOC_FREE(pub_state);
1261 TALLOC_FREE(priv_state);
1265 bool winbindd_use_idmap_cache(void)
1267 return !opt_nocache;
1270 bool winbindd_use_cache(void)
1272 return !opt_nocache;
1275 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1279 /* Setup signal handlers */
1281 if (!winbindd_setup_sig_term_handler(true))
1283 if (!winbindd_setup_stdin_handler(true, foreground))
1285 if (!winbindd_setup_sig_hup_handler(NULL))
1287 if (!winbindd_setup_sig_chld_handler())
1289 if (!winbindd_setup_sig_usr2_handler())
1292 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1295 * Ensure all cache and idmap caches are consistent
1296 * and initialized before we startup.
1298 if (!winbindd_cache_validate_and_initialize()) {
1302 /* get broadcast messages */
1304 if (!serverid_register(messaging_server_id(msg_ctx),
1308 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1312 /* React on 'smbcontrol winbindd reload-config' in the same way
1313 as to SIGHUP signal */
1314 messaging_register(msg_ctx, NULL,
1315 MSG_SMB_CONF_UPDATED, msg_reload_services);
1316 messaging_register(msg_ctx, NULL,
1317 MSG_SHUTDOWN, msg_shutdown);
1319 /* Handle online/offline messages. */
1320 messaging_register(msg_ctx, NULL,
1321 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1322 messaging_register(msg_ctx, NULL,
1323 MSG_WINBIND_ONLINE, winbind_msg_online);
1324 messaging_register(msg_ctx, NULL,
1325 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1327 /* Handle domain online/offline messages for domains */
1328 messaging_register(winbind_messaging_context(), NULL,
1329 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1330 messaging_register(winbind_messaging_context(), NULL,
1331 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1333 messaging_register(msg_ctx, NULL,
1334 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1336 messaging_register(msg_ctx, NULL,
1337 MSG_WINBIND_VALIDATE_CACHE,
1338 winbind_msg_validate_cache);
1340 messaging_register(msg_ctx, NULL,
1341 MSG_WINBIND_DUMP_DOMAIN_LIST,
1342 winbind_msg_dump_domain_list);
1344 messaging_register(msg_ctx, NULL,
1345 MSG_WINBIND_IP_DROPPED,
1346 winbind_msg_ip_dropped_parent);
1348 /* Register handler for MSG_DEBUG. */
1349 messaging_register(msg_ctx, NULL,
1353 netsamlogon_cache_init(); /* Non-critical */
1355 /* clear the cached list of trusted domains */
1359 if (!init_domain_list()) {
1360 DEBUG(0,("unable to initialize domain list\n"));
1365 init_locator_child();
1367 smb_nscd_flush_user_cache();
1368 smb_nscd_flush_group_cache();
1370 if (lp_allow_trusted_domains()) {
1371 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1372 rescan_trusted_domains, NULL) == NULL) {
1373 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1378 status = wb_irpc_register();
1380 if (!NT_STATUS_IS_OK(status)) {
1381 DEBUG(0, ("Could not register IRPC handlers\n"));
1386 struct winbindd_addrchanged_state {
1387 struct addrchange_context *ctx;
1388 struct tevent_context *ev;
1389 struct messaging_context *msg_ctx;
1392 static void winbindd_addr_changed(struct tevent_req *req);
1394 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1395 struct tevent_context *ev,
1396 struct messaging_context *msg_ctx)
1398 struct winbindd_addrchanged_state *state;
1399 struct tevent_req *req;
1402 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1403 if (state == NULL) {
1404 DEBUG(10, ("talloc failed\n"));
1408 state->msg_ctx = msg_ctx;
1410 status = addrchange_context_create(state, &state->ctx);
1411 if (!NT_STATUS_IS_OK(status)) {
1412 DEBUG(10, ("addrchange_context_create failed: %s\n",
1413 nt_errstr(status)));
1417 req = addrchange_send(state, ev, state->ctx);
1419 DEBUG(0, ("addrchange_send failed\n"));
1423 tevent_req_set_callback(req, winbindd_addr_changed, state);
1426 static void winbindd_addr_changed(struct tevent_req *req)
1428 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1429 req, struct winbindd_addrchanged_state);
1430 enum addrchange_type type;
1431 struct sockaddr_storage addr;
1434 status = addrchange_recv(req, &type, &addr);
1436 if (!NT_STATUS_IS_OK(status)) {
1437 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1438 nt_errstr(status)));
1442 if (type == ADDRCHANGE_DEL) {
1443 char addrstr[INET6_ADDRSTRLEN];
1446 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1448 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1451 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1453 status = messaging_send(state->msg_ctx,
1454 messaging_server_id(state->msg_ctx),
1455 MSG_WINBIND_IP_DROPPED, &blob);
1456 if (!NT_STATUS_IS_OK(status)) {
1457 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1458 nt_errstr(status)));
1461 req = addrchange_send(state, state->ev, state->ctx);
1463 DEBUG(0, ("addrchange_send failed\n"));
1467 tevent_req_set_callback(req, winbindd_addr_changed, state);
1472 int main(int argc, const char **argv)
1474 static bool is_daemon = False;
1475 static bool Fork = True;
1476 static bool log_stdout = False;
1477 static bool no_process_group = False;
1481 OPT_NO_PROCESS_GROUP,
1484 struct poptOption long_options[] = {
1486 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1487 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1488 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1489 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1490 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1491 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1502 * Do this before any other talloc operation
1504 talloc_enable_null_tracking();
1505 frame = talloc_stackframe();
1508 * We want total control over the permissions on created files,
1509 * so set our umask to 0.
1513 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1515 /* glibc (?) likes to print "User defined signal 1" and exit if a
1516 SIGUSR[12] is received before a handler is installed */
1518 CatchSignal(SIGUSR1, SIG_IGN);
1519 CatchSignal(SIGUSR2, SIG_IGN);
1522 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1526 /* Initialise for running in non-root mode */
1530 set_remote_machine_name("winbindd", False);
1532 /* Set environment variable so we don't recursively call ourselves.
1533 This may also be useful interactively. */
1535 if ( !winbind_off() ) {
1536 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1540 /* Initialise samba/rpc client stuff */
1542 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1544 while ((opt = poptGetNextOpt(pc)) != -1) {
1546 /* Don't become a daemon */
1558 case OPT_NO_PROCESS_GROUP:
1559 no_process_group = true;
1561 case OPT_LOG_STDOUT:
1568 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1569 poptBadOption(pc, 0), poptStrerror(opt));
1570 poptPrintUsage(pc, stderr, 0);
1575 /* We call dump_core_setup one more time because the command line can
1576 * set the log file or the log-basename and this will influence where
1577 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1578 * the default value derived from build's prefix. For EOM this value
1579 * is often not related to the path where winbindd is actually run
1582 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1583 if (is_daemon && interactive) {
1584 d_fprintf(stderr,"\nERROR: "
1585 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1586 poptPrintUsage(pc, stderr, 0);
1590 if (log_stdout && Fork) {
1591 d_fprintf(stderr, "\nERROR: "
1592 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1593 poptPrintUsage(pc, stderr, 0);
1597 poptFreeContext(pc);
1599 if (!override_logfile) {
1601 if (asprintf(&lfile,"%s/log.winbindd",
1602 get_dyn_LOGFILEBASE()) > 0) {
1603 lp_set_logfile(lfile);
1609 setup_logging("winbindd", DEBUG_STDOUT);
1611 setup_logging("winbindd", DEBUG_FILE);
1615 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1616 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1618 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1619 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1622 /* After parsing the configuration file we setup the core path one more time
1623 * as the log file might have been set in the configuration and cores's
1624 * path is by default basename(lp_logfile()).
1626 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1628 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1629 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1630 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1631 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"));
1635 if (!cluster_probe_ok()) {
1639 /* Initialise messaging system */
1641 if (winbind_messaging_context() == NULL) {
1645 if (!reload_services_file(NULL)) {
1646 DEBUG(0, ("error opening config file\n"));
1650 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1652 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1653 lp_lock_directory(), strerror(errno)));
1657 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1659 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1660 lp_pid_directory(), strerror(errno)));
1671 if (!secrets_init()) {
1673 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1677 status = rpccli_pre_open_netlogon_creds();
1678 if (!NT_STATUS_IS_OK(status)) {
1679 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1680 nt_errstr(status)));
1684 /* Unblock all signals we are interested in as they may have been
1685 blocked by the parent process. */
1687 BlockSignals(False, SIGINT);
1688 BlockSignals(False, SIGQUIT);
1689 BlockSignals(False, SIGTERM);
1690 BlockSignals(False, SIGUSR1);
1691 BlockSignals(False, SIGUSR2);
1692 BlockSignals(False, SIGHUP);
1693 BlockSignals(False, SIGCHLD);
1696 become_daemon(Fork, no_process_group, log_stdout);
1698 pidfile_create(lp_pid_directory(), "winbindd");
1702 * If we're interactive we want to set our own process group for
1703 * signal management.
1705 if (interactive && !no_process_group)
1706 setpgid( (pid_t)0, (pid_t)0);
1711 /* Don't use winbindd_reinit_after_fork here as
1712 * we're just starting up and haven't created any
1713 * winbindd-specific resources we must free yet. JRA.
1716 status = reinit_after_fork(winbind_messaging_context(),
1717 winbind_event_context(),
1719 if (!NT_STATUS_IS_OK(status)) {
1720 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1724 * Do not initialize the parent-child-pipe before becoming
1725 * a daemon: this is used to detect a died parent in the child
1728 status = init_before_fork();
1729 if (!NT_STATUS_IS_OK(status)) {
1730 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1733 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1735 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1739 status = init_system_session_info();
1740 if (!NT_STATUS_IS_OK(status)) {
1741 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1744 rpc_lsarpc_init(NULL);
1745 rpc_samr_init(NULL);
1747 winbindd_init_addrchange(NULL, winbind_event_context(),
1748 winbind_messaging_context());
1750 /* setup listen sockets */
1752 if (!winbindd_setup_listeners()) {
1753 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1756 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1761 daemon_ready("winbindd");
1764 /* Loop waiting for requests */
1766 frame = talloc_stackframe();
1768 if (tevent_loop_once(winbind_event_context()) == -1) {
1769 DEBUG(1, ("tevent_loop_once() failed: %s\n",