build: Do not recurse on symlinks to directories when building tarballs
[Samba.git] / source3 / winbindd / winbindd.c
blobf24451649b6112f2788a10a328b124cc13761f5a
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"
47 #include "libcli/auth/netlogon_creds_cli.h"
49 #undef DBGC_CLASS
50 #define DBGC_CLASS DBGC_WINBIND
52 #define SCRUB_CLIENTS_INTERVAL 5
54 static bool client_is_idle(struct winbindd_cli_state *state);
55 static void remove_client(struct winbindd_cli_state *state);
56 static void winbindd_setup_max_fds(void);
58 static bool opt_nocache = False;
59 static bool interactive = False;
61 extern bool override_logfile;
63 struct tevent_context *winbind_event_context(void)
65 static struct tevent_context *ev = NULL;
67 if (ev != NULL) {
68 return ev;
72 * Note we MUST use the NULL context here, not the autofree context,
73 * to avoid side effects in forked children exiting.
75 ev = samba_tevent_context_init(NULL);
76 if (ev == NULL) {
77 smb_panic("Could not init winbindd's messaging context.\n");
79 return ev;
82 struct messaging_context *winbind_messaging_context(void)
84 static struct messaging_context *msg = NULL;
86 if (msg != NULL) {
87 return msg;
91 * Note we MUST use the NULL context here, not the autofree context,
92 * to avoid side effects in forked children exiting.
94 msg = messaging_init(NULL, winbind_event_context());
95 if (msg == NULL) {
96 smb_panic("Could not init winbindd's messaging context.\n");
98 return msg;
101 struct imessaging_context *winbind_imessaging_context(void)
103 static struct imessaging_context *msg = NULL;
104 struct messaging_context *msg_ctx;
105 struct server_id myself;
106 struct loadparm_context *lp_ctx;
108 if (msg != NULL) {
109 return msg;
112 msg_ctx = server_messaging_context();
113 if (msg_ctx == NULL) {
114 smb_panic("server_messaging_context failed\n");
116 myself = messaging_server_id(msg_ctx);
118 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
119 if (lp_ctx == NULL) {
120 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
124 * Note we MUST use the NULL context here, not the autofree context,
125 * to avoid side effects in forked children exiting.
127 msg = imessaging_init(NULL, lp_ctx, myself, winbind_event_context());
128 talloc_unlink(NULL, lp_ctx);
130 if (msg == NULL) {
131 smb_panic("Could not init winbindd's messaging context.\n");
133 return msg;
136 /* Reload configuration */
138 static bool reload_services_file(const char *lfile)
140 bool ret;
142 if (lp_loaded()) {
143 char *fname = lp_next_configfile(talloc_tos());
145 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
146 set_dyn_CONFIGFILE(fname);
148 TALLOC_FREE(fname);
151 /* if this is a child, restore the logfile to the special
152 name - <domain>, idmap, etc. */
153 if (lfile && *lfile) {
154 lp_set_logfile(lfile);
157 reopen_logs();
158 ret = lp_load_global(get_dyn_CONFIGFILE());
160 reopen_logs();
161 load_interfaces();
162 winbindd_setup_max_fds();
164 return(ret);
168 static void winbindd_status(void)
170 struct winbindd_cli_state *tmp;
172 DEBUG(0, ("winbindd status:\n"));
174 /* Print client state information */
176 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
178 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
179 DEBUG(2, ("\tclient list:\n"));
180 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
181 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
182 (unsigned long)tmp->pid, tmp->sock,
183 client_is_idle(tmp) ? "idle" : "active"));
188 /* Flush client cache */
190 static void flush_caches(void)
192 /* We need to invalidate cached user list entries on a SIGHUP
193 otherwise cached access denied errors due to restrict anonymous
194 hang around until the sequence number changes. */
196 if (!wcache_invalidate_cache()) {
197 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
198 if (!winbindd_cache_validate_and_initialize()) {
199 exit(1);
204 static void flush_caches_noinit(void)
207 * We need to invalidate cached user list entries on a SIGHUP
208 * otherwise cached access denied errors due to restrict anonymous
209 * hang around until the sequence number changes.
210 * NB
211 * Skip uninitialized domains when flush cache.
212 * If domain is not initialized, it means it is never
213 * used or never become online. look, wcache_invalidate_cache()
214 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
215 * for unused domains and large traffic for primay domain's DC if there
216 * are many domains..
219 if (!wcache_invalidate_cache_noinit()) {
220 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
221 if (!winbindd_cache_validate_and_initialize()) {
222 exit(1);
227 /* Handle the signal by unlinking socket and exiting */
229 static void terminate(bool is_parent)
231 if (is_parent) {
232 /* When parent goes away we should
233 * remove the socket file. Not so
234 * when children terminate.
236 char *path = NULL;
238 if (asprintf(&path, "%s/%s",
239 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
240 unlink(path);
241 SAFE_FREE(path);
245 idmap_close();
247 gencache_stabilize();
249 netlogon_creds_cli_close_global_db();
251 #if 0
252 if (interactive) {
253 TALLOC_CTX *mem_ctx = talloc_init("end_description");
254 char *description = talloc_describe_all(mem_ctx);
256 DEBUG(3, ("tallocs left:\n%s\n", description));
257 talloc_destroy(mem_ctx);
259 #endif
261 if (is_parent) {
262 struct messaging_context *msg = winbind_messaging_context();
263 struct server_id self = messaging_server_id(msg);
264 serverid_deregister(self);
265 pidfile_unlink(lp_pid_directory(), "winbindd");
268 exit(0);
271 static void winbindd_sig_term_handler(struct tevent_context *ev,
272 struct tevent_signal *se,
273 int signum,
274 int count,
275 void *siginfo,
276 void *private_data)
278 bool *is_parent = talloc_get_type_abort(private_data, bool);
280 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
281 signum, (int)*is_parent));
282 terminate(*is_parent);
286 handle stdin becoming readable when we are in --foreground mode
288 static void winbindd_stdin_handler(struct tevent_context *ev,
289 struct tevent_fd *fde,
290 uint16_t flags,
291 void *private_data)
293 char c;
294 if (read(0, &c, 1) != 1) {
295 bool *is_parent = talloc_get_type_abort(private_data, bool);
297 /* we have reached EOF on stdin, which means the
298 parent has exited. Shutdown the server */
299 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
300 (int)*is_parent));
301 terminate(*is_parent);
305 bool winbindd_setup_sig_term_handler(bool parent)
307 struct tevent_signal *se;
308 bool *is_parent;
310 is_parent = talloc(winbind_event_context(), bool);
311 if (!is_parent) {
312 return false;
315 *is_parent = parent;
317 se = tevent_add_signal(winbind_event_context(),
318 is_parent,
319 SIGTERM, 0,
320 winbindd_sig_term_handler,
321 is_parent);
322 if (!se) {
323 DEBUG(0,("failed to setup SIGTERM handler"));
324 talloc_free(is_parent);
325 return false;
328 se = tevent_add_signal(winbind_event_context(),
329 is_parent,
330 SIGINT, 0,
331 winbindd_sig_term_handler,
332 is_parent);
333 if (!se) {
334 DEBUG(0,("failed to setup SIGINT handler"));
335 talloc_free(is_parent);
336 return false;
339 se = tevent_add_signal(winbind_event_context(),
340 is_parent,
341 SIGQUIT, 0,
342 winbindd_sig_term_handler,
343 is_parent);
344 if (!se) {
345 DEBUG(0,("failed to setup SIGINT handler"));
346 talloc_free(is_parent);
347 return false;
350 return true;
353 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
355 bool *is_parent;
357 if (foreground) {
358 struct stat st;
360 is_parent = talloc(winbind_event_context(), bool);
361 if (!is_parent) {
362 return false;
365 *is_parent = parent;
367 /* if we are running in the foreground then look for
368 EOF on stdin, and exit if it happens. This allows
369 us to die if the parent process dies
370 Only do this on a pipe or socket, no other device.
372 if (fstat(0, &st) != 0) {
373 return false;
375 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
376 tevent_add_fd(winbind_event_context(),
377 is_parent,
379 TEVENT_FD_READ,
380 winbindd_stdin_handler,
381 is_parent);
385 return true;
388 static void winbindd_sig_hup_handler(struct tevent_context *ev,
389 struct tevent_signal *se,
390 int signum,
391 int count,
392 void *siginfo,
393 void *private_data)
395 const char *file = (const char *)private_data;
397 DEBUG(1,("Reloading services after SIGHUP\n"));
398 flush_caches_noinit();
399 reload_services_file(file);
402 bool winbindd_setup_sig_hup_handler(const char *lfile)
404 struct tevent_signal *se;
405 char *file = NULL;
407 if (lfile) {
408 file = talloc_strdup(winbind_event_context(),
409 lfile);
410 if (!file) {
411 return false;
415 se = tevent_add_signal(winbind_event_context(),
416 winbind_event_context(),
417 SIGHUP, 0,
418 winbindd_sig_hup_handler,
419 file);
420 if (!se) {
421 return false;
424 return true;
427 static void winbindd_sig_chld_handler(struct tevent_context *ev,
428 struct tevent_signal *se,
429 int signum,
430 int count,
431 void *siginfo,
432 void *private_data)
434 pid_t pid;
436 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
437 winbind_child_died(pid);
441 static bool winbindd_setup_sig_chld_handler(void)
443 struct tevent_signal *se;
445 se = tevent_add_signal(winbind_event_context(),
446 winbind_event_context(),
447 SIGCHLD, 0,
448 winbindd_sig_chld_handler,
449 NULL);
450 if (!se) {
451 return false;
454 return true;
457 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
458 struct tevent_signal *se,
459 int signum,
460 int count,
461 void *siginfo,
462 void *private_data)
464 winbindd_status();
467 static bool winbindd_setup_sig_usr2_handler(void)
469 struct tevent_signal *se;
471 se = tevent_add_signal(winbind_event_context(),
472 winbind_event_context(),
473 SIGUSR2, 0,
474 winbindd_sig_usr2_handler,
475 NULL);
476 if (!se) {
477 return false;
480 return true;
483 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
484 static void msg_reload_services(struct messaging_context *msg,
485 void *private_data,
486 uint32_t msg_type,
487 struct server_id server_id,
488 DATA_BLOB *data)
490 /* Flush various caches */
491 flush_caches();
492 reload_services_file((const char *) private_data);
495 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
496 static void msg_shutdown(struct messaging_context *msg,
497 void *private_data,
498 uint32_t msg_type,
499 struct server_id server_id,
500 DATA_BLOB *data)
502 /* only the parent waits for this message */
503 DEBUG(0,("Got shutdown message\n"));
504 terminate(true);
508 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
509 void *private_data,
510 uint32_t msg_type,
511 struct server_id server_id,
512 DATA_BLOB *data)
514 uint8_t ret;
515 pid_t child_pid;
516 NTSTATUS status;
518 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
519 "message.\n"));
522 * call the validation code from a child:
523 * so we don't block the main winbindd and the validation
524 * code can safely use fork/waitpid...
526 child_pid = fork();
528 if (child_pid == -1) {
529 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
530 strerror(errno)));
531 return;
534 if (child_pid != 0) {
535 /* parent */
536 DEBUG(5, ("winbind_msg_validate_cache: child created with "
537 "pid %d.\n", (int)child_pid));
538 return;
541 /* child */
543 status = winbindd_reinit_after_fork(NULL, NULL);
544 if (!NT_STATUS_IS_OK(status)) {
545 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
546 nt_errstr(status)));
547 _exit(0);
550 /* install default SIGCHLD handler: validation code uses fork/waitpid */
551 CatchSignal(SIGCHLD, SIG_DFL);
553 ret = (uint8_t)winbindd_validate_cache_nobackup();
554 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
555 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
556 (size_t)1);
557 _exit(0);
560 static struct winbindd_dispatch_table {
561 enum winbindd_cmd cmd;
562 void (*fn)(struct winbindd_cli_state *state);
563 const char *winbindd_cmd_name;
564 } dispatch_table[] = {
566 /* Enumeration functions */
568 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
569 "LIST_TRUSTDOM" },
571 /* Miscellaneous */
573 { WINBINDD_INFO, winbindd_info, "INFO" },
574 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
575 "INTERFACE_VERSION" },
576 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
577 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
578 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
579 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
580 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
581 "WINBINDD_PRIV_PIPE_DIR" },
583 /* Credential cache access */
584 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
585 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
587 /* End of list */
589 { WINBINDD_NUM_CMDS, NULL, "NONE" }
592 struct winbindd_async_dispatch_table {
593 enum winbindd_cmd cmd;
594 const char *cmd_name;
595 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
596 struct tevent_context *ev,
597 struct winbindd_cli_state *cli,
598 struct winbindd_request *request);
599 NTSTATUS (*recv_req)(struct tevent_req *req,
600 struct winbindd_response *presp);
603 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
604 { WINBINDD_PING, "PING",
605 wb_ping_send, wb_ping_recv },
606 { WINBINDD_LOOKUPSID, "LOOKUPSID",
607 winbindd_lookupsid_send, winbindd_lookupsid_recv },
608 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
609 winbindd_lookupsids_send, winbindd_lookupsids_recv },
610 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
611 winbindd_lookupname_send, winbindd_lookupname_recv },
612 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
613 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
614 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
615 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
616 { WINBINDD_GETPWSID, "GETPWSID",
617 winbindd_getpwsid_send, winbindd_getpwsid_recv },
618 { WINBINDD_GETPWNAM, "GETPWNAM",
619 winbindd_getpwnam_send, winbindd_getpwnam_recv },
620 { WINBINDD_GETPWUID, "GETPWUID",
621 winbindd_getpwuid_send, winbindd_getpwuid_recv },
622 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
623 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
624 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
625 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
626 { WINBINDD_GETGROUPS, "GETGROUPS",
627 winbindd_getgroups_send, winbindd_getgroups_recv },
628 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
629 winbindd_show_sequence_send, winbindd_show_sequence_recv },
630 { WINBINDD_GETGRGID, "GETGRGID",
631 winbindd_getgrgid_send, winbindd_getgrgid_recv },
632 { WINBINDD_GETGRNAM, "GETGRNAM",
633 winbindd_getgrnam_send, winbindd_getgrnam_recv },
634 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
635 winbindd_getusersids_send, winbindd_getusersids_recv },
636 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
637 winbindd_lookuprids_send, winbindd_lookuprids_recv },
638 { WINBINDD_SETPWENT, "SETPWENT",
639 winbindd_setpwent_send, winbindd_setpwent_recv },
640 { WINBINDD_GETPWENT, "GETPWENT",
641 winbindd_getpwent_send, winbindd_getpwent_recv },
642 { WINBINDD_ENDPWENT, "ENDPWENT",
643 winbindd_endpwent_send, winbindd_endpwent_recv },
644 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
645 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
646 { WINBINDD_GETDCNAME, "GETDCNAME",
647 winbindd_getdcname_send, winbindd_getdcname_recv },
648 { WINBINDD_SETGRENT, "SETGRENT",
649 winbindd_setgrent_send, winbindd_setgrent_recv },
650 { WINBINDD_GETGRENT, "GETGRENT",
651 winbindd_getgrent_send, winbindd_getgrent_recv },
652 { WINBINDD_ENDGRENT, "ENDGRENT",
653 winbindd_endgrent_send, winbindd_endgrent_recv },
654 { WINBINDD_LIST_USERS, "LIST_USERS",
655 winbindd_list_users_send, winbindd_list_users_recv },
656 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
657 winbindd_list_groups_send, winbindd_list_groups_recv },
658 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
659 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
660 { WINBINDD_PING_DC, "PING_DC",
661 winbindd_ping_dc_send, winbindd_ping_dc_recv },
662 { WINBINDD_PAM_AUTH, "PAM_AUTH",
663 winbindd_pam_auth_send, winbindd_pam_auth_recv },
664 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
665 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
666 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
667 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
668 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
669 winbindd_pam_chng_pswd_auth_crap_send,
670 winbindd_pam_chng_pswd_auth_crap_recv },
671 { WINBINDD_WINS_BYIP, "WINS_BYIP",
672 winbindd_wins_byip_send, winbindd_wins_byip_recv },
673 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
674 winbindd_wins_byname_send, winbindd_wins_byname_recv },
676 { 0, NULL, NULL, NULL }
679 static struct winbindd_async_dispatch_table async_priv_table[] = {
680 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
681 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
682 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
683 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
684 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
685 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
686 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
687 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
689 { 0, NULL, NULL, NULL }
692 static void wb_request_done(struct tevent_req *req);
694 static void process_request(struct winbindd_cli_state *state)
696 struct winbindd_dispatch_table *table = dispatch_table;
697 struct winbindd_async_dispatch_table *atable;
699 state->mem_ctx = talloc_named(state, 0, "winbind request");
700 if (state->mem_ctx == NULL)
701 return;
703 /* Remember who asked us. */
704 state->pid = state->request->pid;
706 state->cmd_name = "unknown request";
707 state->recv_fn = NULL;
708 /* client is newest */
709 winbindd_promote_client(state);
711 /* Process command */
713 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
714 if (state->request->cmd == atable->cmd) {
715 break;
719 if ((atable->send_req == NULL) && state->privileged) {
720 for (atable = async_priv_table; atable->send_req;
721 atable += 1) {
722 if (state->request->cmd == atable->cmd) {
723 break;
728 if (atable->send_req != NULL) {
729 struct tevent_req *req;
731 state->cmd_name = atable->cmd_name;
732 state->recv_fn = atable->recv_req;
734 DEBUG(10, ("process_request: Handling async request %d:%s\n",
735 (int)state->pid, state->cmd_name));
737 req = atable->send_req(state->mem_ctx, winbind_event_context(),
738 state, state->request);
739 if (req == NULL) {
740 DEBUG(0, ("process_request: atable->send failed for "
741 "%s\n", atable->cmd_name));
742 request_error(state);
743 return;
745 tevent_req_set_callback(req, wb_request_done, state);
746 return;
749 state->response = talloc_zero(state->mem_ctx,
750 struct winbindd_response);
751 if (state->response == NULL) {
752 DEBUG(10, ("talloc failed\n"));
753 remove_client(state);
754 return;
756 state->response->result = WINBINDD_PENDING;
757 state->response->length = sizeof(struct winbindd_response);
759 for (table = dispatch_table; table->fn; table++) {
760 if (state->request->cmd == table->cmd) {
761 DEBUG(10,("process_request: request fn %s\n",
762 table->winbindd_cmd_name ));
763 state->cmd_name = table->winbindd_cmd_name;
764 table->fn(state);
765 break;
769 if (!table->fn) {
770 DEBUG(10,("process_request: unknown request fn number %d\n",
771 (int)state->request->cmd ));
772 request_error(state);
776 static void wb_request_done(struct tevent_req *req)
778 struct winbindd_cli_state *state = tevent_req_callback_data(
779 req, struct winbindd_cli_state);
780 NTSTATUS status;
782 state->response = talloc_zero(state->mem_ctx,
783 struct winbindd_response);
784 if (state->response == NULL) {
785 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
786 (int)state->pid, state->cmd_name));
787 remove_client(state);
788 return;
790 state->response->result = WINBINDD_PENDING;
791 state->response->length = sizeof(struct winbindd_response);
793 status = state->recv_fn(req, state->response);
794 TALLOC_FREE(req);
796 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
797 (int)state->pid, state->cmd_name, nt_errstr(status)));
799 if (!NT_STATUS_IS_OK(status)) {
800 request_error(state);
801 return;
803 request_ok(state);
807 * This is the main event loop of winbind requests. It goes through a
808 * state-machine of 3 read/write requests, 4 if you have extra data to send.
810 * An idle winbind client has a read request of 4 bytes outstanding,
811 * finalizing function is request_len_recv, checking the length. request_recv
812 * then processes the packet. The processing function then at some point has
813 * to call request_finished which schedules sending the response.
816 static void request_finished(struct winbindd_cli_state *state);
818 static void winbind_client_request_read(struct tevent_req *req);
819 static void winbind_client_response_written(struct tevent_req *req);
820 static void winbind_client_activity(struct tevent_req *req);
822 static void request_finished(struct winbindd_cli_state *state)
824 struct tevent_req *req;
826 /* free client socket monitoring request */
827 TALLOC_FREE(state->io_req);
829 TALLOC_FREE(state->request);
831 req = wb_resp_write_send(state, winbind_event_context(),
832 state->out_queue, state->sock,
833 state->response);
834 if (req == NULL) {
835 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
836 (int)state->pid, state->cmd_name));
837 remove_client(state);
838 return;
840 tevent_req_set_callback(req, winbind_client_response_written, state);
841 state->io_req = req;
844 static void winbind_client_response_written(struct tevent_req *req)
846 struct winbindd_cli_state *state = tevent_req_callback_data(
847 req, struct winbindd_cli_state);
848 ssize_t ret;
849 int err;
851 state->io_req = NULL;
853 ret = wb_resp_write_recv(req, &err);
854 TALLOC_FREE(req);
855 if (ret == -1) {
856 close(state->sock);
857 state->sock = -1;
858 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
859 (int)state->pid, state->cmd_name, strerror(err)));
860 remove_client(state);
861 return;
864 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
865 "to client\n", (int)state->pid, state->cmd_name));
867 TALLOC_FREE(state->mem_ctx);
868 state->response = NULL;
869 state->cmd_name = "no request";
870 state->recv_fn = NULL;
872 req = wb_req_read_send(state, winbind_event_context(), state->sock,
873 WINBINDD_MAX_EXTRA_DATA);
874 if (req == NULL) {
875 remove_client(state);
876 return;
878 tevent_req_set_callback(req, winbind_client_request_read, state);
879 state->io_req = req;
882 void request_error(struct winbindd_cli_state *state)
884 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
885 state->response->result = WINBINDD_ERROR;
886 request_finished(state);
889 void request_ok(struct winbindd_cli_state *state)
891 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
892 state->response->result = WINBINDD_OK;
893 request_finished(state);
896 /* Process a new connection by adding it to the client connection list */
898 static void new_connection(int listen_sock, bool privileged)
900 struct sockaddr_un sunaddr;
901 struct winbindd_cli_state *state;
902 struct tevent_req *req;
903 socklen_t len;
904 int sock;
906 /* Accept connection */
908 len = sizeof(sunaddr);
910 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
912 if (sock == -1) {
913 if (errno != EINTR) {
914 DEBUG(0, ("Failed to accept socket - %s\n",
915 strerror(errno)));
917 return;
920 DEBUG(6,("accepted socket %d\n", sock));
922 /* Create new connection structure */
924 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
925 close(sock);
926 return;
929 state->sock = sock;
931 state->out_queue = tevent_queue_create(state, "winbind client reply");
932 if (state->out_queue == NULL) {
933 close(sock);
934 TALLOC_FREE(state);
935 return;
938 state->privileged = privileged;
940 req = wb_req_read_send(state, winbind_event_context(), state->sock,
941 WINBINDD_MAX_EXTRA_DATA);
942 if (req == NULL) {
943 TALLOC_FREE(state);
944 close(sock);
945 return;
947 tevent_req_set_callback(req, winbind_client_request_read, state);
948 state->io_req = req;
950 /* Add to connection list */
952 winbindd_add_client(state);
955 static void winbind_client_request_read(struct tevent_req *req)
957 struct winbindd_cli_state *state = tevent_req_callback_data(
958 req, struct winbindd_cli_state);
959 ssize_t ret;
960 int err;
962 state->io_req = NULL;
964 ret = wb_req_read_recv(req, state, &state->request, &err);
965 TALLOC_FREE(req);
966 if (ret == -1) {
967 if (err == EPIPE) {
968 DEBUG(6, ("closing socket %d, client exited\n",
969 state->sock));
970 } else {
971 DEBUG(2, ("Could not read client request from fd %d: "
972 "%s\n", state->sock, strerror(err)));
974 close(state->sock);
975 state->sock = -1;
976 remove_client(state);
977 return;
980 req = wait_for_read_send(state, winbind_event_context(), state->sock,
981 true);
982 if (req == NULL) {
983 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
984 " wait_for_read_send failed - removing client\n",
985 (int)state->pid, state->cmd_name));
986 remove_client(state);
987 return;
989 tevent_req_set_callback(req, winbind_client_activity, state);
990 state->io_req = req;
992 process_request(state);
995 static void winbind_client_activity(struct tevent_req *req)
997 struct winbindd_cli_state *state =
998 tevent_req_callback_data(req, struct winbindd_cli_state);
999 int err;
1000 bool has_data;
1002 has_data = wait_for_read_recv(req, &err);
1004 if (has_data) {
1005 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1006 "unexpected data from client - removing client\n",
1007 (int)state->pid, state->cmd_name));
1008 } else {
1009 if (err == EPIPE) {
1010 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1011 "client has closed connection - removing "
1012 "client\n",
1013 (int)state->pid, state->cmd_name));
1014 } else {
1015 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1016 "client socket error (%s) - removing "
1017 "client\n",
1018 (int)state->pid, state->cmd_name,
1019 strerror(err)));
1023 remove_client(state);
1026 /* Remove a client connection from client connection list */
1028 static void remove_client(struct winbindd_cli_state *state)
1030 char c = 0;
1031 int nwritten;
1033 /* It's a dead client - hold a funeral */
1035 if (state == NULL) {
1036 return;
1040 * We need to remove a pending wb_req_read_*
1041 * or wb_resp_write_* request before closing the
1042 * socket.
1044 * This is important as they might have used tevent_add_fd() and we
1045 * use the epoll * backend on linux. So we must remove the tevent_fd
1046 * before closing the fd.
1048 * Otherwise we might hit a race with close_conns_after_fork() (via
1049 * winbindd_reinit_after_fork()) where a file description
1050 * is still open in a child, which means it's still active in
1051 * the parents epoll queue, but the related tevent_fd is already
1052 * already gone in the parent.
1054 * See bug #11141.
1056 TALLOC_FREE(state->io_req);
1058 if (state->sock != -1) {
1059 /* tell client, we are closing ... */
1060 nwritten = write(state->sock, &c, sizeof(c));
1061 if (nwritten == -1) {
1062 DEBUG(2, ("final write to client failed: %s\n",
1063 strerror(errno)));
1066 /* Close socket */
1068 close(state->sock);
1069 state->sock = -1;
1072 TALLOC_FREE(state->mem_ctx);
1074 /* Remove from list and free */
1076 winbindd_remove_client(state);
1077 TALLOC_FREE(state);
1080 /* Is a client idle? */
1082 static bool client_is_idle(struct winbindd_cli_state *state) {
1083 return (state->request == NULL &&
1084 state->response == NULL &&
1085 !state->pwent_state && !state->grent_state);
1088 /* Shutdown client connection which has been idle for the longest time */
1090 static bool remove_idle_client(void)
1092 struct winbindd_cli_state *state, *remove_state = NULL;
1093 int nidle = 0;
1095 for (state = winbindd_client_list(); state; state = state->next) {
1096 if (client_is_idle(state)) {
1097 nidle++;
1098 /* list is sorted by access time */
1099 remove_state = state;
1103 if (remove_state) {
1104 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1105 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1106 remove_client(remove_state);
1107 return True;
1110 return False;
1114 * Terminate all clients whose requests have taken longer than
1115 * "winbind request timeout" seconds to process, or have been
1116 * idle for more than "winbind request timeout" seconds.
1119 static void remove_timed_out_clients(void)
1121 struct winbindd_cli_state *state, *prev = NULL;
1122 time_t curr_time = time(NULL);
1123 int timeout_val = lp_winbind_request_timeout();
1125 for (state = winbindd_client_list_tail(); state; state = prev) {
1126 time_t expiry_time;
1128 prev = winbindd_client_list_prev(state);
1129 expiry_time = state->last_access + timeout_val;
1131 if (curr_time <= expiry_time) {
1132 /* list is sorted, previous clients in
1133 list are newer */
1134 break;
1137 if (client_is_idle(state)) {
1138 DEBUG(5,("Idle client timed out, "
1139 "shutting down sock %d, pid %u\n",
1140 state->sock,
1141 (unsigned int)state->pid));
1142 } else {
1143 DEBUG(5,("Client request timed out, "
1144 "shutting down sock %d, pid %u\n",
1145 state->sock,
1146 (unsigned int)state->pid));
1149 remove_client(state);
1153 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1154 struct tevent_timer *te,
1155 struct timeval current_time,
1156 void *private_data)
1158 remove_timed_out_clients();
1159 if (tevent_add_timer(ev, ev,
1160 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1161 winbindd_scrub_clients_handler, NULL) == NULL) {
1162 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1163 exit(1);
1167 struct winbindd_listen_state {
1168 bool privileged;
1169 int fd;
1172 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1173 struct tevent_fd *fde,
1174 uint16_t flags,
1175 void *private_data)
1177 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1178 struct winbindd_listen_state);
1180 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1181 DEBUG(5,("winbindd: Exceeding %d client "
1182 "connections, removing idle "
1183 "connection.\n", lp_winbind_max_clients()));
1184 if (!remove_idle_client()) {
1185 DEBUG(0,("winbindd: Exceeding %d "
1186 "client connections, no idle "
1187 "connection found\n",
1188 lp_winbind_max_clients()));
1189 break;
1192 remove_timed_out_clients();
1193 new_connection(s->fd, s->privileged);
1197 * Winbindd socket accessor functions
1200 char *get_winbind_priv_pipe_dir(void)
1202 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1205 static void winbindd_setup_max_fds(void)
1207 int num_fds = MAX_OPEN_FUDGEFACTOR;
1208 int actual_fds;
1210 num_fds += lp_winbind_max_clients();
1211 /* Add some more to account for 2 sockets open
1212 when the client transitions from unprivileged
1213 to privileged socket
1215 num_fds += lp_winbind_max_clients() / 10;
1217 /* Add one socket per child process
1218 (yeah there are child processes other than the
1219 domain children but only domain children can vary
1220 with configuration
1222 num_fds += lp_winbind_max_domain_connections() *
1223 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1225 actual_fds = set_maxfiles(num_fds);
1227 if (actual_fds < num_fds) {
1228 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1229 "requested %d open files, %d are available.\n",
1230 num_fds, actual_fds));
1234 static bool winbindd_setup_listeners(void)
1236 struct winbindd_listen_state *pub_state = NULL;
1237 struct winbindd_listen_state *priv_state = NULL;
1238 struct tevent_fd *fde;
1239 int rc;
1240 char *socket_path;
1242 pub_state = talloc(winbind_event_context(),
1243 struct winbindd_listen_state);
1244 if (!pub_state) {
1245 goto failed;
1248 pub_state->privileged = false;
1249 pub_state->fd = create_pipe_sock(
1250 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1251 if (pub_state->fd == -1) {
1252 goto failed;
1254 rc = listen(pub_state->fd, 5);
1255 if (rc < 0) {
1256 goto failed;
1259 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1260 TEVENT_FD_READ, winbindd_listen_fde_handler,
1261 pub_state);
1262 if (fde == NULL) {
1263 close(pub_state->fd);
1264 goto failed;
1266 tevent_fd_set_auto_close(fde);
1268 priv_state = talloc(winbind_event_context(),
1269 struct winbindd_listen_state);
1270 if (!priv_state) {
1271 goto failed;
1274 socket_path = get_winbind_priv_pipe_dir();
1275 if (socket_path == NULL) {
1276 goto failed;
1279 priv_state->privileged = true;
1280 priv_state->fd = create_pipe_sock(
1281 socket_path, WINBINDD_SOCKET_NAME, 0750);
1282 TALLOC_FREE(socket_path);
1283 if (priv_state->fd == -1) {
1284 goto failed;
1286 rc = listen(priv_state->fd, 5);
1287 if (rc < 0) {
1288 goto failed;
1291 fde = tevent_add_fd(winbind_event_context(), priv_state,
1292 priv_state->fd, TEVENT_FD_READ,
1293 winbindd_listen_fde_handler, priv_state);
1294 if (fde == NULL) {
1295 close(priv_state->fd);
1296 goto failed;
1298 tevent_fd_set_auto_close(fde);
1300 winbindd_scrub_clients_handler(winbind_event_context(), NULL,
1301 timeval_current(), NULL);
1302 return true;
1303 failed:
1304 TALLOC_FREE(pub_state);
1305 TALLOC_FREE(priv_state);
1306 return false;
1309 bool winbindd_use_idmap_cache(void)
1311 return !opt_nocache;
1314 bool winbindd_use_cache(void)
1316 return !opt_nocache;
1319 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1320 bool foreground)
1322 NTSTATUS status;
1323 /* Setup signal handlers */
1325 if (!winbindd_setup_sig_term_handler(true))
1326 exit(1);
1327 if (!winbindd_setup_stdin_handler(true, foreground))
1328 exit(1);
1329 if (!winbindd_setup_sig_hup_handler(NULL))
1330 exit(1);
1331 if (!winbindd_setup_sig_chld_handler())
1332 exit(1);
1333 if (!winbindd_setup_sig_usr2_handler())
1334 exit(1);
1336 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1339 * Ensure all cache and idmap caches are consistent
1340 * and initialized before we startup.
1342 if (!winbindd_cache_validate_and_initialize()) {
1343 exit(1);
1346 /* get broadcast messages */
1348 if (!serverid_register(messaging_server_id(msg_ctx),
1349 FLAG_MSG_GENERAL |
1350 FLAG_MSG_WINBIND |
1351 FLAG_MSG_DBWRAP)) {
1352 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1353 exit(1);
1356 /* React on 'smbcontrol winbindd reload-config' in the same way
1357 as to SIGHUP signal */
1358 messaging_register(msg_ctx, NULL,
1359 MSG_SMB_CONF_UPDATED, msg_reload_services);
1360 messaging_register(msg_ctx, NULL,
1361 MSG_SHUTDOWN, msg_shutdown);
1363 /* Handle online/offline messages. */
1364 messaging_register(msg_ctx, NULL,
1365 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1366 messaging_register(msg_ctx, NULL,
1367 MSG_WINBIND_ONLINE, winbind_msg_online);
1368 messaging_register(msg_ctx, NULL,
1369 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1371 /* Handle domain online/offline messages for domains */
1372 messaging_register(winbind_messaging_context(), NULL,
1373 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1374 messaging_register(winbind_messaging_context(), NULL,
1375 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1377 messaging_register(msg_ctx, NULL,
1378 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1380 messaging_register(msg_ctx, NULL,
1381 MSG_WINBIND_VALIDATE_CACHE,
1382 winbind_msg_validate_cache);
1384 messaging_register(msg_ctx, NULL,
1385 MSG_WINBIND_DUMP_DOMAIN_LIST,
1386 winbind_msg_dump_domain_list);
1388 messaging_register(msg_ctx, NULL,
1389 MSG_WINBIND_IP_DROPPED,
1390 winbind_msg_ip_dropped_parent);
1392 /* Register handler for MSG_DEBUG. */
1393 messaging_register(msg_ctx, NULL,
1394 MSG_DEBUG,
1395 winbind_msg_debug);
1397 netsamlogon_cache_init(); /* Non-critical */
1399 /* clear the cached list of trusted domains */
1401 wcache_tdc_clear();
1403 if (!init_domain_list()) {
1404 DEBUG(0,("unable to initialize domain list\n"));
1405 exit(1);
1408 init_idmap_child();
1409 init_locator_child();
1411 smb_nscd_flush_user_cache();
1412 smb_nscd_flush_group_cache();
1414 if (lp_allow_trusted_domains()) {
1415 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1416 rescan_trusted_domains, NULL) == NULL) {
1417 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1418 exit(1);
1422 status = wb_irpc_register();
1424 if (!NT_STATUS_IS_OK(status)) {
1425 DEBUG(0, ("Could not register IRPC handlers\n"));
1426 exit(1);
1430 struct winbindd_addrchanged_state {
1431 struct addrchange_context *ctx;
1432 struct tevent_context *ev;
1433 struct messaging_context *msg_ctx;
1436 static void winbindd_addr_changed(struct tevent_req *req);
1438 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1439 struct tevent_context *ev,
1440 struct messaging_context *msg_ctx)
1442 struct winbindd_addrchanged_state *state;
1443 struct tevent_req *req;
1444 NTSTATUS status;
1446 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1447 if (state == NULL) {
1448 DEBUG(10, ("talloc failed\n"));
1449 return;
1451 state->ev = ev;
1452 state->msg_ctx = msg_ctx;
1454 status = addrchange_context_create(state, &state->ctx);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 DEBUG(10, ("addrchange_context_create failed: %s\n",
1457 nt_errstr(status)));
1458 TALLOC_FREE(state);
1459 return;
1461 req = addrchange_send(state, ev, state->ctx);
1462 if (req == NULL) {
1463 DEBUG(0, ("addrchange_send failed\n"));
1464 TALLOC_FREE(state);
1465 return;
1467 tevent_req_set_callback(req, winbindd_addr_changed, state);
1470 static void winbindd_addr_changed(struct tevent_req *req)
1472 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1473 req, struct winbindd_addrchanged_state);
1474 enum addrchange_type type;
1475 struct sockaddr_storage addr;
1476 NTSTATUS status;
1478 status = addrchange_recv(req, &type, &addr);
1479 TALLOC_FREE(req);
1480 if (!NT_STATUS_IS_OK(status)) {
1481 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1482 nt_errstr(status)));
1483 TALLOC_FREE(state);
1484 return;
1486 if (type == ADDRCHANGE_DEL) {
1487 char addrstr[INET6_ADDRSTRLEN];
1488 DATA_BLOB blob;
1490 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1492 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1493 addrstr));
1495 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1497 status = messaging_send(state->msg_ctx,
1498 messaging_server_id(state->msg_ctx),
1499 MSG_WINBIND_IP_DROPPED, &blob);
1500 if (!NT_STATUS_IS_OK(status)) {
1501 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1502 nt_errstr(status)));
1505 req = addrchange_send(state, state->ev, state->ctx);
1506 if (req == NULL) {
1507 DEBUG(0, ("addrchange_send failed\n"));
1508 TALLOC_FREE(state);
1509 return;
1511 tevent_req_set_callback(req, winbindd_addr_changed, state);
1514 /* Main function */
1516 int main(int argc, const char **argv)
1518 static bool is_daemon = False;
1519 static bool Fork = True;
1520 static bool log_stdout = False;
1521 static bool no_process_group = False;
1522 enum {
1523 OPT_DAEMON = 1000,
1524 OPT_FORK,
1525 OPT_NO_PROCESS_GROUP,
1526 OPT_LOG_STDOUT
1528 struct poptOption long_options[] = {
1529 POPT_AUTOHELP
1530 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1531 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1532 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1533 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1534 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1535 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1536 POPT_COMMON_SAMBA
1537 POPT_TABLEEND
1539 poptContext pc;
1540 int opt;
1541 TALLOC_CTX *frame;
1542 NTSTATUS status;
1543 bool ok;
1546 * Do this before any other talloc operation
1548 talloc_enable_null_tracking();
1549 frame = talloc_stackframe();
1552 * We want total control over the permissions on created files,
1553 * so set our umask to 0.
1555 umask(0);
1557 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1559 /* glibc (?) likes to print "User defined signal 1" and exit if a
1560 SIGUSR[12] is received before a handler is installed */
1562 CatchSignal(SIGUSR1, SIG_IGN);
1563 CatchSignal(SIGUSR2, SIG_IGN);
1565 fault_setup();
1566 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1568 smb_init_locale();
1570 /* Initialise for running in non-root mode */
1572 sec_init();
1574 set_remote_machine_name("winbindd", False);
1576 /* Set environment variable so we don't recursively call ourselves.
1577 This may also be useful interactively. */
1579 if ( !winbind_off() ) {
1580 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1581 exit(1);
1584 /* Initialise samba/rpc client stuff */
1586 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1588 while ((opt = poptGetNextOpt(pc)) != -1) {
1589 switch (opt) {
1590 /* Don't become a daemon */
1591 case OPT_DAEMON:
1592 is_daemon = True;
1593 break;
1594 case 'i':
1595 interactive = True;
1596 log_stdout = True;
1597 Fork = False;
1598 break;
1599 case OPT_FORK:
1600 Fork = false;
1601 break;
1602 case OPT_NO_PROCESS_GROUP:
1603 no_process_group = true;
1604 break;
1605 case OPT_LOG_STDOUT:
1606 log_stdout = true;
1607 break;
1608 case 'n':
1609 opt_nocache = true;
1610 break;
1611 default:
1612 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1613 poptBadOption(pc, 0), poptStrerror(opt));
1614 poptPrintUsage(pc, stderr, 0);
1615 exit(1);
1619 /* We call dump_core_setup one more time because the command line can
1620 * set the log file or the log-basename and this will influence where
1621 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1622 * the default value derived from build's prefix. For EOM this value
1623 * is often not related to the path where winbindd is actually run
1624 * in production.
1626 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1627 if (is_daemon && interactive) {
1628 d_fprintf(stderr,"\nERROR: "
1629 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1630 poptPrintUsage(pc, stderr, 0);
1631 exit(1);
1634 if (log_stdout && Fork) {
1635 d_fprintf(stderr, "\nERROR: "
1636 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1637 poptPrintUsage(pc, stderr, 0);
1638 exit(1);
1641 poptFreeContext(pc);
1643 if (!override_logfile) {
1644 char *lfile = NULL;
1645 if (asprintf(&lfile,"%s/log.winbindd",
1646 get_dyn_LOGFILEBASE()) > 0) {
1647 lp_set_logfile(lfile);
1648 SAFE_FREE(lfile);
1652 if (log_stdout) {
1653 setup_logging("winbindd", DEBUG_STDOUT);
1654 } else {
1655 setup_logging("winbindd", DEBUG_FILE);
1657 reopen_logs();
1659 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1660 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1662 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1663 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1664 exit(1);
1666 /* After parsing the configuration file we setup the core path one more time
1667 * as the log file might have been set in the configuration and cores's
1668 * path is by default basename(lp_logfile()).
1670 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1672 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1673 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1674 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1675 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"));
1676 exit(1);
1679 if (!cluster_probe_ok()) {
1680 exit(1);
1683 /* Initialise messaging system */
1685 if (winbind_messaging_context() == NULL) {
1686 exit(1);
1689 if (!reload_services_file(NULL)) {
1690 DEBUG(0, ("error opening config file\n"));
1691 exit(1);
1695 size_t i;
1696 const char *idmap_backend;
1697 const char *invalid_backends[] = {
1698 "ad", "rfc2307", "rid",
1701 idmap_backend = lp_idmap_default_backend();
1702 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1703 ok = strequal(idmap_backend, invalid_backends[i]);
1704 if (ok) {
1705 DBG_ERR("FATAL: Invalid idmap backend %s "
1706 "configured as the default backend!\n",
1707 idmap_backend);
1708 exit(1);
1713 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1714 if (!ok) {
1715 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1716 lp_lock_directory(), strerror(errno)));
1717 exit(1);
1720 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1721 if (!ok) {
1722 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1723 lp_pid_directory(), strerror(errno)));
1724 exit(1);
1727 /* Setup names. */
1729 if (!init_names())
1730 exit(1);
1732 load_interfaces();
1734 if (!secrets_init()) {
1736 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1737 return False;
1740 status = rpccli_pre_open_netlogon_creds();
1741 if (!NT_STATUS_IS_OK(status)) {
1742 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1743 nt_errstr(status)));
1744 exit(1);
1747 /* Unblock all signals we are interested in as they may have been
1748 blocked by the parent process. */
1750 BlockSignals(False, SIGINT);
1751 BlockSignals(False, SIGQUIT);
1752 BlockSignals(False, SIGTERM);
1753 BlockSignals(False, SIGUSR1);
1754 BlockSignals(False, SIGUSR2);
1755 BlockSignals(False, SIGHUP);
1756 BlockSignals(False, SIGCHLD);
1758 if (!interactive)
1759 become_daemon(Fork, no_process_group, log_stdout);
1761 pidfile_create(lp_pid_directory(), "winbindd");
1763 #if HAVE_SETPGID
1765 * If we're interactive we want to set our own process group for
1766 * signal management.
1768 if (interactive && !no_process_group)
1769 setpgid( (pid_t)0, (pid_t)0);
1770 #endif
1772 TimeInit();
1774 /* Don't use winbindd_reinit_after_fork here as
1775 * we're just starting up and haven't created any
1776 * winbindd-specific resources we must free yet. JRA.
1779 status = reinit_after_fork(winbind_messaging_context(),
1780 winbind_event_context(),
1781 false, NULL);
1782 if (!NT_STATUS_IS_OK(status)) {
1783 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1787 * Do not initialize the parent-child-pipe before becoming
1788 * a daemon: this is used to detect a died parent in the child
1789 * process.
1791 status = init_before_fork();
1792 if (!NT_STATUS_IS_OK(status)) {
1793 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1796 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1798 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1799 exit(1);
1802 status = init_system_session_info();
1803 if (!NT_STATUS_IS_OK(status)) {
1804 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1807 rpc_lsarpc_init(NULL);
1808 rpc_samr_init(NULL);
1810 winbindd_init_addrchange(NULL, winbind_event_context(),
1811 winbind_messaging_context());
1813 /* setup listen sockets */
1815 if (!winbindd_setup_listeners()) {
1816 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1819 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1821 TALLOC_FREE(frame);
1823 if (!interactive) {
1824 daemon_ready("winbindd");
1827 /* Loop waiting for requests */
1828 while (1) {
1829 frame = talloc_stackframe();
1831 if (tevent_loop_once(winbind_event_context()) == -1) {
1832 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1833 strerror(errno)));
1834 return 1;
1837 TALLOC_FREE(frame);
1840 return 0;