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"
46 #include "libsmb/samlogon_cache.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 tevent_context *winbind_event_context(void)
64 static struct tevent_context *ev = NULL;
71 * Note we MUST use the NULL context here, not the autofree context,
72 * to avoid side effects in forked children exiting.
74 ev = samba_tevent_context_init(NULL);
76 smb_panic("Could not init winbindd's messaging context.\n");
81 struct messaging_context *winbind_messaging_context(void)
83 static struct messaging_context *msg = NULL;
90 * Note we MUST use the NULL context here, not the autofree context,
91 * to avoid side effects in forked children exiting.
93 msg = messaging_init(NULL, winbind_event_context());
95 smb_panic("Could not init winbindd's messaging context.\n");
100 struct imessaging_context *winbind_imessaging_context(void)
102 static struct imessaging_context *msg = NULL;
103 struct messaging_context *msg_ctx;
104 struct server_id myself;
105 struct loadparm_context *lp_ctx;
111 msg_ctx = server_messaging_context();
112 if (msg_ctx == NULL) {
113 smb_panic("server_messaging_context failed\n");
115 myself = messaging_server_id(msg_ctx);
117 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
118 if (lp_ctx == NULL) {
119 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
123 * Note we MUST use the NULL context here, not the autofree context,
124 * to avoid side effects in forked children exiting.
126 msg = imessaging_init(NULL, lp_ctx, myself, winbind_event_context());
127 talloc_unlink(NULL, lp_ctx);
130 smb_panic("Could not init winbindd's messaging context.\n");
135 /* Reload configuration */
137 static bool reload_services_file(const char *lfile)
142 char *fname = lp_next_configfile(talloc_tos());
144 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
145 set_dyn_CONFIGFILE(fname);
150 /* if this is a child, restore the logfile to the special
151 name - <domain>, idmap, etc. */
152 if (lfile && *lfile) {
153 lp_set_logfile(lfile);
157 ret = lp_load_global(get_dyn_CONFIGFILE());
161 winbindd_setup_max_fds();
167 static void winbindd_status(void)
169 struct winbindd_cli_state *tmp;
171 DEBUG(0, ("winbindd status:\n"));
173 /* Print client state information */
175 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
177 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
178 DEBUG(2, ("\tclient list:\n"));
179 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
180 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
181 (unsigned long)tmp->pid, tmp->sock,
182 client_is_idle(tmp) ? "idle" : "active"));
187 /* Flush client cache */
189 static void flush_caches(void)
191 /* We need to invalidate cached user list entries on a SIGHUP
192 otherwise cached access denied errors due to restrict anonymous
193 hang around until the sequence number changes. */
195 if (!wcache_invalidate_cache()) {
196 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
197 if (!winbindd_cache_validate_and_initialize()) {
203 static void flush_caches_noinit(void)
206 * We need to invalidate cached user list entries on a SIGHUP
207 * otherwise cached access denied errors due to restrict anonymous
208 * hang around until the sequence number changes.
210 * Skip uninitialized domains when flush cache.
211 * If domain is not initialized, it means it is never
212 * used or never become online. look, wcache_invalidate_cache()
213 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
214 * for unused domains and large traffic for primay domain's DC if there
218 if (!wcache_invalidate_cache_noinit()) {
219 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
220 if (!winbindd_cache_validate_and_initialize()) {
226 /* Handle the signal by unlinking socket and exiting */
228 static void terminate(bool is_parent)
231 /* When parent goes away we should
232 * remove the socket file. Not so
233 * when children terminate.
237 if (asprintf(&path, "%s/%s",
238 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
246 gencache_stabilize();
250 TALLOC_CTX *mem_ctx = talloc_init("end_description");
251 char *description = talloc_describe_all(mem_ctx);
253 DEBUG(3, ("tallocs left:\n%s\n", description));
254 talloc_destroy(mem_ctx);
259 struct messaging_context *msg = winbind_messaging_context();
260 struct server_id self = messaging_server_id(msg);
261 serverid_deregister(self);
262 pidfile_unlink(lp_pid_directory(), "winbindd");
268 static void winbindd_sig_term_handler(struct tevent_context *ev,
269 struct tevent_signal *se,
275 bool *is_parent = talloc_get_type_abort(private_data, bool);
277 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
278 signum, (int)*is_parent));
279 terminate(*is_parent);
283 handle stdin becoming readable when we are in --foreground mode
285 static void winbindd_stdin_handler(struct tevent_context *ev,
286 struct tevent_fd *fde,
291 if (read(0, &c, 1) != 1) {
292 bool *is_parent = talloc_get_type_abort(private_data, bool);
294 /* we have reached EOF on stdin, which means the
295 parent has exited. Shutdown the server */
296 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
298 terminate(*is_parent);
302 bool winbindd_setup_sig_term_handler(bool parent)
304 struct tevent_signal *se;
307 is_parent = talloc(winbind_event_context(), bool);
314 se = tevent_add_signal(winbind_event_context(),
317 winbindd_sig_term_handler,
320 DEBUG(0,("failed to setup SIGTERM handler"));
321 talloc_free(is_parent);
325 se = tevent_add_signal(winbind_event_context(),
328 winbindd_sig_term_handler,
331 DEBUG(0,("failed to setup SIGINT handler"));
332 talloc_free(is_parent);
336 se = tevent_add_signal(winbind_event_context(),
339 winbindd_sig_term_handler,
342 DEBUG(0,("failed to setup SIGINT handler"));
343 talloc_free(is_parent);
350 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
357 is_parent = talloc(winbind_event_context(), bool);
364 /* if we are running in the foreground then look for
365 EOF on stdin, and exit if it happens. This allows
366 us to die if the parent process dies
367 Only do this on a pipe or socket, no other device.
369 if (fstat(0, &st) != 0) {
372 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
373 tevent_add_fd(winbind_event_context(),
377 winbindd_stdin_handler,
385 static void winbindd_sig_hup_handler(struct tevent_context *ev,
386 struct tevent_signal *se,
392 const char *file = (const char *)private_data;
394 DEBUG(1,("Reloading services after SIGHUP\n"));
395 flush_caches_noinit();
396 reload_services_file(file);
399 bool winbindd_setup_sig_hup_handler(const char *lfile)
401 struct tevent_signal *se;
405 file = talloc_strdup(winbind_event_context(),
412 se = tevent_add_signal(winbind_event_context(),
413 winbind_event_context(),
415 winbindd_sig_hup_handler,
424 static void winbindd_sig_chld_handler(struct tevent_context *ev,
425 struct tevent_signal *se,
433 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
434 winbind_child_died(pid);
438 static bool winbindd_setup_sig_chld_handler(void)
440 struct tevent_signal *se;
442 se = tevent_add_signal(winbind_event_context(),
443 winbind_event_context(),
445 winbindd_sig_chld_handler,
454 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
455 struct tevent_signal *se,
464 static bool winbindd_setup_sig_usr2_handler(void)
466 struct tevent_signal *se;
468 se = tevent_add_signal(winbind_event_context(),
469 winbind_event_context(),
471 winbindd_sig_usr2_handler,
480 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
481 static void msg_reload_services(struct messaging_context *msg,
484 struct server_id server_id,
487 /* Flush various caches */
489 reload_services_file((const char *) private_data);
492 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
493 static void msg_shutdown(struct messaging_context *msg,
496 struct server_id server_id,
499 /* only the parent waits for this message */
500 DEBUG(0,("Got shutdown message\n"));
505 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
508 struct server_id server_id,
515 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
519 * call the validation code from a child:
520 * so we don't block the main winbindd and the validation
521 * code can safely use fork/waitpid...
525 if (child_pid == -1) {
526 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
531 if (child_pid != 0) {
533 DEBUG(5, ("winbind_msg_validate_cache: child created with "
534 "pid %d.\n", (int)child_pid));
540 status = winbindd_reinit_after_fork(NULL, NULL);
541 if (!NT_STATUS_IS_OK(status)) {
542 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
547 /* install default SIGCHLD handler: validation code uses fork/waitpid */
548 CatchSignal(SIGCHLD, SIG_DFL);
550 ret = (uint8_t)winbindd_validate_cache_nobackup();
551 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
552 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
557 static struct winbindd_dispatch_table {
558 enum winbindd_cmd cmd;
559 void (*fn)(struct winbindd_cli_state *state);
560 const char *winbindd_cmd_name;
561 } dispatch_table[] = {
563 /* Enumeration functions */
565 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
570 { WINBINDD_INFO, winbindd_info, "INFO" },
571 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
572 "INTERFACE_VERSION" },
573 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
574 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
575 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
576 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
577 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
578 "WINBINDD_PRIV_PIPE_DIR" },
580 /* Credential cache access */
581 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
582 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
586 { WINBINDD_NUM_CMDS, NULL, "NONE" }
589 struct winbindd_async_dispatch_table {
590 enum winbindd_cmd cmd;
591 const char *cmd_name;
592 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
593 struct tevent_context *ev,
594 struct winbindd_cli_state *cli,
595 struct winbindd_request *request);
596 NTSTATUS (*recv_req)(struct tevent_req *req,
597 struct winbindd_response *presp);
600 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
601 { WINBINDD_PING, "PING",
602 wb_ping_send, wb_ping_recv },
603 { WINBINDD_LOOKUPSID, "LOOKUPSID",
604 winbindd_lookupsid_send, winbindd_lookupsid_recv },
605 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
606 winbindd_lookupsids_send, winbindd_lookupsids_recv },
607 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
608 winbindd_lookupname_send, winbindd_lookupname_recv },
609 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
610 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
611 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
612 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
613 { WINBINDD_GETPWSID, "GETPWSID",
614 winbindd_getpwsid_send, winbindd_getpwsid_recv },
615 { WINBINDD_GETPWNAM, "GETPWNAM",
616 winbindd_getpwnam_send, winbindd_getpwnam_recv },
617 { WINBINDD_GETPWUID, "GETPWUID",
618 winbindd_getpwuid_send, winbindd_getpwuid_recv },
619 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
620 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
621 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
622 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
623 { WINBINDD_GETGROUPS, "GETGROUPS",
624 winbindd_getgroups_send, winbindd_getgroups_recv },
625 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
626 winbindd_show_sequence_send, winbindd_show_sequence_recv },
627 { WINBINDD_GETGRGID, "GETGRGID",
628 winbindd_getgrgid_send, winbindd_getgrgid_recv },
629 { WINBINDD_GETGRNAM, "GETGRNAM",
630 winbindd_getgrnam_send, winbindd_getgrnam_recv },
631 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
632 winbindd_getusersids_send, winbindd_getusersids_recv },
633 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
634 winbindd_lookuprids_send, winbindd_lookuprids_recv },
635 { WINBINDD_SETPWENT, "SETPWENT",
636 winbindd_setpwent_send, winbindd_setpwent_recv },
637 { WINBINDD_GETPWENT, "GETPWENT",
638 winbindd_getpwent_send, winbindd_getpwent_recv },
639 { WINBINDD_ENDPWENT, "ENDPWENT",
640 winbindd_endpwent_send, winbindd_endpwent_recv },
641 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
642 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
643 { WINBINDD_GETDCNAME, "GETDCNAME",
644 winbindd_getdcname_send, winbindd_getdcname_recv },
645 { WINBINDD_SETGRENT, "SETGRENT",
646 winbindd_setgrent_send, winbindd_setgrent_recv },
647 { WINBINDD_GETGRENT, "GETGRENT",
648 winbindd_getgrent_send, winbindd_getgrent_recv },
649 { WINBINDD_ENDGRENT, "ENDGRENT",
650 winbindd_endgrent_send, winbindd_endgrent_recv },
651 { WINBINDD_LIST_USERS, "LIST_USERS",
652 winbindd_list_users_send, winbindd_list_users_recv },
653 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
654 winbindd_list_groups_send, winbindd_list_groups_recv },
655 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
656 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
657 { WINBINDD_PING_DC, "PING_DC",
658 winbindd_ping_dc_send, winbindd_ping_dc_recv },
659 { WINBINDD_PAM_AUTH, "PAM_AUTH",
660 winbindd_pam_auth_send, winbindd_pam_auth_recv },
661 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
662 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
663 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
664 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
665 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
666 winbindd_pam_chng_pswd_auth_crap_send,
667 winbindd_pam_chng_pswd_auth_crap_recv },
668 { WINBINDD_WINS_BYIP, "WINS_BYIP",
669 winbindd_wins_byip_send, winbindd_wins_byip_recv },
670 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
671 winbindd_wins_byname_send, winbindd_wins_byname_recv },
673 { 0, NULL, NULL, NULL }
676 static struct winbindd_async_dispatch_table async_priv_table[] = {
677 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
678 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
679 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
680 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
681 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
682 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
683 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
684 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
686 { 0, NULL, NULL, NULL }
689 static void wb_request_done(struct tevent_req *req);
691 static void process_request(struct winbindd_cli_state *state)
693 struct winbindd_dispatch_table *table = dispatch_table;
694 struct winbindd_async_dispatch_table *atable;
696 state->mem_ctx = talloc_named(state, 0, "winbind request");
697 if (state->mem_ctx == NULL)
700 /* Remember who asked us. */
701 state->pid = state->request->pid;
703 state->cmd_name = "unknown request";
704 state->recv_fn = NULL;
705 /* client is newest */
706 winbindd_promote_client(state);
708 /* Process command */
710 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
711 if (state->request->cmd == atable->cmd) {
716 if ((atable->send_req == NULL) && state->privileged) {
717 for (atable = async_priv_table; atable->send_req;
719 if (state->request->cmd == atable->cmd) {
725 if (atable->send_req != NULL) {
726 struct tevent_req *req;
728 state->cmd_name = atable->cmd_name;
729 state->recv_fn = atable->recv_req;
731 DEBUG(10, ("process_request: Handling async request %d:%s\n",
732 (int)state->pid, state->cmd_name));
734 req = atable->send_req(state->mem_ctx, winbind_event_context(),
735 state, state->request);
737 DEBUG(0, ("process_request: atable->send failed for "
738 "%s\n", atable->cmd_name));
739 request_error(state);
742 tevent_req_set_callback(req, wb_request_done, state);
746 state->response = talloc_zero(state->mem_ctx,
747 struct winbindd_response);
748 if (state->response == NULL) {
749 DEBUG(10, ("talloc failed\n"));
750 remove_client(state);
753 state->response->result = WINBINDD_PENDING;
754 state->response->length = sizeof(struct winbindd_response);
756 for (table = dispatch_table; table->fn; table++) {
757 if (state->request->cmd == table->cmd) {
758 DEBUG(10,("process_request: request fn %s\n",
759 table->winbindd_cmd_name ));
760 state->cmd_name = table->winbindd_cmd_name;
767 DEBUG(10,("process_request: unknown request fn number %d\n",
768 (int)state->request->cmd ));
769 request_error(state);
773 static void wb_request_done(struct tevent_req *req)
775 struct winbindd_cli_state *state = tevent_req_callback_data(
776 req, struct winbindd_cli_state);
779 state->response = talloc_zero(state->mem_ctx,
780 struct winbindd_response);
781 if (state->response == NULL) {
782 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
783 (int)state->pid, state->cmd_name));
784 remove_client(state);
787 state->response->result = WINBINDD_PENDING;
788 state->response->length = sizeof(struct winbindd_response);
790 status = state->recv_fn(req, state->response);
793 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
794 (int)state->pid, state->cmd_name, nt_errstr(status)));
796 if (!NT_STATUS_IS_OK(status)) {
797 request_error(state);
804 * This is the main event loop of winbind requests. It goes through a
805 * state-machine of 3 read/write requests, 4 if you have extra data to send.
807 * An idle winbind client has a read request of 4 bytes outstanding,
808 * finalizing function is request_len_recv, checking the length. request_recv
809 * then processes the packet. The processing function then at some point has
810 * to call request_finished which schedules sending the response.
813 static void request_finished(struct winbindd_cli_state *state);
815 static void winbind_client_request_read(struct tevent_req *req);
816 static void winbind_client_response_written(struct tevent_req *req);
817 static void winbind_client_activity(struct tevent_req *req);
819 static void request_finished(struct winbindd_cli_state *state)
821 struct tevent_req *req;
823 /* free client socket monitoring request */
824 TALLOC_FREE(state->io_req);
826 TALLOC_FREE(state->request);
828 req = wb_resp_write_send(state, winbind_event_context(),
829 state->out_queue, state->sock,
832 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
833 (int)state->pid, state->cmd_name));
834 remove_client(state);
837 tevent_req_set_callback(req, winbind_client_response_written, state);
841 static void winbind_client_response_written(struct tevent_req *req)
843 struct winbindd_cli_state *state = tevent_req_callback_data(
844 req, struct winbindd_cli_state);
848 state->io_req = NULL;
850 ret = wb_resp_write_recv(req, &err);
855 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
856 (int)state->pid, state->cmd_name, strerror(err)));
857 remove_client(state);
861 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
862 "to client\n", (int)state->pid, state->cmd_name));
864 TALLOC_FREE(state->mem_ctx);
865 state->response = NULL;
866 state->cmd_name = "no request";
867 state->recv_fn = NULL;
869 req = wb_req_read_send(state, winbind_event_context(), state->sock,
870 WINBINDD_MAX_EXTRA_DATA);
872 remove_client(state);
875 tevent_req_set_callback(req, winbind_client_request_read, state);
879 void request_error(struct winbindd_cli_state *state)
881 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
882 state->response->result = WINBINDD_ERROR;
883 request_finished(state);
886 void request_ok(struct winbindd_cli_state *state)
888 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
889 state->response->result = WINBINDD_OK;
890 request_finished(state);
893 /* Process a new connection by adding it to the client connection list */
895 static void new_connection(int listen_sock, bool privileged)
897 struct sockaddr_un sunaddr;
898 struct winbindd_cli_state *state;
899 struct tevent_req *req;
903 /* Accept connection */
905 len = sizeof(sunaddr);
907 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
910 if (errno != EINTR) {
911 DEBUG(0, ("Failed to accept socket - %s\n",
917 DEBUG(6,("accepted socket %d\n", sock));
919 /* Create new connection structure */
921 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
928 state->out_queue = tevent_queue_create(state, "winbind client reply");
929 if (state->out_queue == NULL) {
935 state->privileged = privileged;
937 req = wb_req_read_send(state, winbind_event_context(), state->sock,
938 WINBINDD_MAX_EXTRA_DATA);
944 tevent_req_set_callback(req, winbind_client_request_read, state);
947 /* Add to connection list */
949 winbindd_add_client(state);
952 static void winbind_client_request_read(struct tevent_req *req)
954 struct winbindd_cli_state *state = tevent_req_callback_data(
955 req, struct winbindd_cli_state);
959 state->io_req = NULL;
961 ret = wb_req_read_recv(req, state, &state->request, &err);
965 DEBUG(6, ("closing socket %d, client exited\n",
968 DEBUG(2, ("Could not read client request from fd %d: "
969 "%s\n", state->sock, strerror(err)));
973 remove_client(state);
977 req = wait_for_read_send(state, winbind_event_context(), state->sock,
980 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
981 " wait_for_read_send failed - removing client\n",
982 (int)state->pid, state->cmd_name));
983 remove_client(state);
986 tevent_req_set_callback(req, winbind_client_activity, state);
989 process_request(state);
992 static void winbind_client_activity(struct tevent_req *req)
994 struct winbindd_cli_state *state =
995 tevent_req_callback_data(req, struct winbindd_cli_state);
999 has_data = wait_for_read_recv(req, &err);
1002 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1003 "unexpected data from client - removing client\n",
1004 (int)state->pid, state->cmd_name));
1007 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1008 "client has closed connection - removing "
1010 (int)state->pid, state->cmd_name));
1012 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1013 "client socket error (%s) - removing "
1015 (int)state->pid, state->cmd_name,
1020 remove_client(state);
1023 /* Remove a client connection from client connection list */
1025 static void remove_client(struct winbindd_cli_state *state)
1030 /* It's a dead client - hold a funeral */
1032 if (state == NULL) {
1037 * We need to remove a pending wb_req_read_*
1038 * or wb_resp_write_* request before closing the
1041 * This is important as they might have used tevent_add_fd() and we
1042 * use the epoll * backend on linux. So we must remove the tevent_fd
1043 * before closing the fd.
1045 * Otherwise we might hit a race with close_conns_after_fork() (via
1046 * winbindd_reinit_after_fork()) where a file description
1047 * is still open in a child, which means it's still active in
1048 * the parents epoll queue, but the related tevent_fd is already
1049 * already gone in the parent.
1053 TALLOC_FREE(state->io_req);
1055 if (state->sock != -1) {
1056 /* tell client, we are closing ... */
1057 nwritten = write(state->sock, &c, sizeof(c));
1058 if (nwritten == -1) {
1059 DEBUG(2, ("final write to client failed: %s\n",
1069 TALLOC_FREE(state->mem_ctx);
1071 /* Remove from list and free */
1073 winbindd_remove_client(state);
1077 /* Is a client idle? */
1079 static bool client_is_idle(struct winbindd_cli_state *state) {
1080 return (state->request == NULL &&
1081 state->response == NULL &&
1082 !state->pwent_state && !state->grent_state);
1085 /* Shutdown client connection which has been idle for the longest time */
1087 static bool remove_idle_client(void)
1089 struct winbindd_cli_state *state, *remove_state = NULL;
1092 for (state = winbindd_client_list(); state; state = state->next) {
1093 if (client_is_idle(state)) {
1095 /* list is sorted by access time */
1096 remove_state = state;
1101 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1102 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1103 remove_client(remove_state);
1111 * Terminate all clients whose requests have taken longer than
1112 * "winbind request timeout" seconds to process, or have been
1113 * idle for more than "winbind request timeout" seconds.
1116 static void remove_timed_out_clients(void)
1118 struct winbindd_cli_state *state, *prev = NULL;
1119 time_t curr_time = time(NULL);
1120 int timeout_val = lp_winbind_request_timeout();
1122 for (state = winbindd_client_list_tail(); state; state = prev) {
1125 prev = winbindd_client_list_prev(state);
1126 expiry_time = state->last_access + timeout_val;
1128 if (curr_time > expiry_time) {
1129 if (client_is_idle(state)) {
1130 DEBUG(5,("Idle client timed out, "
1131 "shutting down sock %d, pid %u\n",
1133 (unsigned int)state->pid));
1135 DEBUG(5,("Client request timed out, "
1136 "shutting down sock %d, pid %u\n",
1138 (unsigned int)state->pid));
1140 remove_client(state);
1142 /* list is sorted, previous clients in
1149 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1150 struct tevent_timer *te,
1151 struct timeval current_time,
1154 remove_timed_out_clients();
1155 if (tevent_add_timer(ev, ev,
1156 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1157 winbindd_scrub_clients_handler, NULL) == NULL) {
1158 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1163 struct winbindd_listen_state {
1168 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1169 struct tevent_fd *fde,
1173 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1174 struct winbindd_listen_state);
1176 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1177 DEBUG(5,("winbindd: Exceeding %d client "
1178 "connections, removing idle "
1179 "connection.\n", lp_winbind_max_clients()));
1180 if (!remove_idle_client()) {
1181 DEBUG(0,("winbindd: Exceeding %d "
1182 "client connections, no idle "
1183 "connection found\n",
1184 lp_winbind_max_clients()));
1188 remove_timed_out_clients();
1189 new_connection(s->fd, s->privileged);
1193 * Winbindd socket accessor functions
1196 char *get_winbind_priv_pipe_dir(void)
1198 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1201 static void winbindd_setup_max_fds(void)
1203 int num_fds = MAX_OPEN_FUDGEFACTOR;
1206 num_fds += lp_winbind_max_clients();
1207 /* Add some more to account for 2 sockets open
1208 when the client transitions from unprivileged
1209 to privileged socket
1211 num_fds += lp_winbind_max_clients() / 10;
1213 /* Add one socket per child process
1214 (yeah there are child processes other than the
1215 domain children but only domain children can vary
1218 num_fds += lp_winbind_max_domain_connections() *
1219 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1221 actual_fds = set_maxfiles(num_fds);
1223 if (actual_fds < num_fds) {
1224 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1225 "requested %d open files, %d are available.\n",
1226 num_fds, actual_fds));
1230 static bool winbindd_setup_listeners(void)
1232 struct winbindd_listen_state *pub_state = NULL;
1233 struct winbindd_listen_state *priv_state = NULL;
1234 struct tevent_fd *fde;
1238 pub_state = talloc(winbind_event_context(),
1239 struct winbindd_listen_state);
1244 pub_state->privileged = false;
1245 pub_state->fd = create_pipe_sock(
1246 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1247 if (pub_state->fd == -1) {
1250 rc = listen(pub_state->fd, 5);
1255 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1256 TEVENT_FD_READ, winbindd_listen_fde_handler,
1259 close(pub_state->fd);
1262 tevent_fd_set_auto_close(fde);
1264 priv_state = talloc(winbind_event_context(),
1265 struct winbindd_listen_state);
1270 socket_path = get_winbind_priv_pipe_dir();
1271 if (socket_path == NULL) {
1275 priv_state->privileged = true;
1276 priv_state->fd = create_pipe_sock(
1277 socket_path, WINBINDD_SOCKET_NAME, 0750);
1278 TALLOC_FREE(socket_path);
1279 if (priv_state->fd == -1) {
1282 rc = listen(priv_state->fd, 5);
1287 fde = tevent_add_fd(winbind_event_context(), priv_state,
1288 priv_state->fd, TEVENT_FD_READ,
1289 winbindd_listen_fde_handler, priv_state);
1291 close(priv_state->fd);
1294 tevent_fd_set_auto_close(fde);
1296 winbindd_scrub_clients_handler(winbind_event_context(), NULL,
1297 timeval_current(), NULL);
1300 TALLOC_FREE(pub_state);
1301 TALLOC_FREE(priv_state);
1305 bool winbindd_use_idmap_cache(void)
1307 return !opt_nocache;
1310 bool winbindd_use_cache(void)
1312 return !opt_nocache;
1315 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1319 /* Setup signal handlers */
1321 if (!winbindd_setup_sig_term_handler(true))
1323 if (!winbindd_setup_stdin_handler(true, foreground))
1325 if (!winbindd_setup_sig_hup_handler(NULL))
1327 if (!winbindd_setup_sig_chld_handler())
1329 if (!winbindd_setup_sig_usr2_handler())
1332 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1335 * Ensure all cache and idmap caches are consistent
1336 * and initialized before we startup.
1338 if (!winbindd_cache_validate_and_initialize()) {
1342 /* get broadcast messages */
1344 if (!serverid_register(messaging_server_id(msg_ctx),
1348 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1352 /* React on 'smbcontrol winbindd reload-config' in the same way
1353 as to SIGHUP signal */
1354 messaging_register(msg_ctx, NULL,
1355 MSG_SMB_CONF_UPDATED, msg_reload_services);
1356 messaging_register(msg_ctx, NULL,
1357 MSG_SHUTDOWN, msg_shutdown);
1359 /* Handle online/offline messages. */
1360 messaging_register(msg_ctx, NULL,
1361 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1362 messaging_register(msg_ctx, NULL,
1363 MSG_WINBIND_ONLINE, winbind_msg_online);
1364 messaging_register(msg_ctx, NULL,
1365 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1367 /* Handle domain online/offline messages for domains */
1368 messaging_register(winbind_messaging_context(), NULL,
1369 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1370 messaging_register(winbind_messaging_context(), NULL,
1371 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1373 messaging_register(msg_ctx, NULL,
1374 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1376 messaging_register(msg_ctx, NULL,
1377 MSG_WINBIND_VALIDATE_CACHE,
1378 winbind_msg_validate_cache);
1380 messaging_register(msg_ctx, NULL,
1381 MSG_WINBIND_DUMP_DOMAIN_LIST,
1382 winbind_msg_dump_domain_list);
1384 messaging_register(msg_ctx, NULL,
1385 MSG_WINBIND_IP_DROPPED,
1386 winbind_msg_ip_dropped_parent);
1388 /* Register handler for MSG_DEBUG. */
1389 messaging_register(msg_ctx, NULL,
1393 netsamlogon_cache_init(); /* Non-critical */
1395 /* clear the cached list of trusted domains */
1399 if (!init_domain_list()) {
1400 DEBUG(0,("unable to initialize domain list\n"));
1405 init_locator_child();
1407 smb_nscd_flush_user_cache();
1408 smb_nscd_flush_group_cache();
1410 if (lp_allow_trusted_domains()) {
1411 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1412 rescan_trusted_domains, NULL) == NULL) {
1413 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1418 status = wb_irpc_register();
1420 if (!NT_STATUS_IS_OK(status)) {
1421 DEBUG(0, ("Could not register IRPC handlers\n"));
1426 struct winbindd_addrchanged_state {
1427 struct addrchange_context *ctx;
1428 struct tevent_context *ev;
1429 struct messaging_context *msg_ctx;
1432 static void winbindd_addr_changed(struct tevent_req *req);
1434 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1435 struct tevent_context *ev,
1436 struct messaging_context *msg_ctx)
1438 struct winbindd_addrchanged_state *state;
1439 struct tevent_req *req;
1442 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1443 if (state == NULL) {
1444 DEBUG(10, ("talloc failed\n"));
1448 state->msg_ctx = msg_ctx;
1450 status = addrchange_context_create(state, &state->ctx);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 DEBUG(10, ("addrchange_context_create failed: %s\n",
1453 nt_errstr(status)));
1457 req = addrchange_send(state, ev, state->ctx);
1459 DEBUG(0, ("addrchange_send failed\n"));
1463 tevent_req_set_callback(req, winbindd_addr_changed, state);
1466 static void winbindd_addr_changed(struct tevent_req *req)
1468 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1469 req, struct winbindd_addrchanged_state);
1470 enum addrchange_type type;
1471 struct sockaddr_storage addr;
1474 status = addrchange_recv(req, &type, &addr);
1476 if (!NT_STATUS_IS_OK(status)) {
1477 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1478 nt_errstr(status)));
1482 if (type == ADDRCHANGE_DEL) {
1483 char addrstr[INET6_ADDRSTRLEN];
1486 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1488 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1491 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1493 status = messaging_send(state->msg_ctx,
1494 messaging_server_id(state->msg_ctx),
1495 MSG_WINBIND_IP_DROPPED, &blob);
1496 if (!NT_STATUS_IS_OK(status)) {
1497 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1498 nt_errstr(status)));
1501 req = addrchange_send(state, state->ev, state->ctx);
1503 DEBUG(0, ("addrchange_send failed\n"));
1507 tevent_req_set_callback(req, winbindd_addr_changed, state);
1512 int main(int argc, const char **argv)
1514 static bool is_daemon = False;
1515 static bool Fork = True;
1516 static bool log_stdout = False;
1517 static bool no_process_group = False;
1521 OPT_NO_PROCESS_GROUP,
1524 struct poptOption long_options[] = {
1526 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1527 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1528 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1529 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1530 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1531 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1542 * Do this before any other talloc operation
1544 talloc_enable_null_tracking();
1545 frame = talloc_stackframe();
1548 * We want total control over the permissions on created files,
1549 * so set our umask to 0.
1553 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1555 /* glibc (?) likes to print "User defined signal 1" and exit if a
1556 SIGUSR[12] is received before a handler is installed */
1558 CatchSignal(SIGUSR1, SIG_IGN);
1559 CatchSignal(SIGUSR2, SIG_IGN);
1562 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1566 /* Initialise for running in non-root mode */
1570 set_remote_machine_name("winbindd", False);
1572 /* Set environment variable so we don't recursively call ourselves.
1573 This may also be useful interactively. */
1575 if ( !winbind_off() ) {
1576 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1580 /* Initialise samba/rpc client stuff */
1582 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1584 while ((opt = poptGetNextOpt(pc)) != -1) {
1586 /* Don't become a daemon */
1598 case OPT_NO_PROCESS_GROUP:
1599 no_process_group = true;
1601 case OPT_LOG_STDOUT:
1608 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1609 poptBadOption(pc, 0), poptStrerror(opt));
1610 poptPrintUsage(pc, stderr, 0);
1615 /* We call dump_core_setup one more time because the command line can
1616 * set the log file or the log-basename and this will influence where
1617 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1618 * the default value derived from build's prefix. For EOM this value
1619 * is often not related to the path where winbindd is actually run
1622 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1623 if (is_daemon && interactive) {
1624 d_fprintf(stderr,"\nERROR: "
1625 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1626 poptPrintUsage(pc, stderr, 0);
1630 if (log_stdout && Fork) {
1631 d_fprintf(stderr, "\nERROR: "
1632 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1633 poptPrintUsage(pc, stderr, 0);
1637 poptFreeContext(pc);
1639 if (!override_logfile) {
1641 if (asprintf(&lfile,"%s/log.winbindd",
1642 get_dyn_LOGFILEBASE()) > 0) {
1643 lp_set_logfile(lfile);
1649 setup_logging("winbindd", DEBUG_STDOUT);
1651 setup_logging("winbindd", DEBUG_FILE);
1655 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1656 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1658 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1659 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1662 /* After parsing the configuration file we setup the core path one more time
1663 * as the log file might have been set in the configuration and cores's
1664 * path is by default basename(lp_logfile()).
1666 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1668 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1669 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1670 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1671 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"));
1675 if (!cluster_probe_ok()) {
1679 /* Initialise messaging system */
1681 if (winbind_messaging_context() == NULL) {
1685 if (!reload_services_file(NULL)) {
1686 DEBUG(0, ("error opening config file\n"));
1692 const char *idmap_backend;
1693 const char *invalid_backends[] = {
1694 "ad", "rfc2307", "rid",
1697 idmap_backend = lp_idmap_default_backend();
1698 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1699 ok = strequal(idmap_backend, invalid_backends[i]);
1701 DBG_ERR("FATAL: Invalid idmap backend %s "
1702 "configured as the default backend!\n",
1709 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1711 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1712 lp_lock_directory(), strerror(errno)));
1716 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1718 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1719 lp_pid_directory(), strerror(errno)));
1730 if (!secrets_init()) {
1732 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1736 status = rpccli_pre_open_netlogon_creds();
1737 if (!NT_STATUS_IS_OK(status)) {
1738 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1739 nt_errstr(status)));
1743 /* Unblock all signals we are interested in as they may have been
1744 blocked by the parent process. */
1746 BlockSignals(False, SIGINT);
1747 BlockSignals(False, SIGQUIT);
1748 BlockSignals(False, SIGTERM);
1749 BlockSignals(False, SIGUSR1);
1750 BlockSignals(False, SIGUSR2);
1751 BlockSignals(False, SIGHUP);
1752 BlockSignals(False, SIGCHLD);
1755 become_daemon(Fork, no_process_group, log_stdout);
1757 pidfile_create(lp_pid_directory(), "winbindd");
1761 * If we're interactive we want to set our own process group for
1762 * signal management.
1764 if (interactive && !no_process_group)
1765 setpgid( (pid_t)0, (pid_t)0);
1770 /* Don't use winbindd_reinit_after_fork here as
1771 * we're just starting up and haven't created any
1772 * winbindd-specific resources we must free yet. JRA.
1775 status = reinit_after_fork(winbind_messaging_context(),
1776 winbind_event_context(),
1778 if (!NT_STATUS_IS_OK(status)) {
1779 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1783 * Do not initialize the parent-child-pipe before becoming
1784 * a daemon: this is used to detect a died parent in the child
1787 status = init_before_fork();
1788 if (!NT_STATUS_IS_OK(status)) {
1789 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1792 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1794 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1798 status = init_system_session_info();
1799 if (!NT_STATUS_IS_OK(status)) {
1800 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1803 rpc_lsarpc_init(NULL);
1804 rpc_samr_init(NULL);
1806 winbindd_init_addrchange(NULL, winbind_event_context(),
1807 winbind_messaging_context());
1809 /* setup listen sockets */
1811 if (!winbindd_setup_listeners()) {
1812 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1815 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1820 daemon_ready("winbindd");
1823 /* Loop waiting for requests */
1825 frame = talloc_stackframe();
1827 if (tevent_loop_once(winbind_event_context()) == -1) {
1828 DEBUG(1, ("tevent_loop_once() failed: %s\n",