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"
50 #define DBGC_CLASS DBGC_WINBIND
52 #define SCRUB_CLIENTS_INTERVAL 5
54 static bool client_is_idle(struct winbindd_cli_state *state);
55 static void remove_client(struct winbindd_cli_state *state);
56 static void winbindd_setup_max_fds(void);
58 static bool opt_nocache = False;
59 static bool interactive = False;
61 extern bool override_logfile;
63 struct imessaging_context *winbind_imessaging_context(void)
65 static struct imessaging_context *msg = NULL;
66 struct messaging_context *msg_ctx;
67 struct server_id myself;
68 struct loadparm_context *lp_ctx;
74 msg_ctx = server_messaging_context();
75 if (msg_ctx == NULL) {
76 smb_panic("server_messaging_context failed\n");
78 myself = messaging_server_id(msg_ctx);
80 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
82 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
86 * Note we MUST use the NULL context here, not the autofree context,
87 * to avoid side effects in forked children exiting.
89 msg = imessaging_init(NULL, lp_ctx, myself, server_event_context());
90 talloc_unlink(NULL, lp_ctx);
93 smb_panic("Could not init winbindd's messaging context.\n");
98 /* Reload configuration */
100 static bool reload_services_file(const char *lfile)
105 char *fname = lp_next_configfile(talloc_tos());
107 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
108 set_dyn_CONFIGFILE(fname);
113 /* if this is a child, restore the logfile to the special
114 name - <domain>, idmap, etc. */
115 if (lfile && *lfile) {
116 lp_set_logfile(lfile);
120 ret = lp_load_global(get_dyn_CONFIGFILE());
124 winbindd_setup_max_fds();
130 static void winbindd_status(void)
132 struct winbindd_cli_state *tmp;
134 DEBUG(0, ("winbindd status:\n"));
136 /* Print client state information */
138 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
140 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
141 DEBUG(2, ("\tclient list:\n"));
142 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
143 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
144 (unsigned long)tmp->pid, tmp->sock,
145 client_is_idle(tmp) ? "idle" : "active"));
150 /* Flush client cache */
152 static void flush_caches(void)
154 /* We need to invalidate cached user list entries on a SIGHUP
155 otherwise cached access denied errors due to restrict anonymous
156 hang around until the sequence number changes. */
158 if (!wcache_invalidate_cache()) {
159 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
160 if (!winbindd_cache_validate_and_initialize()) {
166 static void flush_caches_noinit(void)
169 * We need to invalidate cached user list entries on a SIGHUP
170 * otherwise cached access denied errors due to restrict anonymous
171 * hang around until the sequence number changes.
173 * Skip uninitialized domains when flush cache.
174 * If domain is not initialized, it means it is never
175 * used or never become online. look, wcache_invalidate_cache()
176 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
177 * for unused domains and large traffic for primay domain's DC if there
181 if (!wcache_invalidate_cache_noinit()) {
182 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
183 if (!winbindd_cache_validate_and_initialize()) {
189 /* Handle the signal by unlinking socket and exiting */
191 static void terminate(bool is_parent)
194 /* When parent goes away we should
195 * remove the socket file. Not so
196 * when children terminate.
200 if (asprintf(&path, "%s/%s",
201 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
209 gencache_stabilize();
211 netlogon_creds_cli_close_global_db();
215 TALLOC_CTX *mem_ctx = talloc_init("end_description");
216 char *description = talloc_describe_all(mem_ctx);
218 DEBUG(3, ("tallocs left:\n%s\n", description));
219 talloc_destroy(mem_ctx);
224 pidfile_unlink(lp_pid_directory(), "winbindd");
230 static void winbindd_sig_term_handler(struct tevent_context *ev,
231 struct tevent_signal *se,
237 bool *p = talloc_get_type_abort(private_data, bool);
242 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
244 terminate(is_parent);
248 handle stdin becoming readable when we are in --foreground mode
250 static void winbindd_stdin_handler(struct tevent_context *ev,
251 struct tevent_fd *fde,
256 if (read(0, &c, 1) != 1) {
257 bool *is_parent = talloc_get_type_abort(private_data, bool);
259 /* we have reached EOF on stdin, which means the
260 parent has exited. Shutdown the server */
261 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
263 terminate(*is_parent);
267 bool winbindd_setup_sig_term_handler(bool parent)
269 struct tevent_signal *se;
272 is_parent = talloc(server_event_context(), bool);
279 se = tevent_add_signal(server_event_context(),
282 winbindd_sig_term_handler,
285 DEBUG(0,("failed to setup SIGTERM handler"));
286 talloc_free(is_parent);
290 se = tevent_add_signal(server_event_context(),
293 winbindd_sig_term_handler,
296 DEBUG(0,("failed to setup SIGINT handler"));
297 talloc_free(is_parent);
301 se = tevent_add_signal(server_event_context(),
304 winbindd_sig_term_handler,
307 DEBUG(0,("failed to setup SIGINT handler"));
308 talloc_free(is_parent);
315 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
322 is_parent = talloc(server_event_context(), bool);
329 /* if we are running in the foreground then look for
330 EOF on stdin, and exit if it happens. This allows
331 us to die if the parent process dies
332 Only do this on a pipe or socket, no other device.
334 if (fstat(0, &st) != 0) {
337 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
338 tevent_add_fd(server_event_context(),
342 winbindd_stdin_handler,
350 static void winbindd_sig_hup_handler(struct tevent_context *ev,
351 struct tevent_signal *se,
357 const char *file = (const char *)private_data;
359 DEBUG(1,("Reloading services after SIGHUP\n"));
360 flush_caches_noinit();
361 reload_services_file(file);
364 bool winbindd_setup_sig_hup_handler(const char *lfile)
366 struct tevent_signal *se;
370 file = talloc_strdup(server_event_context(),
377 se = tevent_add_signal(server_event_context(),
378 server_event_context(),
380 winbindd_sig_hup_handler,
389 static void winbindd_sig_chld_handler(struct tevent_context *ev,
390 struct tevent_signal *se,
398 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
399 winbind_child_died(pid);
403 static bool winbindd_setup_sig_chld_handler(void)
405 struct tevent_signal *se;
407 se = tevent_add_signal(server_event_context(),
408 server_event_context(),
410 winbindd_sig_chld_handler,
419 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
420 struct tevent_signal *se,
429 static bool winbindd_setup_sig_usr2_handler(void)
431 struct tevent_signal *se;
433 se = tevent_add_signal(server_event_context(),
434 server_event_context(),
436 winbindd_sig_usr2_handler,
445 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
446 static void msg_reload_services(struct messaging_context *msg,
449 struct server_id server_id,
452 /* Flush various caches */
454 reload_services_file((const char *) private_data);
457 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
458 static void msg_shutdown(struct messaging_context *msg,
461 struct server_id server_id,
464 /* only the parent waits for this message */
465 DEBUG(0,("Got shutdown message\n"));
470 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
473 struct server_id server_id,
480 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
484 * call the validation code from a child:
485 * so we don't block the main winbindd and the validation
486 * code can safely use fork/waitpid...
490 if (child_pid == -1) {
491 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
496 if (child_pid != 0) {
498 DEBUG(5, ("winbind_msg_validate_cache: child created with "
499 "pid %d.\n", (int)child_pid));
505 status = winbindd_reinit_after_fork(NULL, NULL);
506 if (!NT_STATUS_IS_OK(status)) {
507 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
512 /* install default SIGCHLD handler: validation code uses fork/waitpid */
513 CatchSignal(SIGCHLD, SIG_DFL);
515 setproctitle("validate cache child");
517 ret = (uint8_t)winbindd_validate_cache_nobackup();
518 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
519 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
524 static struct winbindd_dispatch_table {
525 enum winbindd_cmd cmd;
526 void (*fn)(struct winbindd_cli_state *state);
527 const char *winbindd_cmd_name;
528 } dispatch_table[] = {
530 /* Enumeration functions */
532 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
537 { WINBINDD_INFO, winbindd_info, "INFO" },
538 { WINBINDD_PING, winbindd_ping, "PING" },
539 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
540 "INTERFACE_VERSION" },
541 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
542 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
543 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
544 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
545 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
546 "WINBINDD_PRIV_PIPE_DIR" },
548 /* Credential cache access */
549 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
550 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
554 { WINBINDD_NUM_CMDS, NULL, "NONE" }
557 static struct winbindd_bool_dispatch_table {
558 enum winbindd_cmd cmd;
559 bool (*fn)(struct winbindd_cli_state *state);
560 const char *cmd_name;
561 } bool_dispatch_table[] = {
564 struct winbindd_async_dispatch_table {
565 enum winbindd_cmd cmd;
566 const char *cmd_name;
567 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
568 struct tevent_context *ev,
569 struct winbindd_cli_state *cli,
570 struct winbindd_request *request);
571 NTSTATUS (*recv_req)(struct tevent_req *req,
572 struct winbindd_response *presp);
575 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
576 { WINBINDD_LOOKUPSID, "LOOKUPSID",
577 winbindd_lookupsid_send, winbindd_lookupsid_recv },
578 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
579 winbindd_lookupsids_send, winbindd_lookupsids_recv },
580 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
581 winbindd_lookupname_send, winbindd_lookupname_recv },
582 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
583 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
584 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
585 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
586 { WINBINDD_GETPWSID, "GETPWSID",
587 winbindd_getpwsid_send, winbindd_getpwsid_recv },
588 { WINBINDD_GETPWNAM, "GETPWNAM",
589 winbindd_getpwnam_send, winbindd_getpwnam_recv },
590 { WINBINDD_GETPWUID, "GETPWUID",
591 winbindd_getpwuid_send, winbindd_getpwuid_recv },
592 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
593 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
594 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
595 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
596 { WINBINDD_GETGROUPS, "GETGROUPS",
597 winbindd_getgroups_send, winbindd_getgroups_recv },
598 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
599 winbindd_show_sequence_send, winbindd_show_sequence_recv },
600 { WINBINDD_GETGRGID, "GETGRGID",
601 winbindd_getgrgid_send, winbindd_getgrgid_recv },
602 { WINBINDD_GETGRNAM, "GETGRNAM",
603 winbindd_getgrnam_send, winbindd_getgrnam_recv },
604 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
605 winbindd_getusersids_send, winbindd_getusersids_recv },
606 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
607 winbindd_lookuprids_send, winbindd_lookuprids_recv },
608 { WINBINDD_SETPWENT, "SETPWENT",
609 winbindd_setpwent_send, winbindd_setpwent_recv },
610 { WINBINDD_GETPWENT, "GETPWENT",
611 winbindd_getpwent_send, winbindd_getpwent_recv },
612 { WINBINDD_ENDPWENT, "ENDPWENT",
613 winbindd_endpwent_send, winbindd_endpwent_recv },
614 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
615 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
616 { WINBINDD_GETDCNAME, "GETDCNAME",
617 winbindd_getdcname_send, winbindd_getdcname_recv },
618 { WINBINDD_SETGRENT, "SETGRENT",
619 winbindd_setgrent_send, winbindd_setgrent_recv },
620 { WINBINDD_GETGRENT, "GETGRENT",
621 winbindd_getgrent_send, winbindd_getgrent_recv },
622 { WINBINDD_ENDGRENT, "ENDGRENT",
623 winbindd_endgrent_send, winbindd_endgrent_recv },
624 { WINBINDD_LIST_USERS, "LIST_USERS",
625 winbindd_list_users_send, winbindd_list_users_recv },
626 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
627 winbindd_list_groups_send, winbindd_list_groups_recv },
628 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
629 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
630 { WINBINDD_PING_DC, "PING_DC",
631 winbindd_ping_dc_send, winbindd_ping_dc_recv },
632 { WINBINDD_PAM_AUTH, "PAM_AUTH",
633 winbindd_pam_auth_send, winbindd_pam_auth_recv },
634 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
635 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
636 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
637 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
638 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
639 winbindd_pam_chng_pswd_auth_crap_send,
640 winbindd_pam_chng_pswd_auth_crap_recv },
641 { WINBINDD_WINS_BYIP, "WINS_BYIP",
642 winbindd_wins_byip_send, winbindd_wins_byip_recv },
643 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
644 winbindd_wins_byname_send, winbindd_wins_byname_recv },
646 { 0, NULL, NULL, NULL }
649 static struct winbindd_async_dispatch_table async_priv_table[] = {
650 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
651 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
652 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
653 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
654 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
655 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
656 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
657 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
659 { 0, NULL, NULL, NULL }
662 static void wb_request_done(struct tevent_req *req);
664 static void process_request(struct winbindd_cli_state *state)
666 struct winbindd_dispatch_table *table = dispatch_table;
667 struct winbindd_async_dispatch_table *atable;
671 state->mem_ctx = talloc_named(state, 0, "winbind request");
672 if (state->mem_ctx == NULL)
675 /* Remember who asked us. */
676 state->pid = state->request->pid;
678 state->cmd_name = "unknown request";
679 state->recv_fn = NULL;
680 /* client is newest */
681 winbindd_promote_client(state);
683 /* Process command */
685 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
686 if (state->request->cmd == atable->cmd) {
691 if ((atable->send_req == NULL) && state->privileged) {
692 for (atable = async_priv_table; atable->send_req;
694 if (state->request->cmd == atable->cmd) {
700 if (atable->send_req != NULL) {
701 struct tevent_req *req;
703 state->cmd_name = atable->cmd_name;
704 state->recv_fn = atable->recv_req;
706 DEBUG(10, ("process_request: Handling async request %d:%s\n",
707 (int)state->pid, state->cmd_name));
709 req = atable->send_req(state->mem_ctx, server_event_context(),
710 state, state->request);
712 DEBUG(0, ("process_request: atable->send failed for "
713 "%s\n", atable->cmd_name));
714 request_error(state);
717 tevent_req_set_callback(req, wb_request_done, state);
721 state->response = talloc_zero(state->mem_ctx,
722 struct winbindd_response);
723 if (state->response == NULL) {
724 DEBUG(10, ("talloc failed\n"));
725 remove_client(state);
728 state->response->result = WINBINDD_PENDING;
729 state->response->length = sizeof(struct winbindd_response);
731 for (table = dispatch_table; table->fn; table++) {
732 if (state->request->cmd == table->cmd) {
733 DEBUG(10,("process_request: request fn %s\n",
734 table->winbindd_cmd_name ));
735 state->cmd_name = table->winbindd_cmd_name;
741 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
742 if (bool_dispatch_table[i].cmd == state->request->cmd) {
747 if (i == ARRAY_SIZE(bool_dispatch_table)) {
748 DEBUG(10,("process_request: unknown request fn number %d\n",
749 (int)state->request->cmd ));
750 request_error(state);
754 DBG_DEBUG("process_request: request fn %s\n",
755 bool_dispatch_table[i].cmd_name);
757 ok = bool_dispatch_table[i].fn(state);
762 request_error(state);
766 static void wb_request_done(struct tevent_req *req)
768 struct winbindd_cli_state *state = tevent_req_callback_data(
769 req, struct winbindd_cli_state);
772 state->response = talloc_zero(state->mem_ctx,
773 struct winbindd_response);
774 if (state->response == NULL) {
775 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
776 (int)state->pid, state->cmd_name));
777 remove_client(state);
780 state->response->result = WINBINDD_PENDING;
781 state->response->length = sizeof(struct winbindd_response);
783 status = state->recv_fn(req, state->response);
786 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
787 (int)state->pid, state->cmd_name, nt_errstr(status)));
789 if (!NT_STATUS_IS_OK(status)) {
790 request_error(state);
797 * This is the main event loop of winbind requests. It goes through a
798 * state-machine of 3 read/write requests, 4 if you have extra data to send.
800 * An idle winbind client has a read request of 4 bytes outstanding,
801 * finalizing function is request_len_recv, checking the length. request_recv
802 * then processes the packet. The processing function then at some point has
803 * to call request_finished which schedules sending the response.
806 static void request_finished(struct winbindd_cli_state *state);
808 static void winbind_client_request_read(struct tevent_req *req);
809 static void winbind_client_response_written(struct tevent_req *req);
810 static void winbind_client_activity(struct tevent_req *req);
812 static void request_finished(struct winbindd_cli_state *state)
814 struct tevent_req *req;
816 /* free client socket monitoring request */
817 TALLOC_FREE(state->io_req);
819 TALLOC_FREE(state->request);
821 req = wb_resp_write_send(state, server_event_context(),
822 state->out_queue, state->sock,
825 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
826 (int)state->pid, state->cmd_name));
827 remove_client(state);
830 tevent_req_set_callback(req, winbind_client_response_written, state);
834 static void winbind_client_response_written(struct tevent_req *req)
836 struct winbindd_cli_state *state = tevent_req_callback_data(
837 req, struct winbindd_cli_state);
841 state->io_req = NULL;
843 ret = wb_resp_write_recv(req, &err);
848 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
849 (int)state->pid, state->cmd_name, strerror(err)));
850 remove_client(state);
854 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
855 "to client\n", (int)state->pid, state->cmd_name));
857 TALLOC_FREE(state->mem_ctx);
858 state->response = NULL;
859 state->cmd_name = "no request";
860 state->recv_fn = NULL;
862 req = wb_req_read_send(state, server_event_context(), state->sock,
863 WINBINDD_MAX_EXTRA_DATA);
865 remove_client(state);
868 tevent_req_set_callback(req, winbind_client_request_read, state);
872 void request_error(struct winbindd_cli_state *state)
874 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
875 state->response->result = WINBINDD_ERROR;
876 request_finished(state);
879 void request_ok(struct winbindd_cli_state *state)
881 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
882 state->response->result = WINBINDD_OK;
883 request_finished(state);
886 /* Process a new connection by adding it to the client connection list */
888 static void new_connection(int listen_sock, bool privileged)
890 struct sockaddr_un sunaddr;
891 struct winbindd_cli_state *state;
892 struct tevent_req *req;
896 /* Accept connection */
898 len = sizeof(sunaddr);
900 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
903 if (errno != EINTR) {
904 DEBUG(0, ("Failed to accept socket - %s\n",
909 smb_set_close_on_exec(sock);
911 DEBUG(6,("accepted socket %d\n", sock));
913 /* Create new connection structure */
915 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
922 state->out_queue = tevent_queue_create(state, "winbind client reply");
923 if (state->out_queue == NULL) {
929 state->privileged = privileged;
931 req = wb_req_read_send(state, server_event_context(), state->sock,
932 WINBINDD_MAX_EXTRA_DATA);
938 tevent_req_set_callback(req, winbind_client_request_read, state);
941 /* Add to connection list */
943 winbindd_add_client(state);
946 static void winbind_client_request_read(struct tevent_req *req)
948 struct winbindd_cli_state *state = tevent_req_callback_data(
949 req, struct winbindd_cli_state);
953 state->io_req = NULL;
955 ret = wb_req_read_recv(req, state, &state->request, &err);
959 DEBUG(6, ("closing socket %d, client exited\n",
962 DEBUG(2, ("Could not read client request from fd %d: "
963 "%s\n", state->sock, strerror(err)));
967 remove_client(state);
971 req = wait_for_read_send(state, server_event_context(), state->sock,
974 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
975 " wait_for_read_send failed - removing client\n",
976 (int)state->pid, state->cmd_name));
977 remove_client(state);
980 tevent_req_set_callback(req, winbind_client_activity, state);
983 process_request(state);
986 static void winbind_client_activity(struct tevent_req *req)
988 struct winbindd_cli_state *state =
989 tevent_req_callback_data(req, struct winbindd_cli_state);
993 has_data = wait_for_read_recv(req, &err);
996 DEBUG(0, ("winbind_client_activity[%d:%s]:"
997 "unexpected data from client - removing client\n",
998 (int)state->pid, state->cmd_name));
1001 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1002 "client has closed connection - removing "
1004 (int)state->pid, state->cmd_name));
1006 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1007 "client socket error (%s) - removing "
1009 (int)state->pid, state->cmd_name,
1014 remove_client(state);
1017 /* Remove a client connection from client connection list */
1019 static void remove_client(struct winbindd_cli_state *state)
1024 /* It's a dead client - hold a funeral */
1026 if (state == NULL) {
1031 * We need to remove a pending wb_req_read_*
1032 * or wb_resp_write_* request before closing the
1035 * This is important as they might have used tevent_add_fd() and we
1036 * use the epoll * backend on linux. So we must remove the tevent_fd
1037 * before closing the fd.
1039 * Otherwise we might hit a race with close_conns_after_fork() (via
1040 * winbindd_reinit_after_fork()) where a file description
1041 * is still open in a child, which means it's still active in
1042 * the parents epoll queue, but the related tevent_fd is already
1043 * already gone in the parent.
1047 TALLOC_FREE(state->io_req);
1049 if (state->sock != -1) {
1050 /* tell client, we are closing ... */
1051 nwritten = write(state->sock, &c, sizeof(c));
1052 if (nwritten == -1) {
1053 DEBUG(2, ("final write to client failed: %s\n",
1063 TALLOC_FREE(state->mem_ctx);
1065 /* Remove from list and free */
1067 winbindd_remove_client(state);
1071 /* Is a client idle? */
1073 static bool client_is_idle(struct winbindd_cli_state *state) {
1074 return (state->request == NULL &&
1075 state->response == NULL &&
1076 !state->pwent_state && !state->grent_state);
1079 /* Shutdown client connection which has been idle for the longest time */
1081 static bool remove_idle_client(void)
1083 struct winbindd_cli_state *state, *remove_state = NULL;
1086 for (state = winbindd_client_list(); state; state = state->next) {
1087 if (client_is_idle(state)) {
1089 /* list is sorted by access time */
1090 remove_state = state;
1095 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1096 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1097 remove_client(remove_state);
1105 * Terminate all clients whose requests have taken longer than
1106 * "winbind request timeout" seconds to process, or have been
1107 * idle for more than "winbind request timeout" seconds.
1110 static void remove_timed_out_clients(void)
1112 struct winbindd_cli_state *state, *prev = NULL;
1113 time_t curr_time = time(NULL);
1114 int timeout_val = lp_winbind_request_timeout();
1116 for (state = winbindd_client_list_tail(); state; state = prev) {
1119 prev = winbindd_client_list_prev(state);
1120 expiry_time = state->last_access + timeout_val;
1122 if (curr_time <= expiry_time) {
1123 /* list is sorted, previous clients in
1128 if (client_is_idle(state)) {
1129 DEBUG(5,("Idle client timed out, "
1130 "shutting down sock %d, pid %u\n",
1132 (unsigned int)state->pid));
1134 DEBUG(5,("Client request timed out, "
1135 "shutting down sock %d, pid %u\n",
1137 (unsigned int)state->pid));
1140 remove_client(state);
1144 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1145 struct tevent_timer *te,
1146 struct timeval current_time,
1149 remove_timed_out_clients();
1150 if (tevent_add_timer(ev, ev,
1151 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1152 winbindd_scrub_clients_handler, NULL) == NULL) {
1153 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1158 struct winbindd_listen_state {
1163 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1164 struct tevent_fd *fde,
1168 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1169 struct winbindd_listen_state);
1171 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1172 DEBUG(5,("winbindd: Exceeding %d client "
1173 "connections, removing idle "
1174 "connection.\n", lp_winbind_max_clients()));
1175 if (!remove_idle_client()) {
1176 DEBUG(0,("winbindd: Exceeding %d "
1177 "client connections, no idle "
1178 "connection found\n",
1179 lp_winbind_max_clients()));
1183 remove_timed_out_clients();
1184 new_connection(s->fd, s->privileged);
1188 * Winbindd socket accessor functions
1191 char *get_winbind_priv_pipe_dir(void)
1193 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1196 static void winbindd_setup_max_fds(void)
1198 int num_fds = MAX_OPEN_FUDGEFACTOR;
1201 num_fds += lp_winbind_max_clients();
1202 /* Add some more to account for 2 sockets open
1203 when the client transitions from unprivileged
1204 to privileged socket
1206 num_fds += lp_winbind_max_clients() / 10;
1208 /* Add one socket per child process
1209 (yeah there are child processes other than the
1210 domain children but only domain children can vary
1213 num_fds += lp_winbind_max_domain_connections() *
1214 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1216 actual_fds = set_maxfiles(num_fds);
1218 if (actual_fds < num_fds) {
1219 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1220 "requested %d open files, %d are available.\n",
1221 num_fds, actual_fds));
1225 static bool winbindd_setup_listeners(void)
1227 struct winbindd_listen_state *pub_state = NULL;
1228 struct winbindd_listen_state *priv_state = NULL;
1229 struct tevent_fd *fde;
1233 pub_state = talloc(server_event_context(),
1234 struct winbindd_listen_state);
1239 pub_state->privileged = false;
1240 pub_state->fd = create_pipe_sock(
1241 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1242 if (pub_state->fd == -1) {
1245 rc = listen(pub_state->fd, 5);
1250 fde = tevent_add_fd(server_event_context(), pub_state, pub_state->fd,
1251 TEVENT_FD_READ, winbindd_listen_fde_handler,
1254 close(pub_state->fd);
1257 tevent_fd_set_auto_close(fde);
1259 priv_state = talloc(server_event_context(),
1260 struct winbindd_listen_state);
1265 socket_path = get_winbind_priv_pipe_dir();
1266 if (socket_path == NULL) {
1270 priv_state->privileged = true;
1271 priv_state->fd = create_pipe_sock(
1272 socket_path, WINBINDD_SOCKET_NAME, 0750);
1273 TALLOC_FREE(socket_path);
1274 if (priv_state->fd == -1) {
1277 rc = listen(priv_state->fd, 5);
1282 fde = tevent_add_fd(server_event_context(), priv_state,
1283 priv_state->fd, TEVENT_FD_READ,
1284 winbindd_listen_fde_handler, priv_state);
1286 close(priv_state->fd);
1289 tevent_fd_set_auto_close(fde);
1291 winbindd_scrub_clients_handler(server_event_context(), NULL,
1292 timeval_current(), NULL);
1295 TALLOC_FREE(pub_state);
1296 TALLOC_FREE(priv_state);
1300 bool winbindd_use_idmap_cache(void)
1302 return !opt_nocache;
1305 bool winbindd_use_cache(void)
1307 return !opt_nocache;
1310 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1313 bool scan_trusts = true;
1315 /* Setup signal handlers */
1317 if (!winbindd_setup_sig_term_handler(true))
1319 if (!winbindd_setup_stdin_handler(true, foreground))
1321 if (!winbindd_setup_sig_hup_handler(NULL))
1323 if (!winbindd_setup_sig_chld_handler())
1325 if (!winbindd_setup_sig_usr2_handler())
1328 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1331 * Ensure all cache and idmap caches are consistent
1332 * and initialized before we startup.
1334 if (!winbindd_cache_validate_and_initialize()) {
1338 /* React on 'smbcontrol winbindd reload-config' in the same way
1339 as to SIGHUP signal */
1340 messaging_register(msg_ctx, NULL,
1341 MSG_SMB_CONF_UPDATED, msg_reload_services);
1342 messaging_register(msg_ctx, NULL,
1343 MSG_SHUTDOWN, msg_shutdown);
1345 /* Handle online/offline messages. */
1346 messaging_register(msg_ctx, NULL,
1347 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1348 messaging_register(msg_ctx, NULL,
1349 MSG_WINBIND_ONLINE, winbind_msg_online);
1350 messaging_register(msg_ctx, NULL,
1351 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1353 /* Handle domain online/offline messages for domains */
1354 messaging_register(server_messaging_context(), NULL,
1355 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1356 messaging_register(server_messaging_context(), NULL,
1357 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1359 messaging_register(msg_ctx, NULL,
1360 MSG_WINBIND_VALIDATE_CACHE,
1361 winbind_msg_validate_cache);
1363 messaging_register(msg_ctx, NULL,
1364 MSG_WINBIND_DUMP_DOMAIN_LIST,
1365 winbind_msg_dump_domain_list);
1367 messaging_register(msg_ctx, NULL,
1368 MSG_WINBIND_IP_DROPPED,
1369 winbind_msg_ip_dropped_parent);
1371 /* Register handler for MSG_DEBUG. */
1372 messaging_register(msg_ctx, NULL,
1376 messaging_register(msg_ctx, NULL,
1377 MSG_WINBIND_DISCONNECT_DC,
1378 winbind_disconnect_dc_parent);
1380 netsamlogon_cache_init(); /* Non-critical */
1382 /* clear the cached list of trusted domains */
1386 if (!init_domain_list()) {
1387 DEBUG(0,("unable to initialize domain list\n"));
1392 init_locator_child();
1394 smb_nscd_flush_user_cache();
1395 smb_nscd_flush_group_cache();
1397 if (!lp_winbind_scan_trusted_domains()) {
1398 scan_trusts = false;
1401 if (!lp_allow_trusted_domains()) {
1402 scan_trusts = false;
1406 scan_trusts = false;
1410 if (tevent_add_timer(server_event_context(), NULL, timeval_zero(),
1411 rescan_trusted_domains, NULL) == NULL) {
1412 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1417 status = wb_irpc_register();
1419 if (!NT_STATUS_IS_OK(status)) {
1420 DEBUG(0, ("Could not register IRPC handlers\n"));
1425 struct winbindd_addrchanged_state {
1426 struct addrchange_context *ctx;
1427 struct tevent_context *ev;
1428 struct messaging_context *msg_ctx;
1431 static void winbindd_addr_changed(struct tevent_req *req);
1433 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1434 struct tevent_context *ev,
1435 struct messaging_context *msg_ctx)
1437 struct winbindd_addrchanged_state *state;
1438 struct tevent_req *req;
1441 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1442 if (state == NULL) {
1443 DEBUG(10, ("talloc failed\n"));
1447 state->msg_ctx = msg_ctx;
1449 status = addrchange_context_create(state, &state->ctx);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 DEBUG(10, ("addrchange_context_create failed: %s\n",
1452 nt_errstr(status)));
1456 req = addrchange_send(state, ev, state->ctx);
1458 DEBUG(0, ("addrchange_send failed\n"));
1462 tevent_req_set_callback(req, winbindd_addr_changed, state);
1465 static void winbindd_addr_changed(struct tevent_req *req)
1467 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1468 req, struct winbindd_addrchanged_state);
1469 enum addrchange_type type;
1470 struct sockaddr_storage addr;
1473 status = addrchange_recv(req, &type, &addr);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1477 nt_errstr(status)));
1481 if (type == ADDRCHANGE_DEL) {
1482 char addrstr[INET6_ADDRSTRLEN];
1485 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1487 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1490 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1492 status = messaging_send(state->msg_ctx,
1493 messaging_server_id(state->msg_ctx),
1494 MSG_WINBIND_IP_DROPPED, &blob);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1497 nt_errstr(status)));
1500 req = addrchange_send(state, state->ev, state->ctx);
1502 DEBUG(0, ("addrchange_send failed\n"));
1506 tevent_req_set_callback(req, winbindd_addr_changed, state);
1511 int main(int argc, const char **argv)
1513 static bool is_daemon = False;
1514 static bool Fork = True;
1515 static bool log_stdout = False;
1516 static bool no_process_group = False;
1520 OPT_NO_PROCESS_GROUP,
1523 struct poptOption long_options[] = {
1525 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1526 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1527 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1528 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1529 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1530 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1540 setproctitle_init(argc, discard_const(argv), environ);
1543 * Do this before any other talloc operation
1545 talloc_enable_null_tracking();
1546 frame = talloc_stackframe();
1549 * We want total control over the permissions on created files,
1550 * so set our umask to 0.
1554 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1556 /* glibc (?) likes to print "User defined signal 1" and exit if a
1557 SIGUSR[12] is received before a handler is installed */
1559 CatchSignal(SIGUSR1, SIG_IGN);
1560 CatchSignal(SIGUSR2, SIG_IGN);
1563 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1567 /* Initialise for running in non-root mode */
1571 set_remote_machine_name("winbindd", False);
1573 /* Set environment variable so we don't recursively call ourselves.
1574 This may also be useful interactively. */
1576 if ( !winbind_off() ) {
1577 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1581 /* Initialise samba/rpc client stuff */
1583 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1585 while ((opt = poptGetNextOpt(pc)) != -1) {
1587 /* Don't become a daemon */
1599 case OPT_NO_PROCESS_GROUP:
1600 no_process_group = true;
1602 case OPT_LOG_STDOUT:
1609 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1610 poptBadOption(pc, 0), poptStrerror(opt));
1611 poptPrintUsage(pc, stderr, 0);
1616 /* We call dump_core_setup one more time because the command line can
1617 * set the log file or the log-basename and this will influence where
1618 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1619 * the default value derived from build's prefix. For EOM this value
1620 * is often not related to the path where winbindd is actually run
1623 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1624 if (is_daemon && interactive) {
1625 d_fprintf(stderr,"\nERROR: "
1626 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1627 poptPrintUsage(pc, stderr, 0);
1631 if (log_stdout && Fork) {
1632 d_fprintf(stderr, "\nERROR: "
1633 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1634 poptPrintUsage(pc, stderr, 0);
1638 poptFreeContext(pc);
1640 if (!override_logfile) {
1642 if (asprintf(&lfile,"%s/log.winbindd",
1643 get_dyn_LOGFILEBASE()) > 0) {
1644 lp_set_logfile(lfile);
1650 setup_logging("winbindd", DEBUG_STDOUT);
1652 setup_logging("winbindd", DEBUG_FILE);
1656 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1657 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1659 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1660 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1663 /* After parsing the configuration file we setup the core path one more time
1664 * as the log file might have been set in the configuration and cores's
1665 * path is by default basename(lp_logfile()).
1667 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1669 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1670 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1671 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1672 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"));
1676 if (!cluster_probe_ok()) {
1680 /* Initialise messaging system */
1682 if (server_messaging_context() == NULL) {
1686 if (!reload_services_file(NULL)) {
1687 DEBUG(0, ("error opening config file\n"));
1693 const char *idmap_backend;
1694 const char *invalid_backends[] = {
1695 "ad", "rfc2307", "rid",
1698 idmap_backend = lp_idmap_default_backend();
1699 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1700 ok = strequal(idmap_backend, invalid_backends[i]);
1702 DBG_ERR("FATAL: Invalid idmap backend %s "
1703 "configured as the default backend!\n",
1710 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1712 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1713 lp_lock_directory(), strerror(errno)));
1717 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1719 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1720 lp_pid_directory(), strerror(errno)));
1731 if (!secrets_init()) {
1733 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1737 status = rpccli_pre_open_netlogon_creds();
1738 if (!NT_STATUS_IS_OK(status)) {
1739 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1740 nt_errstr(status)));
1744 /* Unblock all signals we are interested in as they may have been
1745 blocked by the parent process. */
1747 BlockSignals(False, SIGINT);
1748 BlockSignals(False, SIGQUIT);
1749 BlockSignals(False, SIGTERM);
1750 BlockSignals(False, SIGUSR1);
1751 BlockSignals(False, SIGUSR2);
1752 BlockSignals(False, SIGHUP);
1753 BlockSignals(False, SIGCHLD);
1756 become_daemon(Fork, no_process_group, log_stdout);
1758 pidfile_create(lp_pid_directory(), "winbindd");
1762 * If we're interactive we want to set our own process group for
1763 * signal management.
1765 if (interactive && !no_process_group)
1766 setpgid( (pid_t)0, (pid_t)0);
1771 /* Don't use winbindd_reinit_after_fork here as
1772 * we're just starting up and haven't created any
1773 * winbindd-specific resources we must free yet. JRA.
1776 status = reinit_after_fork(server_messaging_context(),
1777 server_event_context(),
1779 if (!NT_STATUS_IS_OK(status)) {
1780 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1782 initialize_password_db(true, server_event_context());
1785 * Do not initialize the parent-child-pipe before becoming
1786 * a daemon: this is used to detect a died parent in the child
1789 status = init_before_fork();
1790 if (!NT_STATUS_IS_OK(status)) {
1791 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1794 winbindd_register_handlers(server_messaging_context(), !Fork);
1796 if (!messaging_parent_dgm_cleanup_init(server_messaging_context())) {
1800 status = init_system_session_info(NULL);
1801 if (!NT_STATUS_IS_OK(status)) {
1802 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1805 rpc_lsarpc_init(NULL);
1806 rpc_samr_init(NULL);
1808 winbindd_init_addrchange(NULL, server_event_context(),
1809 server_messaging_context());
1811 /* setup listen sockets */
1813 if (!winbindd_setup_listeners()) {
1814 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1817 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1822 daemon_ready("winbindd");
1827 /* Loop waiting for requests */
1829 frame = talloc_stackframe();
1831 if (tevent_loop_once(server_event_context()) == -1) {
1832 DEBUG(1, ("tevent_loop_once() failed: %s\n",