param: add extra default parameter to get_parametrics_by_service
[Samba.git] / source3 / winbindd / winbindd.c
bloba1647c947fab0c4d396e4e9afc2a54965e10bfc2
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"
43 #undef DBGC_CLASS
44 #define DBGC_CLASS DBGC_WINBIND
46 static bool client_is_idle(struct winbindd_cli_state *state);
47 static void remove_client(struct winbindd_cli_state *state);
49 static bool opt_nocache = False;
50 static bool interactive = False;
52 extern bool override_logfile;
54 struct tevent_context *winbind_event_context(void)
56 static struct tevent_context *ev = NULL;
58 if (ev != NULL) {
59 return ev;
63 * Note we MUST use the NULL context here, not the autofree context,
64 * to avoid side effects in forked children exiting.
66 ev = samba_tevent_context_init(NULL);
67 if (ev == NULL) {
68 smb_panic("Could not init winbindd's messaging context.\n");
70 return ev;
73 struct messaging_context *winbind_messaging_context(void)
75 static struct messaging_context *msg = NULL;
77 if (msg != NULL) {
78 return msg;
82 * Note we MUST use the NULL context here, not the autofree context,
83 * to avoid side effects in forked children exiting.
85 msg = messaging_init(NULL, winbind_event_context());
86 if (msg == NULL) {
87 smb_panic("Could not init winbindd's messaging context.\n");
89 return msg;
92 /* Reload configuration */
94 static bool reload_services_file(const char *lfile)
96 bool ret;
98 if (lp_loaded()) {
99 char *fname = lp_next_configfile(talloc_tos());
101 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
102 set_dyn_CONFIGFILE(fname);
104 TALLOC_FREE(fname);
107 /* if this is a child, restore the logfile to the special
108 name - <domain>, idmap, etc. */
109 if (lfile && *lfile) {
110 lp_set_logfile(lfile);
113 reopen_logs();
114 ret = lp_load_global(get_dyn_CONFIGFILE());
116 reopen_logs();
117 load_interfaces();
119 return(ret);
123 static void winbindd_status(void)
125 struct winbindd_cli_state *tmp;
127 DEBUG(0, ("winbindd status:\n"));
129 /* Print client state information */
131 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
133 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
134 DEBUG(2, ("\tclient list:\n"));
135 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
136 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
137 (unsigned long)tmp->pid, tmp->sock,
138 client_is_idle(tmp) ? "idle" : "active"));
143 /* Flush client cache */
145 static void flush_caches(void)
147 /* We need to invalidate cached user list entries on a SIGHUP
148 otherwise cached access denied errors due to restrict anonymous
149 hang around until the sequence number changes. */
151 if (!wcache_invalidate_cache()) {
152 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
153 if (!winbindd_cache_validate_and_initialize()) {
154 exit(1);
159 static void flush_caches_noinit(void)
162 * We need to invalidate cached user list entries on a SIGHUP
163 * otherwise cached access denied errors due to restrict anonymous
164 * hang around until the sequence number changes.
165 * NB
166 * Skip uninitialized domains when flush cache.
167 * If domain is not initialized, it means it is never
168 * used or never become online. look, wcache_invalidate_cache()
169 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
170 * for unused domains and large traffic for primay domain's DC if there
171 * are many domains..
174 if (!wcache_invalidate_cache_noinit()) {
175 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
176 if (!winbindd_cache_validate_and_initialize()) {
177 exit(1);
182 /* Handle the signal by unlinking socket and exiting */
184 static void terminate(bool is_parent)
186 if (is_parent) {
187 /* When parent goes away we should
188 * remove the socket file. Not so
189 * when children terminate.
191 char *path = NULL;
193 if (asprintf(&path, "%s/%s",
194 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
195 unlink(path);
196 SAFE_FREE(path);
200 idmap_close();
202 trustdom_cache_shutdown();
204 gencache_stabilize();
206 #if 0
207 if (interactive) {
208 TALLOC_CTX *mem_ctx = talloc_init("end_description");
209 char *description = talloc_describe_all(mem_ctx);
211 DEBUG(3, ("tallocs left:\n%s\n", description));
212 talloc_destroy(mem_ctx);
214 #endif
216 if (is_parent) {
217 struct messaging_context *msg = winbind_messaging_context();
218 struct server_id self = messaging_server_id(msg);
219 serverid_deregister(self);
220 pidfile_unlink(lp_pid_directory(), "winbindd");
223 exit(0);
226 static void winbindd_sig_term_handler(struct tevent_context *ev,
227 struct tevent_signal *se,
228 int signum,
229 int count,
230 void *siginfo,
231 void *private_data)
233 bool *is_parent = talloc_get_type_abort(private_data, bool);
235 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
236 signum, (int)*is_parent));
237 terminate(*is_parent);
241 handle stdin becoming readable when we are in --foreground mode
243 static void winbindd_stdin_handler(struct tevent_context *ev,
244 struct tevent_fd *fde,
245 uint16_t flags,
246 void *private_data)
248 char c;
249 if (read(0, &c, 1) != 1) {
250 bool *is_parent = talloc_get_type_abort(private_data, bool);
252 /* we have reached EOF on stdin, which means the
253 parent has exited. Shutdown the server */
254 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
255 (int)*is_parent));
256 terminate(*is_parent);
260 bool winbindd_setup_sig_term_handler(bool parent)
262 struct tevent_signal *se;
263 bool *is_parent;
265 is_parent = talloc(winbind_event_context(), bool);
266 if (!is_parent) {
267 return false;
270 *is_parent = parent;
272 se = tevent_add_signal(winbind_event_context(),
273 is_parent,
274 SIGTERM, 0,
275 winbindd_sig_term_handler,
276 is_parent);
277 if (!se) {
278 DEBUG(0,("failed to setup SIGTERM handler"));
279 talloc_free(is_parent);
280 return false;
283 se = tevent_add_signal(winbind_event_context(),
284 is_parent,
285 SIGINT, 0,
286 winbindd_sig_term_handler,
287 is_parent);
288 if (!se) {
289 DEBUG(0,("failed to setup SIGINT handler"));
290 talloc_free(is_parent);
291 return false;
294 se = tevent_add_signal(winbind_event_context(),
295 is_parent,
296 SIGQUIT, 0,
297 winbindd_sig_term_handler,
298 is_parent);
299 if (!se) {
300 DEBUG(0,("failed to setup SIGINT handler"));
301 talloc_free(is_parent);
302 return false;
305 return true;
308 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
310 bool *is_parent;
312 if (foreground) {
313 struct stat st;
315 is_parent = talloc(winbind_event_context(), bool);
316 if (!is_parent) {
317 return false;
320 *is_parent = parent;
322 /* if we are running in the foreground then look for
323 EOF on stdin, and exit if it happens. This allows
324 us to die if the parent process dies
325 Only do this on a pipe or socket, no other device.
327 if (fstat(0, &st) != 0) {
328 return false;
330 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
331 tevent_add_fd(winbind_event_context(),
332 is_parent,
334 TEVENT_FD_READ,
335 winbindd_stdin_handler,
336 is_parent);
340 return true;
343 static void winbindd_sig_hup_handler(struct tevent_context *ev,
344 struct tevent_signal *se,
345 int signum,
346 int count,
347 void *siginfo,
348 void *private_data)
350 const char *file = (const char *)private_data;
352 DEBUG(1,("Reloading services after SIGHUP\n"));
353 flush_caches_noinit();
354 reload_services_file(file);
357 bool winbindd_setup_sig_hup_handler(const char *lfile)
359 struct tevent_signal *se;
360 char *file = NULL;
362 if (lfile) {
363 file = talloc_strdup(winbind_event_context(),
364 lfile);
365 if (!file) {
366 return false;
370 se = tevent_add_signal(winbind_event_context(),
371 winbind_event_context(),
372 SIGHUP, 0,
373 winbindd_sig_hup_handler,
374 file);
375 if (!se) {
376 return false;
379 return true;
382 static void winbindd_sig_chld_handler(struct tevent_context *ev,
383 struct tevent_signal *se,
384 int signum,
385 int count,
386 void *siginfo,
387 void *private_data)
389 pid_t pid;
391 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
392 winbind_child_died(pid);
396 static bool winbindd_setup_sig_chld_handler(void)
398 struct tevent_signal *se;
400 se = tevent_add_signal(winbind_event_context(),
401 winbind_event_context(),
402 SIGCHLD, 0,
403 winbindd_sig_chld_handler,
404 NULL);
405 if (!se) {
406 return false;
409 return true;
412 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
413 struct tevent_signal *se,
414 int signum,
415 int count,
416 void *siginfo,
417 void *private_data)
419 winbindd_status();
422 static bool winbindd_setup_sig_usr2_handler(void)
424 struct tevent_signal *se;
426 se = tevent_add_signal(winbind_event_context(),
427 winbind_event_context(),
428 SIGUSR2, 0,
429 winbindd_sig_usr2_handler,
430 NULL);
431 if (!se) {
432 return false;
435 return true;
438 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
439 static void msg_reload_services(struct messaging_context *msg,
440 void *private_data,
441 uint32_t msg_type,
442 struct server_id server_id,
443 DATA_BLOB *data)
445 /* Flush various caches */
446 flush_caches();
447 reload_services_file((const char *) private_data);
450 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
451 static void msg_shutdown(struct messaging_context *msg,
452 void *private_data,
453 uint32_t msg_type,
454 struct server_id server_id,
455 DATA_BLOB *data)
457 /* only the parent waits for this message */
458 DEBUG(0,("Got shutdown message\n"));
459 terminate(true);
463 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
464 void *private_data,
465 uint32_t msg_type,
466 struct server_id server_id,
467 DATA_BLOB *data)
469 uint8 ret;
470 pid_t child_pid;
471 NTSTATUS status;
473 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
474 "message.\n"));
477 * call the validation code from a child:
478 * so we don't block the main winbindd and the validation
479 * code can safely use fork/waitpid...
481 child_pid = fork();
483 if (child_pid == -1) {
484 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
485 strerror(errno)));
486 return;
489 if (child_pid != 0) {
490 /* parent */
491 DEBUG(5, ("winbind_msg_validate_cache: child created with "
492 "pid %d.\n", (int)child_pid));
493 return;
496 /* child */
498 status = winbindd_reinit_after_fork(NULL, NULL);
499 if (!NT_STATUS_IS_OK(status)) {
500 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
501 nt_errstr(status)));
502 _exit(0);
505 /* install default SIGCHLD handler: validation code uses fork/waitpid */
506 CatchSignal(SIGCHLD, SIG_DFL);
508 ret = (uint8)winbindd_validate_cache_nobackup();
509 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
510 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
511 (size_t)1);
512 _exit(0);
515 static struct winbindd_dispatch_table {
516 enum winbindd_cmd cmd;
517 void (*fn)(struct winbindd_cli_state *state);
518 const char *winbindd_cmd_name;
519 } dispatch_table[] = {
521 /* Enumeration functions */
523 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
524 "LIST_TRUSTDOM" },
526 /* Miscellaneous */
528 { WINBINDD_INFO, winbindd_info, "INFO" },
529 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
530 "INTERFACE_VERSION" },
531 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
532 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
533 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
534 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
535 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
536 "WINBINDD_PRIV_PIPE_DIR" },
538 /* Credential cache access */
539 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
540 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
542 /* End of list */
544 { WINBINDD_NUM_CMDS, NULL, "NONE" }
547 struct winbindd_async_dispatch_table {
548 enum winbindd_cmd cmd;
549 const char *cmd_name;
550 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
551 struct tevent_context *ev,
552 struct winbindd_cli_state *cli,
553 struct winbindd_request *request);
554 NTSTATUS (*recv_req)(struct tevent_req *req,
555 struct winbindd_response *presp);
558 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
559 { WINBINDD_PING, "PING",
560 wb_ping_send, wb_ping_recv },
561 { WINBINDD_LOOKUPSID, "LOOKUPSID",
562 winbindd_lookupsid_send, winbindd_lookupsid_recv },
563 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
564 winbindd_lookupsids_send, winbindd_lookupsids_recv },
565 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
566 winbindd_lookupname_send, winbindd_lookupname_recv },
567 { WINBINDD_SID_TO_UID, "SID_TO_UID",
568 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
569 { WINBINDD_SID_TO_GID, "SID_TO_GID",
570 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
571 { WINBINDD_UID_TO_SID, "UID_TO_SID",
572 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
573 { WINBINDD_GID_TO_SID, "GID_TO_SID",
574 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
575 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
576 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
577 { WINBINDD_GETPWSID, "GETPWSID",
578 winbindd_getpwsid_send, winbindd_getpwsid_recv },
579 { WINBINDD_GETPWNAM, "GETPWNAM",
580 winbindd_getpwnam_send, winbindd_getpwnam_recv },
581 { WINBINDD_GETPWUID, "GETPWUID",
582 winbindd_getpwuid_send, winbindd_getpwuid_recv },
583 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
584 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
585 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
586 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
587 { WINBINDD_GETGROUPS, "GETGROUPS",
588 winbindd_getgroups_send, winbindd_getgroups_recv },
589 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
590 winbindd_show_sequence_send, winbindd_show_sequence_recv },
591 { WINBINDD_GETGRGID, "GETGRGID",
592 winbindd_getgrgid_send, winbindd_getgrgid_recv },
593 { WINBINDD_GETGRNAM, "GETGRNAM",
594 winbindd_getgrnam_send, winbindd_getgrnam_recv },
595 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
596 winbindd_getusersids_send, winbindd_getusersids_recv },
597 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
598 winbindd_lookuprids_send, winbindd_lookuprids_recv },
599 { WINBINDD_SETPWENT, "SETPWENT",
600 winbindd_setpwent_send, winbindd_setpwent_recv },
601 { WINBINDD_GETPWENT, "GETPWENT",
602 winbindd_getpwent_send, winbindd_getpwent_recv },
603 { WINBINDD_ENDPWENT, "ENDPWENT",
604 winbindd_endpwent_send, winbindd_endpwent_recv },
605 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
606 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
607 { WINBINDD_GETDCNAME, "GETDCNAME",
608 winbindd_getdcname_send, winbindd_getdcname_recv },
609 { WINBINDD_SETGRENT, "SETGRENT",
610 winbindd_setgrent_send, winbindd_setgrent_recv },
611 { WINBINDD_GETGRENT, "GETGRENT",
612 winbindd_getgrent_send, winbindd_getgrent_recv },
613 { WINBINDD_ENDGRENT, "ENDGRENT",
614 winbindd_endgrent_send, winbindd_endgrent_recv },
615 { WINBINDD_LIST_USERS, "LIST_USERS",
616 winbindd_list_users_send, winbindd_list_users_recv },
617 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
618 winbindd_list_groups_send, winbindd_list_groups_recv },
619 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
620 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
621 { WINBINDD_PING_DC, "PING_DC",
622 winbindd_ping_dc_send, winbindd_ping_dc_recv },
623 { WINBINDD_PAM_AUTH, "PAM_AUTH",
624 winbindd_pam_auth_send, winbindd_pam_auth_recv },
625 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
626 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
627 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
628 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
629 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
630 winbindd_pam_chng_pswd_auth_crap_send,
631 winbindd_pam_chng_pswd_auth_crap_recv },
632 { WINBINDD_WINS_BYIP, "WINS_BYIP",
633 winbindd_wins_byip_send, winbindd_wins_byip_recv },
634 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
635 winbindd_wins_byname_send, winbindd_wins_byname_recv },
637 { 0, NULL, NULL, NULL }
640 static struct winbindd_async_dispatch_table async_priv_table[] = {
641 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
642 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
643 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
644 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
645 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
646 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
647 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
648 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
650 { 0, NULL, NULL, NULL }
653 static void wb_request_done(struct tevent_req *req);
655 static void process_request(struct winbindd_cli_state *state)
657 struct winbindd_dispatch_table *table = dispatch_table;
658 struct winbindd_async_dispatch_table *atable;
660 state->mem_ctx = talloc_named(state, 0, "winbind request");
661 if (state->mem_ctx == NULL)
662 return;
664 /* Remember who asked us. */
665 state->pid = state->request->pid;
667 state->cmd_name = "unknown request";
668 state->recv_fn = NULL;
669 state->last_access = time(NULL);
671 /* Process command */
673 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
674 if (state->request->cmd == atable->cmd) {
675 break;
679 if ((atable->send_req == NULL) && state->privileged) {
680 for (atable = async_priv_table; atable->send_req;
681 atable += 1) {
682 if (state->request->cmd == atable->cmd) {
683 break;
688 if (atable->send_req != NULL) {
689 struct tevent_req *req;
691 state->cmd_name = atable->cmd_name;
692 state->recv_fn = atable->recv_req;
694 DEBUG(10, ("process_request: Handling async request %d:%s\n",
695 (int)state->pid, state->cmd_name));
697 req = atable->send_req(state->mem_ctx, winbind_event_context(),
698 state, state->request);
699 if (req == NULL) {
700 DEBUG(0, ("process_request: atable->send failed for "
701 "%s\n", atable->cmd_name));
702 request_error(state);
703 return;
705 tevent_req_set_callback(req, wb_request_done, state);
706 return;
709 state->response = talloc_zero(state->mem_ctx,
710 struct winbindd_response);
711 if (state->response == NULL) {
712 DEBUG(10, ("talloc failed\n"));
713 remove_client(state);
714 return;
716 state->response->result = WINBINDD_PENDING;
717 state->response->length = sizeof(struct winbindd_response);
719 for (table = dispatch_table; table->fn; table++) {
720 if (state->request->cmd == table->cmd) {
721 DEBUG(10,("process_request: request fn %s\n",
722 table->winbindd_cmd_name ));
723 state->cmd_name = table->winbindd_cmd_name;
724 table->fn(state);
725 break;
729 if (!table->fn) {
730 DEBUG(10,("process_request: unknown request fn number %d\n",
731 (int)state->request->cmd ));
732 request_error(state);
736 static void wb_request_done(struct tevent_req *req)
738 struct winbindd_cli_state *state = tevent_req_callback_data(
739 req, struct winbindd_cli_state);
740 NTSTATUS status;
742 state->response = talloc_zero(state->mem_ctx,
743 struct winbindd_response);
744 if (state->response == NULL) {
745 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
746 (int)state->pid, state->cmd_name));
747 remove_client(state);
748 return;
750 state->response->result = WINBINDD_PENDING;
751 state->response->length = sizeof(struct winbindd_response);
753 status = state->recv_fn(req, state->response);
754 TALLOC_FREE(req);
756 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
757 (int)state->pid, state->cmd_name, nt_errstr(status)));
759 if (!NT_STATUS_IS_OK(status)) {
760 request_error(state);
761 return;
763 request_ok(state);
767 * This is the main event loop of winbind requests. It goes through a
768 * state-machine of 3 read/write requests, 4 if you have extra data to send.
770 * An idle winbind client has a read request of 4 bytes outstanding,
771 * finalizing function is request_len_recv, checking the length. request_recv
772 * then processes the packet. The processing function then at some point has
773 * to call request_finished which schedules sending the response.
776 static void request_finished(struct winbindd_cli_state *state);
778 static void winbind_client_request_read(struct tevent_req *req);
779 static void winbind_client_response_written(struct tevent_req *req);
781 static void request_finished(struct winbindd_cli_state *state)
783 struct tevent_req *req;
785 TALLOC_FREE(state->request);
787 req = wb_resp_write_send(state, winbind_event_context(),
788 state->out_queue, state->sock,
789 state->response);
790 if (req == NULL) {
791 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
792 (int)state->pid, state->cmd_name));
793 remove_client(state);
794 return;
796 tevent_req_set_callback(req, winbind_client_response_written, state);
799 static void winbind_client_response_written(struct tevent_req *req)
801 struct winbindd_cli_state *state = tevent_req_callback_data(
802 req, struct winbindd_cli_state);
803 ssize_t ret;
804 int err;
806 ret = wb_resp_write_recv(req, &err);
807 TALLOC_FREE(req);
808 if (ret == -1) {
809 close(state->sock);
810 state->sock = -1;
811 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
812 (int)state->pid, state->cmd_name, strerror(err)));
813 remove_client(state);
814 return;
817 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
818 "to client\n", (int)state->pid, state->cmd_name));
820 TALLOC_FREE(state->mem_ctx);
821 state->response = NULL;
822 state->cmd_name = "no request";
823 state->recv_fn = NULL;
825 req = wb_req_read_send(state, winbind_event_context(), state->sock,
826 WINBINDD_MAX_EXTRA_DATA);
827 if (req == NULL) {
828 remove_client(state);
829 return;
831 tevent_req_set_callback(req, winbind_client_request_read, state);
834 void request_error(struct winbindd_cli_state *state)
836 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
837 state->response->result = WINBINDD_ERROR;
838 request_finished(state);
841 void request_ok(struct winbindd_cli_state *state)
843 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
844 state->response->result = WINBINDD_OK;
845 request_finished(state);
848 /* Process a new connection by adding it to the client connection list */
850 static void new_connection(int listen_sock, bool privileged)
852 struct sockaddr_un sunaddr;
853 struct winbindd_cli_state *state;
854 struct tevent_req *req;
855 socklen_t len;
856 int sock;
858 /* Accept connection */
860 len = sizeof(sunaddr);
862 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
864 if (sock == -1) {
865 if (errno != EINTR) {
866 DEBUG(0, ("Failed to accept socket - %s\n",
867 strerror(errno)));
869 return;
872 DEBUG(6,("accepted socket %d\n", sock));
874 /* Create new connection structure */
876 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
877 close(sock);
878 return;
881 state->sock = sock;
883 state->out_queue = tevent_queue_create(state, "winbind client reply");
884 if (state->out_queue == NULL) {
885 close(sock);
886 TALLOC_FREE(state);
887 return;
890 state->last_access = time(NULL);
892 state->privileged = privileged;
894 req = wb_req_read_send(state, winbind_event_context(), state->sock,
895 WINBINDD_MAX_EXTRA_DATA);
896 if (req == NULL) {
897 TALLOC_FREE(state);
898 close(sock);
899 return;
901 tevent_req_set_callback(req, winbind_client_request_read, state);
903 /* Add to connection list */
905 winbindd_add_client(state);
908 static void winbind_client_request_read(struct tevent_req *req)
910 struct winbindd_cli_state *state = tevent_req_callback_data(
911 req, struct winbindd_cli_state);
912 ssize_t ret;
913 int err;
915 ret = wb_req_read_recv(req, state, &state->request, &err);
916 TALLOC_FREE(req);
917 if (ret == -1) {
918 if (err == EPIPE) {
919 DEBUG(6, ("closing socket %d, client exited\n",
920 state->sock));
921 } else {
922 DEBUG(2, ("Could not read client request from fd %d: "
923 "%s\n", state->sock, strerror(err)));
925 close(state->sock);
926 state->sock = -1;
927 remove_client(state);
928 return;
930 process_request(state);
933 /* Remove a client connection from client connection list */
935 static void remove_client(struct winbindd_cli_state *state)
937 char c = 0;
938 int nwritten;
940 /* It's a dead client - hold a funeral */
942 if (state == NULL) {
943 return;
946 if (state->sock != -1) {
947 /* tell client, we are closing ... */
948 nwritten = write(state->sock, &c, sizeof(c));
949 if (nwritten == -1) {
950 DEBUG(2, ("final write to client failed: %s\n",
951 strerror(errno)));
954 /* Close socket */
956 close(state->sock);
957 state->sock = -1;
960 TALLOC_FREE(state->mem_ctx);
962 /* Remove from list and free */
964 winbindd_remove_client(state);
965 TALLOC_FREE(state);
968 /* Is a client idle? */
970 static bool client_is_idle(struct winbindd_cli_state *state) {
971 return (state->request == NULL &&
972 state->response == NULL &&
973 !state->pwent_state && !state->grent_state);
976 /* Shutdown client connection which has been idle for the longest time */
978 static bool remove_idle_client(void)
980 struct winbindd_cli_state *state, *remove_state = NULL;
981 time_t last_access = 0;
982 int nidle = 0;
984 for (state = winbindd_client_list(); state; state = state->next) {
985 if (client_is_idle(state)) {
986 nidle++;
987 if (!last_access || state->last_access < last_access) {
988 last_access = state->last_access;
989 remove_state = state;
994 if (remove_state) {
995 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
996 nidle, remove_state->sock, (unsigned int)remove_state->pid));
997 remove_client(remove_state);
998 return True;
1001 return False;
1004 struct winbindd_listen_state {
1005 bool privileged;
1006 int fd;
1009 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1010 struct tevent_fd *fde,
1011 uint16_t flags,
1012 void *private_data)
1014 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1015 struct winbindd_listen_state);
1017 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1018 DEBUG(5,("winbindd: Exceeding %d client "
1019 "connections, removing idle "
1020 "connection.\n", lp_winbind_max_clients()));
1021 if (!remove_idle_client()) {
1022 DEBUG(0,("winbindd: Exceeding %d "
1023 "client connections, no idle "
1024 "connection found\n",
1025 lp_winbind_max_clients()));
1026 break;
1029 new_connection(s->fd, s->privileged);
1033 * Winbindd socket accessor functions
1036 char *get_winbind_priv_pipe_dir(void)
1038 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1041 static bool winbindd_setup_listeners(void)
1043 struct winbindd_listen_state *pub_state = NULL;
1044 struct winbindd_listen_state *priv_state = NULL;
1045 struct tevent_fd *fde;
1046 int rc;
1048 pub_state = talloc(winbind_event_context(),
1049 struct winbindd_listen_state);
1050 if (!pub_state) {
1051 goto failed;
1054 pub_state->privileged = false;
1055 pub_state->fd = create_pipe_sock(
1056 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1057 if (pub_state->fd == -1) {
1058 goto failed;
1060 rc = listen(pub_state->fd, 5);
1061 if (rc < 0) {
1062 goto failed;
1065 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1066 TEVENT_FD_READ, winbindd_listen_fde_handler,
1067 pub_state);
1068 if (fde == NULL) {
1069 close(pub_state->fd);
1070 goto failed;
1072 tevent_fd_set_auto_close(fde);
1074 priv_state = talloc(winbind_event_context(),
1075 struct winbindd_listen_state);
1076 if (!priv_state) {
1077 goto failed;
1080 priv_state->privileged = true;
1081 priv_state->fd = create_pipe_sock(
1082 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
1083 if (priv_state->fd == -1) {
1084 goto failed;
1086 rc = listen(priv_state->fd, 5);
1087 if (rc < 0) {
1088 goto failed;
1091 fde = tevent_add_fd(winbind_event_context(), priv_state,
1092 priv_state->fd, TEVENT_FD_READ,
1093 winbindd_listen_fde_handler, priv_state);
1094 if (fde == NULL) {
1095 close(priv_state->fd);
1096 goto failed;
1098 tevent_fd_set_auto_close(fde);
1100 return true;
1101 failed:
1102 TALLOC_FREE(pub_state);
1103 TALLOC_FREE(priv_state);
1104 return false;
1107 bool winbindd_use_idmap_cache(void)
1109 return !opt_nocache;
1112 bool winbindd_use_cache(void)
1114 return !opt_nocache;
1117 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1118 bool foreground)
1120 /* Setup signal handlers */
1122 if (!winbindd_setup_sig_term_handler(true))
1123 exit(1);
1124 if (!winbindd_setup_stdin_handler(true, foreground))
1125 exit(1);
1126 if (!winbindd_setup_sig_hup_handler(NULL))
1127 exit(1);
1128 if (!winbindd_setup_sig_chld_handler())
1129 exit(1);
1130 if (!winbindd_setup_sig_usr2_handler())
1131 exit(1);
1133 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1136 * Ensure all cache and idmap caches are consistent
1137 * and initialized before we startup.
1139 if (!winbindd_cache_validate_and_initialize()) {
1140 exit(1);
1143 /* get broadcast messages */
1145 if (!serverid_register(messaging_server_id(msg_ctx),
1146 FLAG_MSG_GENERAL |
1147 FLAG_MSG_WINBIND |
1148 FLAG_MSG_DBWRAP)) {
1149 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1150 exit(1);
1153 /* React on 'smbcontrol winbindd reload-config' in the same way
1154 as to SIGHUP signal */
1155 messaging_register(msg_ctx, NULL,
1156 MSG_SMB_CONF_UPDATED, msg_reload_services);
1157 messaging_register(msg_ctx, NULL,
1158 MSG_SHUTDOWN, msg_shutdown);
1160 /* Handle online/offline messages. */
1161 messaging_register(msg_ctx, NULL,
1162 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1163 messaging_register(msg_ctx, NULL,
1164 MSG_WINBIND_ONLINE, winbind_msg_online);
1165 messaging_register(msg_ctx, NULL,
1166 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1168 /* Handle domain online/offline messages for domains */
1169 messaging_register(winbind_messaging_context(), NULL,
1170 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1171 messaging_register(winbind_messaging_context(), NULL,
1172 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1174 messaging_register(msg_ctx, NULL,
1175 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1177 messaging_register(msg_ctx, NULL,
1178 MSG_WINBIND_VALIDATE_CACHE,
1179 winbind_msg_validate_cache);
1181 messaging_register(msg_ctx, NULL,
1182 MSG_WINBIND_DUMP_DOMAIN_LIST,
1183 winbind_msg_dump_domain_list);
1185 messaging_register(msg_ctx, NULL,
1186 MSG_WINBIND_IP_DROPPED,
1187 winbind_msg_ip_dropped_parent);
1189 /* Register handler for MSG_DEBUG. */
1190 messaging_register(msg_ctx, NULL,
1191 MSG_DEBUG,
1192 winbind_msg_debug);
1194 netsamlogon_cache_init(); /* Non-critical */
1196 /* clear the cached list of trusted domains */
1198 wcache_tdc_clear();
1200 if (!init_domain_list()) {
1201 DEBUG(0,("unable to initialize domain list\n"));
1202 exit(1);
1205 init_idmap_child();
1206 init_locator_child();
1208 smb_nscd_flush_user_cache();
1209 smb_nscd_flush_group_cache();
1211 if (lp_allow_trusted_domains()) {
1212 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1213 rescan_trusted_domains, NULL) == NULL) {
1214 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1215 exit(1);
1221 struct winbindd_addrchanged_state {
1222 struct addrchange_context *ctx;
1223 struct tevent_context *ev;
1224 struct messaging_context *msg_ctx;
1227 static void winbindd_addr_changed(struct tevent_req *req);
1229 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1230 struct tevent_context *ev,
1231 struct messaging_context *msg_ctx)
1233 struct winbindd_addrchanged_state *state;
1234 struct tevent_req *req;
1235 NTSTATUS status;
1237 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1238 if (state == NULL) {
1239 DEBUG(10, ("talloc failed\n"));
1240 return;
1242 state->ev = ev;
1243 state->msg_ctx = msg_ctx;
1245 status = addrchange_context_create(state, &state->ctx);
1246 if (!NT_STATUS_IS_OK(status)) {
1247 DEBUG(10, ("addrchange_context_create failed: %s\n",
1248 nt_errstr(status)));
1249 TALLOC_FREE(state);
1250 return;
1252 req = addrchange_send(state, ev, state->ctx);
1253 if (req == NULL) {
1254 DEBUG(0, ("addrchange_send failed\n"));
1255 TALLOC_FREE(state);
1256 return;
1258 tevent_req_set_callback(req, winbindd_addr_changed, state);
1261 static void winbindd_addr_changed(struct tevent_req *req)
1263 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1264 req, struct winbindd_addrchanged_state);
1265 enum addrchange_type type;
1266 struct sockaddr_storage addr;
1267 NTSTATUS status;
1269 status = addrchange_recv(req, &type, &addr);
1270 TALLOC_FREE(req);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1273 nt_errstr(status)));
1274 TALLOC_FREE(state);
1275 return;
1277 if (type == ADDRCHANGE_DEL) {
1278 char addrstr[INET6_ADDRSTRLEN];
1279 DATA_BLOB blob;
1281 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1283 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1284 addrstr));
1286 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1288 status = messaging_send(state->msg_ctx,
1289 messaging_server_id(state->msg_ctx),
1290 MSG_WINBIND_IP_DROPPED, &blob);
1291 if (!NT_STATUS_IS_OK(status)) {
1292 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1293 nt_errstr(status)));
1296 req = addrchange_send(state, state->ev, state->ctx);
1297 if (req == NULL) {
1298 DEBUG(0, ("addrchange_send failed\n"));
1299 TALLOC_FREE(state);
1300 return;
1302 tevent_req_set_callback(req, winbindd_addr_changed, state);
1305 /* Main function */
1307 int main(int argc, const char **argv)
1309 static bool is_daemon = False;
1310 static bool Fork = True;
1311 static bool log_stdout = False;
1312 static bool no_process_group = False;
1313 enum {
1314 OPT_DAEMON = 1000,
1315 OPT_FORK,
1316 OPT_NO_PROCESS_GROUP,
1317 OPT_LOG_STDOUT
1319 struct poptOption long_options[] = {
1320 POPT_AUTOHELP
1321 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1322 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1323 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1324 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1325 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1326 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1327 POPT_COMMON_SAMBA
1328 POPT_TABLEEND
1330 poptContext pc;
1331 int opt;
1332 TALLOC_CTX *frame;
1333 NTSTATUS status;
1334 bool ok;
1337 * Do this before any other talloc operation
1339 talloc_enable_null_tracking();
1340 frame = talloc_stackframe();
1343 * We want total control over the permissions on created files,
1344 * so set our umask to 0.
1346 umask(0);
1348 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1350 /* glibc (?) likes to print "User defined signal 1" and exit if a
1351 SIGUSR[12] is received before a handler is installed */
1353 CatchSignal(SIGUSR1, SIG_IGN);
1354 CatchSignal(SIGUSR2, SIG_IGN);
1356 fault_setup();
1357 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1359 load_case_tables();
1361 /* Initialise for running in non-root mode */
1363 sec_init();
1365 set_remote_machine_name("winbindd", False);
1367 /* Set environment variable so we don't recursively call ourselves.
1368 This may also be useful interactively. */
1370 if ( !winbind_off() ) {
1371 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1372 exit(1);
1375 /* Initialise samba/rpc client stuff */
1377 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1379 while ((opt = poptGetNextOpt(pc)) != -1) {
1380 switch (opt) {
1381 /* Don't become a daemon */
1382 case OPT_DAEMON:
1383 is_daemon = True;
1384 break;
1385 case 'i':
1386 interactive = True;
1387 log_stdout = True;
1388 Fork = False;
1389 break;
1390 case OPT_FORK:
1391 Fork = false;
1392 break;
1393 case OPT_NO_PROCESS_GROUP:
1394 no_process_group = true;
1395 break;
1396 case OPT_LOG_STDOUT:
1397 log_stdout = true;
1398 break;
1399 case 'n':
1400 opt_nocache = true;
1401 break;
1402 default:
1403 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1404 poptBadOption(pc, 0), poptStrerror(opt));
1405 poptPrintUsage(pc, stderr, 0);
1406 exit(1);
1410 /* We call dump_core_setup one more time because the command line can
1411 * set the log file or the log-basename and this will influence where
1412 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1413 * the default value derived from build's prefix. For EOM this value
1414 * is often not related to the path where winbindd is actually run
1415 * in production.
1417 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1418 if (is_daemon && interactive) {
1419 d_fprintf(stderr,"\nERROR: "
1420 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1421 poptPrintUsage(pc, stderr, 0);
1422 exit(1);
1425 if (log_stdout && Fork) {
1426 d_fprintf(stderr, "\nERROR: "
1427 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1428 poptPrintUsage(pc, stderr, 0);
1429 exit(1);
1432 poptFreeContext(pc);
1434 if (!override_logfile) {
1435 char *lfile = NULL;
1436 if (asprintf(&lfile,"%s/log.winbindd",
1437 get_dyn_LOGFILEBASE()) > 0) {
1438 lp_set_logfile(lfile);
1439 SAFE_FREE(lfile);
1443 if (log_stdout) {
1444 setup_logging("winbindd", DEBUG_STDOUT);
1445 } else {
1446 setup_logging("winbindd", DEBUG_FILE);
1448 reopen_logs();
1450 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1451 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1453 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1454 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1455 exit(1);
1457 /* After parsing the configuration file we setup the core path one more time
1458 * as the log file might have been set in the configuration and cores's
1459 * path is by default basename(lp_logfile()).
1461 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1463 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1464 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1465 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1466 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"));
1467 exit(1);
1470 if (!cluster_probe_ok()) {
1471 exit(1);
1474 /* Initialise messaging system */
1476 if (winbind_messaging_context() == NULL) {
1477 exit(1);
1480 if (!reload_services_file(NULL)) {
1481 DEBUG(0, ("error opening config file\n"));
1482 exit(1);
1485 ok = directory_create_or_exist(lp_lock_directory(), geteuid(), 0755);
1486 if (!ok) {
1487 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1488 lp_lock_directory(), strerror(errno)));
1489 exit(1);
1492 ok = directory_create_or_exist(lp_pid_directory(), geteuid(), 0755);
1493 if (!ok) {
1494 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1495 lp_pid_directory(), strerror(errno)));
1496 exit(1);
1499 /* Setup names. */
1501 if (!init_names())
1502 exit(1);
1504 load_interfaces();
1506 if (!secrets_init()) {
1508 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1509 return False;
1512 status = rpccli_pre_open_netlogon_creds();
1513 if (!NT_STATUS_IS_OK(status)) {
1514 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1515 nt_errstr(status)));
1516 exit(1);
1519 /* Unblock all signals we are interested in as they may have been
1520 blocked by the parent process. */
1522 BlockSignals(False, SIGINT);
1523 BlockSignals(False, SIGQUIT);
1524 BlockSignals(False, SIGTERM);
1525 BlockSignals(False, SIGUSR1);
1526 BlockSignals(False, SIGUSR2);
1527 BlockSignals(False, SIGHUP);
1528 BlockSignals(False, SIGCHLD);
1530 if (!interactive)
1531 become_daemon(Fork, no_process_group, log_stdout);
1533 pidfile_create(lp_pid_directory(), "winbindd");
1535 #if HAVE_SETPGID
1537 * If we're interactive we want to set our own process group for
1538 * signal management.
1540 if (interactive && !no_process_group)
1541 setpgid( (pid_t)0, (pid_t)0);
1542 #endif
1544 TimeInit();
1546 /* Don't use winbindd_reinit_after_fork here as
1547 * we're just starting up and haven't created any
1548 * winbindd-specific resources we must free yet. JRA.
1551 status = reinit_after_fork(winbind_messaging_context(),
1552 winbind_event_context(),
1553 false);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1559 * Do not initialize the parent-child-pipe before becoming
1560 * a daemon: this is used to detect a died parent in the child
1561 * process.
1563 status = init_before_fork();
1564 if (!NT_STATUS_IS_OK(status)) {
1565 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1568 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1570 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1571 exit(1);
1574 status = init_system_session_info();
1575 if (!NT_STATUS_IS_OK(status)) {
1576 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1579 rpc_lsarpc_init(NULL);
1580 rpc_samr_init(NULL);
1582 winbindd_init_addrchange(NULL, winbind_event_context(),
1583 winbind_messaging_context());
1585 /* setup listen sockets */
1587 if (!winbindd_setup_listeners()) {
1588 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1591 TALLOC_FREE(frame);
1593 if (!interactive) {
1594 daemon_ready("winbindd");
1597 /* Loop waiting for requests */
1598 while (1) {
1599 frame = talloc_stackframe();
1601 if (tevent_loop_once(winbind_event_context()) == -1) {
1602 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1603 strerror(errno)));
1604 return 1;
1607 TALLOC_FREE(frame);
1610 return 0;