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"
35 #include "lib/addrchange.h"
39 #include "../lib/util/pidfile.h"
40 #include "util_cluster.h"
43 #define DBGC_CLASS DBGC_WINBIND
45 static bool client_is_idle(struct winbindd_cli_state *state);
46 static void remove_client(struct winbindd_cli_state *state);
48 static bool opt_nocache = False;
49 static bool interactive = False;
51 extern bool override_logfile;
53 struct tevent_context *winbind_event_context(void)
55 static struct tevent_context *ev = NULL;
62 * Note we MUST use the NULL context here, not the autofree context,
63 * to avoid side effects in forked children exiting.
65 ev = samba_tevent_context_init(NULL);
67 smb_panic("Could not init winbindd's messaging context.\n");
72 struct messaging_context *winbind_messaging_context(void)
74 static struct messaging_context *msg = NULL;
81 * Note we MUST use the NULL context here, not the autofree context,
82 * to avoid side effects in forked children exiting.
84 msg = messaging_init(NULL, winbind_event_context());
86 smb_panic("Could not init winbindd's messaging context.\n");
91 /* Reload configuration */
93 static bool reload_services_file(const char *lfile)
98 char *fname = lp_configfile(talloc_tos());
100 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
101 set_dyn_CONFIGFILE(fname);
106 /* if this is a child, restore the logfile to the special
107 name - <domain>, idmap, etc. */
108 if (lfile && *lfile) {
109 lp_set_logfile(lfile);
113 ret = lp_load_global(get_dyn_CONFIGFILE());
122 static void winbindd_status(void)
124 struct winbindd_cli_state *tmp;
126 DEBUG(0, ("winbindd status:\n"));
128 /* Print client state information */
130 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
132 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
133 DEBUG(2, ("\tclient list:\n"));
134 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
135 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
136 (unsigned long)tmp->pid, tmp->sock,
137 client_is_idle(tmp) ? "idle" : "active"));
142 /* Flush client cache */
144 static void flush_caches(void)
146 /* We need to invalidate cached user list entries on a SIGHUP
147 otherwise cached access denied errors due to restrict anonymous
148 hang around until the sequence number changes. */
150 if (!wcache_invalidate_cache()) {
151 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
152 if (!winbindd_cache_validate_and_initialize()) {
158 static void flush_caches_noinit(void)
161 * We need to invalidate cached user list entries on a SIGHUP
162 * otherwise cached access denied errors due to restrict anonymous
163 * hang around until the sequence number changes.
165 * Skip uninitialized domains when flush cache.
166 * If domain is not initialized, it means it is never
167 * used or never become online. look, wcache_invalidate_cache()
168 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
169 * for unused domains and large traffic for primay domain's DC if there
173 if (!wcache_invalidate_cache_noinit()) {
174 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
175 if (!winbindd_cache_validate_and_initialize()) {
181 /* Handle the signal by unlinking socket and exiting */
183 static void terminate(bool is_parent)
186 /* When parent goes away we should
187 * remove the socket file. Not so
188 * when children terminate.
192 if (asprintf(&path, "%s/%s",
193 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
201 trustdom_cache_shutdown();
203 gencache_stabilize();
207 TALLOC_CTX *mem_ctx = talloc_init("end_description");
208 char *description = talloc_describe_all(mem_ctx);
210 DEBUG(3, ("tallocs left:\n%s\n", description));
211 talloc_destroy(mem_ctx);
216 struct messaging_context *msg = winbind_messaging_context();
217 struct server_id self = messaging_server_id(msg);
218 serverid_deregister(self);
219 pidfile_unlink(lp_piddir(), "winbindd");
225 static void winbindd_sig_term_handler(struct tevent_context *ev,
226 struct tevent_signal *se,
232 bool *is_parent = talloc_get_type_abort(private_data, bool);
234 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
235 signum, (int)*is_parent));
236 terminate(*is_parent);
240 handle stdin becoming readable when we are in --foreground mode
242 static void winbindd_stdin_handler(struct tevent_context *ev,
243 struct tevent_fd *fde,
248 if (read(0, &c, 1) != 1) {
249 bool *is_parent = talloc_get_type_abort(private_data, bool);
251 /* we have reached EOF on stdin, which means the
252 parent has exited. Shutdown the server */
253 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
255 terminate(*is_parent);
259 bool winbindd_setup_sig_term_handler(bool parent)
261 struct tevent_signal *se;
264 is_parent = talloc(winbind_event_context(), bool);
271 se = tevent_add_signal(winbind_event_context(),
274 winbindd_sig_term_handler,
277 DEBUG(0,("failed to setup SIGTERM handler"));
278 talloc_free(is_parent);
282 se = tevent_add_signal(winbind_event_context(),
285 winbindd_sig_term_handler,
288 DEBUG(0,("failed to setup SIGINT handler"));
289 talloc_free(is_parent);
293 se = tevent_add_signal(winbind_event_context(),
296 winbindd_sig_term_handler,
299 DEBUG(0,("failed to setup SIGINT handler"));
300 talloc_free(is_parent);
307 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
314 is_parent = talloc(winbind_event_context(), bool);
321 /* if we are running in the foreground then look for
322 EOF on stdin, and exit if it happens. This allows
323 us to die if the parent process dies
324 Only do this on a pipe or socket, no other device.
326 if (fstat(0, &st) != 0) {
329 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
330 tevent_add_fd(winbind_event_context(),
334 winbindd_stdin_handler,
342 static void winbindd_sig_hup_handler(struct tevent_context *ev,
343 struct tevent_signal *se,
349 const char *file = (const char *)private_data;
351 DEBUG(1,("Reloading services after SIGHUP\n"));
352 flush_caches_noinit();
353 reload_services_file(file);
356 bool winbindd_setup_sig_hup_handler(const char *lfile)
358 struct tevent_signal *se;
362 file = talloc_strdup(winbind_event_context(),
369 se = tevent_add_signal(winbind_event_context(),
370 winbind_event_context(),
372 winbindd_sig_hup_handler,
381 static void winbindd_sig_chld_handler(struct tevent_context *ev,
382 struct tevent_signal *se,
390 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
391 winbind_child_died(pid);
395 static bool winbindd_setup_sig_chld_handler(void)
397 struct tevent_signal *se;
399 se = tevent_add_signal(winbind_event_context(),
400 winbind_event_context(),
402 winbindd_sig_chld_handler,
411 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
412 struct tevent_signal *se,
421 static bool winbindd_setup_sig_usr2_handler(void)
423 struct tevent_signal *se;
425 se = tevent_add_signal(winbind_event_context(),
426 winbind_event_context(),
428 winbindd_sig_usr2_handler,
437 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
438 static void msg_reload_services(struct messaging_context *msg,
441 struct server_id server_id,
444 /* Flush various caches */
446 reload_services_file((const char *) private_data);
449 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
450 static void msg_shutdown(struct messaging_context *msg,
453 struct server_id server_id,
456 /* only the parent waits for this message */
457 DEBUG(0,("Got shutdown message\n"));
462 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
465 struct server_id server_id,
472 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
476 * call the validation code from a child:
477 * so we don't block the main winbindd and the validation
478 * code can safely use fork/waitpid...
482 if (child_pid == -1) {
483 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
488 if (child_pid != 0) {
490 DEBUG(5, ("winbind_msg_validate_cache: child created with "
491 "pid %d.\n", (int)child_pid));
497 status = winbindd_reinit_after_fork(NULL, NULL);
498 if (!NT_STATUS_IS_OK(status)) {
499 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
504 /* install default SIGCHLD handler: validation code uses fork/waitpid */
505 CatchSignal(SIGCHLD, SIG_DFL);
507 ret = (uint8)winbindd_validate_cache_nobackup();
508 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
509 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
514 static struct winbindd_dispatch_table {
515 enum winbindd_cmd cmd;
516 void (*fn)(struct winbindd_cli_state *state);
517 const char *winbindd_cmd_name;
518 } dispatch_table[] = {
520 /* Enumeration functions */
522 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
527 { WINBINDD_INFO, winbindd_info, "INFO" },
528 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
529 "INTERFACE_VERSION" },
530 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
531 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
532 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
533 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
534 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
535 "WINBINDD_PRIV_PIPE_DIR" },
537 /* Credential cache access */
538 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
539 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
543 { WINBINDD_NUM_CMDS, NULL, "NONE" }
546 struct winbindd_async_dispatch_table {
547 enum winbindd_cmd cmd;
548 const char *cmd_name;
549 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
550 struct tevent_context *ev,
551 struct winbindd_cli_state *cli,
552 struct winbindd_request *request);
553 NTSTATUS (*recv_req)(struct tevent_req *req,
554 struct winbindd_response *presp);
557 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
558 { WINBINDD_PING, "PING",
559 wb_ping_send, wb_ping_recv },
560 { WINBINDD_LOOKUPSID, "LOOKUPSID",
561 winbindd_lookupsid_send, winbindd_lookupsid_recv },
562 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
563 winbindd_lookupsids_send, winbindd_lookupsids_recv },
564 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
565 winbindd_lookupname_send, winbindd_lookupname_recv },
566 { WINBINDD_SID_TO_UID, "SID_TO_UID",
567 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
568 { WINBINDD_SID_TO_GID, "SID_TO_GID",
569 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
570 { WINBINDD_UID_TO_SID, "UID_TO_SID",
571 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
572 { WINBINDD_GID_TO_SID, "GID_TO_SID",
573 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
574 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
575 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
576 { WINBINDD_GETPWSID, "GETPWSID",
577 winbindd_getpwsid_send, winbindd_getpwsid_recv },
578 { WINBINDD_GETPWNAM, "GETPWNAM",
579 winbindd_getpwnam_send, winbindd_getpwnam_recv },
580 { WINBINDD_GETPWUID, "GETPWUID",
581 winbindd_getpwuid_send, winbindd_getpwuid_recv },
582 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
583 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
584 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
585 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
586 { WINBINDD_GETGROUPS, "GETGROUPS",
587 winbindd_getgroups_send, winbindd_getgroups_recv },
588 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
589 winbindd_show_sequence_send, winbindd_show_sequence_recv },
590 { WINBINDD_GETGRGID, "GETGRGID",
591 winbindd_getgrgid_send, winbindd_getgrgid_recv },
592 { WINBINDD_GETGRNAM, "GETGRNAM",
593 winbindd_getgrnam_send, winbindd_getgrnam_recv },
594 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
595 winbindd_getusersids_send, winbindd_getusersids_recv },
596 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
597 winbindd_lookuprids_send, winbindd_lookuprids_recv },
598 { WINBINDD_SETPWENT, "SETPWENT",
599 winbindd_setpwent_send, winbindd_setpwent_recv },
600 { WINBINDD_GETPWENT, "GETPWENT",
601 winbindd_getpwent_send, winbindd_getpwent_recv },
602 { WINBINDD_ENDPWENT, "ENDPWENT",
603 winbindd_endpwent_send, winbindd_endpwent_recv },
604 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
605 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
606 { WINBINDD_GETDCNAME, "GETDCNAME",
607 winbindd_getdcname_send, winbindd_getdcname_recv },
608 { WINBINDD_SETGRENT, "SETGRENT",
609 winbindd_setgrent_send, winbindd_setgrent_recv },
610 { WINBINDD_GETGRENT, "GETGRENT",
611 winbindd_getgrent_send, winbindd_getgrent_recv },
612 { WINBINDD_ENDGRENT, "ENDGRENT",
613 winbindd_endgrent_send, winbindd_endgrent_recv },
614 { WINBINDD_LIST_USERS, "LIST_USERS",
615 winbindd_list_users_send, winbindd_list_users_recv },
616 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
617 winbindd_list_groups_send, winbindd_list_groups_recv },
618 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
619 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
620 { WINBINDD_PING_DC, "PING_DC",
621 winbindd_ping_dc_send, winbindd_ping_dc_recv },
622 { WINBINDD_PAM_AUTH, "PAM_AUTH",
623 winbindd_pam_auth_send, winbindd_pam_auth_recv },
624 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
625 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
626 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
627 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
628 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
629 winbindd_pam_chng_pswd_auth_crap_send,
630 winbindd_pam_chng_pswd_auth_crap_recv },
631 { WINBINDD_WINS_BYIP, "WINS_BYIP",
632 winbindd_wins_byip_send, winbindd_wins_byip_recv },
633 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
634 winbindd_wins_byname_send, winbindd_wins_byname_recv },
636 { 0, NULL, NULL, NULL }
639 static struct winbindd_async_dispatch_table async_priv_table[] = {
640 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
641 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
642 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
643 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
644 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
645 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
646 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
647 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
649 { 0, NULL, NULL, NULL }
652 static void wb_request_done(struct tevent_req *req);
654 static void process_request(struct winbindd_cli_state *state)
656 struct winbindd_dispatch_table *table = dispatch_table;
657 struct winbindd_async_dispatch_table *atable;
659 state->mem_ctx = talloc_named(state, 0, "winbind request");
660 if (state->mem_ctx == NULL)
663 /* Remember who asked us. */
664 state->pid = state->request->pid;
666 state->cmd_name = "unknown request";
667 state->recv_fn = NULL;
668 state->last_access = time(NULL);
670 /* Process command */
672 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
673 if (state->request->cmd == atable->cmd) {
678 if ((atable->send_req == NULL) && state->privileged) {
679 for (atable = async_priv_table; atable->send_req;
681 if (state->request->cmd == atable->cmd) {
687 if (atable->send_req != NULL) {
688 struct tevent_req *req;
690 state->cmd_name = atable->cmd_name;
691 state->recv_fn = atable->recv_req;
693 DEBUG(10, ("process_request: Handling async request %d:%s\n",
694 (int)state->pid, state->cmd_name));
696 req = atable->send_req(state->mem_ctx, winbind_event_context(),
697 state, state->request);
699 DEBUG(0, ("process_request: atable->send failed for "
700 "%s\n", atable->cmd_name));
701 request_error(state);
704 tevent_req_set_callback(req, wb_request_done, state);
708 state->response = talloc_zero(state->mem_ctx,
709 struct winbindd_response);
710 if (state->response == NULL) {
711 DEBUG(10, ("talloc failed\n"));
712 remove_client(state);
715 state->response->result = WINBINDD_PENDING;
716 state->response->length = sizeof(struct winbindd_response);
718 for (table = dispatch_table; table->fn; table++) {
719 if (state->request->cmd == table->cmd) {
720 DEBUG(10,("process_request: request fn %s\n",
721 table->winbindd_cmd_name ));
722 state->cmd_name = table->winbindd_cmd_name;
729 DEBUG(10,("process_request: unknown request fn number %d\n",
730 (int)state->request->cmd ));
731 request_error(state);
735 static void wb_request_done(struct tevent_req *req)
737 struct winbindd_cli_state *state = tevent_req_callback_data(
738 req, struct winbindd_cli_state);
741 state->response = talloc_zero(state->mem_ctx,
742 struct winbindd_response);
743 if (state->response == NULL) {
744 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
745 (int)state->pid, state->cmd_name));
746 remove_client(state);
749 state->response->result = WINBINDD_PENDING;
750 state->response->length = sizeof(struct winbindd_response);
752 status = state->recv_fn(req, state->response);
755 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
756 (int)state->pid, state->cmd_name, nt_errstr(status)));
758 if (!NT_STATUS_IS_OK(status)) {
759 request_error(state);
766 * This is the main event loop of winbind requests. It goes through a
767 * state-machine of 3 read/write requests, 4 if you have extra data to send.
769 * An idle winbind client has a read request of 4 bytes outstanding,
770 * finalizing function is request_len_recv, checking the length. request_recv
771 * then processes the packet. The processing function then at some point has
772 * to call request_finished which schedules sending the response.
775 static void request_finished(struct winbindd_cli_state *state);
777 static void winbind_client_request_read(struct tevent_req *req);
778 static void winbind_client_response_written(struct tevent_req *req);
780 static void request_finished(struct winbindd_cli_state *state)
782 struct tevent_req *req;
784 TALLOC_FREE(state->request);
786 req = wb_resp_write_send(state, winbind_event_context(),
787 state->out_queue, state->sock,
790 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
791 (int)state->pid, state->cmd_name));
792 remove_client(state);
795 tevent_req_set_callback(req, winbind_client_response_written, state);
798 static void winbind_client_response_written(struct tevent_req *req)
800 struct winbindd_cli_state *state = tevent_req_callback_data(
801 req, struct winbindd_cli_state);
805 ret = wb_resp_write_recv(req, &err);
810 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
811 (int)state->pid, state->cmd_name, strerror(err)));
812 remove_client(state);
816 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
817 "to client\n", (int)state->pid, state->cmd_name));
819 TALLOC_FREE(state->mem_ctx);
820 state->response = NULL;
821 state->cmd_name = "no request";
822 state->recv_fn = NULL;
824 req = wb_req_read_send(state, winbind_event_context(), state->sock,
825 WINBINDD_MAX_EXTRA_DATA);
827 remove_client(state);
830 tevent_req_set_callback(req, winbind_client_request_read, state);
833 void request_error(struct winbindd_cli_state *state)
835 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
836 state->response->result = WINBINDD_ERROR;
837 request_finished(state);
840 void request_ok(struct winbindd_cli_state *state)
842 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
843 state->response->result = WINBINDD_OK;
844 request_finished(state);
847 /* Process a new connection by adding it to the client connection list */
849 static void new_connection(int listen_sock, bool privileged)
851 struct sockaddr_un sunaddr;
852 struct winbindd_cli_state *state;
853 struct tevent_req *req;
857 /* Accept connection */
859 len = sizeof(sunaddr);
861 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
864 if (errno != EINTR) {
865 DEBUG(0, ("Failed to accept socket - %s\n",
871 DEBUG(6,("accepted socket %d\n", sock));
873 /* Create new connection structure */
875 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
882 state->out_queue = tevent_queue_create(state, "winbind client reply");
883 if (state->out_queue == NULL) {
889 state->last_access = time(NULL);
891 state->privileged = privileged;
893 req = wb_req_read_send(state, winbind_event_context(), state->sock,
894 WINBINDD_MAX_EXTRA_DATA);
900 tevent_req_set_callback(req, winbind_client_request_read, state);
902 /* Add to connection list */
904 winbindd_add_client(state);
907 static void winbind_client_request_read(struct tevent_req *req)
909 struct winbindd_cli_state *state = tevent_req_callback_data(
910 req, struct winbindd_cli_state);
914 ret = wb_req_read_recv(req, state, &state->request, &err);
918 DEBUG(6, ("closing socket %d, client exited\n",
921 DEBUG(2, ("Could not read client request from fd %d: "
922 "%s\n", state->sock, strerror(err)));
926 remove_client(state);
929 process_request(state);
932 /* Remove a client connection from client connection list */
934 static void remove_client(struct winbindd_cli_state *state)
939 /* It's a dead client - hold a funeral */
945 if (state->sock != -1) {
946 /* tell client, we are closing ... */
947 nwritten = write(state->sock, &c, sizeof(c));
948 if (nwritten == -1) {
949 DEBUG(2, ("final write to client failed: %s\n",
959 TALLOC_FREE(state->mem_ctx);
961 /* Remove from list and free */
963 winbindd_remove_client(state);
967 /* Is a client idle? */
969 static bool client_is_idle(struct winbindd_cli_state *state) {
970 return (state->request == NULL &&
971 state->response == NULL &&
972 !state->pwent_state && !state->grent_state);
975 /* Shutdown client connection which has been idle for the longest time */
977 static bool remove_idle_client(void)
979 struct winbindd_cli_state *state, *remove_state = NULL;
980 time_t last_access = 0;
983 for (state = winbindd_client_list(); state; state = state->next) {
984 if (client_is_idle(state)) {
986 if (!last_access || state->last_access < last_access) {
987 last_access = state->last_access;
988 remove_state = state;
994 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
995 nidle, remove_state->sock, (unsigned int)remove_state->pid));
996 remove_client(remove_state);
1003 struct winbindd_listen_state {
1008 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1009 struct tevent_fd *fde,
1013 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1014 struct winbindd_listen_state);
1016 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1017 DEBUG(5,("winbindd: Exceeding %d client "
1018 "connections, removing idle "
1019 "connection.\n", lp_winbind_max_clients()));
1020 if (!remove_idle_client()) {
1021 DEBUG(0,("winbindd: Exceeding %d "
1022 "client connections, no idle "
1023 "connection found\n",
1024 lp_winbind_max_clients()));
1028 new_connection(s->fd, s->privileged);
1032 * Winbindd socket accessor functions
1035 char *get_winbind_priv_pipe_dir(void)
1037 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1040 static bool winbindd_setup_listeners(void)
1042 struct winbindd_listen_state *pub_state = NULL;
1043 struct winbindd_listen_state *priv_state = NULL;
1044 struct tevent_fd *fde;
1047 pub_state = talloc(winbind_event_context(),
1048 struct winbindd_listen_state);
1053 pub_state->privileged = false;
1054 pub_state->fd = create_pipe_sock(
1055 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1056 if (pub_state->fd == -1) {
1059 rc = listen(pub_state->fd, 5);
1064 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1065 TEVENT_FD_READ, winbindd_listen_fde_handler,
1068 close(pub_state->fd);
1071 tevent_fd_set_auto_close(fde);
1073 priv_state = talloc(winbind_event_context(),
1074 struct winbindd_listen_state);
1079 priv_state->privileged = true;
1080 priv_state->fd = create_pipe_sock(
1081 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
1082 if (priv_state->fd == -1) {
1085 rc = listen(priv_state->fd, 5);
1090 fde = tevent_add_fd(winbind_event_context(), priv_state,
1091 priv_state->fd, TEVENT_FD_READ,
1092 winbindd_listen_fde_handler, priv_state);
1094 close(priv_state->fd);
1097 tevent_fd_set_auto_close(fde);
1101 TALLOC_FREE(pub_state);
1102 TALLOC_FREE(priv_state);
1106 bool winbindd_use_idmap_cache(void)
1108 return !opt_nocache;
1111 bool winbindd_use_cache(void)
1113 return !opt_nocache;
1116 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1119 /* Setup signal handlers */
1121 if (!winbindd_setup_sig_term_handler(true))
1123 if (!winbindd_setup_stdin_handler(true, foreground))
1125 if (!winbindd_setup_sig_hup_handler(NULL))
1127 if (!winbindd_setup_sig_chld_handler())
1129 if (!winbindd_setup_sig_usr2_handler())
1132 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1135 * Ensure all cache and idmap caches are consistent
1136 * and initialized before we startup.
1138 if (!winbindd_cache_validate_and_initialize()) {
1142 /* get broadcast messages */
1144 if (!serverid_register(messaging_server_id(msg_ctx),
1148 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1152 /* React on 'smbcontrol winbindd reload-config' in the same way
1153 as to SIGHUP signal */
1154 messaging_register(msg_ctx, NULL,
1155 MSG_SMB_CONF_UPDATED, msg_reload_services);
1156 messaging_register(msg_ctx, NULL,
1157 MSG_SHUTDOWN, msg_shutdown);
1159 /* Handle online/offline messages. */
1160 messaging_register(msg_ctx, NULL,
1161 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1162 messaging_register(msg_ctx, NULL,
1163 MSG_WINBIND_ONLINE, winbind_msg_online);
1164 messaging_register(msg_ctx, NULL,
1165 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1167 /* Handle domain online/offline messages for domains */
1168 messaging_register(winbind_messaging_context(), NULL,
1169 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1170 messaging_register(winbind_messaging_context(), NULL,
1171 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1173 messaging_register(msg_ctx, NULL,
1174 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1176 messaging_register(msg_ctx, NULL,
1177 MSG_WINBIND_VALIDATE_CACHE,
1178 winbind_msg_validate_cache);
1180 messaging_register(msg_ctx, NULL,
1181 MSG_WINBIND_DUMP_DOMAIN_LIST,
1182 winbind_msg_dump_domain_list);
1184 messaging_register(msg_ctx, NULL,
1185 MSG_WINBIND_IP_DROPPED,
1186 winbind_msg_ip_dropped_parent);
1188 /* Register handler for MSG_DEBUG. */
1189 messaging_register(msg_ctx, NULL,
1193 netsamlogon_cache_init(); /* Non-critical */
1195 /* clear the cached list of trusted domains */
1199 if (!init_domain_list()) {
1200 DEBUG(0,("unable to initialize domain list\n"));
1205 init_locator_child();
1207 smb_nscd_flush_user_cache();
1208 smb_nscd_flush_group_cache();
1210 if (lp_allow_trusted_domains()) {
1211 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1212 rescan_trusted_domains, NULL) == NULL) {
1213 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1220 struct winbindd_addrchanged_state {
1221 struct addrchange_context *ctx;
1222 struct tevent_context *ev;
1223 struct messaging_context *msg_ctx;
1226 static void winbindd_addr_changed(struct tevent_req *req);
1228 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1229 struct tevent_context *ev,
1230 struct messaging_context *msg_ctx)
1232 struct winbindd_addrchanged_state *state;
1233 struct tevent_req *req;
1236 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1237 if (state == NULL) {
1238 DEBUG(10, ("talloc failed\n"));
1242 state->msg_ctx = msg_ctx;
1244 status = addrchange_context_create(state, &state->ctx);
1245 if (!NT_STATUS_IS_OK(status)) {
1246 DEBUG(10, ("addrchange_context_create failed: %s\n",
1247 nt_errstr(status)));
1251 req = addrchange_send(state, ev, state->ctx);
1253 DEBUG(0, ("addrchange_send failed\n"));
1257 tevent_req_set_callback(req, winbindd_addr_changed, state);
1260 static void winbindd_addr_changed(struct tevent_req *req)
1262 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1263 req, struct winbindd_addrchanged_state);
1264 enum addrchange_type type;
1265 struct sockaddr_storage addr;
1268 status = addrchange_recv(req, &type, &addr);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1272 nt_errstr(status)));
1276 if (type == ADDRCHANGE_DEL) {
1277 char addrstr[INET6_ADDRSTRLEN];
1280 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1282 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1285 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1287 status = messaging_send(state->msg_ctx,
1288 messaging_server_id(state->msg_ctx),
1289 MSG_WINBIND_IP_DROPPED, &blob);
1290 if (!NT_STATUS_IS_OK(status)) {
1291 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1292 nt_errstr(status)));
1295 req = addrchange_send(state, state->ev, state->ctx);
1297 DEBUG(0, ("addrchange_send failed\n"));
1301 tevent_req_set_callback(req, winbindd_addr_changed, state);
1306 int main(int argc, char **argv, char **envp)
1308 static bool is_daemon = False;
1309 static bool Fork = True;
1310 static bool log_stdout = False;
1311 static bool no_process_group = False;
1315 OPT_NO_PROCESS_GROUP,
1318 struct poptOption long_options[] = {
1320 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1321 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1322 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1323 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1324 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1325 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1336 * Do this before any other talloc operation
1338 talloc_enable_null_tracking();
1339 frame = talloc_stackframe();
1342 * We want total control over the permissions on created files,
1343 * so set our umask to 0.
1347 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1349 /* glibc (?) likes to print "User defined signal 1" and exit if a
1350 SIGUSR[12] is received before a handler is installed */
1352 CatchSignal(SIGUSR1, SIG_IGN);
1353 CatchSignal(SIGUSR2, SIG_IGN);
1356 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1360 /* Initialise for running in non-root mode */
1364 set_remote_machine_name("winbindd", False);
1366 /* Set environment variable so we don't recursively call ourselves.
1367 This may also be useful interactively. */
1369 if ( !winbind_off() ) {
1370 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1374 /* Initialise samba/rpc client stuff */
1376 pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, 0);
1378 while ((opt = poptGetNextOpt(pc)) != -1) {
1380 /* Don't become a daemon */
1392 case OPT_NO_PROCESS_GROUP:
1393 no_process_group = true;
1395 case OPT_LOG_STDOUT:
1402 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1403 poptBadOption(pc, 0), poptStrerror(opt));
1404 poptPrintUsage(pc, stderr, 0);
1409 /* We call dump_core_setup one more time because the command line can
1410 * set the log file or the log-basename and this will influence where
1411 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1412 * the default value derived from build's prefix. For EOM this value
1413 * is often not related to the path where winbindd is actually run
1416 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1417 if (is_daemon && interactive) {
1418 d_fprintf(stderr,"\nERROR: "
1419 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1420 poptPrintUsage(pc, stderr, 0);
1424 if (log_stdout && Fork) {
1425 d_fprintf(stderr, "\nERROR: "
1426 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1427 poptPrintUsage(pc, stderr, 0);
1431 poptFreeContext(pc);
1433 if (!override_logfile) {
1435 if (asprintf(&lfile,"%s/log.winbindd",
1436 get_dyn_LOGFILEBASE()) > 0) {
1437 lp_set_logfile(lfile);
1443 setup_logging("winbindd", DEBUG_STDOUT);
1445 setup_logging("winbindd", DEBUG_FILE);
1449 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1450 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1452 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1453 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1456 /* After parsing the configuration file we setup the core path one more time
1457 * as the log file might have been set in the configuration and cores's
1458 * path is by default basename(lp_logfile()).
1460 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1462 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1463 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1464 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"));
1468 if (!cluster_probe_ok()) {
1472 /* Initialise messaging system */
1474 if (winbind_messaging_context() == NULL) {
1478 if (!reload_services_file(NULL)) {
1479 DEBUG(0, ("error opening config file\n"));
1483 ok = directory_create_or_exist(lp_lockdir(), geteuid(), 0755);
1485 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1486 lp_lockdir(), strerror(errno)));
1490 ok = directory_create_or_exist(lp_piddir(), geteuid(), 0755);
1492 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1493 lp_piddir(), strerror(errno)));
1504 if (!secrets_init()) {
1506 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1510 /* Unblock all signals we are interested in as they may have been
1511 blocked by the parent process. */
1513 BlockSignals(False, SIGINT);
1514 BlockSignals(False, SIGQUIT);
1515 BlockSignals(False, SIGTERM);
1516 BlockSignals(False, SIGUSR1);
1517 BlockSignals(False, SIGUSR2);
1518 BlockSignals(False, SIGHUP);
1519 BlockSignals(False, SIGCHLD);
1522 become_daemon(Fork, no_process_group, log_stdout);
1524 pidfile_create(lp_piddir(), "winbindd");
1528 * If we're interactive we want to set our own process group for
1529 * signal management.
1531 if (interactive && !no_process_group)
1532 setpgid( (pid_t)0, (pid_t)0);
1537 /* Don't use winbindd_reinit_after_fork here as
1538 * we're just starting up and haven't created any
1539 * winbindd-specific resources we must free yet. JRA.
1542 status = reinit_after_fork(winbind_messaging_context(),
1543 winbind_event_context(),
1545 if (!NT_STATUS_IS_OK(status)) {
1546 DEBUG(0,("reinit_after_fork() failed\n"));
1551 * Do not initialize the parent-child-pipe before becoming
1552 * a daemon: this is used to detect a died parent in the child
1555 status = init_before_fork();
1556 if (!NT_STATUS_IS_OK(status)) {
1557 DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status)));
1561 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1563 status = init_system_session_info();
1564 if (!NT_STATUS_IS_OK(status)) {
1565 DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
1566 nt_errstr(status)));
1570 rpc_lsarpc_init(NULL);
1571 rpc_samr_init(NULL);
1573 winbindd_init_addrchange(NULL, winbind_event_context(),
1574 winbind_messaging_context());
1576 /* setup listen sockets */
1578 if (!winbindd_setup_listeners()) {
1579 DEBUG(0,("winbindd_setup_listeners() failed\n"));
1584 /* Loop waiting for requests */
1586 frame = talloc_stackframe();
1588 if (tevent_loop_once(winbind_event_context()) == -1) {
1589 DEBUG(1, ("tevent_loop_once() failed: %s\n",