2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) by Tim Potter 2000-2002
7 Copyright (C) Andrew Tridgell 2002
8 Copyright (C) Jelmer Vernooij 2003
9 Copyright (C) Volker Lendecke 2004
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "popt_common.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
31 #include "../librpc/gen_ndr/srv_lsa.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
34 #include "rpc_client/cli_netlogon.h"
36 #include "lib/addrchange.h"
39 #include "../lib/util/pidfile.h"
40 #include "util_cluster.h"
41 #include "source4/lib/messaging/irpc.h"
42 #include "source4/lib/messaging/messaging.h"
43 #include "lib/param/param.h"
44 #include "lib/async_req/async_sock.h"
45 #include "libsmb/samlogon_cache.h"
46 #include "libcli/auth/netlogon_creds_cli.h"
49 #define DBGC_CLASS DBGC_WINBIND
51 #define SCRUB_CLIENTS_INTERVAL 5
53 static bool client_is_idle(struct winbindd_cli_state *state);
54 static void remove_client(struct winbindd_cli_state *state);
55 static void winbindd_setup_max_fds(void);
57 static bool opt_nocache = False;
58 static bool interactive = False;
60 extern bool override_logfile;
62 struct imessaging_context *winbind_imessaging_context(void)
64 static struct imessaging_context *msg = NULL;
65 struct messaging_context *msg_ctx;
66 struct server_id myself;
67 struct loadparm_context *lp_ctx;
73 msg_ctx = server_messaging_context();
74 if (msg_ctx == NULL) {
75 smb_panic("server_messaging_context failed\n");
77 myself = messaging_server_id(msg_ctx);
79 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
81 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
85 * Note we MUST use the NULL context here, not the autofree context,
86 * to avoid side effects in forked children exiting.
88 msg = imessaging_init(NULL, lp_ctx, myself, server_event_context());
89 talloc_unlink(NULL, lp_ctx);
92 smb_panic("Could not init winbindd's messaging context.\n");
97 /* Reload configuration */
99 static bool reload_services_file(const char *lfile)
104 char *fname = lp_next_configfile(talloc_tos());
106 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
107 set_dyn_CONFIGFILE(fname);
112 /* if this is a child, restore the logfile to the special
113 name - <domain>, idmap, etc. */
114 if (lfile && *lfile) {
115 lp_set_logfile(lfile);
119 ret = lp_load_global(get_dyn_CONFIGFILE());
123 winbindd_setup_max_fds();
129 static void winbindd_status(void)
131 struct winbindd_cli_state *tmp;
133 DEBUG(0, ("winbindd status:\n"));
135 /* Print client state information */
137 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
139 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
140 DEBUG(2, ("\tclient list:\n"));
141 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
142 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
143 (unsigned long)tmp->pid, tmp->sock,
144 client_is_idle(tmp) ? "idle" : "active"));
149 /* Flush client cache */
151 static void flush_caches(void)
153 /* We need to invalidate cached user list entries on a SIGHUP
154 otherwise cached access denied errors due to restrict anonymous
155 hang around until the sequence number changes. */
157 if (!wcache_invalidate_cache()) {
158 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
159 if (!winbindd_cache_validate_and_initialize()) {
165 static void flush_caches_noinit(void)
168 * We need to invalidate cached user list entries on a SIGHUP
169 * otherwise cached access denied errors due to restrict anonymous
170 * hang around until the sequence number changes.
172 * Skip uninitialized domains when flush cache.
173 * If domain is not initialized, it means it is never
174 * used or never become online. look, wcache_invalidate_cache()
175 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
176 * for unused domains and large traffic for primay domain's DC if there
180 if (!wcache_invalidate_cache_noinit()) {
181 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
182 if (!winbindd_cache_validate_and_initialize()) {
188 /* Handle the signal by unlinking socket and exiting */
190 static void terminate(bool is_parent)
193 /* When parent goes away we should
194 * remove the socket file. Not so
195 * when children terminate.
199 if (asprintf(&path, "%s/%s",
200 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
208 gencache_stabilize();
210 netlogon_creds_cli_close_global_db();
214 TALLOC_CTX *mem_ctx = talloc_init("end_description");
215 char *description = talloc_describe_all(mem_ctx);
217 DEBUG(3, ("tallocs left:\n%s\n", description));
218 talloc_destroy(mem_ctx);
223 pidfile_unlink(lp_pid_directory(), "winbindd");
229 static void winbindd_sig_term_handler(struct tevent_context *ev,
230 struct tevent_signal *se,
236 bool *is_parent = talloc_get_type_abort(private_data, bool);
238 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
239 signum, (int)*is_parent));
240 terminate(*is_parent);
244 handle stdin becoming readable when we are in --foreground mode
246 static void winbindd_stdin_handler(struct tevent_context *ev,
247 struct tevent_fd *fde,
252 if (read(0, &c, 1) != 1) {
253 bool *is_parent = talloc_get_type_abort(private_data, bool);
255 /* we have reached EOF on stdin, which means the
256 parent has exited. Shutdown the server */
257 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
259 terminate(*is_parent);
263 bool winbindd_setup_sig_term_handler(bool parent)
265 struct tevent_signal *se;
268 is_parent = talloc(server_event_context(), bool);
275 se = tevent_add_signal(server_event_context(),
278 winbindd_sig_term_handler,
281 DEBUG(0,("failed to setup SIGTERM handler"));
282 talloc_free(is_parent);
286 se = tevent_add_signal(server_event_context(),
289 winbindd_sig_term_handler,
292 DEBUG(0,("failed to setup SIGINT handler"));
293 talloc_free(is_parent);
297 se = tevent_add_signal(server_event_context(),
300 winbindd_sig_term_handler,
303 DEBUG(0,("failed to setup SIGINT handler"));
304 talloc_free(is_parent);
311 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
318 is_parent = talloc(server_event_context(), bool);
325 /* if we are running in the foreground then look for
326 EOF on stdin, and exit if it happens. This allows
327 us to die if the parent process dies
328 Only do this on a pipe or socket, no other device.
330 if (fstat(0, &st) != 0) {
333 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
334 tevent_add_fd(server_event_context(),
338 winbindd_stdin_handler,
346 static void winbindd_sig_hup_handler(struct tevent_context *ev,
347 struct tevent_signal *se,
353 const char *file = (const char *)private_data;
355 DEBUG(1,("Reloading services after SIGHUP\n"));
356 flush_caches_noinit();
357 reload_services_file(file);
360 bool winbindd_setup_sig_hup_handler(const char *lfile)
362 struct tevent_signal *se;
366 file = talloc_strdup(server_event_context(),
373 se = tevent_add_signal(server_event_context(),
374 server_event_context(),
376 winbindd_sig_hup_handler,
385 static void winbindd_sig_chld_handler(struct tevent_context *ev,
386 struct tevent_signal *se,
394 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
395 winbind_child_died(pid);
399 static bool winbindd_setup_sig_chld_handler(void)
401 struct tevent_signal *se;
403 se = tevent_add_signal(server_event_context(),
404 server_event_context(),
406 winbindd_sig_chld_handler,
415 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
416 struct tevent_signal *se,
425 static bool winbindd_setup_sig_usr2_handler(void)
427 struct tevent_signal *se;
429 se = tevent_add_signal(server_event_context(),
430 server_event_context(),
432 winbindd_sig_usr2_handler,
441 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
442 static void msg_reload_services(struct messaging_context *msg,
445 struct server_id server_id,
448 /* Flush various caches */
450 reload_services_file((const char *) private_data);
453 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
454 static void msg_shutdown(struct messaging_context *msg,
457 struct server_id server_id,
460 /* only the parent waits for this message */
461 DEBUG(0,("Got shutdown message\n"));
466 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
469 struct server_id server_id,
476 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
480 * call the validation code from a child:
481 * so we don't block the main winbindd and the validation
482 * code can safely use fork/waitpid...
486 if (child_pid == -1) {
487 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
492 if (child_pid != 0) {
494 DEBUG(5, ("winbind_msg_validate_cache: child created with "
495 "pid %d.\n", (int)child_pid));
501 status = winbindd_reinit_after_fork(NULL, NULL);
502 if (!NT_STATUS_IS_OK(status)) {
503 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
508 /* install default SIGCHLD handler: validation code uses fork/waitpid */
509 CatchSignal(SIGCHLD, SIG_DFL);
511 ret = (uint8_t)winbindd_validate_cache_nobackup();
512 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
513 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
518 static struct winbindd_dispatch_table {
519 enum winbindd_cmd cmd;
520 void (*fn)(struct winbindd_cli_state *state);
521 const char *winbindd_cmd_name;
522 } dispatch_table[] = {
524 /* Enumeration functions */
526 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
531 { WINBINDD_INFO, winbindd_info, "INFO" },
532 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
533 "INTERFACE_VERSION" },
534 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
535 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
536 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
537 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
538 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
539 "WINBINDD_PRIV_PIPE_DIR" },
541 /* Credential cache access */
542 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
543 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
547 { WINBINDD_NUM_CMDS, NULL, "NONE" }
550 struct winbindd_async_dispatch_table {
551 enum winbindd_cmd cmd;
552 const char *cmd_name;
553 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
554 struct tevent_context *ev,
555 struct winbindd_cli_state *cli,
556 struct winbindd_request *request);
557 NTSTATUS (*recv_req)(struct tevent_req *req,
558 struct winbindd_response *presp);
561 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
562 { WINBINDD_PING, "PING",
563 wb_ping_send, wb_ping_recv },
564 { WINBINDD_LOOKUPSID, "LOOKUPSID",
565 winbindd_lookupsid_send, winbindd_lookupsid_recv },
566 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
567 winbindd_lookupsids_send, winbindd_lookupsids_recv },
568 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
569 winbindd_lookupname_send, winbindd_lookupname_recv },
570 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
571 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
572 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
573 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
574 { WINBINDD_GETPWSID, "GETPWSID",
575 winbindd_getpwsid_send, winbindd_getpwsid_recv },
576 { WINBINDD_GETPWNAM, "GETPWNAM",
577 winbindd_getpwnam_send, winbindd_getpwnam_recv },
578 { WINBINDD_GETPWUID, "GETPWUID",
579 winbindd_getpwuid_send, winbindd_getpwuid_recv },
580 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
581 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
582 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
583 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
584 { WINBINDD_GETGROUPS, "GETGROUPS",
585 winbindd_getgroups_send, winbindd_getgroups_recv },
586 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
587 winbindd_show_sequence_send, winbindd_show_sequence_recv },
588 { WINBINDD_GETGRGID, "GETGRGID",
589 winbindd_getgrgid_send, winbindd_getgrgid_recv },
590 { WINBINDD_GETGRNAM, "GETGRNAM",
591 winbindd_getgrnam_send, winbindd_getgrnam_recv },
592 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
593 winbindd_getusersids_send, winbindd_getusersids_recv },
594 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
595 winbindd_lookuprids_send, winbindd_lookuprids_recv },
596 { WINBINDD_SETPWENT, "SETPWENT",
597 winbindd_setpwent_send, winbindd_setpwent_recv },
598 { WINBINDD_GETPWENT, "GETPWENT",
599 winbindd_getpwent_send, winbindd_getpwent_recv },
600 { WINBINDD_ENDPWENT, "ENDPWENT",
601 winbindd_endpwent_send, winbindd_endpwent_recv },
602 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
603 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
604 { WINBINDD_GETDCNAME, "GETDCNAME",
605 winbindd_getdcname_send, winbindd_getdcname_recv },
606 { WINBINDD_SETGRENT, "SETGRENT",
607 winbindd_setgrent_send, winbindd_setgrent_recv },
608 { WINBINDD_GETGRENT, "GETGRENT",
609 winbindd_getgrent_send, winbindd_getgrent_recv },
610 { WINBINDD_ENDGRENT, "ENDGRENT",
611 winbindd_endgrent_send, winbindd_endgrent_recv },
612 { WINBINDD_LIST_USERS, "LIST_USERS",
613 winbindd_list_users_send, winbindd_list_users_recv },
614 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
615 winbindd_list_groups_send, winbindd_list_groups_recv },
616 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
617 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
618 { WINBINDD_PING_DC, "PING_DC",
619 winbindd_ping_dc_send, winbindd_ping_dc_recv },
620 { WINBINDD_PAM_AUTH, "PAM_AUTH",
621 winbindd_pam_auth_send, winbindd_pam_auth_recv },
622 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
623 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
624 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
625 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
626 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
627 winbindd_pam_chng_pswd_auth_crap_send,
628 winbindd_pam_chng_pswd_auth_crap_recv },
629 { WINBINDD_WINS_BYIP, "WINS_BYIP",
630 winbindd_wins_byip_send, winbindd_wins_byip_recv },
631 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
632 winbindd_wins_byname_send, winbindd_wins_byname_recv },
634 { 0, NULL, NULL, NULL }
637 static struct winbindd_async_dispatch_table async_priv_table[] = {
638 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
639 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
640 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
641 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
642 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
643 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
644 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
645 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
647 { 0, NULL, NULL, NULL }
650 static void wb_request_done(struct tevent_req *req);
652 static void process_request(struct winbindd_cli_state *state)
654 struct winbindd_dispatch_table *table = dispatch_table;
655 struct winbindd_async_dispatch_table *atable;
657 state->mem_ctx = talloc_named(state, 0, "winbind request");
658 if (state->mem_ctx == NULL)
661 /* Remember who asked us. */
662 state->pid = state->request->pid;
664 state->cmd_name = "unknown request";
665 state->recv_fn = NULL;
666 /* client is newest */
667 winbindd_promote_client(state);
669 /* Process command */
671 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
672 if (state->request->cmd == atable->cmd) {
677 if ((atable->send_req == NULL) && state->privileged) {
678 for (atable = async_priv_table; atable->send_req;
680 if (state->request->cmd == atable->cmd) {
686 if (atable->send_req != NULL) {
687 struct tevent_req *req;
689 state->cmd_name = atable->cmd_name;
690 state->recv_fn = atable->recv_req;
692 DEBUG(10, ("process_request: Handling async request %d:%s\n",
693 (int)state->pid, state->cmd_name));
695 req = atable->send_req(state->mem_ctx, server_event_context(),
696 state, state->request);
698 DEBUG(0, ("process_request: atable->send failed for "
699 "%s\n", atable->cmd_name));
700 request_error(state);
703 tevent_req_set_callback(req, wb_request_done, state);
707 state->response = talloc_zero(state->mem_ctx,
708 struct winbindd_response);
709 if (state->response == NULL) {
710 DEBUG(10, ("talloc failed\n"));
711 remove_client(state);
714 state->response->result = WINBINDD_PENDING;
715 state->response->length = sizeof(struct winbindd_response);
717 for (table = dispatch_table; table->fn; table++) {
718 if (state->request->cmd == table->cmd) {
719 DEBUG(10,("process_request: request fn %s\n",
720 table->winbindd_cmd_name ));
721 state->cmd_name = table->winbindd_cmd_name;
728 DEBUG(10,("process_request: unknown request fn number %d\n",
729 (int)state->request->cmd ));
730 request_error(state);
734 static void wb_request_done(struct tevent_req *req)
736 struct winbindd_cli_state *state = tevent_req_callback_data(
737 req, struct winbindd_cli_state);
740 state->response = talloc_zero(state->mem_ctx,
741 struct winbindd_response);
742 if (state->response == NULL) {
743 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
744 (int)state->pid, state->cmd_name));
745 remove_client(state);
748 state->response->result = WINBINDD_PENDING;
749 state->response->length = sizeof(struct winbindd_response);
751 status = state->recv_fn(req, state->response);
754 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
755 (int)state->pid, state->cmd_name, nt_errstr(status)));
757 if (!NT_STATUS_IS_OK(status)) {
758 request_error(state);
765 * This is the main event loop of winbind requests. It goes through a
766 * state-machine of 3 read/write requests, 4 if you have extra data to send.
768 * An idle winbind client has a read request of 4 bytes outstanding,
769 * finalizing function is request_len_recv, checking the length. request_recv
770 * then processes the packet. The processing function then at some point has
771 * to call request_finished which schedules sending the response.
774 static void request_finished(struct winbindd_cli_state *state);
776 static void winbind_client_request_read(struct tevent_req *req);
777 static void winbind_client_response_written(struct tevent_req *req);
778 static void winbind_client_activity(struct tevent_req *req);
780 static void request_finished(struct winbindd_cli_state *state)
782 struct tevent_req *req;
784 /* free client socket monitoring request */
785 TALLOC_FREE(state->io_req);
787 TALLOC_FREE(state->request);
789 req = wb_resp_write_send(state, server_event_context(),
790 state->out_queue, state->sock,
793 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
794 (int)state->pid, state->cmd_name));
795 remove_client(state);
798 tevent_req_set_callback(req, winbind_client_response_written, state);
802 static void winbind_client_response_written(struct tevent_req *req)
804 struct winbindd_cli_state *state = tevent_req_callback_data(
805 req, struct winbindd_cli_state);
809 state->io_req = NULL;
811 ret = wb_resp_write_recv(req, &err);
816 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
817 (int)state->pid, state->cmd_name, strerror(err)));
818 remove_client(state);
822 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
823 "to client\n", (int)state->pid, state->cmd_name));
825 TALLOC_FREE(state->mem_ctx);
826 state->response = NULL;
827 state->cmd_name = "no request";
828 state->recv_fn = NULL;
830 req = wb_req_read_send(state, server_event_context(), state->sock,
831 WINBINDD_MAX_EXTRA_DATA);
833 remove_client(state);
836 tevent_req_set_callback(req, winbind_client_request_read, state);
840 void request_error(struct winbindd_cli_state *state)
842 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
843 state->response->result = WINBINDD_ERROR;
844 request_finished(state);
847 void request_ok(struct winbindd_cli_state *state)
849 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
850 state->response->result = WINBINDD_OK;
851 request_finished(state);
854 /* Process a new connection by adding it to the client connection list */
856 static void new_connection(int listen_sock, bool privileged)
858 struct sockaddr_un sunaddr;
859 struct winbindd_cli_state *state;
860 struct tevent_req *req;
864 /* Accept connection */
866 len = sizeof(sunaddr);
868 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
871 if (errno != EINTR) {
872 DEBUG(0, ("Failed to accept socket - %s\n",
878 DEBUG(6,("accepted socket %d\n", sock));
880 /* Create new connection structure */
882 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
889 state->out_queue = tevent_queue_create(state, "winbind client reply");
890 if (state->out_queue == NULL) {
896 state->privileged = privileged;
898 req = wb_req_read_send(state, server_event_context(), state->sock,
899 WINBINDD_MAX_EXTRA_DATA);
905 tevent_req_set_callback(req, winbind_client_request_read, state);
908 /* Add to connection list */
910 winbindd_add_client(state);
913 static void winbind_client_request_read(struct tevent_req *req)
915 struct winbindd_cli_state *state = tevent_req_callback_data(
916 req, struct winbindd_cli_state);
920 state->io_req = NULL;
922 ret = wb_req_read_recv(req, state, &state->request, &err);
926 DEBUG(6, ("closing socket %d, client exited\n",
929 DEBUG(2, ("Could not read client request from fd %d: "
930 "%s\n", state->sock, strerror(err)));
934 remove_client(state);
938 req = wait_for_read_send(state, server_event_context(), state->sock,
941 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
942 " wait_for_read_send failed - removing client\n",
943 (int)state->pid, state->cmd_name));
944 remove_client(state);
947 tevent_req_set_callback(req, winbind_client_activity, state);
950 process_request(state);
953 static void winbind_client_activity(struct tevent_req *req)
955 struct winbindd_cli_state *state =
956 tevent_req_callback_data(req, struct winbindd_cli_state);
960 has_data = wait_for_read_recv(req, &err);
963 DEBUG(0, ("winbind_client_activity[%d:%s]:"
964 "unexpected data from client - removing client\n",
965 (int)state->pid, state->cmd_name));
968 DEBUG(6, ("winbind_client_activity[%d:%s]: "
969 "client has closed connection - removing "
971 (int)state->pid, state->cmd_name));
973 DEBUG(2, ("winbind_client_activity[%d:%s]: "
974 "client socket error (%s) - removing "
976 (int)state->pid, state->cmd_name,
981 remove_client(state);
984 /* Remove a client connection from client connection list */
986 static void remove_client(struct winbindd_cli_state *state)
991 /* It's a dead client - hold a funeral */
998 * We need to remove a pending wb_req_read_*
999 * or wb_resp_write_* request before closing the
1002 * This is important as they might have used tevent_add_fd() and we
1003 * use the epoll * backend on linux. So we must remove the tevent_fd
1004 * before closing the fd.
1006 * Otherwise we might hit a race with close_conns_after_fork() (via
1007 * winbindd_reinit_after_fork()) where a file description
1008 * is still open in a child, which means it's still active in
1009 * the parents epoll queue, but the related tevent_fd is already
1010 * already gone in the parent.
1014 TALLOC_FREE(state->io_req);
1016 if (state->sock != -1) {
1017 /* tell client, we are closing ... */
1018 nwritten = write(state->sock, &c, sizeof(c));
1019 if (nwritten == -1) {
1020 DEBUG(2, ("final write to client failed: %s\n",
1030 TALLOC_FREE(state->mem_ctx);
1032 /* Remove from list and free */
1034 winbindd_remove_client(state);
1038 /* Is a client idle? */
1040 static bool client_is_idle(struct winbindd_cli_state *state) {
1041 return (state->request == NULL &&
1042 state->response == NULL &&
1043 !state->pwent_state && !state->grent_state);
1046 /* Shutdown client connection which has been idle for the longest time */
1048 static bool remove_idle_client(void)
1050 struct winbindd_cli_state *state, *remove_state = NULL;
1053 for (state = winbindd_client_list(); state; state = state->next) {
1054 if (client_is_idle(state)) {
1056 /* list is sorted by access time */
1057 remove_state = state;
1062 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1063 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1064 remove_client(remove_state);
1072 * Terminate all clients whose requests have taken longer than
1073 * "winbind request timeout" seconds to process, or have been
1074 * idle for more than "winbind request timeout" seconds.
1077 static void remove_timed_out_clients(void)
1079 struct winbindd_cli_state *state, *prev = NULL;
1080 time_t curr_time = time(NULL);
1081 int timeout_val = lp_winbind_request_timeout();
1083 for (state = winbindd_client_list_tail(); state; state = prev) {
1086 prev = winbindd_client_list_prev(state);
1087 expiry_time = state->last_access + timeout_val;
1089 if (curr_time <= expiry_time) {
1090 /* list is sorted, previous clients in
1095 if (client_is_idle(state)) {
1096 DEBUG(5,("Idle client timed out, "
1097 "shutting down sock %d, pid %u\n",
1099 (unsigned int)state->pid));
1101 DEBUG(5,("Client request timed out, "
1102 "shutting down sock %d, pid %u\n",
1104 (unsigned int)state->pid));
1107 remove_client(state);
1111 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1112 struct tevent_timer *te,
1113 struct timeval current_time,
1116 remove_timed_out_clients();
1117 if (tevent_add_timer(ev, ev,
1118 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1119 winbindd_scrub_clients_handler, NULL) == NULL) {
1120 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
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(server_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(server_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(server_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(server_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);
1258 winbindd_scrub_clients_handler(server_event_context(), NULL,
1259 timeval_current(), NULL);
1262 TALLOC_FREE(pub_state);
1263 TALLOC_FREE(priv_state);
1267 bool winbindd_use_idmap_cache(void)
1269 return !opt_nocache;
1272 bool winbindd_use_cache(void)
1274 return !opt_nocache;
1277 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1281 /* Setup signal handlers */
1283 if (!winbindd_setup_sig_term_handler(true))
1285 if (!winbindd_setup_stdin_handler(true, foreground))
1287 if (!winbindd_setup_sig_hup_handler(NULL))
1289 if (!winbindd_setup_sig_chld_handler())
1291 if (!winbindd_setup_sig_usr2_handler())
1294 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1297 * Ensure all cache and idmap caches are consistent
1298 * and initialized before we startup.
1300 if (!winbindd_cache_validate_and_initialize()) {
1304 /* React on 'smbcontrol winbindd reload-config' in the same way
1305 as to SIGHUP signal */
1306 messaging_register(msg_ctx, NULL,
1307 MSG_SMB_CONF_UPDATED, msg_reload_services);
1308 messaging_register(msg_ctx, NULL,
1309 MSG_SHUTDOWN, msg_shutdown);
1311 /* Handle online/offline messages. */
1312 messaging_register(msg_ctx, NULL,
1313 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1314 messaging_register(msg_ctx, NULL,
1315 MSG_WINBIND_ONLINE, winbind_msg_online);
1316 messaging_register(msg_ctx, NULL,
1317 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1319 /* Handle domain online/offline messages for domains */
1320 messaging_register(server_messaging_context(), NULL,
1321 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1322 messaging_register(server_messaging_context(), NULL,
1323 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1325 messaging_register(msg_ctx, NULL,
1326 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1328 messaging_register(msg_ctx, NULL,
1329 MSG_WINBIND_VALIDATE_CACHE,
1330 winbind_msg_validate_cache);
1332 messaging_register(msg_ctx, NULL,
1333 MSG_WINBIND_DUMP_DOMAIN_LIST,
1334 winbind_msg_dump_domain_list);
1336 messaging_register(msg_ctx, NULL,
1337 MSG_WINBIND_IP_DROPPED,
1338 winbind_msg_ip_dropped_parent);
1340 /* Register handler for MSG_DEBUG. */
1341 messaging_register(msg_ctx, NULL,
1345 netsamlogon_cache_init(); /* Non-critical */
1347 /* clear the cached list of trusted domains */
1351 if (!init_domain_list()) {
1352 DEBUG(0,("unable to initialize domain list\n"));
1357 init_locator_child();
1359 smb_nscd_flush_user_cache();
1360 smb_nscd_flush_group_cache();
1362 if (lp_allow_trusted_domains()) {
1363 if (tevent_add_timer(server_event_context(), NULL, timeval_zero(),
1364 rescan_trusted_domains, NULL) == NULL) {
1365 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1370 status = wb_irpc_register();
1372 if (!NT_STATUS_IS_OK(status)) {
1373 DEBUG(0, ("Could not register IRPC handlers\n"));
1378 struct winbindd_addrchanged_state {
1379 struct addrchange_context *ctx;
1380 struct tevent_context *ev;
1381 struct messaging_context *msg_ctx;
1384 static void winbindd_addr_changed(struct tevent_req *req);
1386 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1387 struct tevent_context *ev,
1388 struct messaging_context *msg_ctx)
1390 struct winbindd_addrchanged_state *state;
1391 struct tevent_req *req;
1394 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1395 if (state == NULL) {
1396 DEBUG(10, ("talloc failed\n"));
1400 state->msg_ctx = msg_ctx;
1402 status = addrchange_context_create(state, &state->ctx);
1403 if (!NT_STATUS_IS_OK(status)) {
1404 DEBUG(10, ("addrchange_context_create failed: %s\n",
1405 nt_errstr(status)));
1409 req = addrchange_send(state, ev, state->ctx);
1411 DEBUG(0, ("addrchange_send failed\n"));
1415 tevent_req_set_callback(req, winbindd_addr_changed, state);
1418 static void winbindd_addr_changed(struct tevent_req *req)
1420 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1421 req, struct winbindd_addrchanged_state);
1422 enum addrchange_type type;
1423 struct sockaddr_storage addr;
1426 status = addrchange_recv(req, &type, &addr);
1428 if (!NT_STATUS_IS_OK(status)) {
1429 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1430 nt_errstr(status)));
1434 if (type == ADDRCHANGE_DEL) {
1435 char addrstr[INET6_ADDRSTRLEN];
1438 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1440 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1443 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1445 status = messaging_send(state->msg_ctx,
1446 messaging_server_id(state->msg_ctx),
1447 MSG_WINBIND_IP_DROPPED, &blob);
1448 if (!NT_STATUS_IS_OK(status)) {
1449 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1450 nt_errstr(status)));
1453 req = addrchange_send(state, state->ev, state->ctx);
1455 DEBUG(0, ("addrchange_send failed\n"));
1459 tevent_req_set_callback(req, winbindd_addr_changed, state);
1464 int main(int argc, const char **argv)
1466 static bool is_daemon = False;
1467 static bool Fork = True;
1468 static bool log_stdout = False;
1469 static bool no_process_group = False;
1473 OPT_NO_PROCESS_GROUP,
1476 struct poptOption long_options[] = {
1478 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1479 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1480 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1481 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1482 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1483 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1494 * Do this before any other talloc operation
1496 talloc_enable_null_tracking();
1497 frame = talloc_stackframe();
1500 * We want total control over the permissions on created files,
1501 * so set our umask to 0.
1505 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1507 /* glibc (?) likes to print "User defined signal 1" and exit if a
1508 SIGUSR[12] is received before a handler is installed */
1510 CatchSignal(SIGUSR1, SIG_IGN);
1511 CatchSignal(SIGUSR2, SIG_IGN);
1514 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1518 /* Initialise for running in non-root mode */
1522 set_remote_machine_name("winbindd", False);
1524 /* Set environment variable so we don't recursively call ourselves.
1525 This may also be useful interactively. */
1527 if ( !winbind_off() ) {
1528 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1532 /* Initialise samba/rpc client stuff */
1534 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1536 while ((opt = poptGetNextOpt(pc)) != -1) {
1538 /* Don't become a daemon */
1550 case OPT_NO_PROCESS_GROUP:
1551 no_process_group = true;
1553 case OPT_LOG_STDOUT:
1560 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1561 poptBadOption(pc, 0), poptStrerror(opt));
1562 poptPrintUsage(pc, stderr, 0);
1567 /* We call dump_core_setup one more time because the command line can
1568 * set the log file or the log-basename and this will influence where
1569 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1570 * the default value derived from build's prefix. For EOM this value
1571 * is often not related to the path where winbindd is actually run
1574 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1575 if (is_daemon && interactive) {
1576 d_fprintf(stderr,"\nERROR: "
1577 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1578 poptPrintUsage(pc, stderr, 0);
1582 if (log_stdout && Fork) {
1583 d_fprintf(stderr, "\nERROR: "
1584 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1585 poptPrintUsage(pc, stderr, 0);
1589 poptFreeContext(pc);
1591 if (!override_logfile) {
1593 if (asprintf(&lfile,"%s/log.winbindd",
1594 get_dyn_LOGFILEBASE()) > 0) {
1595 lp_set_logfile(lfile);
1601 setup_logging("winbindd", DEBUG_STDOUT);
1603 setup_logging("winbindd", DEBUG_FILE);
1607 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1608 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1610 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1611 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1614 /* After parsing the configuration file we setup the core path one more time
1615 * as the log file might have been set in the configuration and cores's
1616 * path is by default basename(lp_logfile()).
1618 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1620 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1621 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1622 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1623 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"));
1627 if (!cluster_probe_ok()) {
1631 /* Initialise messaging system */
1633 if (server_messaging_context() == NULL) {
1637 if (!reload_services_file(NULL)) {
1638 DEBUG(0, ("error opening config file\n"));
1644 const char *idmap_backend;
1645 const char *invalid_backends[] = {
1646 "ad", "rfc2307", "rid",
1649 idmap_backend = lp_idmap_default_backend();
1650 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1651 ok = strequal(idmap_backend, invalid_backends[i]);
1653 DBG_ERR("FATAL: Invalid idmap backend %s "
1654 "configured as the default backend!\n",
1661 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1663 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1664 lp_lock_directory(), strerror(errno)));
1668 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1670 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1671 lp_pid_directory(), strerror(errno)));
1682 if (!secrets_init()) {
1684 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1688 status = rpccli_pre_open_netlogon_creds();
1689 if (!NT_STATUS_IS_OK(status)) {
1690 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1691 nt_errstr(status)));
1695 /* Unblock all signals we are interested in as they may have been
1696 blocked by the parent process. */
1698 BlockSignals(False, SIGINT);
1699 BlockSignals(False, SIGQUIT);
1700 BlockSignals(False, SIGTERM);
1701 BlockSignals(False, SIGUSR1);
1702 BlockSignals(False, SIGUSR2);
1703 BlockSignals(False, SIGHUP);
1704 BlockSignals(False, SIGCHLD);
1707 become_daemon(Fork, no_process_group, log_stdout);
1709 pidfile_create(lp_pid_directory(), "winbindd");
1713 * If we're interactive we want to set our own process group for
1714 * signal management.
1716 if (interactive && !no_process_group)
1717 setpgid( (pid_t)0, (pid_t)0);
1722 /* Don't use winbindd_reinit_after_fork here as
1723 * we're just starting up and haven't created any
1724 * winbindd-specific resources we must free yet. JRA.
1727 status = reinit_after_fork(server_messaging_context(),
1728 server_event_context(),
1730 if (!NT_STATUS_IS_OK(status)) {
1731 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1735 * Do not initialize the parent-child-pipe before becoming
1736 * a daemon: this is used to detect a died parent in the child
1739 status = init_before_fork();
1740 if (!NT_STATUS_IS_OK(status)) {
1741 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1744 winbindd_register_handlers(server_messaging_context(), !Fork);
1746 if (!messaging_parent_dgm_cleanup_init(server_messaging_context())) {
1750 status = init_system_session_info();
1751 if (!NT_STATUS_IS_OK(status)) {
1752 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1755 rpc_lsarpc_init(NULL);
1756 rpc_samr_init(NULL);
1758 winbindd_init_addrchange(NULL, server_event_context(),
1759 server_messaging_context());
1761 /* setup listen sockets */
1763 if (!winbindd_setup_listeners()) {
1764 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1767 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1772 daemon_ready("winbindd");
1775 /* Loop waiting for requests */
1777 frame = talloc_stackframe();
1779 if (tevent_loop_once(server_event_context()) == -1) {
1780 DEBUG(1, ("tevent_loop_once() failed: %s\n",