librpc/idl: Merge wbint.idl with winbind.idl so we can forward IRPC requests to inter...
[Samba/wip.git] / source3 / winbindd / winbindd.c
blobb9bf8be812ae42b8ad13eda6c870ece6050880a3
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 "rpc_client/cli_netlogon.h"
35 #include "idmap.h"
36 #include "lib/addrchange.h"
37 #include "serverid.h"
38 #include "auth.h"
39 #include "messages.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 "librpc/gen_ndr/ndr_winbind.h"
47 #undef DBGC_CLASS
48 #define DBGC_CLASS DBGC_WINBIND
50 static bool client_is_idle(struct winbindd_cli_state *state);
51 static void remove_client(struct winbindd_cli_state *state);
53 static bool opt_nocache = False;
54 static bool interactive = False;
56 extern bool override_logfile;
58 struct tevent_context *winbind_event_context(void)
60 static struct tevent_context *ev = NULL;
62 if (ev != NULL) {
63 return ev;
67 * Note we MUST use the NULL context here, not the autofree context,
68 * to avoid side effects in forked children exiting.
70 ev = samba_tevent_context_init(NULL);
71 if (ev == NULL) {
72 smb_panic("Could not init winbindd's messaging context.\n");
74 return ev;
77 struct messaging_context *winbind_messaging_context(void)
79 static struct messaging_context *msg = NULL;
81 if (msg != NULL) {
82 return msg;
86 * Note we MUST use the NULL context here, not the autofree context,
87 * to avoid side effects in forked children exiting.
89 msg = messaging_init(NULL, winbind_event_context());
90 if (msg == NULL) {
91 smb_panic("Could not init winbindd's messaging context.\n");
93 return msg;
96 struct imessaging_context *winbind_imessaging_context(void)
98 static struct imessaging_context *msg = NULL;
99 struct loadparm_context *lp_ctx;
101 if (msg != NULL) {
102 return msg;
105 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
106 if (lp_ctx == NULL) {
107 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
111 * Note we MUST use the NULL context here, not the autofree context,
112 * to avoid side effects in forked children exiting.
114 msg = imessaging_init(NULL, lp_ctx, procid_self(), winbind_event_context(), false);
115 talloc_unlink(NULL, lp_ctx);
117 if (msg == NULL) {
118 smb_panic("Could not init winbindd's messaging context.\n");
120 return msg;
123 /* Reload configuration */
125 static bool reload_services_file(const char *lfile)
127 bool ret;
129 if (lp_loaded()) {
130 char *fname = lp_next_configfile(talloc_tos());
132 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
133 set_dyn_CONFIGFILE(fname);
135 TALLOC_FREE(fname);
138 /* if this is a child, restore the logfile to the special
139 name - <domain>, idmap, etc. */
140 if (lfile && *lfile) {
141 lp_set_logfile(lfile);
144 reopen_logs();
145 ret = lp_load_global(get_dyn_CONFIGFILE());
147 reopen_logs();
148 load_interfaces();
150 return(ret);
154 static void winbindd_status(void)
156 struct winbindd_cli_state *tmp;
158 DEBUG(0, ("winbindd status:\n"));
160 /* Print client state information */
162 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
164 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
165 DEBUG(2, ("\tclient list:\n"));
166 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
167 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
168 (unsigned long)tmp->pid, tmp->sock,
169 client_is_idle(tmp) ? "idle" : "active"));
174 /* Flush client cache */
176 static void flush_caches(void)
178 /* We need to invalidate cached user list entries on a SIGHUP
179 otherwise cached access denied errors due to restrict anonymous
180 hang around until the sequence number changes. */
182 if (!wcache_invalidate_cache()) {
183 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
184 if (!winbindd_cache_validate_and_initialize()) {
185 exit(1);
190 static void flush_caches_noinit(void)
193 * We need to invalidate cached user list entries on a SIGHUP
194 * otherwise cached access denied errors due to restrict anonymous
195 * hang around until the sequence number changes.
196 * NB
197 * Skip uninitialized domains when flush cache.
198 * If domain is not initialized, it means it is never
199 * used or never become online. look, wcache_invalidate_cache()
200 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
201 * for unused domains and large traffic for primay domain's DC if there
202 * are many domains..
205 if (!wcache_invalidate_cache_noinit()) {
206 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
207 if (!winbindd_cache_validate_and_initialize()) {
208 exit(1);
213 /* Handle the signal by unlinking socket and exiting */
215 static void terminate(bool is_parent)
217 if (is_parent) {
218 /* When parent goes away we should
219 * remove the socket file. Not so
220 * when children terminate.
222 char *path = NULL;
224 if (asprintf(&path, "%s/%s",
225 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
226 unlink(path);
227 SAFE_FREE(path);
231 idmap_close();
233 trustdom_cache_shutdown();
235 gencache_stabilize();
237 #if 0
238 if (interactive) {
239 TALLOC_CTX *mem_ctx = talloc_init("end_description");
240 char *description = talloc_describe_all(mem_ctx);
242 DEBUG(3, ("tallocs left:\n%s\n", description));
243 talloc_destroy(mem_ctx);
245 #endif
247 if (is_parent) {
248 struct messaging_context *msg = winbind_messaging_context();
249 struct server_id self = messaging_server_id(msg);
250 serverid_deregister(self);
251 pidfile_unlink(lp_pid_directory(), "winbindd");
254 exit(0);
257 static void winbindd_sig_term_handler(struct tevent_context *ev,
258 struct tevent_signal *se,
259 int signum,
260 int count,
261 void *siginfo,
262 void *private_data)
264 bool *is_parent = talloc_get_type_abort(private_data, bool);
266 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
267 signum, (int)*is_parent));
268 terminate(*is_parent);
272 handle stdin becoming readable when we are in --foreground mode
274 static void winbindd_stdin_handler(struct tevent_context *ev,
275 struct tevent_fd *fde,
276 uint16_t flags,
277 void *private_data)
279 char c;
280 if (read(0, &c, 1) != 1) {
281 bool *is_parent = talloc_get_type_abort(private_data, bool);
283 /* we have reached EOF on stdin, which means the
284 parent has exited. Shutdown the server */
285 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
286 (int)*is_parent));
287 terminate(*is_parent);
291 bool winbindd_setup_sig_term_handler(bool parent)
293 struct tevent_signal *se;
294 bool *is_parent;
296 is_parent = talloc(winbind_event_context(), bool);
297 if (!is_parent) {
298 return false;
301 *is_parent = parent;
303 se = tevent_add_signal(winbind_event_context(),
304 is_parent,
305 SIGTERM, 0,
306 winbindd_sig_term_handler,
307 is_parent);
308 if (!se) {
309 DEBUG(0,("failed to setup SIGTERM handler"));
310 talloc_free(is_parent);
311 return false;
314 se = tevent_add_signal(winbind_event_context(),
315 is_parent,
316 SIGINT, 0,
317 winbindd_sig_term_handler,
318 is_parent);
319 if (!se) {
320 DEBUG(0,("failed to setup SIGINT handler"));
321 talloc_free(is_parent);
322 return false;
325 se = tevent_add_signal(winbind_event_context(),
326 is_parent,
327 SIGQUIT, 0,
328 winbindd_sig_term_handler,
329 is_parent);
330 if (!se) {
331 DEBUG(0,("failed to setup SIGINT handler"));
332 talloc_free(is_parent);
333 return false;
336 return true;
339 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
341 bool *is_parent;
343 if (foreground) {
344 struct stat st;
346 is_parent = talloc(winbind_event_context(), bool);
347 if (!is_parent) {
348 return false;
351 *is_parent = parent;
353 /* if we are running in the foreground then look for
354 EOF on stdin, and exit if it happens. This allows
355 us to die if the parent process dies
356 Only do this on a pipe or socket, no other device.
358 if (fstat(0, &st) != 0) {
359 return false;
361 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
362 tevent_add_fd(winbind_event_context(),
363 is_parent,
365 TEVENT_FD_READ,
366 winbindd_stdin_handler,
367 is_parent);
371 return true;
374 static void winbindd_sig_hup_handler(struct tevent_context *ev,
375 struct tevent_signal *se,
376 int signum,
377 int count,
378 void *siginfo,
379 void *private_data)
381 const char *file = (const char *)private_data;
383 DEBUG(1,("Reloading services after SIGHUP\n"));
384 flush_caches_noinit();
385 reload_services_file(file);
388 bool winbindd_setup_sig_hup_handler(const char *lfile)
390 struct tevent_signal *se;
391 char *file = NULL;
393 if (lfile) {
394 file = talloc_strdup(winbind_event_context(),
395 lfile);
396 if (!file) {
397 return false;
401 se = tevent_add_signal(winbind_event_context(),
402 winbind_event_context(),
403 SIGHUP, 0,
404 winbindd_sig_hup_handler,
405 file);
406 if (!se) {
407 return false;
410 return true;
413 static void winbindd_sig_chld_handler(struct tevent_context *ev,
414 struct tevent_signal *se,
415 int signum,
416 int count,
417 void *siginfo,
418 void *private_data)
420 pid_t pid;
422 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
423 winbind_child_died(pid);
427 static bool winbindd_setup_sig_chld_handler(void)
429 struct tevent_signal *se;
431 se = tevent_add_signal(winbind_event_context(),
432 winbind_event_context(),
433 SIGCHLD, 0,
434 winbindd_sig_chld_handler,
435 NULL);
436 if (!se) {
437 return false;
440 return true;
443 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
444 struct tevent_signal *se,
445 int signum,
446 int count,
447 void *siginfo,
448 void *private_data)
450 winbindd_status();
453 static bool winbindd_setup_sig_usr2_handler(void)
455 struct tevent_signal *se;
457 se = tevent_add_signal(winbind_event_context(),
458 winbind_event_context(),
459 SIGUSR2, 0,
460 winbindd_sig_usr2_handler,
461 NULL);
462 if (!se) {
463 return false;
466 return true;
469 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
470 static void msg_reload_services(struct messaging_context *msg,
471 void *private_data,
472 uint32_t msg_type,
473 struct server_id server_id,
474 DATA_BLOB *data)
476 /* Flush various caches */
477 flush_caches();
478 reload_services_file((const char *) private_data);
481 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
482 static void msg_shutdown(struct messaging_context *msg,
483 void *private_data,
484 uint32_t msg_type,
485 struct server_id server_id,
486 DATA_BLOB *data)
488 /* only the parent waits for this message */
489 DEBUG(0,("Got shutdown message\n"));
490 terminate(true);
494 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
495 void *private_data,
496 uint32_t msg_type,
497 struct server_id server_id,
498 DATA_BLOB *data)
500 uint8 ret;
501 pid_t child_pid;
502 NTSTATUS status;
504 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
505 "message.\n"));
508 * call the validation code from a child:
509 * so we don't block the main winbindd and the validation
510 * code can safely use fork/waitpid...
512 child_pid = fork();
514 if (child_pid == -1) {
515 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
516 strerror(errno)));
517 return;
520 if (child_pid != 0) {
521 /* parent */
522 DEBUG(5, ("winbind_msg_validate_cache: child created with "
523 "pid %d.\n", (int)child_pid));
524 return;
527 /* child */
529 status = winbindd_reinit_after_fork(NULL, NULL);
530 if (!NT_STATUS_IS_OK(status)) {
531 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
532 nt_errstr(status)));
533 _exit(0);
536 /* install default SIGCHLD handler: validation code uses fork/waitpid */
537 CatchSignal(SIGCHLD, SIG_DFL);
539 ret = (uint8)winbindd_validate_cache_nobackup();
540 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
541 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
542 (size_t)1);
543 _exit(0);
546 static struct winbindd_dispatch_table {
547 enum winbindd_cmd cmd;
548 void (*fn)(struct winbindd_cli_state *state);
549 const char *winbindd_cmd_name;
550 } dispatch_table[] = {
552 /* Enumeration functions */
554 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
555 "LIST_TRUSTDOM" },
557 /* Miscellaneous */
559 { WINBINDD_INFO, winbindd_info, "INFO" },
560 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
561 "INTERFACE_VERSION" },
562 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
563 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
564 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
565 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
566 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
567 "WINBINDD_PRIV_PIPE_DIR" },
569 /* Credential cache access */
570 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
571 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
573 /* End of list */
575 { WINBINDD_NUM_CMDS, NULL, "NONE" }
578 struct winbindd_async_dispatch_table {
579 enum winbindd_cmd cmd;
580 const char *cmd_name;
581 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
582 struct tevent_context *ev,
583 struct winbindd_cli_state *cli,
584 struct winbindd_request *request);
585 NTSTATUS (*recv_req)(struct tevent_req *req,
586 struct winbindd_response *presp);
589 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
590 { WINBINDD_PING, "PING",
591 wb_ping_send, wb_ping_recv },
592 { WINBINDD_LOOKUPSID, "LOOKUPSID",
593 winbindd_lookupsid_send, winbindd_lookupsid_recv },
594 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
595 winbindd_lookupsids_send, winbindd_lookupsids_recv },
596 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
597 winbindd_lookupname_send, winbindd_lookupname_recv },
598 { WINBINDD_SID_TO_UID, "SID_TO_UID",
599 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
600 { WINBINDD_SID_TO_GID, "SID_TO_GID",
601 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
602 { WINBINDD_UID_TO_SID, "UID_TO_SID",
603 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
604 { WINBINDD_GID_TO_SID, "GID_TO_SID",
605 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
606 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
607 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
608 { WINBINDD_GETPWSID, "GETPWSID",
609 winbindd_getpwsid_send, winbindd_getpwsid_recv },
610 { WINBINDD_GETPWNAM, "GETPWNAM",
611 winbindd_getpwnam_send, winbindd_getpwnam_recv },
612 { WINBINDD_GETPWUID, "GETPWUID",
613 winbindd_getpwuid_send, winbindd_getpwuid_recv },
614 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
615 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
616 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
617 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
618 { WINBINDD_GETGROUPS, "GETGROUPS",
619 winbindd_getgroups_send, winbindd_getgroups_recv },
620 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
621 winbindd_show_sequence_send, winbindd_show_sequence_recv },
622 { WINBINDD_GETGRGID, "GETGRGID",
623 winbindd_getgrgid_send, winbindd_getgrgid_recv },
624 { WINBINDD_GETGRNAM, "GETGRNAM",
625 winbindd_getgrnam_send, winbindd_getgrnam_recv },
626 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
627 winbindd_getusersids_send, winbindd_getusersids_recv },
628 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
629 winbindd_lookuprids_send, winbindd_lookuprids_recv },
630 { WINBINDD_SETPWENT, "SETPWENT",
631 winbindd_setpwent_send, winbindd_setpwent_recv },
632 { WINBINDD_GETPWENT, "GETPWENT",
633 winbindd_getpwent_send, winbindd_getpwent_recv },
634 { WINBINDD_ENDPWENT, "ENDPWENT",
635 winbindd_endpwent_send, winbindd_endpwent_recv },
636 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
637 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
638 { WINBINDD_GETDCNAME, "GETDCNAME",
639 winbindd_getdcname_send, winbindd_getdcname_recv },
640 { WINBINDD_SETGRENT, "SETGRENT",
641 winbindd_setgrent_send, winbindd_setgrent_recv },
642 { WINBINDD_GETGRENT, "GETGRENT",
643 winbindd_getgrent_send, winbindd_getgrent_recv },
644 { WINBINDD_ENDGRENT, "ENDGRENT",
645 winbindd_endgrent_send, winbindd_endgrent_recv },
646 { WINBINDD_LIST_USERS, "LIST_USERS",
647 winbindd_list_users_send, winbindd_list_users_recv },
648 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
649 winbindd_list_groups_send, winbindd_list_groups_recv },
650 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
651 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
652 { WINBINDD_PING_DC, "PING_DC",
653 winbindd_ping_dc_send, winbindd_ping_dc_recv },
654 { WINBINDD_PAM_AUTH, "PAM_AUTH",
655 winbindd_pam_auth_send, winbindd_pam_auth_recv },
656 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
657 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
658 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
659 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
660 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
661 winbindd_pam_chng_pswd_auth_crap_send,
662 winbindd_pam_chng_pswd_auth_crap_recv },
663 { WINBINDD_WINS_BYIP, "WINS_BYIP",
664 winbindd_wins_byip_send, winbindd_wins_byip_recv },
665 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
666 winbindd_wins_byname_send, winbindd_wins_byname_recv },
668 { 0, NULL, NULL, NULL }
671 static struct winbindd_async_dispatch_table async_priv_table[] = {
672 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
673 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
674 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
675 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
676 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
677 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
678 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
679 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
681 { 0, NULL, NULL, NULL }
684 static void wb_request_done(struct tevent_req *req);
686 static void process_request(struct winbindd_cli_state *state)
688 struct winbindd_dispatch_table *table = dispatch_table;
689 struct winbindd_async_dispatch_table *atable;
691 state->mem_ctx = talloc_named(state, 0, "winbind request");
692 if (state->mem_ctx == NULL)
693 return;
695 /* Remember who asked us. */
696 state->pid = state->request->pid;
698 state->cmd_name = "unknown request";
699 state->recv_fn = NULL;
700 state->last_access = time(NULL);
702 /* Process command */
704 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
705 if (state->request->cmd == atable->cmd) {
706 break;
710 if ((atable->send_req == NULL) && state->privileged) {
711 for (atable = async_priv_table; atable->send_req;
712 atable += 1) {
713 if (state->request->cmd == atable->cmd) {
714 break;
719 if (atable->send_req != NULL) {
720 struct tevent_req *req;
722 state->cmd_name = atable->cmd_name;
723 state->recv_fn = atable->recv_req;
725 DEBUG(10, ("process_request: Handling async request %d:%s\n",
726 (int)state->pid, state->cmd_name));
728 req = atable->send_req(state->mem_ctx, winbind_event_context(),
729 state, state->request);
730 if (req == NULL) {
731 DEBUG(0, ("process_request: atable->send failed for "
732 "%s\n", atable->cmd_name));
733 request_error(state);
734 return;
736 tevent_req_set_callback(req, wb_request_done, state);
737 return;
740 state->response = talloc_zero(state->mem_ctx,
741 struct winbindd_response);
742 if (state->response == NULL) {
743 DEBUG(10, ("talloc failed\n"));
744 remove_client(state);
745 return;
747 state->response->result = WINBINDD_PENDING;
748 state->response->length = sizeof(struct winbindd_response);
750 for (table = dispatch_table; table->fn; table++) {
751 if (state->request->cmd == table->cmd) {
752 DEBUG(10,("process_request: request fn %s\n",
753 table->winbindd_cmd_name ));
754 state->cmd_name = table->winbindd_cmd_name;
755 table->fn(state);
756 break;
760 if (!table->fn) {
761 DEBUG(10,("process_request: unknown request fn number %d\n",
762 (int)state->request->cmd ));
763 request_error(state);
767 static void wb_request_done(struct tevent_req *req)
769 struct winbindd_cli_state *state = tevent_req_callback_data(
770 req, struct winbindd_cli_state);
771 NTSTATUS status;
773 state->response = talloc_zero(state->mem_ctx,
774 struct winbindd_response);
775 if (state->response == NULL) {
776 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
777 (int)state->pid, state->cmd_name));
778 remove_client(state);
779 return;
781 state->response->result = WINBINDD_PENDING;
782 state->response->length = sizeof(struct winbindd_response);
784 status = state->recv_fn(req, state->response);
785 TALLOC_FREE(req);
787 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
788 (int)state->pid, state->cmd_name, nt_errstr(status)));
790 if (!NT_STATUS_IS_OK(status)) {
791 request_error(state);
792 return;
794 request_ok(state);
798 * This is the main event loop of winbind requests. It goes through a
799 * state-machine of 3 read/write requests, 4 if you have extra data to send.
801 * An idle winbind client has a read request of 4 bytes outstanding,
802 * finalizing function is request_len_recv, checking the length. request_recv
803 * then processes the packet. The processing function then at some point has
804 * to call request_finished which schedules sending the response.
807 static void request_finished(struct winbindd_cli_state *state);
809 static void winbind_client_request_read(struct tevent_req *req);
810 static void winbind_client_response_written(struct tevent_req *req);
812 static void request_finished(struct winbindd_cli_state *state)
814 struct tevent_req *req;
816 TALLOC_FREE(state->request);
818 req = wb_resp_write_send(state, winbind_event_context(),
819 state->out_queue, state->sock,
820 state->response);
821 if (req == NULL) {
822 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
823 (int)state->pid, state->cmd_name));
824 remove_client(state);
825 return;
827 tevent_req_set_callback(req, winbind_client_response_written, state);
830 static void winbind_client_response_written(struct tevent_req *req)
832 struct winbindd_cli_state *state = tevent_req_callback_data(
833 req, struct winbindd_cli_state);
834 ssize_t ret;
835 int err;
837 ret = wb_resp_write_recv(req, &err);
838 TALLOC_FREE(req);
839 if (ret == -1) {
840 close(state->sock);
841 state->sock = -1;
842 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
843 (int)state->pid, state->cmd_name, strerror(err)));
844 remove_client(state);
845 return;
848 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
849 "to client\n", (int)state->pid, state->cmd_name));
851 TALLOC_FREE(state->mem_ctx);
852 state->response = NULL;
853 state->cmd_name = "no request";
854 state->recv_fn = NULL;
856 req = wb_req_read_send(state, winbind_event_context(), state->sock,
857 WINBINDD_MAX_EXTRA_DATA);
858 if (req == NULL) {
859 remove_client(state);
860 return;
862 tevent_req_set_callback(req, winbind_client_request_read, state);
865 void request_error(struct winbindd_cli_state *state)
867 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
868 state->response->result = WINBINDD_ERROR;
869 request_finished(state);
872 void request_ok(struct winbindd_cli_state *state)
874 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
875 state->response->result = WINBINDD_OK;
876 request_finished(state);
879 /* Process a new connection by adding it to the client connection list */
881 static void new_connection(int listen_sock, bool privileged)
883 struct sockaddr_un sunaddr;
884 struct winbindd_cli_state *state;
885 struct tevent_req *req;
886 socklen_t len;
887 int sock;
889 /* Accept connection */
891 len = sizeof(sunaddr);
893 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
895 if (sock == -1) {
896 if (errno != EINTR) {
897 DEBUG(0, ("Failed to accept socket - %s\n",
898 strerror(errno)));
900 return;
903 DEBUG(6,("accepted socket %d\n", sock));
905 /* Create new connection structure */
907 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
908 close(sock);
909 return;
912 state->sock = sock;
914 state->out_queue = tevent_queue_create(state, "winbind client reply");
915 if (state->out_queue == NULL) {
916 close(sock);
917 TALLOC_FREE(state);
918 return;
921 state->last_access = time(NULL);
923 state->privileged = privileged;
925 req = wb_req_read_send(state, winbind_event_context(), state->sock,
926 WINBINDD_MAX_EXTRA_DATA);
927 if (req == NULL) {
928 TALLOC_FREE(state);
929 close(sock);
930 return;
932 tevent_req_set_callback(req, winbind_client_request_read, state);
934 /* Add to connection list */
936 winbindd_add_client(state);
939 static void winbind_client_request_read(struct tevent_req *req)
941 struct winbindd_cli_state *state = tevent_req_callback_data(
942 req, struct winbindd_cli_state);
943 ssize_t ret;
944 int err;
946 ret = wb_req_read_recv(req, state, &state->request, &err);
947 TALLOC_FREE(req);
948 if (ret == -1) {
949 if (err == EPIPE) {
950 DEBUG(6, ("closing socket %d, client exited\n",
951 state->sock));
952 } else {
953 DEBUG(2, ("Could not read client request from fd %d: "
954 "%s\n", state->sock, strerror(err)));
956 close(state->sock);
957 state->sock = -1;
958 remove_client(state);
959 return;
961 process_request(state);
964 /* Remove a client connection from client connection list */
966 static void remove_client(struct winbindd_cli_state *state)
968 char c = 0;
969 int nwritten;
971 /* It's a dead client - hold a funeral */
973 if (state == NULL) {
974 return;
977 if (state->sock != -1) {
978 /* tell client, we are closing ... */
979 nwritten = write(state->sock, &c, sizeof(c));
980 if (nwritten == -1) {
981 DEBUG(2, ("final write to client failed: %s\n",
982 strerror(errno)));
985 /* Close socket */
987 close(state->sock);
988 state->sock = -1;
991 TALLOC_FREE(state->mem_ctx);
993 /* Remove from list and free */
995 winbindd_remove_client(state);
996 TALLOC_FREE(state);
999 /* Is a client idle? */
1001 static bool client_is_idle(struct winbindd_cli_state *state) {
1002 return (state->request == NULL &&
1003 state->response == NULL &&
1004 !state->pwent_state && !state->grent_state);
1007 /* Shutdown client connection which has been idle for the longest time */
1009 static bool remove_idle_client(void)
1011 struct winbindd_cli_state *state, *remove_state = NULL;
1012 time_t last_access = 0;
1013 int nidle = 0;
1015 for (state = winbindd_client_list(); state; state = state->next) {
1016 if (client_is_idle(state)) {
1017 nidle++;
1018 if (!last_access || state->last_access < last_access) {
1019 last_access = state->last_access;
1020 remove_state = state;
1025 if (remove_state) {
1026 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1027 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1028 remove_client(remove_state);
1029 return True;
1032 return False;
1035 struct winbindd_listen_state {
1036 bool privileged;
1037 int fd;
1040 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1041 struct tevent_fd *fde,
1042 uint16_t flags,
1043 void *private_data)
1045 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1046 struct winbindd_listen_state);
1048 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1049 DEBUG(5,("winbindd: Exceeding %d client "
1050 "connections, removing idle "
1051 "connection.\n", lp_winbind_max_clients()));
1052 if (!remove_idle_client()) {
1053 DEBUG(0,("winbindd: Exceeding %d "
1054 "client connections, no idle "
1055 "connection found\n",
1056 lp_winbind_max_clients()));
1057 break;
1060 new_connection(s->fd, s->privileged);
1064 * Winbindd socket accessor functions
1067 char *get_winbind_priv_pipe_dir(void)
1069 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1072 static bool winbindd_setup_listeners(void)
1074 struct winbindd_listen_state *pub_state = NULL;
1075 struct winbindd_listen_state *priv_state = NULL;
1076 struct tevent_fd *fde;
1077 int rc;
1079 pub_state = talloc(winbind_event_context(),
1080 struct winbindd_listen_state);
1081 if (!pub_state) {
1082 goto failed;
1085 pub_state->privileged = false;
1086 pub_state->fd = create_pipe_sock(
1087 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1088 if (pub_state->fd == -1) {
1089 goto failed;
1091 rc = listen(pub_state->fd, 5);
1092 if (rc < 0) {
1093 goto failed;
1096 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1097 TEVENT_FD_READ, winbindd_listen_fde_handler,
1098 pub_state);
1099 if (fde == NULL) {
1100 close(pub_state->fd);
1101 goto failed;
1103 tevent_fd_set_auto_close(fde);
1105 priv_state = talloc(winbind_event_context(),
1106 struct winbindd_listen_state);
1107 if (!priv_state) {
1108 goto failed;
1111 priv_state->privileged = true;
1112 priv_state->fd = create_pipe_sock(
1113 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
1114 if (priv_state->fd == -1) {
1115 goto failed;
1117 rc = listen(priv_state->fd, 5);
1118 if (rc < 0) {
1119 goto failed;
1122 fde = tevent_add_fd(winbind_event_context(), priv_state,
1123 priv_state->fd, TEVENT_FD_READ,
1124 winbindd_listen_fde_handler, priv_state);
1125 if (fde == NULL) {
1126 close(priv_state->fd);
1127 goto failed;
1129 tevent_fd_set_auto_close(fde);
1131 return true;
1132 failed:
1133 TALLOC_FREE(pub_state);
1134 TALLOC_FREE(priv_state);
1135 return false;
1138 bool winbindd_use_idmap_cache(void)
1140 return !opt_nocache;
1143 bool winbindd_use_cache(void)
1145 return !opt_nocache;
1148 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1149 bool foreground)
1151 NTSTATUS status;
1152 /* Setup signal handlers */
1154 if (!winbindd_setup_sig_term_handler(true))
1155 exit(1);
1156 if (!winbindd_setup_stdin_handler(true, foreground))
1157 exit(1);
1158 if (!winbindd_setup_sig_hup_handler(NULL))
1159 exit(1);
1160 if (!winbindd_setup_sig_chld_handler())
1161 exit(1);
1162 if (!winbindd_setup_sig_usr2_handler())
1163 exit(1);
1165 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1168 * Ensure all cache and idmap caches are consistent
1169 * and initialized before we startup.
1171 if (!winbindd_cache_validate_and_initialize()) {
1172 exit(1);
1175 /* get broadcast messages */
1177 if (!serverid_register(messaging_server_id(msg_ctx),
1178 FLAG_MSG_GENERAL |
1179 FLAG_MSG_WINBIND |
1180 FLAG_MSG_DBWRAP)) {
1181 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1182 exit(1);
1185 /* React on 'smbcontrol winbindd reload-config' in the same way
1186 as to SIGHUP signal */
1187 messaging_register(msg_ctx, NULL,
1188 MSG_SMB_CONF_UPDATED, msg_reload_services);
1189 messaging_register(msg_ctx, NULL,
1190 MSG_SHUTDOWN, msg_shutdown);
1192 /* Handle online/offline messages. */
1193 messaging_register(msg_ctx, NULL,
1194 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1195 messaging_register(msg_ctx, NULL,
1196 MSG_WINBIND_ONLINE, winbind_msg_online);
1197 messaging_register(msg_ctx, NULL,
1198 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1200 /* Handle domain online/offline messages for domains */
1201 messaging_register(winbind_messaging_context(), NULL,
1202 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1203 messaging_register(winbind_messaging_context(), NULL,
1204 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1206 messaging_register(msg_ctx, NULL,
1207 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1209 messaging_register(msg_ctx, NULL,
1210 MSG_WINBIND_VALIDATE_CACHE,
1211 winbind_msg_validate_cache);
1213 messaging_register(msg_ctx, NULL,
1214 MSG_WINBIND_DUMP_DOMAIN_LIST,
1215 winbind_msg_dump_domain_list);
1217 messaging_register(msg_ctx, NULL,
1218 MSG_WINBIND_IP_DROPPED,
1219 winbind_msg_ip_dropped_parent);
1221 /* Register handler for MSG_DEBUG. */
1222 messaging_register(msg_ctx, NULL,
1223 MSG_DEBUG,
1224 winbind_msg_debug);
1226 netsamlogon_cache_init(); /* Non-critical */
1228 /* clear the cached list of trusted domains */
1230 wcache_tdc_clear();
1232 if (!init_domain_list()) {
1233 DEBUG(0,("unable to initialize domain list\n"));
1234 exit(1);
1237 init_idmap_child();
1238 init_locator_child();
1240 smb_nscd_flush_user_cache();
1241 smb_nscd_flush_group_cache();
1243 if (lp_allow_trusted_domains()) {
1244 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1245 rescan_trusted_domains, NULL) == NULL) {
1246 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1247 exit(1);
1251 status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
1252 wb_irpc_DsrUpdateReadOnlyServerDnsRecords, NULL);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 DEBUG(0, ("Could not register IRPC handler for wb_irpc_DsrUpdateReadOnlyServerDnsRecords\n"));
1255 exit(1);
1259 struct winbindd_addrchanged_state {
1260 struct addrchange_context *ctx;
1261 struct tevent_context *ev;
1262 struct messaging_context *msg_ctx;
1265 static void winbindd_addr_changed(struct tevent_req *req);
1267 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1268 struct tevent_context *ev,
1269 struct messaging_context *msg_ctx)
1271 struct winbindd_addrchanged_state *state;
1272 struct tevent_req *req;
1273 NTSTATUS status;
1275 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1276 if (state == NULL) {
1277 DEBUG(10, ("talloc failed\n"));
1278 return;
1280 state->ev = ev;
1281 state->msg_ctx = msg_ctx;
1283 status = addrchange_context_create(state, &state->ctx);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 DEBUG(10, ("addrchange_context_create failed: %s\n",
1286 nt_errstr(status)));
1287 TALLOC_FREE(state);
1288 return;
1290 req = addrchange_send(state, ev, state->ctx);
1291 if (req == NULL) {
1292 DEBUG(0, ("addrchange_send failed\n"));
1293 TALLOC_FREE(state);
1294 return;
1296 tevent_req_set_callback(req, winbindd_addr_changed, state);
1299 static void winbindd_addr_changed(struct tevent_req *req)
1301 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1302 req, struct winbindd_addrchanged_state);
1303 enum addrchange_type type;
1304 struct sockaddr_storage addr;
1305 NTSTATUS status;
1307 status = addrchange_recv(req, &type, &addr);
1308 TALLOC_FREE(req);
1309 if (!NT_STATUS_IS_OK(status)) {
1310 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1311 nt_errstr(status)));
1312 TALLOC_FREE(state);
1313 return;
1315 if (type == ADDRCHANGE_DEL) {
1316 char addrstr[INET6_ADDRSTRLEN];
1317 DATA_BLOB blob;
1319 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1321 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1322 addrstr));
1324 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1326 status = messaging_send(state->msg_ctx,
1327 messaging_server_id(state->msg_ctx),
1328 MSG_WINBIND_IP_DROPPED, &blob);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1331 nt_errstr(status)));
1334 req = addrchange_send(state, state->ev, state->ctx);
1335 if (req == NULL) {
1336 DEBUG(0, ("addrchange_send failed\n"));
1337 TALLOC_FREE(state);
1338 return;
1340 tevent_req_set_callback(req, winbindd_addr_changed, state);
1343 /* Main function */
1345 int main(int argc, const char **argv)
1347 static bool is_daemon = False;
1348 static bool Fork = True;
1349 static bool log_stdout = False;
1350 static bool no_process_group = False;
1351 enum {
1352 OPT_DAEMON = 1000,
1353 OPT_FORK,
1354 OPT_NO_PROCESS_GROUP,
1355 OPT_LOG_STDOUT
1357 struct poptOption long_options[] = {
1358 POPT_AUTOHELP
1359 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1360 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1361 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1362 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1363 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1364 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1365 POPT_COMMON_SAMBA
1366 POPT_TABLEEND
1368 poptContext pc;
1369 int opt;
1370 TALLOC_CTX *frame;
1371 NTSTATUS status;
1372 bool ok;
1375 * Do this before any other talloc operation
1377 talloc_enable_null_tracking();
1378 frame = talloc_stackframe();
1381 * We want total control over the permissions on created files,
1382 * so set our umask to 0.
1384 umask(0);
1386 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1388 /* glibc (?) likes to print "User defined signal 1" and exit if a
1389 SIGUSR[12] is received before a handler is installed */
1391 CatchSignal(SIGUSR1, SIG_IGN);
1392 CatchSignal(SIGUSR2, SIG_IGN);
1394 fault_setup();
1395 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1397 load_case_tables();
1399 /* Initialise for running in non-root mode */
1401 sec_init();
1403 set_remote_machine_name("winbindd", False);
1405 /* Set environment variable so we don't recursively call ourselves.
1406 This may also be useful interactively. */
1408 if ( !winbind_off() ) {
1409 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1410 exit(1);
1413 /* Initialise samba/rpc client stuff */
1415 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1417 while ((opt = poptGetNextOpt(pc)) != -1) {
1418 switch (opt) {
1419 /* Don't become a daemon */
1420 case OPT_DAEMON:
1421 is_daemon = True;
1422 break;
1423 case 'i':
1424 interactive = True;
1425 log_stdout = True;
1426 Fork = False;
1427 break;
1428 case OPT_FORK:
1429 Fork = false;
1430 break;
1431 case OPT_NO_PROCESS_GROUP:
1432 no_process_group = true;
1433 break;
1434 case OPT_LOG_STDOUT:
1435 log_stdout = true;
1436 break;
1437 case 'n':
1438 opt_nocache = true;
1439 break;
1440 default:
1441 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1442 poptBadOption(pc, 0), poptStrerror(opt));
1443 poptPrintUsage(pc, stderr, 0);
1444 exit(1);
1448 /* We call dump_core_setup one more time because the command line can
1449 * set the log file or the log-basename and this will influence where
1450 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1451 * the default value derived from build's prefix. For EOM this value
1452 * is often not related to the path where winbindd is actually run
1453 * in production.
1455 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1456 if (is_daemon && interactive) {
1457 d_fprintf(stderr,"\nERROR: "
1458 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1459 poptPrintUsage(pc, stderr, 0);
1460 exit(1);
1463 if (log_stdout && Fork) {
1464 d_fprintf(stderr, "\nERROR: "
1465 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1466 poptPrintUsage(pc, stderr, 0);
1467 exit(1);
1470 poptFreeContext(pc);
1472 if (!override_logfile) {
1473 char *lfile = NULL;
1474 if (asprintf(&lfile,"%s/log.winbindd",
1475 get_dyn_LOGFILEBASE()) > 0) {
1476 lp_set_logfile(lfile);
1477 SAFE_FREE(lfile);
1481 if (log_stdout) {
1482 setup_logging("winbindd", DEBUG_STDOUT);
1483 } else {
1484 setup_logging("winbindd", DEBUG_FILE);
1486 reopen_logs();
1488 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1489 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1491 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1492 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1493 exit(1);
1495 /* After parsing the configuration file we setup the core path one more time
1496 * as the log file might have been set in the configuration and cores's
1497 * path is by default basename(lp_logfile()).
1499 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1501 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1502 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1503 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1504 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"));
1505 exit(1);
1508 if (!cluster_probe_ok()) {
1509 exit(1);
1512 /* Initialise messaging system */
1514 if (winbind_messaging_context() == NULL) {
1515 exit(1);
1518 if (!reload_services_file(NULL)) {
1519 DEBUG(0, ("error opening config file\n"));
1520 exit(1);
1523 ok = directory_create_or_exist(lp_lock_directory(), geteuid(), 0755);
1524 if (!ok) {
1525 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1526 lp_lock_directory(), strerror(errno)));
1527 exit(1);
1530 ok = directory_create_or_exist(lp_pid_directory(), geteuid(), 0755);
1531 if (!ok) {
1532 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1533 lp_pid_directory(), strerror(errno)));
1534 exit(1);
1537 /* Setup names. */
1539 if (!init_names())
1540 exit(1);
1542 load_interfaces();
1544 if (!secrets_init()) {
1546 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1547 return False;
1550 status = rpccli_pre_open_netlogon_creds();
1551 if (!NT_STATUS_IS_OK(status)) {
1552 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1553 nt_errstr(status)));
1554 exit(1);
1557 /* Unblock all signals we are interested in as they may have been
1558 blocked by the parent process. */
1560 BlockSignals(False, SIGINT);
1561 BlockSignals(False, SIGQUIT);
1562 BlockSignals(False, SIGTERM);
1563 BlockSignals(False, SIGUSR1);
1564 BlockSignals(False, SIGUSR2);
1565 BlockSignals(False, SIGHUP);
1566 BlockSignals(False, SIGCHLD);
1568 if (!interactive)
1569 become_daemon(Fork, no_process_group, log_stdout);
1571 pidfile_create(lp_pid_directory(), "winbindd");
1573 #if HAVE_SETPGID
1575 * If we're interactive we want to set our own process group for
1576 * signal management.
1578 if (interactive && !no_process_group)
1579 setpgid( (pid_t)0, (pid_t)0);
1580 #endif
1582 TimeInit();
1584 /* Don't use winbindd_reinit_after_fork here as
1585 * we're just starting up and haven't created any
1586 * winbindd-specific resources we must free yet. JRA.
1589 status = reinit_after_fork(winbind_messaging_context(),
1590 winbind_event_context(),
1591 false);
1592 if (!NT_STATUS_IS_OK(status)) {
1593 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1597 * Do not initialize the parent-child-pipe before becoming
1598 * a daemon: this is used to detect a died parent in the child
1599 * process.
1601 status = init_before_fork();
1602 if (!NT_STATUS_IS_OK(status)) {
1603 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1606 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1608 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1609 exit(1);
1612 status = init_system_session_info();
1613 if (!NT_STATUS_IS_OK(status)) {
1614 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1617 rpc_lsarpc_init(NULL);
1618 rpc_samr_init(NULL);
1620 winbindd_init_addrchange(NULL, winbind_event_context(),
1621 winbind_messaging_context());
1623 /* setup listen sockets */
1625 if (!winbindd_setup_listeners()) {
1626 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1629 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1631 TALLOC_FREE(frame);
1633 if (!interactive) {
1634 daemon_ready("winbindd");
1637 /* Loop waiting for requests */
1638 while (1) {
1639 frame = talloc_stackframe();
1641 if (tevent_loop_once(winbind_event_context()) == -1) {
1642 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1643 strerror(errno)));
1644 return 1;
1647 TALLOC_FREE(frame);
1650 return 0;