ctdb-docs: Document configuration variable CTDB_NFS_CHECKS_DIR
[Samba.git] / source3 / winbindd / winbindd.c
blob2cd200142673f9c15f4f15952fb48180d1c21520
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 "lib/async_req/async_sock.h"
46 #include "libsmb/samlogon_cache.h"
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_WINBIND
51 #define SCRUB_CLIENTS_INTERVAL 5
53 static bool client_is_idle(struct winbindd_cli_state *state);
54 static void remove_client(struct winbindd_cli_state *state);
55 static void winbindd_setup_max_fds(void);
57 static bool opt_nocache = False;
58 static bool interactive = False;
60 extern bool override_logfile;
62 struct tevent_context *winbind_event_context(void)
64 static struct tevent_context *ev = NULL;
66 if (ev != NULL) {
67 return ev;
71 * Note we MUST use the NULL context here, not the autofree context,
72 * to avoid side effects in forked children exiting.
74 ev = samba_tevent_context_init(NULL);
75 if (ev == NULL) {
76 smb_panic("Could not init winbindd's messaging context.\n");
78 return ev;
81 struct messaging_context *winbind_messaging_context(void)
83 static struct messaging_context *msg = NULL;
85 if (msg != NULL) {
86 return msg;
90 * Note we MUST use the NULL context here, not the autofree context,
91 * to avoid side effects in forked children exiting.
93 msg = messaging_init(NULL, winbind_event_context());
94 if (msg == NULL) {
95 smb_panic("Could not init winbindd's messaging context.\n");
97 return msg;
100 struct imessaging_context *winbind_imessaging_context(void)
102 static struct imessaging_context *msg = NULL;
103 struct messaging_context *msg_ctx;
104 struct server_id myself;
105 struct loadparm_context *lp_ctx;
107 if (msg != NULL) {
108 return msg;
111 msg_ctx = server_messaging_context();
112 if (msg_ctx == NULL) {
113 smb_panic("server_messaging_context failed\n");
115 myself = messaging_server_id(msg_ctx);
117 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
118 if (lp_ctx == NULL) {
119 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
123 * Note we MUST use the NULL context here, not the autofree context,
124 * to avoid side effects in forked children exiting.
126 msg = imessaging_init(NULL, lp_ctx, myself, winbind_event_context());
127 talloc_unlink(NULL, lp_ctx);
129 if (msg == NULL) {
130 smb_panic("Could not init winbindd's messaging context.\n");
132 return msg;
135 /* Reload configuration */
137 static bool reload_services_file(const char *lfile)
139 bool ret;
141 if (lp_loaded()) {
142 char *fname = lp_next_configfile(talloc_tos());
144 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
145 set_dyn_CONFIGFILE(fname);
147 TALLOC_FREE(fname);
150 /* if this is a child, restore the logfile to the special
151 name - <domain>, idmap, etc. */
152 if (lfile && *lfile) {
153 lp_set_logfile(lfile);
156 reopen_logs();
157 ret = lp_load_global(get_dyn_CONFIGFILE());
159 reopen_logs();
160 load_interfaces();
161 winbindd_setup_max_fds();
163 return(ret);
167 static void winbindd_status(void)
169 struct winbindd_cli_state *tmp;
171 DEBUG(0, ("winbindd status:\n"));
173 /* Print client state information */
175 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
177 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
178 DEBUG(2, ("\tclient list:\n"));
179 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
180 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
181 (unsigned long)tmp->pid, tmp->sock,
182 client_is_idle(tmp) ? "idle" : "active"));
187 /* Flush client cache */
189 static void flush_caches(void)
191 /* We need to invalidate cached user list entries on a SIGHUP
192 otherwise cached access denied errors due to restrict anonymous
193 hang around until the sequence number changes. */
195 if (!wcache_invalidate_cache()) {
196 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
197 if (!winbindd_cache_validate_and_initialize()) {
198 exit(1);
203 static void flush_caches_noinit(void)
206 * We need to invalidate cached user list entries on a SIGHUP
207 * otherwise cached access denied errors due to restrict anonymous
208 * hang around until the sequence number changes.
209 * NB
210 * Skip uninitialized domains when flush cache.
211 * If domain is not initialized, it means it is never
212 * used or never become online. look, wcache_invalidate_cache()
213 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
214 * for unused domains and large traffic for primay domain's DC if there
215 * are many domains..
218 if (!wcache_invalidate_cache_noinit()) {
219 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
220 if (!winbindd_cache_validate_and_initialize()) {
221 exit(1);
226 /* Handle the signal by unlinking socket and exiting */
228 static void terminate(bool is_parent)
230 if (is_parent) {
231 /* When parent goes away we should
232 * remove the socket file. Not so
233 * when children terminate.
235 char *path = NULL;
237 if (asprintf(&path, "%s/%s",
238 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
239 unlink(path);
240 SAFE_FREE(path);
244 idmap_close();
246 trustdom_cache_shutdown();
248 gencache_stabilize();
250 #if 0
251 if (interactive) {
252 TALLOC_CTX *mem_ctx = talloc_init("end_description");
253 char *description = talloc_describe_all(mem_ctx);
255 DEBUG(3, ("tallocs left:\n%s\n", description));
256 talloc_destroy(mem_ctx);
258 #endif
260 if (is_parent) {
261 struct messaging_context *msg = winbind_messaging_context();
262 struct server_id self = messaging_server_id(msg);
263 serverid_deregister(self);
264 pidfile_unlink(lp_pid_directory(), "winbindd");
267 exit(0);
270 static void winbindd_sig_term_handler(struct tevent_context *ev,
271 struct tevent_signal *se,
272 int signum,
273 int count,
274 void *siginfo,
275 void *private_data)
277 bool *is_parent = talloc_get_type_abort(private_data, bool);
279 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
280 signum, (int)*is_parent));
281 terminate(*is_parent);
285 handle stdin becoming readable when we are in --foreground mode
287 static void winbindd_stdin_handler(struct tevent_context *ev,
288 struct tevent_fd *fde,
289 uint16_t flags,
290 void *private_data)
292 char c;
293 if (read(0, &c, 1) != 1) {
294 bool *is_parent = talloc_get_type_abort(private_data, bool);
296 /* we have reached EOF on stdin, which means the
297 parent has exited. Shutdown the server */
298 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
299 (int)*is_parent));
300 terminate(*is_parent);
304 bool winbindd_setup_sig_term_handler(bool parent)
306 struct tevent_signal *se;
307 bool *is_parent;
309 is_parent = talloc(winbind_event_context(), bool);
310 if (!is_parent) {
311 return false;
314 *is_parent = parent;
316 se = tevent_add_signal(winbind_event_context(),
317 is_parent,
318 SIGTERM, 0,
319 winbindd_sig_term_handler,
320 is_parent);
321 if (!se) {
322 DEBUG(0,("failed to setup SIGTERM handler"));
323 talloc_free(is_parent);
324 return false;
327 se = tevent_add_signal(winbind_event_context(),
328 is_parent,
329 SIGINT, 0,
330 winbindd_sig_term_handler,
331 is_parent);
332 if (!se) {
333 DEBUG(0,("failed to setup SIGINT handler"));
334 talloc_free(is_parent);
335 return false;
338 se = tevent_add_signal(winbind_event_context(),
339 is_parent,
340 SIGQUIT, 0,
341 winbindd_sig_term_handler,
342 is_parent);
343 if (!se) {
344 DEBUG(0,("failed to setup SIGINT handler"));
345 talloc_free(is_parent);
346 return false;
349 return true;
352 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
354 bool *is_parent;
356 if (foreground) {
357 struct stat st;
359 is_parent = talloc(winbind_event_context(), bool);
360 if (!is_parent) {
361 return false;
364 *is_parent = parent;
366 /* if we are running in the foreground then look for
367 EOF on stdin, and exit if it happens. This allows
368 us to die if the parent process dies
369 Only do this on a pipe or socket, no other device.
371 if (fstat(0, &st) != 0) {
372 return false;
374 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
375 tevent_add_fd(winbind_event_context(),
376 is_parent,
378 TEVENT_FD_READ,
379 winbindd_stdin_handler,
380 is_parent);
384 return true;
387 static void winbindd_sig_hup_handler(struct tevent_context *ev,
388 struct tevent_signal *se,
389 int signum,
390 int count,
391 void *siginfo,
392 void *private_data)
394 const char *file = (const char *)private_data;
396 DEBUG(1,("Reloading services after SIGHUP\n"));
397 flush_caches_noinit();
398 reload_services_file(file);
401 bool winbindd_setup_sig_hup_handler(const char *lfile)
403 struct tevent_signal *se;
404 char *file = NULL;
406 if (lfile) {
407 file = talloc_strdup(winbind_event_context(),
408 lfile);
409 if (!file) {
410 return false;
414 se = tevent_add_signal(winbind_event_context(),
415 winbind_event_context(),
416 SIGHUP, 0,
417 winbindd_sig_hup_handler,
418 file);
419 if (!se) {
420 return false;
423 return true;
426 static void winbindd_sig_chld_handler(struct tevent_context *ev,
427 struct tevent_signal *se,
428 int signum,
429 int count,
430 void *siginfo,
431 void *private_data)
433 pid_t pid;
435 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
436 winbind_child_died(pid);
440 static bool winbindd_setup_sig_chld_handler(void)
442 struct tevent_signal *se;
444 se = tevent_add_signal(winbind_event_context(),
445 winbind_event_context(),
446 SIGCHLD, 0,
447 winbindd_sig_chld_handler,
448 NULL);
449 if (!se) {
450 return false;
453 return true;
456 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
457 struct tevent_signal *se,
458 int signum,
459 int count,
460 void *siginfo,
461 void *private_data)
463 winbindd_status();
466 static bool winbindd_setup_sig_usr2_handler(void)
468 struct tevent_signal *se;
470 se = tevent_add_signal(winbind_event_context(),
471 winbind_event_context(),
472 SIGUSR2, 0,
473 winbindd_sig_usr2_handler,
474 NULL);
475 if (!se) {
476 return false;
479 return true;
482 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
483 static void msg_reload_services(struct messaging_context *msg,
484 void *private_data,
485 uint32_t msg_type,
486 struct server_id server_id,
487 DATA_BLOB *data)
489 /* Flush various caches */
490 flush_caches();
491 reload_services_file((const char *) private_data);
494 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
495 static void msg_shutdown(struct messaging_context *msg,
496 void *private_data,
497 uint32_t msg_type,
498 struct server_id server_id,
499 DATA_BLOB *data)
501 /* only the parent waits for this message */
502 DEBUG(0,("Got shutdown message\n"));
503 terminate(true);
507 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
508 void *private_data,
509 uint32_t msg_type,
510 struct server_id server_id,
511 DATA_BLOB *data)
513 uint8_t ret;
514 pid_t child_pid;
515 NTSTATUS status;
517 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
518 "message.\n"));
521 * call the validation code from a child:
522 * so we don't block the main winbindd and the validation
523 * code can safely use fork/waitpid...
525 child_pid = fork();
527 if (child_pid == -1) {
528 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
529 strerror(errno)));
530 return;
533 if (child_pid != 0) {
534 /* parent */
535 DEBUG(5, ("winbind_msg_validate_cache: child created with "
536 "pid %d.\n", (int)child_pid));
537 return;
540 /* child */
542 status = winbindd_reinit_after_fork(NULL, NULL);
543 if (!NT_STATUS_IS_OK(status)) {
544 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
545 nt_errstr(status)));
546 _exit(0);
549 /* install default SIGCHLD handler: validation code uses fork/waitpid */
550 CatchSignal(SIGCHLD, SIG_DFL);
552 ret = (uint8_t)winbindd_validate_cache_nobackup();
553 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
554 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
555 (size_t)1);
556 _exit(0);
559 static struct winbindd_dispatch_table {
560 enum winbindd_cmd cmd;
561 void (*fn)(struct winbindd_cli_state *state);
562 const char *winbindd_cmd_name;
563 } dispatch_table[] = {
565 /* Enumeration functions */
567 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
568 "LIST_TRUSTDOM" },
570 /* Miscellaneous */
572 { WINBINDD_INFO, winbindd_info, "INFO" },
573 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
574 "INTERFACE_VERSION" },
575 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
576 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
577 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
578 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
579 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
580 "WINBINDD_PRIV_PIPE_DIR" },
582 /* Credential cache access */
583 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
584 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
586 /* End of list */
588 { WINBINDD_NUM_CMDS, NULL, "NONE" }
591 struct winbindd_async_dispatch_table {
592 enum winbindd_cmd cmd;
593 const char *cmd_name;
594 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
595 struct tevent_context *ev,
596 struct winbindd_cli_state *cli,
597 struct winbindd_request *request);
598 NTSTATUS (*recv_req)(struct tevent_req *req,
599 struct winbindd_response *presp);
602 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
603 { WINBINDD_PING, "PING",
604 wb_ping_send, wb_ping_recv },
605 { WINBINDD_LOOKUPSID, "LOOKUPSID",
606 winbindd_lookupsid_send, winbindd_lookupsid_recv },
607 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
608 winbindd_lookupsids_send, winbindd_lookupsids_recv },
609 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
610 winbindd_lookupname_send, winbindd_lookupname_recv },
611 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
612 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
613 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
614 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
615 { WINBINDD_GETPWSID, "GETPWSID",
616 winbindd_getpwsid_send, winbindd_getpwsid_recv },
617 { WINBINDD_GETPWNAM, "GETPWNAM",
618 winbindd_getpwnam_send, winbindd_getpwnam_recv },
619 { WINBINDD_GETPWUID, "GETPWUID",
620 winbindd_getpwuid_send, winbindd_getpwuid_recv },
621 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
622 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
623 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
624 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
625 { WINBINDD_GETGROUPS, "GETGROUPS",
626 winbindd_getgroups_send, winbindd_getgroups_recv },
627 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
628 winbindd_show_sequence_send, winbindd_show_sequence_recv },
629 { WINBINDD_GETGRGID, "GETGRGID",
630 winbindd_getgrgid_send, winbindd_getgrgid_recv },
631 { WINBINDD_GETGRNAM, "GETGRNAM",
632 winbindd_getgrnam_send, winbindd_getgrnam_recv },
633 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
634 winbindd_getusersids_send, winbindd_getusersids_recv },
635 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
636 winbindd_lookuprids_send, winbindd_lookuprids_recv },
637 { WINBINDD_SETPWENT, "SETPWENT",
638 winbindd_setpwent_send, winbindd_setpwent_recv },
639 { WINBINDD_GETPWENT, "GETPWENT",
640 winbindd_getpwent_send, winbindd_getpwent_recv },
641 { WINBINDD_ENDPWENT, "ENDPWENT",
642 winbindd_endpwent_send, winbindd_endpwent_recv },
643 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
644 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
645 { WINBINDD_GETDCNAME, "GETDCNAME",
646 winbindd_getdcname_send, winbindd_getdcname_recv },
647 { WINBINDD_SETGRENT, "SETGRENT",
648 winbindd_setgrent_send, winbindd_setgrent_recv },
649 { WINBINDD_GETGRENT, "GETGRENT",
650 winbindd_getgrent_send, winbindd_getgrent_recv },
651 { WINBINDD_ENDGRENT, "ENDGRENT",
652 winbindd_endgrent_send, winbindd_endgrent_recv },
653 { WINBINDD_LIST_USERS, "LIST_USERS",
654 winbindd_list_users_send, winbindd_list_users_recv },
655 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
656 winbindd_list_groups_send, winbindd_list_groups_recv },
657 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
658 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
659 { WINBINDD_PING_DC, "PING_DC",
660 winbindd_ping_dc_send, winbindd_ping_dc_recv },
661 { WINBINDD_PAM_AUTH, "PAM_AUTH",
662 winbindd_pam_auth_send, winbindd_pam_auth_recv },
663 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
664 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
665 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
666 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
667 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
668 winbindd_pam_chng_pswd_auth_crap_send,
669 winbindd_pam_chng_pswd_auth_crap_recv },
670 { WINBINDD_WINS_BYIP, "WINS_BYIP",
671 winbindd_wins_byip_send, winbindd_wins_byip_recv },
672 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
673 winbindd_wins_byname_send, winbindd_wins_byname_recv },
675 { 0, NULL, NULL, NULL }
678 static struct winbindd_async_dispatch_table async_priv_table[] = {
679 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
680 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
681 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
682 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
683 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
684 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
685 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
686 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
688 { 0, NULL, NULL, NULL }
691 static void wb_request_done(struct tevent_req *req);
693 static void process_request(struct winbindd_cli_state *state)
695 struct winbindd_dispatch_table *table = dispatch_table;
696 struct winbindd_async_dispatch_table *atable;
698 state->mem_ctx = talloc_named(state, 0, "winbind request");
699 if (state->mem_ctx == NULL)
700 return;
702 /* Remember who asked us. */
703 state->pid = state->request->pid;
705 state->cmd_name = "unknown request";
706 state->recv_fn = NULL;
707 /* client is newest */
708 winbindd_promote_client(state);
710 /* Process command */
712 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
713 if (state->request->cmd == atable->cmd) {
714 break;
718 if ((atable->send_req == NULL) && state->privileged) {
719 for (atable = async_priv_table; atable->send_req;
720 atable += 1) {
721 if (state->request->cmd == atable->cmd) {
722 break;
727 if (atable->send_req != NULL) {
728 struct tevent_req *req;
730 state->cmd_name = atable->cmd_name;
731 state->recv_fn = atable->recv_req;
733 DEBUG(10, ("process_request: Handling async request %d:%s\n",
734 (int)state->pid, state->cmd_name));
736 req = atable->send_req(state->mem_ctx, winbind_event_context(),
737 state, state->request);
738 if (req == NULL) {
739 DEBUG(0, ("process_request: atable->send failed for "
740 "%s\n", atable->cmd_name));
741 request_error(state);
742 return;
744 tevent_req_set_callback(req, wb_request_done, state);
745 return;
748 state->response = talloc_zero(state->mem_ctx,
749 struct winbindd_response);
750 if (state->response == NULL) {
751 DEBUG(10, ("talloc failed\n"));
752 remove_client(state);
753 return;
755 state->response->result = WINBINDD_PENDING;
756 state->response->length = sizeof(struct winbindd_response);
758 for (table = dispatch_table; table->fn; table++) {
759 if (state->request->cmd == table->cmd) {
760 DEBUG(10,("process_request: request fn %s\n",
761 table->winbindd_cmd_name ));
762 state->cmd_name = table->winbindd_cmd_name;
763 table->fn(state);
764 break;
768 if (!table->fn) {
769 DEBUG(10,("process_request: unknown request fn number %d\n",
770 (int)state->request->cmd ));
771 request_error(state);
775 static void wb_request_done(struct tevent_req *req)
777 struct winbindd_cli_state *state = tevent_req_callback_data(
778 req, struct winbindd_cli_state);
779 NTSTATUS status;
781 state->response = talloc_zero(state->mem_ctx,
782 struct winbindd_response);
783 if (state->response == NULL) {
784 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
785 (int)state->pid, state->cmd_name));
786 remove_client(state);
787 return;
789 state->response->result = WINBINDD_PENDING;
790 state->response->length = sizeof(struct winbindd_response);
792 status = state->recv_fn(req, state->response);
793 TALLOC_FREE(req);
795 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
796 (int)state->pid, state->cmd_name, nt_errstr(status)));
798 if (!NT_STATUS_IS_OK(status)) {
799 request_error(state);
800 return;
802 request_ok(state);
806 * This is the main event loop of winbind requests. It goes through a
807 * state-machine of 3 read/write requests, 4 if you have extra data to send.
809 * An idle winbind client has a read request of 4 bytes outstanding,
810 * finalizing function is request_len_recv, checking the length. request_recv
811 * then processes the packet. The processing function then at some point has
812 * to call request_finished which schedules sending the response.
815 static void request_finished(struct winbindd_cli_state *state);
817 static void winbind_client_request_read(struct tevent_req *req);
818 static void winbind_client_response_written(struct tevent_req *req);
819 static void winbind_client_activity(struct tevent_req *req);
821 static void request_finished(struct winbindd_cli_state *state)
823 struct tevent_req *req;
825 /* free client socket monitoring request */
826 TALLOC_FREE(state->io_req);
828 TALLOC_FREE(state->request);
830 req = wb_resp_write_send(state, winbind_event_context(),
831 state->out_queue, state->sock,
832 state->response);
833 if (req == NULL) {
834 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
835 (int)state->pid, state->cmd_name));
836 remove_client(state);
837 return;
839 tevent_req_set_callback(req, winbind_client_response_written, state);
840 state->io_req = req;
843 static void winbind_client_response_written(struct tevent_req *req)
845 struct winbindd_cli_state *state = tevent_req_callback_data(
846 req, struct winbindd_cli_state);
847 ssize_t ret;
848 int err;
850 state->io_req = NULL;
852 ret = wb_resp_write_recv(req, &err);
853 TALLOC_FREE(req);
854 if (ret == -1) {
855 close(state->sock);
856 state->sock = -1;
857 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
858 (int)state->pid, state->cmd_name, strerror(err)));
859 remove_client(state);
860 return;
863 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
864 "to client\n", (int)state->pid, state->cmd_name));
866 TALLOC_FREE(state->mem_ctx);
867 state->response = NULL;
868 state->cmd_name = "no request";
869 state->recv_fn = NULL;
871 req = wb_req_read_send(state, winbind_event_context(), state->sock,
872 WINBINDD_MAX_EXTRA_DATA);
873 if (req == NULL) {
874 remove_client(state);
875 return;
877 tevent_req_set_callback(req, winbind_client_request_read, state);
878 state->io_req = req;
881 void request_error(struct winbindd_cli_state *state)
883 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
884 state->response->result = WINBINDD_ERROR;
885 request_finished(state);
888 void request_ok(struct winbindd_cli_state *state)
890 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
891 state->response->result = WINBINDD_OK;
892 request_finished(state);
895 /* Process a new connection by adding it to the client connection list */
897 static void new_connection(int listen_sock, bool privileged)
899 struct sockaddr_un sunaddr;
900 struct winbindd_cli_state *state;
901 struct tevent_req *req;
902 socklen_t len;
903 int sock;
905 /* Accept connection */
907 len = sizeof(sunaddr);
909 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
911 if (sock == -1) {
912 if (errno != EINTR) {
913 DEBUG(0, ("Failed to accept socket - %s\n",
914 strerror(errno)));
916 return;
919 DEBUG(6,("accepted socket %d\n", sock));
921 /* Create new connection structure */
923 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
924 close(sock);
925 return;
928 state->sock = sock;
930 state->out_queue = tevent_queue_create(state, "winbind client reply");
931 if (state->out_queue == NULL) {
932 close(sock);
933 TALLOC_FREE(state);
934 return;
937 state->privileged = privileged;
939 req = wb_req_read_send(state, winbind_event_context(), state->sock,
940 WINBINDD_MAX_EXTRA_DATA);
941 if (req == NULL) {
942 TALLOC_FREE(state);
943 close(sock);
944 return;
946 tevent_req_set_callback(req, winbind_client_request_read, state);
947 state->io_req = req;
949 /* Add to connection list */
951 winbindd_add_client(state);
954 static void winbind_client_request_read(struct tevent_req *req)
956 struct winbindd_cli_state *state = tevent_req_callback_data(
957 req, struct winbindd_cli_state);
958 ssize_t ret;
959 int err;
961 state->io_req = NULL;
963 ret = wb_req_read_recv(req, state, &state->request, &err);
964 TALLOC_FREE(req);
965 if (ret == -1) {
966 if (err == EPIPE) {
967 DEBUG(6, ("closing socket %d, client exited\n",
968 state->sock));
969 } else {
970 DEBUG(2, ("Could not read client request from fd %d: "
971 "%s\n", state->sock, strerror(err)));
973 close(state->sock);
974 state->sock = -1;
975 remove_client(state);
976 return;
979 req = wait_for_read_send(state, winbind_event_context(), state->sock,
980 true);
981 if (req == NULL) {
982 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
983 " wait_for_read_send failed - removing client\n",
984 (int)state->pid, state->cmd_name));
985 remove_client(state);
986 return;
988 tevent_req_set_callback(req, winbind_client_activity, state);
989 state->io_req = req;
991 process_request(state);
994 static void winbind_client_activity(struct tevent_req *req)
996 struct winbindd_cli_state *state =
997 tevent_req_callback_data(req, struct winbindd_cli_state);
998 int err;
999 bool has_data;
1001 has_data = wait_for_read_recv(req, &err);
1003 if (has_data) {
1004 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1005 "unexpected data from client - removing client\n",
1006 (int)state->pid, state->cmd_name));
1007 } else {
1008 if (err == EPIPE) {
1009 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1010 "client has closed connection - removing "
1011 "client\n",
1012 (int)state->pid, state->cmd_name));
1013 } else {
1014 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1015 "client socket error (%s) - removing "
1016 "client\n",
1017 (int)state->pid, state->cmd_name,
1018 strerror(err)));
1022 remove_client(state);
1025 /* Remove a client connection from client connection list */
1027 static void remove_client(struct winbindd_cli_state *state)
1029 char c = 0;
1030 int nwritten;
1032 /* It's a dead client - hold a funeral */
1034 if (state == NULL) {
1035 return;
1039 * We need to remove a pending wb_req_read_*
1040 * or wb_resp_write_* request before closing the
1041 * socket.
1043 * This is important as they might have used tevent_add_fd() and we
1044 * use the epoll * backend on linux. So we must remove the tevent_fd
1045 * before closing the fd.
1047 * Otherwise we might hit a race with close_conns_after_fork() (via
1048 * winbindd_reinit_after_fork()) where a file description
1049 * is still open in a child, which means it's still active in
1050 * the parents epoll queue, but the related tevent_fd is already
1051 * already gone in the parent.
1053 * See bug #11141.
1055 TALLOC_FREE(state->io_req);
1057 if (state->sock != -1) {
1058 /* tell client, we are closing ... */
1059 nwritten = write(state->sock, &c, sizeof(c));
1060 if (nwritten == -1) {
1061 DEBUG(2, ("final write to client failed: %s\n",
1062 strerror(errno)));
1065 /* Close socket */
1067 close(state->sock);
1068 state->sock = -1;
1071 TALLOC_FREE(state->mem_ctx);
1073 /* Remove from list and free */
1075 winbindd_remove_client(state);
1076 TALLOC_FREE(state);
1079 /* Is a client idle? */
1081 static bool client_is_idle(struct winbindd_cli_state *state) {
1082 return (state->request == NULL &&
1083 state->response == NULL &&
1084 !state->pwent_state && !state->grent_state);
1087 /* Shutdown client connection which has been idle for the longest time */
1089 static bool remove_idle_client(void)
1091 struct winbindd_cli_state *state, *remove_state = NULL;
1092 int nidle = 0;
1094 for (state = winbindd_client_list(); state; state = state->next) {
1095 if (client_is_idle(state)) {
1096 nidle++;
1097 /* list is sorted by access time */
1098 remove_state = state;
1102 if (remove_state) {
1103 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1104 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1105 remove_client(remove_state);
1106 return True;
1109 return False;
1113 * Terminate all clients whose requests have taken longer than
1114 * "winbind request timeout" seconds to process, or have been
1115 * idle for more than "winbind request timeout" seconds.
1118 static void remove_timed_out_clients(void)
1120 struct winbindd_cli_state *state, *prev = NULL;
1121 time_t curr_time = time(NULL);
1122 int timeout_val = lp_winbind_request_timeout();
1124 for (state = winbindd_client_list_tail(); state; state = prev) {
1125 time_t expiry_time;
1127 prev = winbindd_client_list_prev(state);
1128 expiry_time = state->last_access + timeout_val;
1130 if (curr_time > expiry_time) {
1131 if (client_is_idle(state)) {
1132 DEBUG(5,("Idle client timed out, "
1133 "shutting down sock %d, pid %u\n",
1134 state->sock,
1135 (unsigned int)state->pid));
1136 } else {
1137 DEBUG(5,("Client request timed out, "
1138 "shutting down sock %d, pid %u\n",
1139 state->sock,
1140 (unsigned int)state->pid));
1142 remove_client(state);
1143 } else {
1144 /* list is sorted, previous clients in
1145 list are newer */
1146 break;
1151 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1152 struct tevent_timer *te,
1153 struct timeval current_time,
1154 void *private_data)
1156 remove_timed_out_clients();
1157 if (tevent_add_timer(ev, ev,
1158 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1159 winbindd_scrub_clients_handler, NULL) == NULL) {
1160 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1161 exit(1);
1165 struct winbindd_listen_state {
1166 bool privileged;
1167 int fd;
1170 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1171 struct tevent_fd *fde,
1172 uint16_t flags,
1173 void *private_data)
1175 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1176 struct winbindd_listen_state);
1178 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1179 DEBUG(5,("winbindd: Exceeding %d client "
1180 "connections, removing idle "
1181 "connection.\n", lp_winbind_max_clients()));
1182 if (!remove_idle_client()) {
1183 DEBUG(0,("winbindd: Exceeding %d "
1184 "client connections, no idle "
1185 "connection found\n",
1186 lp_winbind_max_clients()));
1187 break;
1190 remove_timed_out_clients();
1191 new_connection(s->fd, s->privileged);
1195 * Winbindd socket accessor functions
1198 char *get_winbind_priv_pipe_dir(void)
1200 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1203 static void winbindd_setup_max_fds(void)
1205 int num_fds = MAX_OPEN_FUDGEFACTOR;
1206 int actual_fds;
1208 num_fds += lp_winbind_max_clients();
1209 /* Add some more to account for 2 sockets open
1210 when the client transitions from unprivileged
1211 to privileged socket
1213 num_fds += lp_winbind_max_clients() / 10;
1215 /* Add one socket per child process
1216 (yeah there are child processes other than the
1217 domain children but only domain children can vary
1218 with configuration
1220 num_fds += lp_winbind_max_domain_connections() *
1221 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1223 actual_fds = set_maxfiles(num_fds);
1225 if (actual_fds < num_fds) {
1226 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1227 "requested %d open files, %d are available.\n",
1228 num_fds, actual_fds));
1232 static bool winbindd_setup_listeners(void)
1234 struct winbindd_listen_state *pub_state = NULL;
1235 struct winbindd_listen_state *priv_state = NULL;
1236 struct tevent_fd *fde;
1237 int rc;
1238 char *socket_path;
1240 pub_state = talloc(winbind_event_context(),
1241 struct winbindd_listen_state);
1242 if (!pub_state) {
1243 goto failed;
1246 pub_state->privileged = false;
1247 pub_state->fd = create_pipe_sock(
1248 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1249 if (pub_state->fd == -1) {
1250 goto failed;
1252 rc = listen(pub_state->fd, 5);
1253 if (rc < 0) {
1254 goto failed;
1257 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1258 TEVENT_FD_READ, winbindd_listen_fde_handler,
1259 pub_state);
1260 if (fde == NULL) {
1261 close(pub_state->fd);
1262 goto failed;
1264 tevent_fd_set_auto_close(fde);
1266 priv_state = talloc(winbind_event_context(),
1267 struct winbindd_listen_state);
1268 if (!priv_state) {
1269 goto failed;
1272 socket_path = get_winbind_priv_pipe_dir();
1273 if (socket_path == NULL) {
1274 goto failed;
1277 priv_state->privileged = true;
1278 priv_state->fd = create_pipe_sock(
1279 socket_path, WINBINDD_SOCKET_NAME, 0750);
1280 TALLOC_FREE(socket_path);
1281 if (priv_state->fd == -1) {
1282 goto failed;
1284 rc = listen(priv_state->fd, 5);
1285 if (rc < 0) {
1286 goto failed;
1289 fde = tevent_add_fd(winbind_event_context(), priv_state,
1290 priv_state->fd, TEVENT_FD_READ,
1291 winbindd_listen_fde_handler, priv_state);
1292 if (fde == NULL) {
1293 close(priv_state->fd);
1294 goto failed;
1296 tevent_fd_set_auto_close(fde);
1298 winbindd_scrub_clients_handler(winbind_event_context(), NULL,
1299 timeval_current(), NULL);
1300 return true;
1301 failed:
1302 TALLOC_FREE(pub_state);
1303 TALLOC_FREE(priv_state);
1304 return false;
1307 bool winbindd_use_idmap_cache(void)
1309 return !opt_nocache;
1312 bool winbindd_use_cache(void)
1314 return !opt_nocache;
1317 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1318 bool foreground)
1320 NTSTATUS status;
1321 /* Setup signal handlers */
1323 if (!winbindd_setup_sig_term_handler(true))
1324 exit(1);
1325 if (!winbindd_setup_stdin_handler(true, foreground))
1326 exit(1);
1327 if (!winbindd_setup_sig_hup_handler(NULL))
1328 exit(1);
1329 if (!winbindd_setup_sig_chld_handler())
1330 exit(1);
1331 if (!winbindd_setup_sig_usr2_handler())
1332 exit(1);
1334 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1337 * Ensure all cache and idmap caches are consistent
1338 * and initialized before we startup.
1340 if (!winbindd_cache_validate_and_initialize()) {
1341 exit(1);
1344 /* get broadcast messages */
1346 if (!serverid_register(messaging_server_id(msg_ctx),
1347 FLAG_MSG_GENERAL |
1348 FLAG_MSG_WINBIND |
1349 FLAG_MSG_DBWRAP)) {
1350 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1351 exit(1);
1354 /* React on 'smbcontrol winbindd reload-config' in the same way
1355 as to SIGHUP signal */
1356 messaging_register(msg_ctx, NULL,
1357 MSG_SMB_CONF_UPDATED, msg_reload_services);
1358 messaging_register(msg_ctx, NULL,
1359 MSG_SHUTDOWN, msg_shutdown);
1361 /* Handle online/offline messages. */
1362 messaging_register(msg_ctx, NULL,
1363 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1364 messaging_register(msg_ctx, NULL,
1365 MSG_WINBIND_ONLINE, winbind_msg_online);
1366 messaging_register(msg_ctx, NULL,
1367 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1369 /* Handle domain online/offline messages for domains */
1370 messaging_register(winbind_messaging_context(), NULL,
1371 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1372 messaging_register(winbind_messaging_context(), NULL,
1373 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1375 messaging_register(msg_ctx, NULL,
1376 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1378 messaging_register(msg_ctx, NULL,
1379 MSG_WINBIND_VALIDATE_CACHE,
1380 winbind_msg_validate_cache);
1382 messaging_register(msg_ctx, NULL,
1383 MSG_WINBIND_DUMP_DOMAIN_LIST,
1384 winbind_msg_dump_domain_list);
1386 messaging_register(msg_ctx, NULL,
1387 MSG_WINBIND_IP_DROPPED,
1388 winbind_msg_ip_dropped_parent);
1390 /* Register handler for MSG_DEBUG. */
1391 messaging_register(msg_ctx, NULL,
1392 MSG_DEBUG,
1393 winbind_msg_debug);
1395 netsamlogon_cache_init(); /* Non-critical */
1397 /* clear the cached list of trusted domains */
1399 wcache_tdc_clear();
1401 if (!init_domain_list()) {
1402 DEBUG(0,("unable to initialize domain list\n"));
1403 exit(1);
1406 init_idmap_child();
1407 init_locator_child();
1409 smb_nscd_flush_user_cache();
1410 smb_nscd_flush_group_cache();
1412 if (lp_allow_trusted_domains()) {
1413 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1414 rescan_trusted_domains, NULL) == NULL) {
1415 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1416 exit(1);
1420 status = wb_irpc_register();
1422 if (!NT_STATUS_IS_OK(status)) {
1423 DEBUG(0, ("Could not register IRPC handlers\n"));
1424 exit(1);
1428 struct winbindd_addrchanged_state {
1429 struct addrchange_context *ctx;
1430 struct tevent_context *ev;
1431 struct messaging_context *msg_ctx;
1434 static void winbindd_addr_changed(struct tevent_req *req);
1436 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1437 struct tevent_context *ev,
1438 struct messaging_context *msg_ctx)
1440 struct winbindd_addrchanged_state *state;
1441 struct tevent_req *req;
1442 NTSTATUS status;
1444 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1445 if (state == NULL) {
1446 DEBUG(10, ("talloc failed\n"));
1447 return;
1449 state->ev = ev;
1450 state->msg_ctx = msg_ctx;
1452 status = addrchange_context_create(state, &state->ctx);
1453 if (!NT_STATUS_IS_OK(status)) {
1454 DEBUG(10, ("addrchange_context_create failed: %s\n",
1455 nt_errstr(status)));
1456 TALLOC_FREE(state);
1457 return;
1459 req = addrchange_send(state, ev, state->ctx);
1460 if (req == NULL) {
1461 DEBUG(0, ("addrchange_send failed\n"));
1462 TALLOC_FREE(state);
1463 return;
1465 tevent_req_set_callback(req, winbindd_addr_changed, state);
1468 static void winbindd_addr_changed(struct tevent_req *req)
1470 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1471 req, struct winbindd_addrchanged_state);
1472 enum addrchange_type type;
1473 struct sockaddr_storage addr;
1474 NTSTATUS status;
1476 status = addrchange_recv(req, &type, &addr);
1477 TALLOC_FREE(req);
1478 if (!NT_STATUS_IS_OK(status)) {
1479 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1480 nt_errstr(status)));
1481 TALLOC_FREE(state);
1482 return;
1484 if (type == ADDRCHANGE_DEL) {
1485 char addrstr[INET6_ADDRSTRLEN];
1486 DATA_BLOB blob;
1488 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1490 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1491 addrstr));
1493 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1495 status = messaging_send(state->msg_ctx,
1496 messaging_server_id(state->msg_ctx),
1497 MSG_WINBIND_IP_DROPPED, &blob);
1498 if (!NT_STATUS_IS_OK(status)) {
1499 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1500 nt_errstr(status)));
1503 req = addrchange_send(state, state->ev, state->ctx);
1504 if (req == NULL) {
1505 DEBUG(0, ("addrchange_send failed\n"));
1506 TALLOC_FREE(state);
1507 return;
1509 tevent_req_set_callback(req, winbindd_addr_changed, state);
1512 /* Main function */
1514 int main(int argc, const char **argv)
1516 static bool is_daemon = False;
1517 static bool Fork = True;
1518 static bool log_stdout = False;
1519 static bool no_process_group = False;
1520 enum {
1521 OPT_DAEMON = 1000,
1522 OPT_FORK,
1523 OPT_NO_PROCESS_GROUP,
1524 OPT_LOG_STDOUT
1526 struct poptOption long_options[] = {
1527 POPT_AUTOHELP
1528 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1529 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1530 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1531 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1532 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1533 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1534 POPT_COMMON_SAMBA
1535 POPT_TABLEEND
1537 poptContext pc;
1538 int opt;
1539 TALLOC_CTX *frame;
1540 NTSTATUS status;
1541 bool ok;
1544 * Do this before any other talloc operation
1546 talloc_enable_null_tracking();
1547 frame = talloc_stackframe();
1550 * We want total control over the permissions on created files,
1551 * so set our umask to 0.
1553 umask(0);
1555 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1557 /* glibc (?) likes to print "User defined signal 1" and exit if a
1558 SIGUSR[12] is received before a handler is installed */
1560 CatchSignal(SIGUSR1, SIG_IGN);
1561 CatchSignal(SIGUSR2, SIG_IGN);
1563 fault_setup();
1564 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1566 smb_init_locale();
1568 /* Initialise for running in non-root mode */
1570 sec_init();
1572 set_remote_machine_name("winbindd", False);
1574 /* Set environment variable so we don't recursively call ourselves.
1575 This may also be useful interactively. */
1577 if ( !winbind_off() ) {
1578 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1579 exit(1);
1582 /* Initialise samba/rpc client stuff */
1584 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1586 while ((opt = poptGetNextOpt(pc)) != -1) {
1587 switch (opt) {
1588 /* Don't become a daemon */
1589 case OPT_DAEMON:
1590 is_daemon = True;
1591 break;
1592 case 'i':
1593 interactive = True;
1594 log_stdout = True;
1595 Fork = False;
1596 break;
1597 case OPT_FORK:
1598 Fork = false;
1599 break;
1600 case OPT_NO_PROCESS_GROUP:
1601 no_process_group = true;
1602 break;
1603 case OPT_LOG_STDOUT:
1604 log_stdout = true;
1605 break;
1606 case 'n':
1607 opt_nocache = true;
1608 break;
1609 default:
1610 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1611 poptBadOption(pc, 0), poptStrerror(opt));
1612 poptPrintUsage(pc, stderr, 0);
1613 exit(1);
1617 /* We call dump_core_setup one more time because the command line can
1618 * set the log file or the log-basename and this will influence where
1619 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1620 * the default value derived from build's prefix. For EOM this value
1621 * is often not related to the path where winbindd is actually run
1622 * in production.
1624 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1625 if (is_daemon && interactive) {
1626 d_fprintf(stderr,"\nERROR: "
1627 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1628 poptPrintUsage(pc, stderr, 0);
1629 exit(1);
1632 if (log_stdout && Fork) {
1633 d_fprintf(stderr, "\nERROR: "
1634 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1635 poptPrintUsage(pc, stderr, 0);
1636 exit(1);
1639 poptFreeContext(pc);
1641 if (!override_logfile) {
1642 char *lfile = NULL;
1643 if (asprintf(&lfile,"%s/log.winbindd",
1644 get_dyn_LOGFILEBASE()) > 0) {
1645 lp_set_logfile(lfile);
1646 SAFE_FREE(lfile);
1650 if (log_stdout) {
1651 setup_logging("winbindd", DEBUG_STDOUT);
1652 } else {
1653 setup_logging("winbindd", DEBUG_FILE);
1655 reopen_logs();
1657 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1658 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1660 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1661 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1662 exit(1);
1664 /* After parsing the configuration file we setup the core path one more time
1665 * as the log file might have been set in the configuration and cores's
1666 * path is by default basename(lp_logfile()).
1668 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1670 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1671 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1672 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1673 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"));
1674 exit(1);
1677 if (!cluster_probe_ok()) {
1678 exit(1);
1681 /* Initialise messaging system */
1683 if (winbind_messaging_context() == NULL) {
1684 exit(1);
1687 if (!reload_services_file(NULL)) {
1688 DEBUG(0, ("error opening config file\n"));
1689 exit(1);
1693 size_t i;
1694 const char *idmap_backend;
1695 const char *invalid_backends[] = {
1696 "ad", "rfc2307", "rid",
1699 idmap_backend = lp_idmap_default_backend();
1700 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1701 ok = strequal(idmap_backend, invalid_backends[i]);
1702 if (ok) {
1703 DBG_ERR("FATAL: Invalid idmap backend %s "
1704 "configured as the default backend!\n",
1705 idmap_backend);
1706 exit(1);
1711 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1712 if (!ok) {
1713 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1714 lp_lock_directory(), strerror(errno)));
1715 exit(1);
1718 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1719 if (!ok) {
1720 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1721 lp_pid_directory(), strerror(errno)));
1722 exit(1);
1725 /* Setup names. */
1727 if (!init_names())
1728 exit(1);
1730 load_interfaces();
1732 if (!secrets_init()) {
1734 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1735 return False;
1738 status = rpccli_pre_open_netlogon_creds();
1739 if (!NT_STATUS_IS_OK(status)) {
1740 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1741 nt_errstr(status)));
1742 exit(1);
1745 /* Unblock all signals we are interested in as they may have been
1746 blocked by the parent process. */
1748 BlockSignals(False, SIGINT);
1749 BlockSignals(False, SIGQUIT);
1750 BlockSignals(False, SIGTERM);
1751 BlockSignals(False, SIGUSR1);
1752 BlockSignals(False, SIGUSR2);
1753 BlockSignals(False, SIGHUP);
1754 BlockSignals(False, SIGCHLD);
1756 if (!interactive)
1757 become_daemon(Fork, no_process_group, log_stdout);
1759 pidfile_create(lp_pid_directory(), "winbindd");
1761 #if HAVE_SETPGID
1763 * If we're interactive we want to set our own process group for
1764 * signal management.
1766 if (interactive && !no_process_group)
1767 setpgid( (pid_t)0, (pid_t)0);
1768 #endif
1770 TimeInit();
1772 /* Don't use winbindd_reinit_after_fork here as
1773 * we're just starting up and haven't created any
1774 * winbindd-specific resources we must free yet. JRA.
1777 status = reinit_after_fork(winbind_messaging_context(),
1778 winbind_event_context(),
1779 false, NULL);
1780 if (!NT_STATUS_IS_OK(status)) {
1781 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1785 * Do not initialize the parent-child-pipe before becoming
1786 * a daemon: this is used to detect a died parent in the child
1787 * process.
1789 status = init_before_fork();
1790 if (!NT_STATUS_IS_OK(status)) {
1791 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1794 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1796 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1797 exit(1);
1800 status = init_system_session_info();
1801 if (!NT_STATUS_IS_OK(status)) {
1802 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1805 rpc_lsarpc_init(NULL);
1806 rpc_samr_init(NULL);
1808 winbindd_init_addrchange(NULL, winbind_event_context(),
1809 winbind_messaging_context());
1811 /* setup listen sockets */
1813 if (!winbindd_setup_listeners()) {
1814 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1817 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1819 TALLOC_FREE(frame);
1821 if (!interactive) {
1822 daemon_ready("winbindd");
1825 /* Loop waiting for requests */
1826 while (1) {
1827 frame = talloc_stackframe();
1829 if (tevent_loop_once(winbind_event_context()) == -1) {
1830 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1831 strerror(errno)));
1832 return 1;
1835 TALLOC_FREE(frame);
1838 return 0;