s3: daemons - ensure nmbd and winbindd are consistent in command line processing...
[Samba.git] / source3 / winbindd / winbindd.c
blob27c43dc29d76dcf1629b3ef6bec53bf0f43a07e1
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 tevent_context *winbind_event_context(void)
54 static struct tevent_context *ev = NULL;
56 if (ev != NULL) {
57 return ev;
61 * Note we MUST use the NULL context here, not the autofree context,
62 * to avoid side effects in forked children exiting.
64 ev = samba_tevent_context_init(NULL);
65 if (ev == NULL) {
66 smb_panic("Could not init winbindd's messaging context.\n");
68 return ev;
71 struct messaging_context *winbind_messaging_context(void)
73 static struct messaging_context *msg = NULL;
75 if (msg != NULL) {
76 return msg;
80 * Note we MUST use the NULL context here, not the autofree context,
81 * to avoid side effects in forked children exiting.
83 msg = messaging_init(NULL, winbind_event_context());
84 if (msg == NULL) {
85 smb_panic("Could not init winbindd's messaging context.\n");
87 return msg;
90 /* Reload configuration */
92 static bool reload_services_file(const char *lfile)
94 bool ret;
96 if (lp_loaded()) {
97 char *fname = lp_configfile(talloc_tos());
99 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
100 set_dyn_CONFIGFILE(fname);
102 TALLOC_FREE(fname);
105 /* if this is a child, restore the logfile to the special
106 name - <domain>, idmap, etc. */
107 if (lfile && *lfile) {
108 lp_set_logfile(lfile);
111 reopen_logs();
112 ret = lp_load_global(get_dyn_CONFIGFILE());
114 reopen_logs();
115 load_interfaces();
117 return(ret);
121 static void winbindd_status(void)
123 struct winbindd_cli_state *tmp;
125 DEBUG(0, ("winbindd status:\n"));
127 /* Print client state information */
129 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
131 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
132 DEBUG(2, ("\tclient list:\n"));
133 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
134 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
135 (unsigned long)tmp->pid, tmp->sock,
136 client_is_idle(tmp) ? "idle" : "active"));
141 /* Flush client cache */
143 static void flush_caches(void)
145 /* We need to invalidate cached user list entries on a SIGHUP
146 otherwise cached access denied errors due to restrict anonymous
147 hang around until the sequence number changes. */
149 if (!wcache_invalidate_cache()) {
150 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
151 if (!winbindd_cache_validate_and_initialize()) {
152 exit(1);
157 static void flush_caches_noinit(void)
160 * We need to invalidate cached user list entries on a SIGHUP
161 * otherwise cached access denied errors due to restrict anonymous
162 * hang around until the sequence number changes.
163 * NB
164 * Skip uninitialized domains when flush cache.
165 * If domain is not initialized, it means it is never
166 * used or never become online. look, wcache_invalidate_cache()
167 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
168 * for unused domains and large traffic for primay domain's DC if there
169 * are many domains..
172 if (!wcache_invalidate_cache_noinit()) {
173 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
174 if (!winbindd_cache_validate_and_initialize()) {
175 exit(1);
180 /* Handle the signal by unlinking socket and exiting */
182 static void terminate(bool is_parent)
184 if (is_parent) {
185 /* When parent goes away we should
186 * remove the socket file. Not so
187 * when children terminate.
189 char *path = NULL;
191 if (asprintf(&path, "%s/%s",
192 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) {
193 unlink(path);
194 SAFE_FREE(path);
198 idmap_close();
200 trustdom_cache_shutdown();
202 gencache_stabilize();
204 #if 0
205 if (interactive) {
206 TALLOC_CTX *mem_ctx = talloc_init("end_description");
207 char *description = talloc_describe_all(mem_ctx);
209 DEBUG(3, ("tallocs left:\n%s\n", description));
210 talloc_destroy(mem_ctx);
212 #endif
214 if (is_parent) {
215 struct messaging_context *msg = winbind_messaging_context();
216 struct server_id self = messaging_server_id(msg);
217 serverid_deregister(self);
218 pidfile_unlink(lp_piddir(), "winbindd");
221 exit(0);
224 static void winbindd_sig_term_handler(struct tevent_context *ev,
225 struct tevent_signal *se,
226 int signum,
227 int count,
228 void *siginfo,
229 void *private_data)
231 bool *is_parent = talloc_get_type_abort(private_data, bool);
233 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
234 signum, (int)*is_parent));
235 terminate(*is_parent);
239 handle stdin becoming readable when we are in --foreground mode
241 static void winbindd_stdin_handler(struct tevent_context *ev,
242 struct tevent_fd *fde,
243 uint16_t flags,
244 void *private_data)
246 char c;
247 if (read(0, &c, 1) != 1) {
248 bool *is_parent = talloc_get_type_abort(private_data, bool);
250 /* we have reached EOF on stdin, which means the
251 parent has exited. Shutdown the server */
252 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
253 (int)*is_parent));
254 terminate(*is_parent);
258 bool winbindd_setup_sig_term_handler(bool parent)
260 struct tevent_signal *se;
261 bool *is_parent;
263 is_parent = talloc(winbind_event_context(), bool);
264 if (!is_parent) {
265 return false;
268 *is_parent = parent;
270 se = tevent_add_signal(winbind_event_context(),
271 is_parent,
272 SIGTERM, 0,
273 winbindd_sig_term_handler,
274 is_parent);
275 if (!se) {
276 DEBUG(0,("failed to setup SIGTERM handler"));
277 talloc_free(is_parent);
278 return false;
281 se = tevent_add_signal(winbind_event_context(),
282 is_parent,
283 SIGINT, 0,
284 winbindd_sig_term_handler,
285 is_parent);
286 if (!se) {
287 DEBUG(0,("failed to setup SIGINT handler"));
288 talloc_free(is_parent);
289 return false;
292 se = tevent_add_signal(winbind_event_context(),
293 is_parent,
294 SIGQUIT, 0,
295 winbindd_sig_term_handler,
296 is_parent);
297 if (!se) {
298 DEBUG(0,("failed to setup SIGINT handler"));
299 talloc_free(is_parent);
300 return false;
303 return true;
306 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
308 bool *is_parent;
310 if (foreground) {
311 struct stat st;
313 is_parent = talloc(winbind_event_context(), bool);
314 if (!is_parent) {
315 return false;
318 *is_parent = parent;
320 /* if we are running in the foreground then look for
321 EOF on stdin, and exit if it happens. This allows
322 us to die if the parent process dies
323 Only do this on a pipe or socket, no other device.
325 if (fstat(0, &st) != 0) {
326 return false;
328 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
329 tevent_add_fd(winbind_event_context(),
330 is_parent,
332 TEVENT_FD_READ,
333 winbindd_stdin_handler,
334 is_parent);
338 return true;
341 static void winbindd_sig_hup_handler(struct tevent_context *ev,
342 struct tevent_signal *se,
343 int signum,
344 int count,
345 void *siginfo,
346 void *private_data)
348 const char *file = (const char *)private_data;
350 DEBUG(1,("Reloading services after SIGHUP\n"));
351 flush_caches_noinit();
352 reload_services_file(file);
355 bool winbindd_setup_sig_hup_handler(const char *lfile)
357 struct tevent_signal *se;
358 char *file = NULL;
360 if (lfile) {
361 file = talloc_strdup(winbind_event_context(),
362 lfile);
363 if (!file) {
364 return false;
368 se = tevent_add_signal(winbind_event_context(),
369 winbind_event_context(),
370 SIGHUP, 0,
371 winbindd_sig_hup_handler,
372 file);
373 if (!se) {
374 return false;
377 return true;
380 static void winbindd_sig_chld_handler(struct tevent_context *ev,
381 struct tevent_signal *se,
382 int signum,
383 int count,
384 void *siginfo,
385 void *private_data)
387 pid_t pid;
389 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
390 winbind_child_died(pid);
394 static bool winbindd_setup_sig_chld_handler(void)
396 struct tevent_signal *se;
398 se = tevent_add_signal(winbind_event_context(),
399 winbind_event_context(),
400 SIGCHLD, 0,
401 winbindd_sig_chld_handler,
402 NULL);
403 if (!se) {
404 return false;
407 return true;
410 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
411 struct tevent_signal *se,
412 int signum,
413 int count,
414 void *siginfo,
415 void *private_data)
417 winbindd_status();
420 static bool winbindd_setup_sig_usr2_handler(void)
422 struct tevent_signal *se;
424 se = tevent_add_signal(winbind_event_context(),
425 winbind_event_context(),
426 SIGUSR2, 0,
427 winbindd_sig_usr2_handler,
428 NULL);
429 if (!se) {
430 return false;
433 return true;
436 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
437 static void msg_reload_services(struct messaging_context *msg,
438 void *private_data,
439 uint32_t msg_type,
440 struct server_id server_id,
441 DATA_BLOB *data)
443 /* Flush various caches */
444 flush_caches();
445 reload_services_file((const char *) private_data);
448 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
449 static void msg_shutdown(struct messaging_context *msg,
450 void *private_data,
451 uint32_t msg_type,
452 struct server_id server_id,
453 DATA_BLOB *data)
455 /* only the parent waits for this message */
456 DEBUG(0,("Got shutdown message\n"));
457 terminate(true);
461 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
462 void *private_data,
463 uint32_t msg_type,
464 struct server_id server_id,
465 DATA_BLOB *data)
467 uint8 ret;
468 pid_t child_pid;
469 NTSTATUS status;
471 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
472 "message.\n"));
475 * call the validation code from a child:
476 * so we don't block the main winbindd and the validation
477 * code can safely use fork/waitpid...
479 child_pid = fork();
481 if (child_pid == -1) {
482 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
483 strerror(errno)));
484 return;
487 if (child_pid != 0) {
488 /* parent */
489 DEBUG(5, ("winbind_msg_validate_cache: child created with "
490 "pid %d.\n", (int)child_pid));
491 return;
494 /* child */
496 status = winbindd_reinit_after_fork(NULL, NULL);
497 if (!NT_STATUS_IS_OK(status)) {
498 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
499 nt_errstr(status)));
500 _exit(0);
503 /* install default SIGCHLD handler: validation code uses fork/waitpid */
504 CatchSignal(SIGCHLD, SIG_DFL);
506 ret = (uint8)winbindd_validate_cache_nobackup();
507 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
508 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
509 (size_t)1);
510 _exit(0);
513 static struct winbindd_dispatch_table {
514 enum winbindd_cmd cmd;
515 void (*fn)(struct winbindd_cli_state *state);
516 const char *winbindd_cmd_name;
517 } dispatch_table[] = {
519 /* Enumeration functions */
521 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
522 "LIST_TRUSTDOM" },
524 /* Miscellaneous */
526 { WINBINDD_INFO, winbindd_info, "INFO" },
527 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
528 "INTERFACE_VERSION" },
529 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
530 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
531 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
532 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
533 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
534 "WINBINDD_PRIV_PIPE_DIR" },
536 /* Credential cache access */
537 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
538 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
540 /* End of list */
542 { WINBINDD_NUM_CMDS, NULL, "NONE" }
545 struct winbindd_async_dispatch_table {
546 enum winbindd_cmd cmd;
547 const char *cmd_name;
548 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
549 struct tevent_context *ev,
550 struct winbindd_cli_state *cli,
551 struct winbindd_request *request);
552 NTSTATUS (*recv_req)(struct tevent_req *req,
553 struct winbindd_response *presp);
556 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
557 { WINBINDD_PING, "PING",
558 wb_ping_send, wb_ping_recv },
559 { WINBINDD_LOOKUPSID, "LOOKUPSID",
560 winbindd_lookupsid_send, winbindd_lookupsid_recv },
561 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
562 winbindd_lookupsids_send, winbindd_lookupsids_recv },
563 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
564 winbindd_lookupname_send, winbindd_lookupname_recv },
565 { WINBINDD_SID_TO_UID, "SID_TO_UID",
566 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
567 { WINBINDD_SID_TO_GID, "SID_TO_GID",
568 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
569 { WINBINDD_UID_TO_SID, "UID_TO_SID",
570 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
571 { WINBINDD_GID_TO_SID, "GID_TO_SID",
572 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
573 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
574 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
575 { WINBINDD_GETPWSID, "GETPWSID",
576 winbindd_getpwsid_send, winbindd_getpwsid_recv },
577 { WINBINDD_GETPWNAM, "GETPWNAM",
578 winbindd_getpwnam_send, winbindd_getpwnam_recv },
579 { WINBINDD_GETPWUID, "GETPWUID",
580 winbindd_getpwuid_send, winbindd_getpwuid_recv },
581 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
582 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
583 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
584 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
585 { WINBINDD_GETGROUPS, "GETGROUPS",
586 winbindd_getgroups_send, winbindd_getgroups_recv },
587 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
588 winbindd_show_sequence_send, winbindd_show_sequence_recv },
589 { WINBINDD_GETGRGID, "GETGRGID",
590 winbindd_getgrgid_send, winbindd_getgrgid_recv },
591 { WINBINDD_GETGRNAM, "GETGRNAM",
592 winbindd_getgrnam_send, winbindd_getgrnam_recv },
593 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
594 winbindd_getusersids_send, winbindd_getusersids_recv },
595 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
596 winbindd_lookuprids_send, winbindd_lookuprids_recv },
597 { WINBINDD_SETPWENT, "SETPWENT",
598 winbindd_setpwent_send, winbindd_setpwent_recv },
599 { WINBINDD_GETPWENT, "GETPWENT",
600 winbindd_getpwent_send, winbindd_getpwent_recv },
601 { WINBINDD_ENDPWENT, "ENDPWENT",
602 winbindd_endpwent_send, winbindd_endpwent_recv },
603 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
604 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
605 { WINBINDD_GETDCNAME, "GETDCNAME",
606 winbindd_getdcname_send, winbindd_getdcname_recv },
607 { WINBINDD_SETGRENT, "SETGRENT",
608 winbindd_setgrent_send, winbindd_setgrent_recv },
609 { WINBINDD_GETGRENT, "GETGRENT",
610 winbindd_getgrent_send, winbindd_getgrent_recv },
611 { WINBINDD_ENDGRENT, "ENDGRENT",
612 winbindd_endgrent_send, winbindd_endgrent_recv },
613 { WINBINDD_LIST_USERS, "LIST_USERS",
614 winbindd_list_users_send, winbindd_list_users_recv },
615 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
616 winbindd_list_groups_send, winbindd_list_groups_recv },
617 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
618 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
619 { WINBINDD_PING_DC, "PING_DC",
620 winbindd_ping_dc_send, winbindd_ping_dc_recv },
621 { WINBINDD_PAM_AUTH, "PAM_AUTH",
622 winbindd_pam_auth_send, winbindd_pam_auth_recv },
623 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
624 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
625 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
626 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
627 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
628 winbindd_pam_chng_pswd_auth_crap_send,
629 winbindd_pam_chng_pswd_auth_crap_recv },
630 { WINBINDD_WINS_BYIP, "WINS_BYIP",
631 winbindd_wins_byip_send, winbindd_wins_byip_recv },
632 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
633 winbindd_wins_byname_send, winbindd_wins_byname_recv },
635 { 0, NULL, NULL, NULL }
638 static struct winbindd_async_dispatch_table async_priv_table[] = {
639 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
640 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
641 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
642 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
643 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
644 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
645 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
646 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
648 { 0, NULL, NULL, NULL }
651 static void wb_request_done(struct tevent_req *req);
653 static void process_request(struct winbindd_cli_state *state)
655 struct winbindd_dispatch_table *table = dispatch_table;
656 struct winbindd_async_dispatch_table *atable;
658 state->mem_ctx = talloc_named(state, 0, "winbind request");
659 if (state->mem_ctx == NULL)
660 return;
662 /* Remember who asked us. */
663 state->pid = state->request->pid;
665 state->cmd_name = "unknown request";
666 state->recv_fn = NULL;
667 state->last_access = time(NULL);
669 /* Process command */
671 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
672 if (state->request->cmd == atable->cmd) {
673 break;
677 if ((atable->send_req == NULL) && state->privileged) {
678 for (atable = async_priv_table; atable->send_req;
679 atable += 1) {
680 if (state->request->cmd == atable->cmd) {
681 break;
686 if (atable->send_req != NULL) {
687 struct tevent_req *req;
689 state->cmd_name = atable->cmd_name;
690 state->recv_fn = atable->recv_req;
692 DEBUG(10, ("process_request: Handling async request %d:%s\n",
693 (int)state->pid, state->cmd_name));
695 req = atable->send_req(state->mem_ctx, winbind_event_context(),
696 state, state->request);
697 if (req == NULL) {
698 DEBUG(0, ("process_request: atable->send failed for "
699 "%s\n", atable->cmd_name));
700 request_error(state);
701 return;
703 tevent_req_set_callback(req, wb_request_done, state);
704 return;
707 state->response = talloc_zero(state->mem_ctx,
708 struct winbindd_response);
709 if (state->response == NULL) {
710 DEBUG(10, ("talloc failed\n"));
711 remove_client(state);
712 return;
714 state->response->result = WINBINDD_PENDING;
715 state->response->length = sizeof(struct winbindd_response);
717 for (table = dispatch_table; table->fn; table++) {
718 if (state->request->cmd == table->cmd) {
719 DEBUG(10,("process_request: request fn %s\n",
720 table->winbindd_cmd_name ));
721 state->cmd_name = table->winbindd_cmd_name;
722 table->fn(state);
723 break;
727 if (!table->fn) {
728 DEBUG(10,("process_request: unknown request fn number %d\n",
729 (int)state->request->cmd ));
730 request_error(state);
734 static void wb_request_done(struct tevent_req *req)
736 struct winbindd_cli_state *state = tevent_req_callback_data(
737 req, struct winbindd_cli_state);
738 NTSTATUS status;
740 state->response = talloc_zero(state->mem_ctx,
741 struct winbindd_response);
742 if (state->response == NULL) {
743 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
744 (int)state->pid, state->cmd_name));
745 remove_client(state);
746 return;
748 state->response->result = WINBINDD_PENDING;
749 state->response->length = sizeof(struct winbindd_response);
751 status = state->recv_fn(req, state->response);
752 TALLOC_FREE(req);
754 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
755 (int)state->pid, state->cmd_name, nt_errstr(status)));
757 if (!NT_STATUS_IS_OK(status)) {
758 request_error(state);
759 return;
761 request_ok(state);
765 * This is the main event loop of winbind requests. It goes through a
766 * state-machine of 3 read/write requests, 4 if you have extra data to send.
768 * An idle winbind client has a read request of 4 bytes outstanding,
769 * finalizing function is request_len_recv, checking the length. request_recv
770 * then processes the packet. The processing function then at some point has
771 * to call request_finished which schedules sending the response.
774 static void request_finished(struct winbindd_cli_state *state);
776 static void winbind_client_request_read(struct tevent_req *req);
777 static void winbind_client_response_written(struct tevent_req *req);
779 static void request_finished(struct winbindd_cli_state *state)
781 struct tevent_req *req;
783 TALLOC_FREE(state->request);
785 req = wb_resp_write_send(state, winbind_event_context(),
786 state->out_queue, state->sock,
787 state->response);
788 if (req == NULL) {
789 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
790 (int)state->pid, state->cmd_name));
791 remove_client(state);
792 return;
794 tevent_req_set_callback(req, winbind_client_response_written, state);
797 static void winbind_client_response_written(struct tevent_req *req)
799 struct winbindd_cli_state *state = tevent_req_callback_data(
800 req, struct winbindd_cli_state);
801 ssize_t ret;
802 int err;
804 ret = wb_resp_write_recv(req, &err);
805 TALLOC_FREE(req);
806 if (ret == -1) {
807 close(state->sock);
808 state->sock = -1;
809 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
810 (int)state->pid, state->cmd_name, strerror(err)));
811 remove_client(state);
812 return;
815 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
816 "to client\n", (int)state->pid, state->cmd_name));
818 TALLOC_FREE(state->mem_ctx);
819 state->response = NULL;
820 state->cmd_name = "no request";
821 state->recv_fn = NULL;
823 req = wb_req_read_send(state, winbind_event_context(), state->sock,
824 WINBINDD_MAX_EXTRA_DATA);
825 if (req == NULL) {
826 remove_client(state);
827 return;
829 tevent_req_set_callback(req, winbind_client_request_read, state);
832 void request_error(struct winbindd_cli_state *state)
834 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
835 state->response->result = WINBINDD_ERROR;
836 request_finished(state);
839 void request_ok(struct winbindd_cli_state *state)
841 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
842 state->response->result = WINBINDD_OK;
843 request_finished(state);
846 /* Process a new connection by adding it to the client connection list */
848 static void new_connection(int listen_sock, bool privileged)
850 struct sockaddr_un sunaddr;
851 struct winbindd_cli_state *state;
852 struct tevent_req *req;
853 socklen_t len;
854 int sock;
856 /* Accept connection */
858 len = sizeof(sunaddr);
860 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
862 if (sock == -1) {
863 if (errno != EINTR) {
864 DEBUG(0, ("Failed to accept socket - %s\n",
865 strerror(errno)));
867 return;
870 DEBUG(6,("accepted socket %d\n", sock));
872 /* Create new connection structure */
874 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
875 close(sock);
876 return;
879 state->sock = sock;
881 state->out_queue = tevent_queue_create(state, "winbind client reply");
882 if (state->out_queue == NULL) {
883 close(sock);
884 TALLOC_FREE(state);
885 return;
888 state->last_access = time(NULL);
890 state->privileged = privileged;
892 req = wb_req_read_send(state, winbind_event_context(), state->sock,
893 WINBINDD_MAX_EXTRA_DATA);
894 if (req == NULL) {
895 TALLOC_FREE(state);
896 close(sock);
897 return;
899 tevent_req_set_callback(req, winbind_client_request_read, state);
901 /* Add to connection list */
903 winbindd_add_client(state);
906 static void winbind_client_request_read(struct tevent_req *req)
908 struct winbindd_cli_state *state = tevent_req_callback_data(
909 req, struct winbindd_cli_state);
910 ssize_t ret;
911 int err;
913 ret = wb_req_read_recv(req, state, &state->request, &err);
914 TALLOC_FREE(req);
915 if (ret == -1) {
916 if (err == EPIPE) {
917 DEBUG(6, ("closing socket %d, client exited\n",
918 state->sock));
919 } else {
920 DEBUG(2, ("Could not read client request from fd %d: "
921 "%s\n", state->sock, strerror(err)));
923 close(state->sock);
924 state->sock = -1;
925 remove_client(state);
926 return;
928 process_request(state);
931 /* Remove a client connection from client connection list */
933 static void remove_client(struct winbindd_cli_state *state)
935 char c = 0;
936 int nwritten;
938 /* It's a dead client - hold a funeral */
940 if (state == NULL) {
941 return;
944 if (state->sock != -1) {
945 /* tell client, we are closing ... */
946 nwritten = write(state->sock, &c, sizeof(c));
947 if (nwritten == -1) {
948 DEBUG(2, ("final write to client failed: %s\n",
949 strerror(errno)));
952 /* Close socket */
954 close(state->sock);
955 state->sock = -1;
958 TALLOC_FREE(state->mem_ctx);
960 /* Remove from list and free */
962 winbindd_remove_client(state);
963 TALLOC_FREE(state);
966 /* Is a client idle? */
968 static bool client_is_idle(struct winbindd_cli_state *state) {
969 return (state->request == NULL &&
970 state->response == NULL &&
971 !state->pwent_state && !state->grent_state);
974 /* Shutdown client connection which has been idle for the longest time */
976 static bool remove_idle_client(void)
978 struct winbindd_cli_state *state, *remove_state = NULL;
979 time_t last_access = 0;
980 int nidle = 0;
982 for (state = winbindd_client_list(); state; state = state->next) {
983 if (client_is_idle(state)) {
984 nidle++;
985 if (!last_access || state->last_access < last_access) {
986 last_access = state->last_access;
987 remove_state = state;
992 if (remove_state) {
993 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
994 nidle, remove_state->sock, (unsigned int)remove_state->pid));
995 remove_client(remove_state);
996 return True;
999 return False;
1003 * Terminate all clients whose requests have taken longer than
1004 * "winbind request timeout" seconds to process, or have been
1005 * idle for more than "winbind request timeout" seconds.
1008 static void remove_timed_out_clients(void)
1010 struct winbindd_cli_state *state, *next = NULL;
1011 time_t curr_time = time(NULL);
1012 int timeout_val = lp_winbind_request_timeout();
1014 for (state = winbindd_client_list(); state; state = next) {
1015 time_t expiry_time;
1017 next = state->next;
1018 expiry_time = state->last_access + timeout_val;
1020 if (curr_time > expiry_time) {
1021 if (client_is_idle(state)) {
1022 DEBUG(5,("Idle client timed out, "
1023 "shutting down sock %d, pid %u\n",
1024 state->sock,
1025 (unsigned int)state->pid));
1026 } else {
1027 DEBUG(5,("Client request timed out, "
1028 "shutting down sock %d, pid %u\n",
1029 state->sock,
1030 (unsigned int)state->pid));
1032 remove_client(state);
1037 struct winbindd_listen_state {
1038 bool privileged;
1039 int fd;
1042 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1043 struct tevent_fd *fde,
1044 uint16_t flags,
1045 void *private_data)
1047 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1048 struct winbindd_listen_state);
1050 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1051 DEBUG(5,("winbindd: Exceeding %d client "
1052 "connections, removing idle "
1053 "connection.\n", lp_winbind_max_clients()));
1054 if (!remove_idle_client()) {
1055 DEBUG(0,("winbindd: Exceeding %d "
1056 "client connections, no idle "
1057 "connection found\n",
1058 lp_winbind_max_clients()));
1059 break;
1062 remove_timed_out_clients();
1063 new_connection(s->fd, s->privileged);
1067 * Winbindd socket accessor functions
1070 const char *get_winbind_pipe_dir(void)
1072 return lp_parm_const_string(-1, "winbindd", "socket dir", get_dyn_WINBINDD_SOCKET_DIR());
1075 char *get_winbind_priv_pipe_dir(void)
1077 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1080 static bool winbindd_setup_listeners(void)
1082 struct winbindd_listen_state *pub_state = NULL;
1083 struct winbindd_listen_state *priv_state = NULL;
1084 struct tevent_fd *fde;
1085 int rc;
1087 pub_state = talloc(winbind_event_context(),
1088 struct winbindd_listen_state);
1089 if (!pub_state) {
1090 goto failed;
1093 pub_state->privileged = false;
1094 pub_state->fd = create_pipe_sock(
1095 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755);
1096 if (pub_state->fd == -1) {
1097 goto failed;
1099 rc = listen(pub_state->fd, 5);
1100 if (rc < 0) {
1101 goto failed;
1104 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1105 TEVENT_FD_READ, winbindd_listen_fde_handler,
1106 pub_state);
1107 if (fde == NULL) {
1108 close(pub_state->fd);
1109 goto failed;
1111 tevent_fd_set_auto_close(fde);
1113 priv_state = talloc(winbind_event_context(),
1114 struct winbindd_listen_state);
1115 if (!priv_state) {
1116 goto failed;
1119 priv_state->privileged = true;
1120 priv_state->fd = create_pipe_sock(
1121 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
1122 if (priv_state->fd == -1) {
1123 goto failed;
1125 rc = listen(priv_state->fd, 5);
1126 if (rc < 0) {
1127 goto failed;
1130 fde = tevent_add_fd(winbind_event_context(), priv_state,
1131 priv_state->fd, TEVENT_FD_READ,
1132 winbindd_listen_fde_handler, priv_state);
1133 if (fde == NULL) {
1134 close(priv_state->fd);
1135 goto failed;
1137 tevent_fd_set_auto_close(fde);
1139 return true;
1140 failed:
1141 TALLOC_FREE(pub_state);
1142 TALLOC_FREE(priv_state);
1143 return false;
1146 bool winbindd_use_idmap_cache(void)
1148 return !opt_nocache;
1151 bool winbindd_use_cache(void)
1153 return !opt_nocache;
1156 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1157 bool foreground)
1159 /* Setup signal handlers */
1161 if (!winbindd_setup_sig_term_handler(true))
1162 exit(1);
1163 if (!winbindd_setup_stdin_handler(true, foreground))
1164 exit(1);
1165 if (!winbindd_setup_sig_hup_handler(NULL))
1166 exit(1);
1167 if (!winbindd_setup_sig_chld_handler())
1168 exit(1);
1169 if (!winbindd_setup_sig_usr2_handler())
1170 exit(1);
1172 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1175 * Ensure all cache and idmap caches are consistent
1176 * and initialized before we startup.
1178 if (!winbindd_cache_validate_and_initialize()) {
1179 exit(1);
1182 /* get broadcast messages */
1184 if (!serverid_register(messaging_server_id(msg_ctx),
1185 FLAG_MSG_GENERAL |
1186 FLAG_MSG_WINBIND |
1187 FLAG_MSG_DBWRAP)) {
1188 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1189 exit(1);
1192 /* React on 'smbcontrol winbindd reload-config' in the same way
1193 as to SIGHUP signal */
1194 messaging_register(msg_ctx, NULL,
1195 MSG_SMB_CONF_UPDATED, msg_reload_services);
1196 messaging_register(msg_ctx, NULL,
1197 MSG_SHUTDOWN, msg_shutdown);
1199 /* Handle online/offline messages. */
1200 messaging_register(msg_ctx, NULL,
1201 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1202 messaging_register(msg_ctx, NULL,
1203 MSG_WINBIND_ONLINE, winbind_msg_online);
1204 messaging_register(msg_ctx, NULL,
1205 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1207 /* Handle domain online/offline messages for domains */
1208 messaging_register(winbind_messaging_context(), NULL,
1209 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1210 messaging_register(winbind_messaging_context(), NULL,
1211 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1213 messaging_register(msg_ctx, NULL,
1214 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1216 messaging_register(msg_ctx, NULL,
1217 MSG_WINBIND_VALIDATE_CACHE,
1218 winbind_msg_validate_cache);
1220 messaging_register(msg_ctx, NULL,
1221 MSG_WINBIND_DUMP_DOMAIN_LIST,
1222 winbind_msg_dump_domain_list);
1224 messaging_register(msg_ctx, NULL,
1225 MSG_WINBIND_IP_DROPPED,
1226 winbind_msg_ip_dropped_parent);
1228 /* Register handler for MSG_DEBUG. */
1229 messaging_register(msg_ctx, NULL,
1230 MSG_DEBUG,
1231 winbind_msg_debug);
1233 netsamlogon_cache_init(); /* Non-critical */
1235 /* clear the cached list of trusted domains */
1237 wcache_tdc_clear();
1239 if (!init_domain_list()) {
1240 DEBUG(0,("unable to initialize domain list\n"));
1241 exit(1);
1244 init_idmap_child();
1245 init_locator_child();
1247 smb_nscd_flush_user_cache();
1248 smb_nscd_flush_group_cache();
1250 if (lp_allow_trusted_domains()) {
1251 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1252 rescan_trusted_domains, NULL) == NULL) {
1253 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1254 exit(1);
1260 struct winbindd_addrchanged_state {
1261 struct addrchange_context *ctx;
1262 struct tevent_context *ev;
1263 struct messaging_context *msg_ctx;
1266 static void winbindd_addr_changed(struct tevent_req *req);
1268 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1269 struct tevent_context *ev,
1270 struct messaging_context *msg_ctx)
1272 struct winbindd_addrchanged_state *state;
1273 struct tevent_req *req;
1274 NTSTATUS status;
1276 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1277 if (state == NULL) {
1278 DEBUG(10, ("talloc failed\n"));
1279 return;
1281 state->ev = ev;
1282 state->msg_ctx = msg_ctx;
1284 status = addrchange_context_create(state, &state->ctx);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 DEBUG(10, ("addrchange_context_create failed: %s\n",
1287 nt_errstr(status)));
1288 TALLOC_FREE(state);
1289 return;
1291 req = addrchange_send(state, ev, state->ctx);
1292 if (req == NULL) {
1293 DEBUG(0, ("addrchange_send failed\n"));
1294 TALLOC_FREE(state);
1295 return;
1297 tevent_req_set_callback(req, winbindd_addr_changed, state);
1300 static void winbindd_addr_changed(struct tevent_req *req)
1302 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1303 req, struct winbindd_addrchanged_state);
1304 enum addrchange_type type;
1305 struct sockaddr_storage addr;
1306 NTSTATUS status;
1308 status = addrchange_recv(req, &type, &addr);
1309 TALLOC_FREE(req);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1312 nt_errstr(status)));
1313 TALLOC_FREE(state);
1314 return;
1316 if (type == ADDRCHANGE_DEL) {
1317 char addrstr[INET6_ADDRSTRLEN];
1318 DATA_BLOB blob;
1320 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1322 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1323 addrstr));
1325 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1327 status = messaging_send(state->msg_ctx,
1328 messaging_server_id(state->msg_ctx),
1329 MSG_WINBIND_IP_DROPPED, &blob);
1330 if (!NT_STATUS_IS_OK(status)) {
1331 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1332 nt_errstr(status)));
1335 req = addrchange_send(state, state->ev, state->ctx);
1336 if (req == NULL) {
1337 DEBUG(0, ("addrchange_send failed\n"));
1338 TALLOC_FREE(state);
1339 return;
1341 tevent_req_set_callback(req, winbindd_addr_changed, state);
1344 /* Main function */
1346 int main(int argc, char **argv, char **envp)
1348 static bool is_daemon = False;
1349 static bool Fork = True;
1350 static bool log_stdout = False;
1351 static bool no_process_group = False;
1352 enum {
1353 OPT_DAEMON = 1000,
1354 OPT_FORK,
1355 OPT_NO_PROCESS_GROUP,
1356 OPT_LOG_STDOUT
1358 struct poptOption long_options[] = {
1359 POPT_AUTOHELP
1360 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1361 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1362 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1363 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1364 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1365 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1366 POPT_COMMON_SAMBA
1367 POPT_COMMON_DYNCONFIG
1368 POPT_TABLEEND
1370 poptContext pc;
1371 int opt;
1372 TALLOC_CTX *frame;
1373 NTSTATUS status;
1374 bool ok;
1377 * Do this before any other talloc operation
1379 talloc_enable_null_tracking();
1380 frame = talloc_stackframe();
1383 * We want total control over the permissions on created files,
1384 * so set our umask to 0.
1386 umask(0);
1388 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1390 /* glibc (?) likes to print "User defined signal 1" and exit if a
1391 SIGUSR[12] is received before a handler is installed */
1393 CatchSignal(SIGUSR1, SIG_IGN);
1394 CatchSignal(SIGUSR2, SIG_IGN);
1396 fault_setup();
1397 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1399 load_case_tables();
1401 /* Initialise for running in non-root mode */
1403 sec_init();
1405 set_remote_machine_name("winbindd", False);
1407 /* Set environment variable so we don't recursively call ourselves.
1408 This may also be useful interactively. */
1410 if ( !winbind_off() ) {
1411 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1412 exit(1);
1415 /* Initialise samba/rpc client stuff */
1417 pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, 0);
1419 while ((opt = poptGetNextOpt(pc)) != -1) {
1420 switch (opt) {
1421 /* Don't become a daemon */
1422 case OPT_DAEMON:
1423 is_daemon = True;
1424 break;
1425 case 'i':
1426 interactive = True;
1427 log_stdout = True;
1428 Fork = False;
1429 break;
1430 case OPT_FORK:
1431 Fork = false;
1432 break;
1433 case OPT_NO_PROCESS_GROUP:
1434 no_process_group = true;
1435 break;
1436 case OPT_LOG_STDOUT:
1437 log_stdout = true;
1438 break;
1439 case 'n':
1440 opt_nocache = true;
1441 break;
1442 default:
1443 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1444 poptBadOption(pc, 0), poptStrerror(opt));
1445 poptPrintUsage(pc, stderr, 0);
1446 exit(1);
1450 /* We call dump_core_setup one more time because the command line can
1451 * set the log file or the log-basename and this will influence where
1452 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1453 * the default value derived from build's prefix. For EOM this value
1454 * is often not related to the path where winbindd is actually run
1455 * in production.
1457 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1458 if (is_daemon && interactive) {
1459 d_fprintf(stderr,"\nERROR: "
1460 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1461 poptPrintUsage(pc, stderr, 0);
1462 exit(1);
1465 if (log_stdout && Fork) {
1466 d_fprintf(stderr, "\nERROR: "
1467 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1468 poptPrintUsage(pc, stderr, 0);
1469 exit(1);
1472 poptFreeContext(pc);
1474 if (!override_logfile) {
1475 char *lfile = NULL;
1476 if (asprintf(&lfile,"%s/log.winbindd",
1477 get_dyn_LOGFILEBASE()) > 0) {
1478 lp_set_logfile(lfile);
1479 SAFE_FREE(lfile);
1483 if (log_stdout) {
1484 setup_logging("winbindd", DEBUG_STDOUT);
1485 } else {
1486 setup_logging("winbindd", DEBUG_FILE);
1488 reopen_logs();
1490 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1491 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1493 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1494 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1495 exit(1);
1497 /* After parsing the configuration file we setup the core path one more time
1498 * as the log file might have been set in the configuration and cores's
1499 * path is by default basename(lp_logfile()).
1501 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1503 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1504 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1505 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"));
1506 exit(1);
1509 /* Initialise messaging system */
1511 if (winbind_messaging_context() == NULL) {
1512 exit(1);
1515 if (!reload_services_file(NULL)) {
1516 DEBUG(0, ("error opening config file\n"));
1517 exit(1);
1520 ok = directory_create_or_exist(lp_lockdir(), geteuid(), 0755);
1521 if (!ok) {
1522 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1523 lp_lockdir(), strerror(errno)));
1524 exit(1);
1527 ok = directory_create_or_exist(lp_piddir(), geteuid(), 0755);
1528 if (!ok) {
1529 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1530 lp_piddir(), strerror(errno)));
1531 exit(1);
1534 /* Setup names. */
1536 if (!init_names())
1537 exit(1);
1539 load_interfaces();
1541 if (!secrets_init()) {
1543 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1544 return False;
1547 /* Unblock all signals we are interested in as they may have been
1548 blocked by the parent process. */
1550 BlockSignals(False, SIGINT);
1551 BlockSignals(False, SIGQUIT);
1552 BlockSignals(False, SIGTERM);
1553 BlockSignals(False, SIGUSR1);
1554 BlockSignals(False, SIGUSR2);
1555 BlockSignals(False, SIGHUP);
1556 BlockSignals(False, SIGCHLD);
1558 if (!interactive)
1559 become_daemon(Fork, no_process_group, log_stdout);
1561 pidfile_create(lp_piddir(), "winbindd");
1563 #if HAVE_SETPGID
1565 * If we're interactive we want to set our own process group for
1566 * signal management.
1568 if (interactive && !no_process_group)
1569 setpgid( (pid_t)0, (pid_t)0);
1570 #endif
1572 TimeInit();
1574 /* Don't use winbindd_reinit_after_fork here as
1575 * we're just starting up and haven't created any
1576 * winbindd-specific resources we must free yet. JRA.
1579 status = reinit_after_fork(winbind_messaging_context(),
1580 winbind_event_context(),
1581 false);
1582 if (!NT_STATUS_IS_OK(status)) {
1583 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1587 * Do not initialize the parent-child-pipe before becoming
1588 * a daemon: this is used to detect a died parent in the child
1589 * process.
1591 status = init_before_fork();
1592 if (!NT_STATUS_IS_OK(status)) {
1593 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1596 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1598 status = init_system_session_info();
1599 if (!NT_STATUS_IS_OK(status)) {
1600 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1603 rpc_lsarpc_init(NULL);
1604 rpc_samr_init(NULL);
1606 winbindd_init_addrchange(NULL, winbind_event_context(),
1607 winbind_messaging_context());
1609 /* setup listen sockets */
1611 if (!winbindd_setup_listeners()) {
1612 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1615 TALLOC_FREE(frame);
1617 if (!interactive) {
1618 daemon_ready("winbindd");
1621 /* Loop waiting for requests */
1622 while (1) {
1623 frame = talloc_stackframe();
1625 if (tevent_loop_once(winbind_event_context()) == -1) {
1626 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1627 strerror(errno)));
1628 return 1;
1631 TALLOC_FREE(frame);
1634 return 0;