CVE-2013-4408:s3:Ensure we always check call_id when validating an RPC reply.
[Samba.git] / source3 / winbindd / winbindd.c
blob839655ee3a6f48117c63e5a932062b72c71b41d3
1 /*
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/>.
25 #include "includes.h"
26 #include "popt_common.h"
27 #include "winbindd.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
30 #include "ntdomain.h"
31 #include "../librpc/gen_ndr/srv_lsa.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
33 #include "secrets.h"
34 #include "idmap.h"
35 #include "lib/addrchange.h"
36 #include "serverid.h"
37 #include "auth.h"
38 #include "messages.h"
39 #include "../lib/util/pidfile.h"
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_WINBIND
44 static bool client_is_idle(struct winbindd_cli_state *state);
45 static void remove_client(struct winbindd_cli_state *state);
47 static bool opt_nocache = False;
48 static bool interactive = False;
50 extern bool override_logfile;
52 struct messaging_context *winbind_messaging_context(void)
54 struct messaging_context *msg_ctx = server_messaging_context();
55 if (likely(msg_ctx != NULL)) {
56 return msg_ctx;
58 smb_panic("Could not init winbindd's messaging context.\n");
59 return NULL;
62 /* Reload configuration */
64 static bool reload_services_file(const char *lfile)
66 bool ret;
68 if (lp_loaded()) {
69 char *fname = lp_configfile(talloc_tos());
71 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
72 set_dyn_CONFIGFILE(fname);
74 TALLOC_FREE(fname);
77 /* if this is a child, restore the logfile to the special
78 name - <domain>, idmap, etc. */
79 if (lfile && *lfile) {
80 lp_set_logfile(lfile);
83 reopen_logs();
84 ret = lp_load_global(get_dyn_CONFIGFILE());
86 reopen_logs();
87 load_interfaces();
89 return(ret);
93 static void winbindd_status(void)
95 struct winbindd_cli_state *tmp;
97 DEBUG(0, ("winbindd status:\n"));
99 /* Print client state information */
101 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
103 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
104 DEBUG(2, ("\tclient list:\n"));
105 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
106 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
107 (unsigned long)tmp->pid, tmp->sock,
108 client_is_idle(tmp) ? "idle" : "active"));
113 /* Flush client cache */
115 static void flush_caches(void)
117 /* We need to invalidate cached user list entries on a SIGHUP
118 otherwise cached access denied errors due to restrict anonymous
119 hang around until the sequence number changes. */
121 if (!wcache_invalidate_cache()) {
122 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
123 if (!winbindd_cache_validate_and_initialize()) {
124 exit(1);
129 static void flush_caches_noinit(void)
132 * We need to invalidate cached user list entries on a SIGHUP
133 * otherwise cached access denied errors due to restrict anonymous
134 * hang around until the sequence number changes.
135 * NB
136 * Skip uninitialized domains when flush cache.
137 * If domain is not initialized, it means it is never
138 * used or never become online. look, wcache_invalidate_cache()
139 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
140 * for unused domains and large traffic for primay domain's DC if there
141 * are many domains..
144 if (!wcache_invalidate_cache_noinit()) {
145 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
146 if (!winbindd_cache_validate_and_initialize()) {
147 exit(1);
152 /* Handle the signal by unlinking socket and exiting */
154 static void terminate(bool is_parent)
156 if (is_parent) {
157 /* When parent goes away we should
158 * remove the socket file. Not so
159 * when children terminate.
161 char *path = NULL;
163 if (asprintf(&path, "%s/%s",
164 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) {
165 unlink(path);
166 SAFE_FREE(path);
170 idmap_close();
172 trustdom_cache_shutdown();
174 gencache_stabilize();
176 #if 0
177 if (interactive) {
178 TALLOC_CTX *mem_ctx = talloc_init("end_description");
179 char *description = talloc_describe_all(mem_ctx);
181 DEBUG(3, ("tallocs left:\n%s\n", description));
182 talloc_destroy(mem_ctx);
184 #endif
186 if (is_parent) {
187 serverid_deregister(procid_self());
188 pidfile_unlink(lp_piddir(), "winbindd");
191 exit(0);
194 static void winbindd_sig_term_handler(struct tevent_context *ev,
195 struct tevent_signal *se,
196 int signum,
197 int count,
198 void *siginfo,
199 void *private_data)
201 bool *is_parent = talloc_get_type_abort(private_data, bool);
203 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
204 signum, (int)*is_parent));
205 terminate(*is_parent);
209 handle stdin becoming readable when we are in --foreground mode
211 static void winbindd_stdin_handler(struct tevent_context *ev,
212 struct tevent_fd *fde,
213 uint16_t flags,
214 void *private_data)
216 char c;
217 if (read(0, &c, 1) != 1) {
218 bool *is_parent = talloc_get_type_abort(private_data, bool);
220 /* we have reached EOF on stdin, which means the
221 parent has exited. Shutdown the server */
222 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
223 (int)*is_parent));
224 terminate(*is_parent);
228 bool winbindd_setup_sig_term_handler(bool parent)
230 struct tevent_signal *se;
231 bool *is_parent;
233 is_parent = talloc(winbind_event_context(), bool);
234 if (!is_parent) {
235 return false;
238 *is_parent = parent;
240 se = tevent_add_signal(winbind_event_context(),
241 is_parent,
242 SIGTERM, 0,
243 winbindd_sig_term_handler,
244 is_parent);
245 if (!se) {
246 DEBUG(0,("failed to setup SIGTERM handler"));
247 talloc_free(is_parent);
248 return false;
251 se = tevent_add_signal(winbind_event_context(),
252 is_parent,
253 SIGINT, 0,
254 winbindd_sig_term_handler,
255 is_parent);
256 if (!se) {
257 DEBUG(0,("failed to setup SIGINT handler"));
258 talloc_free(is_parent);
259 return false;
262 se = tevent_add_signal(winbind_event_context(),
263 is_parent,
264 SIGQUIT, 0,
265 winbindd_sig_term_handler,
266 is_parent);
267 if (!se) {
268 DEBUG(0,("failed to setup SIGINT handler"));
269 talloc_free(is_parent);
270 return false;
273 return true;
276 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
278 bool *is_parent;
280 if (foreground) {
281 struct stat st;
283 is_parent = talloc(winbind_event_context(), bool);
284 if (!is_parent) {
285 return false;
288 *is_parent = parent;
290 /* if we are running in the foreground then look for
291 EOF on stdin, and exit if it happens. This allows
292 us to die if the parent process dies
293 Only do this on a pipe or socket, no other device.
295 if (fstat(0, &st) != 0) {
296 return false;
298 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
299 tevent_add_fd(winbind_event_context(),
300 is_parent,
302 TEVENT_FD_READ,
303 winbindd_stdin_handler,
304 is_parent);
308 return true;
311 static void winbindd_sig_hup_handler(struct tevent_context *ev,
312 struct tevent_signal *se,
313 int signum,
314 int count,
315 void *siginfo,
316 void *private_data)
318 const char *file = (const char *)private_data;
320 DEBUG(1,("Reloading services after SIGHUP\n"));
321 flush_caches_noinit();
322 reload_services_file(file);
325 bool winbindd_setup_sig_hup_handler(const char *lfile)
327 struct tevent_signal *se;
328 char *file = NULL;
330 if (lfile) {
331 file = talloc_strdup(winbind_event_context(),
332 lfile);
333 if (!file) {
334 return false;
338 se = tevent_add_signal(winbind_event_context(),
339 winbind_event_context(),
340 SIGHUP, 0,
341 winbindd_sig_hup_handler,
342 file);
343 if (!se) {
344 return false;
347 return true;
350 static void winbindd_sig_chld_handler(struct tevent_context *ev,
351 struct tevent_signal *se,
352 int signum,
353 int count,
354 void *siginfo,
355 void *private_data)
357 pid_t pid;
359 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
360 winbind_child_died(pid);
364 static bool winbindd_setup_sig_chld_handler(void)
366 struct tevent_signal *se;
368 se = tevent_add_signal(winbind_event_context(),
369 winbind_event_context(),
370 SIGCHLD, 0,
371 winbindd_sig_chld_handler,
372 NULL);
373 if (!se) {
374 return false;
377 return true;
380 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
381 struct tevent_signal *se,
382 int signum,
383 int count,
384 void *siginfo,
385 void *private_data)
387 winbindd_status();
390 static bool winbindd_setup_sig_usr2_handler(void)
392 struct tevent_signal *se;
394 se = tevent_add_signal(winbind_event_context(),
395 winbind_event_context(),
396 SIGUSR2, 0,
397 winbindd_sig_usr2_handler,
398 NULL);
399 if (!se) {
400 return false;
403 return true;
406 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
407 static void msg_reload_services(struct messaging_context *msg,
408 void *private_data,
409 uint32_t msg_type,
410 struct server_id server_id,
411 DATA_BLOB *data)
413 /* Flush various caches */
414 flush_caches();
415 reload_services_file((const char *) private_data);
418 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
419 static void msg_shutdown(struct messaging_context *msg,
420 void *private_data,
421 uint32_t msg_type,
422 struct server_id server_id,
423 DATA_BLOB *data)
425 /* only the parent waits for this message */
426 DEBUG(0,("Got shutdown message\n"));
427 terminate(true);
431 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
432 void *private_data,
433 uint32_t msg_type,
434 struct server_id server_id,
435 DATA_BLOB *data)
437 uint8 ret;
438 pid_t child_pid;
439 NTSTATUS status;
441 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
442 "message.\n"));
445 * call the validation code from a child:
446 * so we don't block the main winbindd and the validation
447 * code can safely use fork/waitpid...
449 child_pid = fork();
451 if (child_pid == -1) {
452 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
453 strerror(errno)));
454 return;
457 if (child_pid != 0) {
458 /* parent */
459 DEBUG(5, ("winbind_msg_validate_cache: child created with "
460 "pid %d.\n", (int)child_pid));
461 return;
464 /* child */
466 status = winbindd_reinit_after_fork(NULL, NULL);
467 if (!NT_STATUS_IS_OK(status)) {
468 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
469 nt_errstr(status)));
470 _exit(0);
473 /* install default SIGCHLD handler: validation code uses fork/waitpid */
474 CatchSignal(SIGCHLD, SIG_DFL);
476 ret = (uint8)winbindd_validate_cache_nobackup();
477 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
478 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
479 (size_t)1);
480 _exit(0);
483 static struct winbindd_dispatch_table {
484 enum winbindd_cmd cmd;
485 void (*fn)(struct winbindd_cli_state *state);
486 const char *winbindd_cmd_name;
487 } dispatch_table[] = {
489 /* Enumeration functions */
491 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
492 "LIST_TRUSTDOM" },
494 /* Miscellaneous */
496 { WINBINDD_INFO, winbindd_info, "INFO" },
497 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
498 "INTERFACE_VERSION" },
499 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
500 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
501 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
502 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
503 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
504 "WINBINDD_PRIV_PIPE_DIR" },
506 /* Credential cache access */
507 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
508 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
510 /* End of list */
512 { WINBINDD_NUM_CMDS, NULL, "NONE" }
515 struct winbindd_async_dispatch_table {
516 enum winbindd_cmd cmd;
517 const char *cmd_name;
518 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
519 struct tevent_context *ev,
520 struct winbindd_cli_state *cli,
521 struct winbindd_request *request);
522 NTSTATUS (*recv_req)(struct tevent_req *req,
523 struct winbindd_response *presp);
526 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
527 { WINBINDD_PING, "PING",
528 wb_ping_send, wb_ping_recv },
529 { WINBINDD_LOOKUPSID, "LOOKUPSID",
530 winbindd_lookupsid_send, winbindd_lookupsid_recv },
531 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
532 winbindd_lookupsids_send, winbindd_lookupsids_recv },
533 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
534 winbindd_lookupname_send, winbindd_lookupname_recv },
535 { WINBINDD_SID_TO_UID, "SID_TO_UID",
536 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
537 { WINBINDD_SID_TO_GID, "SID_TO_GID",
538 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
539 { WINBINDD_UID_TO_SID, "UID_TO_SID",
540 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
541 { WINBINDD_GID_TO_SID, "GID_TO_SID",
542 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
543 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
544 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
545 { WINBINDD_GETPWSID, "GETPWSID",
546 winbindd_getpwsid_send, winbindd_getpwsid_recv },
547 { WINBINDD_GETPWNAM, "GETPWNAM",
548 winbindd_getpwnam_send, winbindd_getpwnam_recv },
549 { WINBINDD_GETPWUID, "GETPWUID",
550 winbindd_getpwuid_send, winbindd_getpwuid_recv },
551 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
552 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
553 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
554 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
555 { WINBINDD_GETGROUPS, "GETGROUPS",
556 winbindd_getgroups_send, winbindd_getgroups_recv },
557 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
558 winbindd_show_sequence_send, winbindd_show_sequence_recv },
559 { WINBINDD_GETGRGID, "GETGRGID",
560 winbindd_getgrgid_send, winbindd_getgrgid_recv },
561 { WINBINDD_GETGRNAM, "GETGRNAM",
562 winbindd_getgrnam_send, winbindd_getgrnam_recv },
563 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
564 winbindd_getusersids_send, winbindd_getusersids_recv },
565 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
566 winbindd_lookuprids_send, winbindd_lookuprids_recv },
567 { WINBINDD_SETPWENT, "SETPWENT",
568 winbindd_setpwent_send, winbindd_setpwent_recv },
569 { WINBINDD_GETPWENT, "GETPWENT",
570 winbindd_getpwent_send, winbindd_getpwent_recv },
571 { WINBINDD_ENDPWENT, "ENDPWENT",
572 winbindd_endpwent_send, winbindd_endpwent_recv },
573 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
574 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
575 { WINBINDD_GETDCNAME, "GETDCNAME",
576 winbindd_getdcname_send, winbindd_getdcname_recv },
577 { WINBINDD_SETGRENT, "SETGRENT",
578 winbindd_setgrent_send, winbindd_setgrent_recv },
579 { WINBINDD_GETGRENT, "GETGRENT",
580 winbindd_getgrent_send, winbindd_getgrent_recv },
581 { WINBINDD_ENDGRENT, "ENDGRENT",
582 winbindd_endgrent_send, winbindd_endgrent_recv },
583 { WINBINDD_LIST_USERS, "LIST_USERS",
584 winbindd_list_users_send, winbindd_list_users_recv },
585 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
586 winbindd_list_groups_send, winbindd_list_groups_recv },
587 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
588 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
589 { WINBINDD_PING_DC, "PING_DC",
590 winbindd_ping_dc_send, winbindd_ping_dc_recv },
591 { WINBINDD_PAM_AUTH, "PAM_AUTH",
592 winbindd_pam_auth_send, winbindd_pam_auth_recv },
593 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
594 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
595 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
596 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
597 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
598 winbindd_pam_chng_pswd_auth_crap_send,
599 winbindd_pam_chng_pswd_auth_crap_recv },
600 { WINBINDD_WINS_BYIP, "WINS_BYIP",
601 winbindd_wins_byip_send, winbindd_wins_byip_recv },
602 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
603 winbindd_wins_byname_send, winbindd_wins_byname_recv },
605 { 0, NULL, NULL, NULL }
608 static struct winbindd_async_dispatch_table async_priv_table[] = {
609 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
610 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
611 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
612 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
613 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
614 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
615 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
616 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
618 { 0, NULL, NULL, NULL }
621 static void wb_request_done(struct tevent_req *req);
623 static void process_request(struct winbindd_cli_state *state)
625 struct winbindd_dispatch_table *table = dispatch_table;
626 struct winbindd_async_dispatch_table *atable;
628 state->mem_ctx = talloc_named(state, 0, "winbind request");
629 if (state->mem_ctx == NULL)
630 return;
632 /* Remember who asked us. */
633 state->pid = state->request->pid;
635 state->cmd_name = "unknown request";
636 state->recv_fn = NULL;
637 state->last_access = time(NULL);
639 /* Process command */
641 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
642 if (state->request->cmd == atable->cmd) {
643 break;
647 if ((atable->send_req == NULL) && state->privileged) {
648 for (atable = async_priv_table; atable->send_req;
649 atable += 1) {
650 if (state->request->cmd == atable->cmd) {
651 break;
656 if (atable->send_req != NULL) {
657 struct tevent_req *req;
659 state->cmd_name = atable->cmd_name;
660 state->recv_fn = atable->recv_req;
662 DEBUG(10, ("process_request: Handling async request %d:%s\n",
663 (int)state->pid, state->cmd_name));
665 req = atable->send_req(state->mem_ctx, winbind_event_context(),
666 state, state->request);
667 if (req == NULL) {
668 DEBUG(0, ("process_request: atable->send failed for "
669 "%s\n", atable->cmd_name));
670 request_error(state);
671 return;
673 tevent_req_set_callback(req, wb_request_done, state);
674 return;
677 state->response = talloc_zero(state->mem_ctx,
678 struct winbindd_response);
679 if (state->response == NULL) {
680 DEBUG(10, ("talloc failed\n"));
681 remove_client(state);
682 return;
684 state->response->result = WINBINDD_PENDING;
685 state->response->length = sizeof(struct winbindd_response);
687 for (table = dispatch_table; table->fn; table++) {
688 if (state->request->cmd == table->cmd) {
689 DEBUG(10,("process_request: request fn %s\n",
690 table->winbindd_cmd_name ));
691 state->cmd_name = table->winbindd_cmd_name;
692 table->fn(state);
693 break;
697 if (!table->fn) {
698 DEBUG(10,("process_request: unknown request fn number %d\n",
699 (int)state->request->cmd ));
700 request_error(state);
704 static void wb_request_done(struct tevent_req *req)
706 struct winbindd_cli_state *state = tevent_req_callback_data(
707 req, struct winbindd_cli_state);
708 NTSTATUS status;
710 state->response = talloc_zero(state->mem_ctx,
711 struct winbindd_response);
712 if (state->response == NULL) {
713 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
714 (int)state->pid, state->cmd_name));
715 remove_client(state);
716 return;
718 state->response->result = WINBINDD_PENDING;
719 state->response->length = sizeof(struct winbindd_response);
721 status = state->recv_fn(req, state->response);
722 TALLOC_FREE(req);
724 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
725 (int)state->pid, state->cmd_name, nt_errstr(status)));
727 if (!NT_STATUS_IS_OK(status)) {
728 request_error(state);
729 return;
731 request_ok(state);
735 * This is the main event loop of winbind requests. It goes through a
736 * state-machine of 3 read/write requests, 4 if you have extra data to send.
738 * An idle winbind client has a read request of 4 bytes outstanding,
739 * finalizing function is request_len_recv, checking the length. request_recv
740 * then processes the packet. The processing function then at some point has
741 * to call request_finished which schedules sending the response.
744 static void request_finished(struct winbindd_cli_state *state);
746 static void winbind_client_request_read(struct tevent_req *req);
747 static void winbind_client_response_written(struct tevent_req *req);
749 static void request_finished(struct winbindd_cli_state *state)
751 struct tevent_req *req;
753 TALLOC_FREE(state->request);
755 req = wb_resp_write_send(state, winbind_event_context(),
756 state->out_queue, state->sock,
757 state->response);
758 if (req == NULL) {
759 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
760 (int)state->pid, state->cmd_name));
761 remove_client(state);
762 return;
764 tevent_req_set_callback(req, winbind_client_response_written, state);
767 static void winbind_client_response_written(struct tevent_req *req)
769 struct winbindd_cli_state *state = tevent_req_callback_data(
770 req, struct winbindd_cli_state);
771 ssize_t ret;
772 int err;
774 ret = wb_resp_write_recv(req, &err);
775 TALLOC_FREE(req);
776 if (ret == -1) {
777 close(state->sock);
778 state->sock = -1;
779 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
780 (int)state->pid, state->cmd_name, strerror(err)));
781 remove_client(state);
782 return;
785 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
786 "to client\n", (int)state->pid, state->cmd_name));
788 TALLOC_FREE(state->mem_ctx);
789 state->response = NULL;
790 state->cmd_name = "no request";
791 state->recv_fn = NULL;
793 req = wb_req_read_send(state, winbind_event_context(), state->sock,
794 WINBINDD_MAX_EXTRA_DATA);
795 if (req == NULL) {
796 remove_client(state);
797 return;
799 tevent_req_set_callback(req, winbind_client_request_read, state);
802 void request_error(struct winbindd_cli_state *state)
804 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
805 state->response->result = WINBINDD_ERROR;
806 request_finished(state);
809 void request_ok(struct winbindd_cli_state *state)
811 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
812 state->response->result = WINBINDD_OK;
813 request_finished(state);
816 /* Process a new connection by adding it to the client connection list */
818 static void new_connection(int listen_sock, bool privileged)
820 struct sockaddr_un sunaddr;
821 struct winbindd_cli_state *state;
822 struct tevent_req *req;
823 socklen_t len;
824 int sock;
826 /* Accept connection */
828 len = sizeof(sunaddr);
830 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
832 if (sock == -1) {
833 if (errno != EINTR) {
834 DEBUG(0, ("Faild to accept socket - %s\n",
835 strerror(errno)));
837 return;
840 DEBUG(6,("accepted socket %d\n", sock));
842 /* Create new connection structure */
844 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
845 close(sock);
846 return;
849 state->sock = sock;
851 state->out_queue = tevent_queue_create(state, "winbind client reply");
852 if (state->out_queue == NULL) {
853 close(sock);
854 TALLOC_FREE(state);
855 return;
858 state->last_access = time(NULL);
860 state->privileged = privileged;
862 req = wb_req_read_send(state, winbind_event_context(), state->sock,
863 WINBINDD_MAX_EXTRA_DATA);
864 if (req == NULL) {
865 TALLOC_FREE(state);
866 close(sock);
867 return;
869 tevent_req_set_callback(req, winbind_client_request_read, state);
871 /* Add to connection list */
873 winbindd_add_client(state);
876 static void winbind_client_request_read(struct tevent_req *req)
878 struct winbindd_cli_state *state = tevent_req_callback_data(
879 req, struct winbindd_cli_state);
880 ssize_t ret;
881 int err;
883 ret = wb_req_read_recv(req, state, &state->request, &err);
884 TALLOC_FREE(req);
885 if (ret == -1) {
886 if (err == EPIPE) {
887 DEBUG(6, ("closing socket %d, client exited\n",
888 state->sock));
889 } else {
890 DEBUG(2, ("Could not read client request from fd %d: "
891 "%s\n", state->sock, strerror(err)));
893 close(state->sock);
894 state->sock = -1;
895 remove_client(state);
896 return;
898 process_request(state);
901 /* Remove a client connection from client connection list */
903 static void remove_client(struct winbindd_cli_state *state)
905 char c = 0;
906 int nwritten;
908 /* It's a dead client - hold a funeral */
910 if (state == NULL) {
911 return;
914 if (state->sock != -1) {
915 /* tell client, we are closing ... */
916 nwritten = write(state->sock, &c, sizeof(c));
917 if (nwritten == -1) {
918 DEBUG(2, ("final write to client failed: %s\n",
919 strerror(errno)));
922 /* Close socket */
924 close(state->sock);
925 state->sock = -1;
928 TALLOC_FREE(state->mem_ctx);
930 /* Remove from list and free */
932 winbindd_remove_client(state);
933 TALLOC_FREE(state);
936 /* Is a client idle? */
938 static bool client_is_idle(struct winbindd_cli_state *state) {
939 return (state->request == NULL &&
940 state->response == NULL &&
941 !state->pwent_state && !state->grent_state);
944 /* Shutdown client connection which has been idle for the longest time */
946 static bool remove_idle_client(void)
948 struct winbindd_cli_state *state, *remove_state = NULL;
949 time_t last_access = 0;
950 int nidle = 0;
952 for (state = winbindd_client_list(); state; state = state->next) {
953 if (client_is_idle(state)) {
954 nidle++;
955 if (!last_access || state->last_access < last_access) {
956 last_access = state->last_access;
957 remove_state = state;
962 if (remove_state) {
963 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
964 nidle, remove_state->sock, (unsigned int)remove_state->pid));
965 remove_client(remove_state);
966 return True;
969 return False;
972 struct winbindd_listen_state {
973 bool privileged;
974 int fd;
977 static void winbindd_listen_fde_handler(struct tevent_context *ev,
978 struct tevent_fd *fde,
979 uint16_t flags,
980 void *private_data)
982 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
983 struct winbindd_listen_state);
985 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
986 DEBUG(5,("winbindd: Exceeding %d client "
987 "connections, removing idle "
988 "connection.\n", lp_winbind_max_clients()));
989 if (!remove_idle_client()) {
990 DEBUG(0,("winbindd: Exceeding %d "
991 "client connections, no idle "
992 "connection found\n",
993 lp_winbind_max_clients()));
994 break;
997 new_connection(s->fd, s->privileged);
1001 * Winbindd socket accessor functions
1004 const char *get_winbind_pipe_dir(void)
1006 return lp_parm_const_string(-1, "winbindd", "socket dir", get_dyn_WINBINDD_SOCKET_DIR());
1009 char *get_winbind_priv_pipe_dir(void)
1011 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1014 static bool winbindd_setup_listeners(void)
1016 struct winbindd_listen_state *pub_state = NULL;
1017 struct winbindd_listen_state *priv_state = NULL;
1018 struct tevent_fd *fde;
1019 int rc;
1021 pub_state = talloc(winbind_event_context(),
1022 struct winbindd_listen_state);
1023 if (!pub_state) {
1024 goto failed;
1027 pub_state->privileged = false;
1028 pub_state->fd = create_pipe_sock(
1029 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755);
1030 if (pub_state->fd == -1) {
1031 goto failed;
1033 rc = listen(pub_state->fd, 5);
1034 if (rc < 0) {
1035 goto failed;
1038 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1039 TEVENT_FD_READ, winbindd_listen_fde_handler,
1040 pub_state);
1041 if (fde == NULL) {
1042 close(pub_state->fd);
1043 goto failed;
1045 tevent_fd_set_auto_close(fde);
1047 priv_state = talloc(winbind_event_context(),
1048 struct winbindd_listen_state);
1049 if (!priv_state) {
1050 goto failed;
1053 priv_state->privileged = true;
1054 priv_state->fd = create_pipe_sock(
1055 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
1056 if (priv_state->fd == -1) {
1057 goto failed;
1059 rc = listen(priv_state->fd, 5);
1060 if (rc < 0) {
1061 goto failed;
1064 fde = tevent_add_fd(winbind_event_context(), priv_state,
1065 priv_state->fd, TEVENT_FD_READ,
1066 winbindd_listen_fde_handler, priv_state);
1067 if (fde == NULL) {
1068 close(priv_state->fd);
1069 goto failed;
1071 tevent_fd_set_auto_close(fde);
1073 return true;
1074 failed:
1075 TALLOC_FREE(pub_state);
1076 TALLOC_FREE(priv_state);
1077 return false;
1080 bool winbindd_use_idmap_cache(void)
1082 return !opt_nocache;
1085 bool winbindd_use_cache(void)
1087 return !opt_nocache;
1090 void winbindd_register_handlers(bool foreground)
1092 /* Setup signal handlers */
1094 if (!winbindd_setup_sig_term_handler(true))
1095 exit(1);
1096 if (!winbindd_setup_stdin_handler(true, foreground))
1097 exit(1);
1098 if (!winbindd_setup_sig_hup_handler(NULL))
1099 exit(1);
1100 if (!winbindd_setup_sig_chld_handler())
1101 exit(1);
1102 if (!winbindd_setup_sig_usr2_handler())
1103 exit(1);
1105 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1108 * Ensure all cache and idmap caches are consistent
1109 * and initialized before we startup.
1111 if (!winbindd_cache_validate_and_initialize()) {
1112 exit(1);
1115 /* get broadcast messages */
1117 if (!serverid_register(procid_self(),
1118 FLAG_MSG_GENERAL |
1119 FLAG_MSG_WINBIND |
1120 FLAG_MSG_DBWRAP)) {
1121 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1122 exit(1);
1125 /* React on 'smbcontrol winbindd reload-config' in the same way
1126 as to SIGHUP signal */
1127 messaging_register(winbind_messaging_context(), NULL,
1128 MSG_SMB_CONF_UPDATED, msg_reload_services);
1129 messaging_register(winbind_messaging_context(), NULL,
1130 MSG_SHUTDOWN, msg_shutdown);
1132 /* Handle online/offline messages. */
1133 messaging_register(winbind_messaging_context(), NULL,
1134 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1135 messaging_register(winbind_messaging_context(), NULL,
1136 MSG_WINBIND_ONLINE, winbind_msg_online);
1137 messaging_register(winbind_messaging_context(), NULL,
1138 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1140 /* Handle domain online/offline messages for domains */
1141 messaging_register(winbind_messaging_context(), NULL,
1142 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1143 messaging_register(winbind_messaging_context(), NULL,
1144 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1146 messaging_register(winbind_messaging_context(), NULL,
1147 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1149 messaging_register(winbind_messaging_context(), NULL,
1150 MSG_WINBIND_VALIDATE_CACHE,
1151 winbind_msg_validate_cache);
1153 messaging_register(winbind_messaging_context(), NULL,
1154 MSG_WINBIND_DUMP_DOMAIN_LIST,
1155 winbind_msg_dump_domain_list);
1157 messaging_register(winbind_messaging_context(), NULL,
1158 MSG_WINBIND_IP_DROPPED,
1159 winbind_msg_ip_dropped_parent);
1161 /* Register handler for MSG_DEBUG. */
1162 messaging_register(winbind_messaging_context(), NULL,
1163 MSG_DEBUG,
1164 winbind_msg_debug);
1166 netsamlogon_cache_init(); /* Non-critical */
1168 /* clear the cached list of trusted domains */
1170 wcache_tdc_clear();
1172 if (!init_domain_list()) {
1173 DEBUG(0,("unable to initialize domain list\n"));
1174 exit(1);
1177 init_idmap_child();
1178 init_locator_child();
1180 smb_nscd_flush_user_cache();
1181 smb_nscd_flush_group_cache();
1183 if (lp_allow_trusted_domains()) {
1184 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1185 rescan_trusted_domains, NULL) == NULL) {
1186 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1187 exit(1);
1193 struct winbindd_addrchanged_state {
1194 struct addrchange_context *ctx;
1195 struct tevent_context *ev;
1196 struct messaging_context *msg_ctx;
1199 static void winbindd_addr_changed(struct tevent_req *req);
1201 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1202 struct tevent_context *ev,
1203 struct messaging_context *msg_ctx)
1205 struct winbindd_addrchanged_state *state;
1206 struct tevent_req *req;
1207 NTSTATUS status;
1209 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1210 if (state == NULL) {
1211 DEBUG(10, ("talloc failed\n"));
1212 return;
1214 state->ev = ev;
1215 state->msg_ctx = msg_ctx;
1217 status = addrchange_context_create(state, &state->ctx);
1218 if (!NT_STATUS_IS_OK(status)) {
1219 DEBUG(10, ("addrchange_context_create failed: %s\n",
1220 nt_errstr(status)));
1221 TALLOC_FREE(state);
1222 return;
1224 req = addrchange_send(state, ev, state->ctx);
1225 if (req == NULL) {
1226 DEBUG(0, ("addrchange_send failed\n"));
1227 TALLOC_FREE(state);
1228 return;
1230 tevent_req_set_callback(req, winbindd_addr_changed, state);
1233 static void winbindd_addr_changed(struct tevent_req *req)
1235 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1236 req, struct winbindd_addrchanged_state);
1237 enum addrchange_type type;
1238 struct sockaddr_storage addr;
1239 NTSTATUS status;
1241 status = addrchange_recv(req, &type, &addr);
1242 TALLOC_FREE(req);
1243 if (!NT_STATUS_IS_OK(status)) {
1244 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1245 nt_errstr(status)));
1246 TALLOC_FREE(state);
1247 return;
1249 if (type == ADDRCHANGE_DEL) {
1250 char addrstr[INET6_ADDRSTRLEN];
1251 DATA_BLOB blob;
1253 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1255 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1256 addrstr));
1258 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1260 status = messaging_send(state->msg_ctx,
1261 messaging_server_id(state->msg_ctx),
1262 MSG_WINBIND_IP_DROPPED, &blob);
1263 if (!NT_STATUS_IS_OK(status)) {
1264 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1265 nt_errstr(status)));
1268 req = addrchange_send(state, state->ev, state->ctx);
1269 if (req == NULL) {
1270 DEBUG(0, ("addrchange_send failed\n"));
1271 TALLOC_FREE(state);
1272 return;
1274 tevent_req_set_callback(req, winbindd_addr_changed, state);
1277 /* Main function */
1279 int main(int argc, char **argv, char **envp)
1281 static bool is_daemon = False;
1282 static bool Fork = True;
1283 static bool log_stdout = False;
1284 static bool no_process_group = False;
1285 enum {
1286 OPT_DAEMON = 1000,
1287 OPT_FORK,
1288 OPT_NO_PROCESS_GROUP,
1289 OPT_LOG_STDOUT
1291 struct poptOption long_options[] = {
1292 POPT_AUTOHELP
1293 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1294 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1295 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1296 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1297 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1298 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1299 POPT_COMMON_SAMBA
1300 POPT_TABLEEND
1302 poptContext pc;
1303 int opt;
1304 TALLOC_CTX *frame;
1305 NTSTATUS status;
1308 * Do this before any other talloc operation
1310 talloc_enable_null_tracking();
1311 frame = talloc_stackframe();
1313 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1315 /* glibc (?) likes to print "User defined signal 1" and exit if a
1316 SIGUSR[12] is received before a handler is installed */
1318 CatchSignal(SIGUSR1, SIG_IGN);
1319 CatchSignal(SIGUSR2, SIG_IGN);
1321 fault_setup();
1322 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1324 load_case_tables();
1326 /* Initialise for running in non-root mode */
1328 sec_init();
1330 set_remote_machine_name("winbindd", False);
1332 /* Set environment variable so we don't recursively call ourselves.
1333 This may also be useful interactively. */
1335 if ( !winbind_off() ) {
1336 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1337 exit(1);
1340 /* Initialise samba/rpc client stuff */
1342 pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, 0);
1344 while ((opt = poptGetNextOpt(pc)) != -1) {
1345 switch (opt) {
1346 /* Don't become a daemon */
1347 case OPT_DAEMON:
1348 is_daemon = True;
1349 break;
1350 case 'i':
1351 interactive = True;
1352 log_stdout = True;
1353 Fork = False;
1354 break;
1355 case OPT_FORK:
1356 Fork = false;
1357 break;
1358 case OPT_NO_PROCESS_GROUP:
1359 no_process_group = true;
1360 break;
1361 case OPT_LOG_STDOUT:
1362 log_stdout = true;
1363 break;
1364 case 'n':
1365 opt_nocache = true;
1366 break;
1367 default:
1368 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1369 poptBadOption(pc, 0), poptStrerror(opt));
1370 poptPrintUsage(pc, stderr, 0);
1371 exit(1);
1375 /* We call dump_core_setup one more time because the command line can
1376 * set the log file or the log-basename and this will influence where
1377 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1378 * the default value derived from build's prefix. For EOM this value
1379 * is often not related to the path where winbindd is actually run
1380 * in production.
1382 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1383 if (is_daemon && interactive) {
1384 d_fprintf(stderr,"\nERROR: "
1385 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1386 poptPrintUsage(pc, stderr, 0);
1387 exit(1);
1390 if (log_stdout && Fork) {
1391 d_fprintf(stderr, "\nERROR: "
1392 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1393 poptPrintUsage(pc, stderr, 0);
1394 exit(1);
1397 poptFreeContext(pc);
1399 if (!override_logfile) {
1400 char *lfile = NULL;
1401 if (asprintf(&lfile,"%s/log.winbindd",
1402 get_dyn_LOGFILEBASE()) > 0) {
1403 lp_set_logfile(lfile);
1404 SAFE_FREE(lfile);
1408 if (log_stdout) {
1409 setup_logging("winbindd", DEBUG_STDOUT);
1410 } else {
1411 setup_logging("winbindd", DEBUG_FILE);
1413 reopen_logs();
1415 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1416 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1418 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1419 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1420 exit(1);
1422 /* After parsing the configuration file we setup the core path one more time
1423 * as the log file might have been set in the configuration and cores's
1424 * path is by default basename(lp_logfile()).
1426 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1428 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1429 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1430 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"));
1431 exit(1);
1434 /* Initialise messaging system */
1436 if (winbind_messaging_context() == NULL) {
1437 exit(1);
1440 if (!reload_services_file(NULL)) {
1441 DEBUG(0, ("error opening config file\n"));
1442 exit(1);
1445 if (!directory_exist(lp_lockdir())) {
1446 mkdir(lp_lockdir(), 0755);
1449 if (!directory_exist(lp_piddir())) {
1450 mkdir(lp_piddir(), 0755);
1453 /* Setup names. */
1455 if (!init_names())
1456 exit(1);
1458 load_interfaces();
1460 if (!secrets_init()) {
1462 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1463 return False;
1466 /* Unblock all signals we are interested in as they may have been
1467 blocked by the parent process. */
1469 BlockSignals(False, SIGINT);
1470 BlockSignals(False, SIGQUIT);
1471 BlockSignals(False, SIGTERM);
1472 BlockSignals(False, SIGUSR1);
1473 BlockSignals(False, SIGUSR2);
1474 BlockSignals(False, SIGHUP);
1475 BlockSignals(False, SIGCHLD);
1477 if (!interactive)
1478 become_daemon(Fork, no_process_group, log_stdout);
1480 pidfile_create(lp_piddir(), "winbindd");
1482 #if HAVE_SETPGID
1484 * If we're interactive we want to set our own process group for
1485 * signal management.
1487 if (interactive && !no_process_group)
1488 setpgid( (pid_t)0, (pid_t)0);
1489 #endif
1491 TimeInit();
1493 /* Don't use winbindd_reinit_after_fork here as
1494 * we're just starting up and haven't created any
1495 * winbindd-specific resources we must free yet. JRA.
1498 status = reinit_after_fork(winbind_messaging_context(),
1499 winbind_event_context(),
1500 false);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 DEBUG(0,("reinit_after_fork() failed\n"));
1503 exit(1);
1507 * Do not initialize the parent-child-pipe before becoming
1508 * a daemon: this is used to detect a died parent in the child
1509 * process.
1511 status = init_before_fork();
1512 if (!NT_STATUS_IS_OK(status)) {
1513 DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status)));
1514 exit(1);
1517 winbindd_register_handlers(!Fork);
1519 status = init_system_session_info();
1520 if (!NT_STATUS_IS_OK(status)) {
1521 DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
1522 nt_errstr(status)));
1523 exit(1);
1526 rpc_lsarpc_init(NULL);
1527 rpc_samr_init(NULL);
1529 winbindd_init_addrchange(NULL, winbind_event_context(),
1530 winbind_messaging_context());
1532 /* setup listen sockets */
1534 if (!winbindd_setup_listeners()) {
1535 DEBUG(0,("winbindd_setup_listeners() failed\n"));
1536 exit(1);
1539 TALLOC_FREE(frame);
1540 /* Loop waiting for requests */
1541 while (1) {
1542 frame = talloc_stackframe();
1544 if (tevent_loop_once(winbind_event_context()) == -1) {
1545 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1546 strerror(errno)));
1547 return 1;
1550 TALLOC_FREE(frame);
1553 return 0;